validate([ 'code' => 'required' ], [ 'code.required' => '授权码必填' ]); $app = $this->getWechatApp(); $result = $app->auth->session($request->input('code')); if (data_get($result, 'errcode')) { throw new BizException(data_get($result, 'errmsg')); } $openid = data_get($result, 'openid'); $type = SocialiteType::WechatMiniProgram->value; if (!$openid) { throw new BizException('授权失败, 未找到 openid'); } $time = now(); $ip = $request->realIp(); $inviter = null; if ($request->filled('invite_code')) { $inviter = $this->findUserByCode($request->input('invite_code', '')); } try { DB::beginTransaction(); $user_social = SocialiteUser::where(['socialite_id' => $openid, 'socialite_type' => $type])->first(); if (!$user_social) { $attributes = [ 'register_ip' => $ip, 'last_login_at' => $time, 'last_login_ip' => $ip, ]; $user = User::create($attributes, $inviter); $user->socialites()->create([ 'socialite_id' => $openid, 'socialite_type' => $type, ]); } else { $user = $user_social->user; } if (!$user) { throw new BizException($openid); } $token = $user->createToken($type); DB::commit(); return response()->json([ 'token' => $token->plainTextToken ]); } catch (Throwable $e) { DB::rollBack(); report($e); throw new BizException($e->getMessage()); } } public function bindPhone(Request $request) { $user = $request->user(); $request->validate([ 'code' => 'required' ], [ 'code.required' => '授权码必填' ]); $app = $this->getWechatApp(); $result = $app->phone_number->getUserPhoneNumber($request->input('code')); if (data_get($result, 'errcode')) { throw new BizException(data_get($result, 'errmsg')); } $phone = data_get($result, 'phone_info.purePhoneNumber'); try { DB::beginTransaction(); // 检测手机号是否已经注册 $old_user = User::where('phone', $phone)->where('status', User::STATUS_ACTIVE)->where('id', '!=', $user->id)->first(); if ($old_user) { // 禁用新用户 $user->update([ 'phone' => '', 'status' => User::STATUS_DISABLED, 'status_remark' => '手机号重复: ' . $phone ]); $user = $old_user; } else { $user->update([ 'phone' => $phone, 'phone_verified_at' => now(), ]); } $token = $user->createToken(SocialiteType::WechatMiniProgram->value); DB::commit(); return response()->json([ 'token' => $token->plainTextToken ]); } catch (Throwable $e) { DB::rollBack(); report($e); throw new BizException($e->getMessage()); } } /** * 通过邀请码搜索用户 * * @param string $code * @return \App\Models\User|null * * @throws \App\Exceptions\BizException */ protected function findUserByCode(string $code): ?User { if ($code === '') { return null; } $user = User::when(PhoneNumber::validate($code), function ($query) use ($code) { $query->where('phone', $code); }, function ($query) use ($code) { $query->whereRelation('userInfo', 'code', $code); })->first(); if ($user === null) { throw new BizException(__('Inviter does not exist')); } return $user; } protected function getWechatApp($getway = 'default') { return Factory::miniProgram(config('wechat.mini_program.' . $getway)); } }