Kaynağa Gözat

新增:新版用户端授权登录

Yahoo 4 yıl önce
ebeveyn
işleme
278bb7fef3

+ 22 - 21
app/api/controller/Passport.php

@@ -13,8 +13,6 @@ declare (strict_types=1);
 namespace app\api\controller;
 
 use app\api\service\passport\Login as LoginService;
-use app\api\service\passport\Captcha as CaptchaService;
-use app\api\service\passport\SmsCaptcha as SmsCaptchaService;
 
 /**
  * 用户认证模块
@@ -27,6 +25,7 @@ class Passport extends Controller
      * 登录接口 (需提交手机号、短信验证码、第三方用户信息)
      * @return array|\think\response\Json
      * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
@@ -48,19 +47,20 @@ class Passport extends Controller
 
     /**
      * 微信小程序快捷登录 (需提交wx.login接口返回的code、微信用户公开信息)
-     * 实现流程:判断openid是否存在 -> 存在:  更新用户登录信息 -> 返回userId和token
+     * 业务流程:判断openid是否存在 -> 存在:  更新用户登录信息 -> 返回userId和token
      *                          -> 不存在: 返回false, 跳转到注册页面
      * @return array|\think\response\Json
      * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    public function mpWxLogin()
+    public function loginMpWx()
     {
         // 微信小程序一键登录
         $LoginService = new LoginService;
-        if (!$LoginService->mpWxLogin($this->postForm())) {
+        if (!$LoginService->loginMpWx($this->postForm())) {
             return $this->renderError($LoginService->getError());
         }
         // 获取登录成功后的用户信息
@@ -72,25 +72,26 @@ class Passport extends Controller
     }
 
     /**
-     * 图形验证码
+     * 快捷登录: 微信小程序授权手机号登录
      * @return array|\think\response\Json
+     * @throws \app\common\exception\BaseException
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
-    public function captcha()
+    public function loginMpWxMobile()
     {
-        $CaptchaService = new CaptchaService;
-        return $this->renderSuccess($CaptchaService->create());
-    }
-
-    /**
-     * 发送短信验证码
-     * @return array|\think\response\Json
-     */
-    public function sendSmsCaptcha()
-    {
-        $SmsCaptchaService = new SmsCaptchaService;
-        if (!$SmsCaptchaService->sendSmsCaptcha($this->postForm())) {
-            return $this->renderError($SmsCaptchaService->getError());
+        // 微信小程序一键登录
+        $LoginService = new LoginService;
+        if (!$LoginService->loginMpWxMobile($this->postForm())) {
+            return $this->renderError($LoginService->getError());
         }
-        return $this->renderSuccess('发送成功,请注意查收');
+        // 获取登录成功后的用户信息
+        $userInfo = $LoginService->getUserInfo();
+        return $this->renderSuccess([
+            'userId' => (int)$userInfo['user_id'],
+            'token' => $LoginService->getToken((int)$userInfo['user_id'])
+        ], '登录成功');
     }
 }

+ 1 - 2
app/api/service/passport/Captcha.php

@@ -8,13 +8,12 @@
 // +----------------------------------------------------------------------
 // | Author: 萤火科技 <admin@yiovo.com>
 // +----------------------------------------------------------------------
-declare (strict_types = 1);
+declare (strict_types=1);
 
 namespace app\api\service\passport;
 
 use app\common\service\BaseService;
 use yiovo\captcha\facade\CaptchaApi;
-use think\response\Json;
 
 class Captcha extends BaseService
 {

+ 133 - 84
app/api/service/passport/Login.php

@@ -12,14 +12,14 @@ declare (strict_types=1);
 
 namespace app\api\service\passport;
 
-use app\api\model\User as UserModel;
-use app\api\service\user\Oauth as OauthService;
-use app\api\service\user\Avatar as AvatarService;
+use think\facade\Cache;
+use yiovo\captcha\facade\CaptchaApi;
+use app\api\model\{User as UserModel, Setting as SettingModel, dealer\Referee as RefereeModel};
+use app\api\service\{user\Oauth as OauthService, user\Avatar as AvatarService, passport\Party as PartyService};
 use app\api\validate\passport\Login as ValidateLogin;
-use cores\exception\BaseException;
 use app\common\service\BaseService;
-use yiovo\captcha\facade\CaptchaApi;
-use think\facade\Cache;
+use app\common\enum\Setting as SettingEnum;
+use cores\exception\BaseException;
 
 /**
  * 服务类:用户登录
@@ -39,6 +39,7 @@ class Login extends BaseService
      * @param array $data
      * @return bool
      * @throws BaseException
+     * @throws \think\Exception
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
@@ -46,64 +47,124 @@ class Login extends BaseService
     public function login(array $data): bool
     {
         // 数据验证
-        if (!$this->validate($data)) {
-            return false;
-        }
+        $this->validate($data);
         // 自动登录注册
         $this->register($data);
-        // 保存oauth信息
-        $this->oauth($data);
+        // 保存第三方用户信息
+        $this->createUserOauth($this->getUserId(), $data['isParty'], $data['partyData']);
         // 记录登录态
-        return $this->session();
+        return $this->setSession();
     }
 
     /**
      * 快捷登录:微信小程序用户
-     * @param array $data
+     * @param array $form
      * @return bool
      * @throws BaseException
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\Exception
      */
-    public function mpWxLogin(array $data): bool
+    public function loginMpWx(array $form): bool
     {
-        try {
-            // 根据code换取openid
-            $wxSession = OauthService::wxCode2Session($data['code']);
-        } catch (BaseException $e) {
-            // showError参数表示让前端显示错误
-            throwError($e->getMessage(), null, ['showError' => true]);
-            return false;
-        }
+        // 获取微信小程序登录态(session)
+        $wxSession = PartyService::getMpWxSession($form['partyData']['code']);
+
         // 判断openid是否存在
         $userId = OauthService::getUserIdByOauthId($wxSession['openid'], 'MP-WEIXIN');
         // 获取用户信息
         $userInfo = !empty($userId) ? UserModel::detail($userId) : null;
-        if (empty($userId) || empty($userInfo)) {
-            $this->error = '第三方用户不存在';
-            return false;
+
+        // 用户信息存在, 更新登录信息
+        if (!empty($userInfo)) {
+            // 更新用户登录信息
+            $this->updateUser($userInfo, true, $form['partyData']);
+            // 记录登录态
+            return $this->setSession();
+        }
+
+        // 用户信息不存在 => 注册新用户 或者 跳转到绑定手机号页
+        $setting = SettingModel::getItem(SettingEnum::REGISTER);
+        // 后台设置了需强制绑定手机号, 返回前端isBindMobile, 跳转到手机号验证页
+        if ($setting['isForceBindMpweixin']) {
+            throwError('当前用户未绑定手机号', null, ['isBindMobile' => true]);
         }
-        // 更新用户登录信息
-        $this->updateUser($userInfo, true, $data);
+        // 后台设置了强制绑定手机号, 直接保存新用户
+        if (!$setting['isForceBindMpweixin']) {
+            // 推荐人ID
+            $refereeId = $form['refereeId'] ?? null;
+            // 用户不存在: 创建一个新用户
+            $this->createUser('', true, $form['partyData'], (int)$refereeId);
+            // 保存第三方用户信息
+            $this->createUserOauth($this->getUserId(), true, $form['partyData']);
+            return true;
+        }
+        return true;
+    }
+
+    /**
+     * 快捷登录:微信小程序用户
+     * @param array $form
+     * @return bool
+     * @throws BaseException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\Exception
+     */
+    public function loginMpWxMobile(array $form): bool
+    {
+        // 获取微信小程序登录态(session)
+        $wxSession = PartyService::getMpWxSession($form['code']);
+        // 解密encryptedData -> 拿到手机号
+        $wxData = OauthService::wxDecryptData($wxSession['session_key'], $form['encryptedData'], $form['iv']);
+        // 整理登录注册数据
+        $loginData = [
+            'mobile' => $wxData['purePhoneNumber'],
+            'isParty' => $form['isParty'],
+            'partyData' => $form['partyData'],
+            'refereeId' => $form['refereeId'] ?? null
+        ];
+        // 自动登录注册
+        $this->register($loginData);
+        // 保存第三方用户信息
+        $this->createUserOauth($this->getUserId(), $loginData['isParty'], $loginData['partyData']);
         // 记录登录态
-        return $this->session();
+        return $this->setSession();
     }
 
     /**
-     * 保存oauth信息
-     * @param array $data
+     * 绑定推荐关系
+     * @param int $userId 当前用户ID
+     * @param int $refereeId 推荐人ID
+     * @return bool
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    private function bindRelation(int $userId, int $refereeId): bool
+    {
+        return $refereeId > 0 && RefereeModel::createRelation($userId, $refereeId);
+    }
+
+    /**
+     * 保存oauth信息(第三方用户信息)
+     * @param int $userId 用户ID
+     * @param bool $isParty 是否为第三方用户
+     * @param array $partyData 第三方用户数据
      * @return bool
      * @throws BaseException
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    private function oauth(array $data): bool
+    private function createUserOauth(int $userId, bool $isParty, array $partyData = []): bool
     {
-        if ($data['isParty']) {
-            $Oauth = new OauthService;
-            return $Oauth->party((int)$this->userInfo['user_id'], $data['partyData']);
+        if ($isParty) {
+            $Oauth = new PartyService;
+            return $Oauth->createUserOauth($userId, $partyData);
         }
         return true;
     }
@@ -117,22 +178,36 @@ class Login extends BaseService
         return $this->userInfo;
     }
 
+    /**
+     * 当前登录的用户ID
+     * @return int
+     */
+    private function getUserId(): int
+    {
+        return (int)$this->getUserInfo()['user_id'];
+    }
+
     /**
      * 自动登录注册
      * @param array $data
      * @return bool
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
     private function register(array $data): bool
     {
         // 查询用户是否已存在
+        // 用户存在: 更新用户登录信息
         $userInfo = UserModel::detail(['mobile' => $data['mobile']]);
         if ($userInfo) {
-            // 用户存在: 更新登录信息
             return $this->updateUser($userInfo, $data['isParty'], $data['partyData']);
-        } else {
-            // 用户不存在: 新增用户
-            return $this->createUser($data['mobile'], $data['isParty'], $data['partyData']);
         }
+        // 推荐人ID
+        $refereeId = (int)$data['refereeId'] ?? null;
+        // 用户不存在: 创建一个新用户
+        return $this->createUser($data['mobile'], $data['isParty'], $data['partyData'], $refereeId);
     }
 
     /**
@@ -140,21 +215,26 @@ class Login extends BaseService
      * @param string $mobile 手机号
      * @param bool $isParty 是否存在第三方用户信息
      * @param array $partyData 用户信息(第三方)
+     * @param int|null $refereeId 推荐人ID
      * @return bool
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
      */
-    private function createUser(string $mobile, bool $isParty, array $partyData = []): bool
+    private function createUser(string $mobile, bool $isParty, array $partyData = [], ?int $refereeId = null): bool
     {
         // 用户信息
         $data = [
             'mobile' => $mobile,
-            'nick_name' => hide_mobile($mobile),
+            'nick_name' => !empty($mobile) ? hide_mobile($mobile) : '',
             'platform' => getPlatform(),
             'last_login_time' => time(),
             'store_id' => $this->storeId
         ];
         // 写入用户信息(第三方)
         if ($isParty === true && !empty($partyData)) {
-            $partyUserInfo = $this->partyUserInfo($partyData, true);
+            $partyUserInfo = PartyService::partyUserInfo($partyData, true);
             $data = array_merge($data, $partyUserInfo);
         }
         // 新增用户记录
@@ -162,41 +242,11 @@ class Login extends BaseService
         $status = $model->save($data);
         // 记录用户信息
         $this->userInfo = $model;
+        // 记录推荐人关系
+        $this->bindRelation($this->getUserId(), (int)$refereeId);
         return $status;
     }
 
-    /**
-     * 第三方用户信息
-     * @param array $partyData 第三方用户信息
-     * @param bool $isGetAvatarUrl 是否下载头像
-     * @return array
-     */
-    private function partyUserInfo(array $partyData, bool $isGetAvatarUrl = true): array
-    {
-        $partyUserInfo = $partyData['userInfo'];
-        $data = [
-            'nick_name' => $partyUserInfo['nickName'],
-            'gender' => $partyUserInfo['gender']
-        ];
-        // 下载用户头像
-        if ($isGetAvatarUrl) {
-            $data['avatar_id'] = $this->partyAvatar($partyUserInfo['avatarUrl']);
-        }
-        return $data;
-    }
-
-    /**
-     * 下载第三方头像并写入文件库
-     * @param string $avatarUrl
-     * @return int
-     */
-    private function partyAvatar(string $avatarUrl): int
-    {
-        $Avatar = new AvatarService;
-        $fileId = $Avatar->party($avatarUrl);
-        return $fileId ? $fileId : 0;
-    }
-
     /**
      * 更新用户登录信息
      * @param UserModel $userInfo
@@ -212,8 +262,9 @@ class Login extends BaseService
             'store_id' => $this->storeId
         ];
         // 写入用户信息(第三方)
+        // 如果不需要每次登录都更新微信用户头像昵称, 下面4行代码可以屏蔽掉
         if ($isParty === true && !empty($partyData)) {
-            $partyUserInfo = $this->partyUserInfo($partyData, !$userInfo['avatar_id']);
+            $partyUserInfo = PartyService::partyUserInfo($partyData, true);
             $data = array_merge($data, $partyUserInfo);
         }
         // 更新用户记录
@@ -228,11 +279,11 @@ class Login extends BaseService
      * @return bool
      * @throws BaseException
      */
-    private function session(): bool
+    private function setSession(): bool
     {
         empty($this->userInfo) && throwError('未找到用户信息');
         // 登录的token
-        $token = $this->getToken((int)$this->userInfo['user_id']);
+        $token = $this->getToken($this->getUserId());
         // 记录缓存, 30天
         Cache::set($token, [
             'user' => $this->userInfo,
@@ -245,22 +296,20 @@ class Login extends BaseService
     /**
      * 数据验证
      * @param array $data
-     * @return bool
+     * @return void
+     * @throws BaseException
      */
-    private function validate(array $data): bool
+    private function validate(array $data): void
     {
         // 数据验证
         $validate = new ValidateLogin;
         if (!$validate->check($data)) {
-            $this->error = $validate->getError();
-            return false;
+            throwError($validate->getError());
         }
         // 验证短信验证码是否匹配
         if (!CaptchaApi::checkSms($data['smsCode'], $data['mobile'])) {
-            $this->error = '短信验证码不正确';
-            return false;
+            throwError('短信验证码不正确');
         }
-        return true;
     }
 
     /**
@@ -282,7 +331,7 @@ class Login extends BaseService
      * @param int $userId
      * @return string
      */
-    public function makeToken(int $userId): string
+    private function makeToken(int $userId): string
     {
         $storeId = $this->storeId;
         // 生成一个不会重复的随机字符串

+ 142 - 0
app/api/service/passport/Party.php

@@ -0,0 +1,142 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\api\service\passport;
+
+use app\api\model\UserOauth as UserOauthModel;
+use app\api\service\user\Oauth as OauthService;
+use app\api\service\user\Avatar as AvatarService;
+use app\common\service\BaseService;
+use cores\exception\BaseException;
+
+/**
+ * 第三方用户注册登录服务
+ * Class Party
+ * @package app\api\service\passport
+ */
+class Party extends BaseService
+{
+    /**
+     * 保存用户的第三方认证信息
+     * @param int $userId 用户ID
+     * @param array $partyData 第三方登录信息
+     * @return bool
+     * @throws BaseException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function createUserOauth(int $userId, array $partyData = []): bool
+    {
+        try {
+            // 获取oauthId和unionId
+            $oauthInfo = $this->getOauthInfo($partyData);
+        } catch (BaseException $e) {
+            // isBack参数代表需重新获取code, 前端拿到该参数进行页面返回
+            throwError($e->getMessage(), null, ['isBack' => true]);
+            return false;
+        }
+        // 是否存在第三方用户
+        $oauthId = UserOauthModel::getOauthIdByUserId($userId, $partyData['oauth']);
+        // 如果不存在oauth则写入
+        if (empty($oauthId)) {
+            return (new UserOauthModel)->add([
+                'user_id' => $userId,
+                'oauth_type' => $partyData['oauth'],
+                'oauth_id' => $oauthInfo['oauth_id'],
+                'unionid' => $oauthInfo['unionid'] ?? '',   // unionid可以不存在
+                'store_id' => $this->storeId
+            ]);
+        }
+        // 如果存在第三方用户, 需判断oauthId是否相同
+        if ($oauthId != $oauthInfo['oauth_id']) {
+            throwError('很抱歉,当前手机号已绑定其他微信号', null, ['isBack' => true]);
+        }
+        return true;
+    }
+
+    /**
+     * 获取微信小程序登录态(session)
+     * 这里支持静态变量缓存, 用于实现第二次调用该方法时直接返回已获得的session
+     * @param string $code
+     * @return array|false
+     * @throws BaseException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public static function getMpWxSession(string $code)
+    {
+        static $session;
+        if (empty($session)) {
+            try {
+                // 微信小程序通过code获取session
+                $session = OauthService::wxCode2Session($code);
+            } catch (BaseException $e) {
+                // showError参数表示让前端显示错误
+                throwError($e->getMessage(), null, ['showError' => true]);
+                return false;
+            }
+        }
+        return $session;
+    }
+
+    /**
+     * 第三方用户信息
+     * @param array $partyData 第三方用户信息
+     * @param bool $isGetAvatarUrl 是否下载头像
+     * @return array
+     */
+    public static function partyUserInfo(array $partyData, bool $isGetAvatarUrl = true): array
+    {
+        $partyUserInfo = $partyData['userInfo'];
+        $data = [
+            'nick_name' => $partyUserInfo['nickName'],
+            'gender' => $partyUserInfo['gender']
+        ];
+        // 下载用户头像
+        if ($isGetAvatarUrl) {
+            $data['avatar_id'] = static::partyAvatar($partyUserInfo['avatarUrl']);
+        }
+        return $data;
+    }
+
+    /**
+     * 下载第三方头像并写入文件库
+     * @param string $avatarUrl
+     * @return int
+     */
+    private static function partyAvatar(string $avatarUrl): int
+    {
+        $Avatar = new AvatarService;
+        $fileId = $Avatar->party($avatarUrl);
+        return $fileId ? $fileId : 0;
+    }
+
+    /**
+     * 获取第三方用户session信息 (openid、unionid、session_key等)
+     * @param array $partyData
+     * @return array|null
+     * @throws BaseException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    private function getOauthInfo(array $partyData): ?array
+    {
+        if ($partyData['oauth'] === 'MP-WEIXIN') {
+            $wxSession = static::getMpWxSession($partyData['code']);
+            return ['oauth_id' => $wxSession['openid'], 'unionid' => $wxSession['unionid'] ?? null];
+        }
+        return null;
+    }
+}

+ 7 - 8
app/api/service/user/Avatar.php

@@ -16,8 +16,8 @@ use app\common\service\BaseService;
 use app\api\model\Setting as SettingModel;
 use app\api\model\UploadFile as UploadFileModel;
 use app\common\enum\file\FileType as FileTypeEnum;
-use app\common\library\Download;
-use app\common\library\storage\Driver as Storage;
+use app\common\library\{Download, storage\Driver as Storage};
+use cores\exception\BaseException;
 
 /**
  * 服务类: 用户头像
@@ -46,7 +46,7 @@ class Avatar extends BaseService
     /**
      * 下载第三方头像并返回文件记录ID
      * @param string $avatarUrl
-     * @return false|mixed
+     * @return int|false
      */
     public function party(string $avatarUrl)
     {
@@ -89,9 +89,9 @@ class Avatar extends BaseService
     /**
      * 添加文件库记录
      * @param array $fileInfo
-     * @return mixed
+     * @return int
      */
-    private function record(array $fileInfo)
+    private function record(array $fileInfo): int
     {
         $model = new UploadFileModel;
         $model->add($fileInfo, FileTypeEnum::IMAGE, 0);
@@ -102,12 +102,11 @@ class Avatar extends BaseService
      * 下载网络图片
      * @param string $avatarUrl
      * @return string
-     * @throws \app\common\exception\BaseException
+     * @throws BaseException
      */
-    private function download(string $avatarUrl)
+    private function download(string $avatarUrl): string
     {
         $Download = new Download;
         return $Download->saveTempImage($this->storeId, $avatarUrl, 'avatar');
     }
-
 }

+ 34 - 58
app/api/service/user/Oauth.php

@@ -16,7 +16,9 @@ use app\api\model\UserOauth as UserOauthModel;
 use app\api\model\wxapp\Setting as WxappSettingModel;
 use app\common\service\BaseService;
 use app\common\library\wechat\WxUser;
-use app\common\exception\BaseException;
+use app\common\library\wechat\ErrorCode;
+use app\common\library\wechat\WXBizDataCrypt;
+use cores\exception\BaseException;
 
 /**
  * 服务类: 第三方用户服务类
@@ -26,92 +28,66 @@ use app\common\exception\BaseException;
 class Oauth extends BaseService
 {
     /**
-     * 保存第三方认证信息
-     * @param int $userId 用户ID
-     * @param array $partyData 第三方登录信息
-     * @return bool
+     * 微信小程序通过code获取session (openid session_key unionid)
+     * @param string $code
+     * @return array|false
      * @throws BaseException
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    public function party(int $userId, array $partyData = [])
+    public static function wxCode2Session(string $code)
     {
-        try {
-            // 获取oauthId和unionId
-            $oauthInfo = $this->getOauthInfo($partyData);
-        } catch (BaseException $e) {
-            // isBack参数代表需重新获取code, 前端拿到该参数进行页面返回
-            throwError($e->getMessage(), null, ['isBack' => true]);
-            return false;
-        }
-        // 是否存在第三方用户
-        $oauthId = UserOauthModel::getOauthIdByUserId($userId, $partyData['oauth']);
-        // 如果不存在oauth则写入
-        if (empty($oauthId)) {
-            return (new UserOauthModel)->add([
-                'user_id' => $userId,
-                'oauth_type' => $partyData['oauth'],
-                'oauth_id' => $oauthInfo['oauth_id'],
-                'unionid' => $oauthInfo['unionid'] ?? '',   // unionid可以不存在
-                'store_id' => $this->storeId
-            ]);
-        }
-        // 如果存在第三方用户, 需判断oauthId是否相同
-        if ($oauthId != $oauthInfo['oauth_id']) {
-            throwError('很抱歉,当前手机号已绑定其他微信号', null, ['isBack' => true]);
-        }
-        return true;
-    }
-
-    /**
-     * 获取第三方用户session信息 (openid、unionid、session_key等)
-     * @param array $partyData
-     * @return mixed|null
-     * @throws BaseException
-     * @throws \think\db\exception\DataNotFoundException
-     * @throws \think\db\exception\DbException
-     * @throws \think\db\exception\ModelNotFoundException
-     */
-    private function getOauthInfo(array $partyData)
-    {
-        if ($partyData['oauth'] === 'MP-WEIXIN') {
-            $wxSession = static::wxCode2Session($partyData['code']);
-            return ['oauth_id' => $wxSession['openid'], 'unionid' => $wxSession['unionid'] ?? null];
-        }
-        return null;
+        // 获取当前小程序信息
+        $wxConfig = static::getMpWxConfig();
+        // 微信登录 (获取session_key)
+        $WxUser = new WxUser($wxConfig['app_id'], $wxConfig['app_secret']);
+        $result = $WxUser->jscode2session($code);
+        !$result && throwError($WxUser->getError());
+        return $result;
     }
 
     /**
-     * 微信小程序code换openid
-     * @param string $code
+     * 解密微信的加密数据encryptedData
+     * @param string $sessionKey
+     * @param string $encryptedData
+     * @param string $iv
      * @return mixed
      * @throws BaseException
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
+     * @throws \cores\exception\BaseException
      */
-    public static function wxCode2Session(string $code)
+    public static function wxDecryptData(string $sessionKey, string $encryptedData, string $iv)
     {
         // 获取当前小程序信息
         $wxConfig = static::getMpWxConfig();
-        // 微信登录 (获取session_key)
-        $WxUser = new WxUser($wxConfig['app_id'], $wxConfig['app_secret']);
-        $result = $WxUser->jscode2session($code);
-        !$result && throwError($WxUser->getError());
-        return $result;
+        // 微信数据解密
+        $WXBizDataCrypt = new WXBizDataCrypt($wxConfig['app_id'], $sessionKey);
+        $content = null;
+        $code = $WXBizDataCrypt->decryptData($encryptedData, $iv, $content);
+        if ($code !== ErrorCode::$OK) {
+            throwError('微信数据解密失败');
+        }
+        return $content;
     }
 
     /**
      * 获取微信小程序配置项
      * @return array
+     * @throws \cores\exception\BaseException
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
     private static function getMpWxConfig(): array
     {
-        return WxappSettingModel::getWxappConfig();
+        $wxConfig = WxappSettingModel::getWxappConfig();
+        if (empty($wxConfig['app_id']) || empty($wxConfig['app_secret'])) {
+            throwError('请到后台小程序设置填写AppID和AppSecret参数');
+        }
+        return $wxConfig;
     }
 
     /**