- 一开始我的处理方式是在页面直接用checkSession,我的session_key是在index.js登录的时候保存到storage,这里check回调的是“success”。
- 但是把此时storage里面的session_key结合授权按钮的参数去进行解密是失败的,需要在当前的Page再登陆一次才能成功。
- 不推荐把session_key存放在缓存。所以以上做法直接跳过。
- 最后参考了一个朋友的做法,在Page onLoad的时候执行一次wx.login(),然后拿到新的session_key,再用此时的新key去解密就通了。或者改为请求解密之前执行一次登录,据说出问题的概率还是很大
- 结尾补充:最后一种方法还有个问题要考虑,就是最好执行获取手机号之前再checkSession一下(尽管没啥用)。
问题源头,由于这个函数在校验session_key的时候,无论是过期的key还是新的key都是success,所以有了之后一些列的问题,session_key的状态没法把控
Page({
data: {
currentSessionKey: null
},
onLoad: function(options) {
const here = this;
wx.login({
success(res) {
if (res.code) {
const data = call(userLogin, {
code: res.code
});
data.then(obj => {
if (!obj.error) {
here.setData({ currentSessionKey: obj.result.session_key })
}
});
}
},
fail(error) {
throw error;
}
});
},
getPhoneNumber: function (e) {
const { encryptedData, iv } = e.detail;
const options = { encryptedData: encryptedData, iv: iv, sessionKey: this.data.currentSessionKey };
here.doGetPhone(options);
},
doMyAction: function() {
},
doGetPhone: function (options) {
const {
sessionKey,
encryptedData,
iv
} = options;
const here = this;
wx.request({
url: 'https://xxx.com/python/decrypt',
method: 'POST',
data: {
sessionKey: sessionKey,
encryptedData: encryptedData,
iv: iv
},
success(res) {
const { countryCode, purePhoneNumber } = res.data;
here.pageForward(countryCode, purePhoneNumber);
},
fail(error) {
console.log(error);
here.pageForward();
}
})
},
pageForward: function(countryCode, purePhoneNumber) {
wx.navigateTo({
url: `/pages/person/index?phone=${purePhoneNumber}`
})
}
})
你们有碰到过sessionkey 里面带 空格吗 ? 然后解密失败
这个文章666,厉害了,我的哥,是真的解决了
我每次获取手机号码之前,都会重新调用 wx.login 通过 code 让后端解密,也会经常失效。然后今天官方文档看到如下:
所以下周回去看看
在以往做用户打通的时候,会经常遇到解密失败的情况,印象中就是因为 sessionKey 匹配不上用户,然后就解密失败了。(那会应该还没看到上面截图那段话,现在回想起来大概就是如图所说吧)
说说我的做法:
1. 根据我们业务特点,需要登录才能进行后面的功能。因为 sessionKey、openId 是在服务端通过 appid + appsecret + code(即 wx.login() 返回值)来获取到的。
2. 首次进来经过以上步骤,然后我们的策略是,服务端回传给客户端,我会将 sessionKey、openId 保存在全局对象中。
3. 需要利用 sessionKey 来解密信息的,主要有:获取用户信息、获取手机号
4. 等待下次需要用到 sessionKey 时,前端直接传递给服务端。但由于 sessionKey 是会过期的,具体时效性会根据用户行为而定(假设用户很活跃,sessionKey 的有效时间可能会越长,这个状态由微信维护)。因此有一个 API wx.checkSession 去检查登录态。
5. 所以我的整体流程是:初次进入小程序 wx.login() 获取 code,服务端通过该 code 拿到 sessionKey 并返回前端返回。等到需要解密时,先通过 wx.checkSession() 检查 sessionKey 是否已过期,若有效,则直接传递给服务端进行解密。若已过期,则重新获取 sessionKey 再进行解密。
以下为示例(不完整),仅供参考:
const getPhone = async () => {
let { sessionKey, openId } = app.globalData // 首次进来已保存
// 检查登录态
let checkFlag = true
await api.promisify('checkSession').catch(err => {
checkFlag = false
})
// 若登录态过期,则重新获取 sessionKey
const getPhone = async () => {
if (!sessionKey || !checkFlag) {
; ({ sessionKey, openId } = await getSessionKeyAndOpenId())
}
// 解密
commonService .getPhoneNumber({ openId, sessionKey, iv, encryptedData }).then(res => {
// ...
})
}
// 获取 sessionKey、openId
const getSessionKeyAndOpenId = async () => {
const result = await api.promisify('login')
if (!result || !result.code) throw result
const res = await commonService.login({ code: result.code })
if (res.code === 1000) {
return {
openId: res.openId,
sessionKey: res.sessionKey
}
}
// 否则当做异常情况,并抛出错误
throw res
}
感谢,按照楼主的方法解决了
问题: 1分30秒 请求服务器会获取 unid 失败!
解决: 在 onLoad 里面执行一次 wx.login({ success: function () { // 什么都没写 } })
我们也是弄了好久,这个解密功能微信做的逻辑太考究运气和试错性总结了
果然是个大坑,code已经用过,checkSession检查依旧通过。
我现在也出现问题了,之前几次还能获取的,之后就出现了乱码问题
我现在也遇到这个问题,请官方尽快解决!
这个问题我也碰到了, 真的坑, 希望有官方的人员能介入一下。另外,微信不建议把session_key保存在小程序端