微信小程序登录

默认分类 微信小程序

好久没写东西了,写点东西 滥竽充数 记录一下。

大体登录流程:前端调用wx.login()接口就可获取登录凭证(js_code)传给后端,后端再使用小程序的appid、secret和这个js_code获取到用户的openID和session_key,数据库如果有这个openID的话直接就登录成功。

注册流程:前端把encryptedData、iv以及用户头像、昵称传过来,后端解密一下encryptedData获得手机号,至此就获取到了用户必要的注册信息了,然后再把上面登录步骤获取的openid一起插入数据库,即注册成功。

简单直接上代码,thinkphp的代码

代码

     /**
     * 微信小程序登录
     *
     * @return response|\think\response\Json
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function wx_login()
    {
        //组装数据
        $data = [
            'appid'      => Config::get('appid'),//配置文件获取appid
            'secret'     => Config::get('secret'),//配置文件获取secret
            'js_code'    => Request::post('code'),//post请求接收code参数
            'grant_type' => 'authorization_code',
        ];
        if (empty($data['appid']) || empty($data['secret'] || empty($data['js_code']))) return Json::error('缺少必要参数');
        //组装get请求
        $url      = 'https://api.weixin.qq.com/sns/jscode2session?' . http_build_query($data);
        $response = json_decode($this->curl($url), true); //发起请求
        if (empty($response['openid'])) return Json::unLogin('系统异常');
        $user = Db::name('user')->where('openid', $response['openid'])->findOrEmpty();//查找用户
        if (!empty($user)) return Json::success('登录成功', ['token' => JWT::encode(['id' => $user['id'], 'password' => ''], $this->key)]);
        //我这里是直接把session_key和openid用JWT压到token里面,能防止注册接口被随便插openID注册,因为注册必须要有我的这个token才行
        return Json::error('用户未注册', [
            'token' => JWT::encode([
                'session_key' => $response['session_key'],
                'openid'      => $response['openid'],
            ], $this->key),
        ]);
    }

    private function curl(string $url): string
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // https请求 不验证证书和hosts
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }

    /**
     * 微信小程序用户注册
     *
     * @return response|\think\response\Json
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function wx_register()
    {
        //接收参数
        $request  = Request::only(['token', 'encryptedData', 'iv', 'nick_name', 'avatar']);
        $validate = Validate::make([
            'token'         => 'require',
            'encryptedData' => 'require',
            'iv'            => 'require',
            'nick_name'     => 'require',
            'avatar'        => 'require',
        ]);
        if (!$validate->check($request)) return Json::error($validate->getError());//这里做数据验证
        try {
            //这里做token解析
            $data = (array)JWT::decode($request['token'], $this->key, ['HS256']);
        } catch (Exception $e) {
            return Json::error('Token有误');
        }
        if (!isset($data['openid']) || !isset($data['session_key'])) return Json::error('Token有误');
        //解密encryptedData获取手机号
        $info              = $this->decryptData($request['encryptedData'], $request['iv'], Config::get('appid'), $data['session_key']);
        $user              = [];
        $user['openid']    = $data['openid'];
        $user['nick_name'] = $request['nick_name'];
        $user['avatar']    = $request['avatar'];
        $user['ctime']     = time();
        $user['phone']     = $info['data']['phoneNumber'];
        $uid = Db::name('user')->insertGetId($user);
        if ($uid) return Json::success('注册成功', ['token' => JWT::encode(['id' => $uid, 'password' => ''], $this->key)]);
        return Json::error('注册失败');
    }

    /**
     * 检验数据的真实性,并且获取解密后的明文.
     *
     * @param string $encryptedData
     * @param string $iv
     * @param string $appid
     * @param string $sessionKey
     *
     * @return array
     */
    private function decryptData(string $encryptedData, string $iv, string $appid, string $sessionKey): array
    {
        if (mb_strlen($sessionKey) != 24) return ['status' => false, 'msg' => 'encodingAesKey 非法'];
        $aesKey = base64_decode($sessionKey);
        if (mb_strlen($iv) != 24) return ['status' => false, 'msg' => 'iv 非法'];
        $aesIV     = base64_decode($iv);
        $aesCipher = base64_decode($encryptedData);
        $result    = openssl_decrypt($aesCipher, 'AES-128-CBC', $aesKey, 1, $aesIV);
        $data      = json_decode($result, true);
        if (empty($data)) return ['status' => false, 'msg' => 'aes 解密失败'];

        if (!isset($data['watermark']) || !isset($data['watermark']['appid']) || $data['watermark']['appid'] != $appid) {
            return ['status' => false, 'msg' => 'aes 解密失败'];
        }

        return ['status' => false, 'data' => $data];
    }

大体就这样

新评论

称呼不能为空
邮箱格式不合法
网站格式不合法
内容不能为空