diff --git a/app/Endpoint/Api/Http/Controllers/Auth/MiniprogramController.php b/app/Endpoint/Api/Http/Controllers/Auth/MiniprogramController.php new file mode 100644 index 00000000..c375736d --- /dev/null +++ b/app/Endpoint/Api/Http/Controllers/Auth/MiniprogramController.php @@ -0,0 +1,157 @@ +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 = $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; + } + + $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) { + // 禁用老用户 + $old_user->update([ + 'phone' => '', + 'status' => User::STATUS_DISABLED, + 'status_remark' => '手机号重复: ' . $phone + ]); + } + + $user->update([ + 'phone' => $phone, + 'phone_verified_at' => now(), + ]); + DB::commit(); + return response()->noContent(); + } 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)); + } +}