validate([ 'code' => ['required', 'string', 'max:128'], 'nickname' => ['nullable', 'string', 'max:64'], 'avatar_url' => ['nullable', 'string', 'max:512'], ]); try { $session = $this->wechat->codeToSession($data['code']); } catch (\Throwable $e) { return $this->fail($e->getMessage(), 422); } $user = MiniappUser::query()->firstOrNew(['openid' => $session['openid']]); if ($session['unionid']) { $user->unionid = $session['unionid']; } if (! empty($data['nickname'])) { $user->nickname = $data['nickname']; } if (! empty($data['avatar_url'])) { $user->avatar_url = $data['avatar_url']; } if (! $user->exists) { $user->status = 1; $displayName = $data['nickname'] ?? '微信用户'; $user->name = $displayName; if (empty($user->nickname)) { $user->nickname = $displayName; } } $user->save(); if ((int) $user->status !== 1) { return $this->fail('账号已停用', 403); } return $this->ok($this->issueToken($user)); } /** * 本地开发专用:浏览器 H5 调试时无法调用 wx.login,使用此接口模拟登录。 */ public function devLogin(Request $request): JsonResponse { if (! app()->environment('local')) { return $this->fail('仅 local 环境可用', 404); } $data = $request->validate([ 'nickname' => ['nullable', 'string', 'max:64'], 'avatar_url' => ['nullable', 'string', 'max:512'], ]); $openid = 'dev_'.Str::lower(Str::random(24)); $user = MiniappUser::query()->create([ 'openid' => $openid, 'unionid' => null, 'nickname' => $data['nickname'] ?? '本地调试用户', 'avatar_url' => $data['avatar_url'] ?? null, 'name' => $data['nickname'] ?? '本地调试用户', 'status' => 1, ]); return $this->ok($this->issueToken($user)); } public function me(Request $request): JsonResponse { /** @var MiniappUser $user */ $user = $request->user(); return $this->ok(MiniappPresenter::userPayload($user)); } public function logout(Request $request): JsonResponse { $request->user()?->currentAccessToken()?->delete(); return $this->ok(null, '已退出'); } /** @return array */ protected function issueToken(MiniappUser $user): array { $user->tokens()->where('name', 'miniapp-api')->delete(); $token = $user->createToken('miniapp-api')->plainTextToken; return [ 'token' => $token, 'token_type' => 'Bearer', 'user' => MiniappPresenter::userPayload($user), ]; } }