Crmeb二开服务号静默授权登录

序言:

前提这个走不开是基于原来的架构,前后端分离的。

一、前端组织判断是是否有token,token是否有效。

二、如果token无效,则由前端来组装跳转的URI,如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=这个公众号的appid&redirect_uri=前端拿code的URI&response_type=code&scope=snsapi_base&state=123#wechat_redirect

三、拿到token后调用后端接口换token
{{api}}v2/wechat/auth_login?code=aaaaaaa

接口返回:

理想是上面的状态。但是这个Crmeb的开源的静默授权是有问题的。

{{api}}v2/wechat/auth_login?code=aaaaaaa

这个接口在处理显式授权的时候是没有问题的。

但是在处理静默授权的时候会有一个问题。就是以前授权过的用户可以正常过。新用户会有问题,调用微信接口的时候会返回一个错误:

api unauthorized

这是个很棘手的问题,最终追踪到

crmeb/services/easywechat/oauth2/wechat/WechatOauth.php line 148.

/**
     * 授权获取token
     * @param string $code
     * @return false|mixed
     * @throws HttpException
     */
    public function oauth(string $code = '')
    {
        $params = [
            'appid' => $this->appId,
            'secret' => $this->secret,
            'code' => $code ?: $this->getCode(),
            'grant_type' => 'authorization_code',
        ];

        $http = new Http();

        $token = $http->parseJSON($http->get(self::API_OAUTH_ACCESS_TOKEN, $params));

        if (empty($token[$this->tokenJsonKey])) {
            throw new HttpException('Request AccessToken fail. response: ' . json_encode($token, JSON_UNESCAPED_UNICODE));
        }
        $this->setCache($token);

        return $token;
    }

这个函数看上去也很正常,但是这个问题很奇怪,有些微信用户是正常的,,特别是授权过的。有的就是返回上面的错误。

不纠结这个了,解决问题才是判断。自己写一个吧。

app/services/wechat/WechatServices.php 新增一个函数。

/**
     * 静默授权登录
     * @auther Hotlinhao
     * @createAt 2026/3/23 20:52
     * @return void
     */
    public function baseLogin($code,$spread = '', $agent_id = ''){
        $appId = sys_config('wechat_appid');
        $secret = sys_config('wechat_appsecret');
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appId&secret=$secret&code=$code&grant_type=authorization_code";
        $res = HttpService::request($url);
        $res = json_decode($res,true);
        if(isset($res['errcode']) && intval($res['errcode']) != 0){
            throw new ApiException($res['errmsg']);
        }

        $wechatInfo = [
            'openid'    => $res['openid'],
            'nickname'  => mt_rand(1000,9999),
            'user_type' => 'wechat',
        ];
        //通过openId注册新的用户,并返回token
        $openid = $res['openid'];
        /** @var WechatUserServices $wechatUserServices */
        $wechatUserServices = app()->make(WechatUserServices::class);
        $user = $wechatUserServices->getAuthUserInfo($openid, 'wechat');
        $createData = [$openid, $wechatInfo, $spread, $agent_id, 'wechat', 'wechat'];
        $storeUserMobile = sys_config('store_user_mobile');
        if ($storeUserMobile && (($user && $user['phone'] == '') || !$user)) {
            $userInfoKey = md5($openid . '_' . time() . '_wechat');
            CacheService::set($userInfoKey, $createData, 7200);
            return ['bindPhone' => true, 'key' => $userInfoKey];
        }
        $user = $wechatUserServices->wechatOauthAfter($createData);
        $wechatUserServices->wechatUpdata([$user['uid'], $wechatInfo]);
        $token = $this->createToken((int)$user['uid'], 'api');
        if ($token) {
            app()->make(UserVisitServices::class)->loginSaveVisit($user);
            $token['bindPhone'] = false;
            return [
                'token' => $token['token'],
                'expires_time' => $token['params']['exp'],
                'bindPhone' => false
            ];
        } else {
            throw new ApiException(410019);
        }
    }

这个函数注册新用户以前就是通过静默来获取Openid,下面就是把上面的authLogn();函数的下半部分,注册用户并返回token拿过来用用。

然后在控制器上调用这个方法即可。

over.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值