序言:
前提这个走不开是基于原来的架构,前后端分离的。
一、前端组织判断是是否有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.
8278

被折叠的 条评论
为什么被折叠?



