最近在开发小程序遇到这样一个问题, 在用户点击授权后去解密手机号时会出现第一次失败,第二次成功的情况。研究了一段时间,终于找到比较合理的解决方案,在此记录并总结一下,希望可以帮助到大家。
需求描述
在用户点击获取电话按钮后, 将用户在微信内设置的电话解密显示在联系电话输入框内
具体代码
<view class="cu-form-group">
<view class="title text-black">联系电话</view>
<input class="radius" name="mobile" placeholder="请输入联系电话" value="{{detail.mobile}}" bindinput="onInputMobile"></input>
<button bindgetphonenumber="getPhoneNumber" class="cu-btn line-blue sm" openType="getPhoneNumber">获取电话</button>
</view>
首先需要小程序button
组件并设置 openType="getPhoneNumber"
onl oad: async function () {
this.getSessionKey()
},
async getSessionKey() {
const { code } = await wx.login()
const res = await Index.getSessionKey({
code
})
if (res.code == 1) {
this.setData({
session_key: res.data
})
}
},
getPhoneNumber: async function (e) {
if (e.detail.errMsg === "getPhoneNumber:ok") {
const res = await Index.getPhone({
iv: e.detail.iv,
encryptedData: e.detail.encryptedData,
session_key: this.data.session_key
})
if (res.err == 0) {
wx.showToast({
title: '网络有点儿小波动,请点击重试',
icon: 'none'
})
return
}
const detail = this.data.detail
detail.mobile = res.err.phoneNumber
this.setData({
detail
})
} else if (e.detail.errMsg === "getPhoneNumber:fail user deny") {
wx.showModal({
title: '提示',
content: '你已拒绝授权,请重新点击并授权',
showCancel: false,
confirmText: "知道了"
})
}
},
在 onLoad
生命周期内获取登录code
, 并将code
码发送给服务端获取session_key
服务端获取session_key
请参考小程序官方文档。
在用户点击获取电话按钮后, 将session_key
以及获取到的iv
,encryptedData
发送给服务端进行解密。
这样就可以获取到用户的手机号了。
坑
之前我们的方案是, 在用户点击获取电话按钮后, 直接在getPhoneNumber
函数内调用wx.logon()
,将code
,iv
,encryptedData
发送给服务端, 服务端先拿code
获取session_key
, 然后和iv
,encryptedData
结合进行解密,这样做的话就会出现第一次解密失败,然后再次点击按钮调用该解密接口就能成功。 而且隔5-6分钟就又会出现该情况。
当调用wx.checkSession(Object object)
检查登录态是否过期也是一直成功的。
猜测
后来想了一下,为什么在getPhoneNumber
函数内调用wx.login
, 然后服务端拿code
换session_key
,并结合iv
,encryptedData
解密不行呢?而把wx.login
放进onLoad
内获取session_key
就可以呢?
我想应该是在wx.login
调用时会刷新微信服务器的session_key
,直接在getPhoneNumber
调wx.login
,或许微信服务器还没来得及刷新,服务端就拿着进行解密, 解密时用的还是上次过期的session_key
,所以只有第二次以后才能成功。而wx.login
放到onload
内,就能来的及session_key
了。