最近在開發小程式遇到這樣一個問題, 在使用者點選授權後去解密手機號時會出現第一次失敗,第二次成功的情況。研究了一段時間,終於找到比較合理的解決方案,在此記錄並總結一下,希望可以幫助到大家。
需求描述
在使用者點選獲取電話按鈕後, 將使用者在微信內設定的電話解密顯示在聯絡電話輸入框內
具體程式碼
<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"
onLoad: 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
了。