之前做项目的时候遇到微信授权登录偶现的41003问题,也是排查了好久才找到原因,在这边做下记录,也做下分享。
原因一(iv和encryptedData转码问题)
因为微信小程序提供的特定授权按钮 button open-type=“getPhoneNumber”,获得的iv和encryptedData,会含有 "+ ?"特殊符号,所以前端这边传输的时候需要使用encodeURIComponent 函数进行 urlencode,后端接收urldecode,
例如:
// An highlighted blocklet param = { encryptedData: encodeURIComponent(e.detail.encryptedData), iv: encodeURIComponent(e.detail.iv), code: code}
试了一下全部转码了,结果没啥卵用,还是没有解决 偶现的41003问题,重新排查,排查终于排查到了第二个原因。
原因二(wx.login()获取code顺序问题)
本来的的代码是这样,例:
// An highlighted block<buttonopen-type="getPhoneNumber" @getphonenumber="getPhoneNumber">微信一键登录,领取名片
// An highlighted blockgetPhoneNumber: function(e) { uni.login({ success: function(loginRes) { let param = { encryptedData: encodeURIComponent(e.detail.encryptedData), iv: encodeURIComponent(e.detail.iv), code: loginRes.code } wx.request({ data: param, success:function() { }) } }) }
经过尝试发现wx.login()里code的获取是不能放在 button* *open-type="getPhoneNumber"的回调函数里面的,code应该是需要提前获取了,例:
// An highlighted block<buttonopen-type="getPhoneNumber" @getphonenumber="getPhoneNumber">微信一键登录,领取名片
// An highlighted block// 每次已进入页面就请求code,存放本地,过了有效期五分钟,重新请求codeonShow() { wxlogin() // 微信登录code有效期 五分钟 this.globalTimer = setInterval(() => { wxlogin() }, 299990)}// 请求code方法wxlogin = function() { uni.login({ success: function(loginRes) { uni.setStorageSync('code', loginRes.code); } })}// *button** ==*open-type="getPhoneNumber"回调getPhoneNumber: function(e) { let param = { encryptedData: encodeURIComponent(e.detail.encryptedData), iv: encodeURIComponent(e.detail.iv), code: uni.getStorageSync('code'); } wx.request({ data: param, success:function() { })}// 离开页面 清除定时器onHide() { if (this.globalTimer) { clearInterval(this.globalTimer) }}, 后端应该修改成这样:
/** * 换取用户信息 * @param string $code 用户登录凭证(有效期五分钟) * @param string $iv 加密算法的初始向量 * @param string $encryptedData 加密数据( encryptedData ) * @return array * @throws InvalidDecryptException * @throws InvalidResponseException * @throws \WeChat\Exceptions\LocalCacheException */ public function userInfo($code, $iv, $encryptedData) { $result = $this->session($code); if (empty($result['session_key'])) { //code换取session失败 再试一次 $result = $this->session($code); if (empty($result['session_key'])) { throw new InvalidResponseException('Code 换取 SessionKey 失败', 403); } } $userinfo = $this->decode($iv, $result['session_key'], $encryptedData); if (empty($userinfo)) { $iv = urldecode($iv); $encryptedData = urldecode($encryptedData); $userinfo = $this->decode($iv, $result['session_key'], $encryptedData); if (empty($userinfo)) { throw new InvalidDecryptException('用户信息解析失败', 403); } } return array_merge($result, $userinfo); }
改成这种提前获取code然后再传入getPhoneNumber的回调函数使用仪器传给后端发现 偶现的==41003== 问题就解决了。
引用 https://www.icode9.com/content-1-896152.html