问题
维护公司代码,发现授权手机号,有时会失败,提示“请重新授权手机号”。
去和后端沟通,后端说我code失效。
但是code有效时间为5分钟。【官方】
打印出获取到code到发送给后端的时间,发现几乎在一分钟内完成,不会是codo超过五分钟失效。
代码
(注:此代码是错误案例❌)
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
getPhoneNumber (e) {
//授权手机号,用户点击确认
if ('getPhoneNumber:ok' === e.detail.errMsg) {
//调用wx.login获取code
wx.login({
success: function(res) {
console.log('login接口获取的code', res.code, '当前时间', new Date())
//传给后端进行解密
getPhoneNo(res.code, e)
}
})
} else {
...
}
}
//后端解密接口
getPhoneNo () {
...
console.log('getPhoneNo接口入参的code', code, '当前时间', new Date())
...
}
打印出的结果
获取到的code与传给后端的code一致,并且在有效期内
那么,为什么还会 授权失败呢?
原来官方文档已经写的很清楚了
小程序官方文档 /开放能力 /用户信息 /获取手机号 (点击查看官方文档)
在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。建议开发者提前进行 login
;或者在回调中先使用 checkSession
进行登录态检查,避免 login
刷新登录态。
我对此的理解是:
① 获取用户手机号授权 → ② 用户点击确定 → ③ 微信对开放数据做签名和加密处理 → ④ 返回给前端 → ⑤ 前端将 数据 密文 密文串 发送给后端 → ⑥ 后端去微信服务器解密获取明文信息
如图:开放数据校验与解密 (点击查看官方文档)
所以,在执行wx.login之前,先检查一下登录态wx.checkSession
:
getPhoneNumber (e) {
//授权手机号,用户点击确认
if ('getPhoneNumber:ok' === e.detail.errMsg) {
wx.checkSession({
success (res) {
//session_key 未过期,并且在本生命周期一直有效
//不传code给后端,让后端自己从缓存中去拿session_key
getPhoneNo('', e, callback)
},
fail () {
// session_key 已经失效,需要重新执行登录流程
wx.login({
...
})
}
})
} else {
...
}
}
【官方】 wx.login 调用时,用户的 session_key 可能会被更新而致使旧 session_key 失效(刷新机制存在最短周期,如果同一个用户短时间内多次调用 wx.login,并非每次调用都导致 session_key 刷新)。开发者应该在明确需要重新登录时才调用 wx.login,及时通过 auth.code2Session 接口更新服务器存储的 session_key。