在微信小程序開(kāi)發(fā)時(shí),當(dāng)我們調(diào)用API wx.getUserInfo(OBJECT) 時(shí),需要用戶(hù)授權(quán)。但如果用戶(hù)拒絕授權(quán),我們?nèi)绾渭嫒萦脩?hù)拒絕授權(quán)狀態(tài),擁有更好的用戶(hù)體驗(yàn)?zāi)兀?/p>
先看看這個(gè)接口的官方文檔:
獲取用戶(hù)信息,需要先調(diào)用 wx.login 接口。
OBJECT參數(shù)說(shuō)明:
| 參數(shù)名 | 類(lèi)型 | 必填 | 說(shuō)明 |
|---|---|---|---|
| withCredentials | Boolean | 否 | 是否帶上登錄態(tài)信息 |
| success | Function | 否 | 接口調(diào)用成功的回調(diào)函數(shù) |
| fail | Function | 否 | 接口調(diào)用失敗的回調(diào)函數(shù) |
| complete | Function | 否 | 接口調(diào)用結(jié)束的回調(diào)函數(shù)(調(diào)用成功、失敗都會(huì)執(zhí)行) |
我們就是要在用戶(hù)點(diǎn)擊拒絕的時(shí)候,彈出提示框,提示用戶(hù)以提升用戶(hù)體驗(yàn)。像下面這樣的。

用具體代碼實(shí)現(xiàn)就是,將彈窗寫(xiě)在 wx.getUserInfo 的fail回調(diào)函數(shù)中,像下面這樣:
wx.getUserInfo({
success: function (resuser) {
console.log(success)
},
fail: function () {
// 調(diào)用微信彈窗接口
wx.showModal({
title: '警告',
content: '您點(diǎn)擊了拒絕授權(quán),將無(wú)法正常使用******的功能體驗(yàn)。請(qǐng)10分鐘后再次點(diǎn)擊授權(quán),或者刪除小程序重新進(jìn)入。',
success: function (res) {
if (res.confirm) {
console.log('用戶(hù)點(diǎn)擊確定')
}
}
})
}
})
|
這樣用戶(hù)就獲得了提示信息,但此時(shí),用戶(hù)還是停留在頁(yè)面的,如果某些展示信息,還是給要給用戶(hù)展示的,只是在進(jìn)行某些操作的時(shí)候要對(duì)授權(quán)進(jìn)行驗(yàn)證的話(huà),那就得繼續(xù)修改我們的代碼,保存用戶(hù)的登錄態(tài),在其他地方做驗(yàn)證使用。
第一種思路:
保存登錄態(tài)這里是這樣的,將用戶(hù)的登錄信息傳給后臺(tái),后臺(tái)保存用戶(hù)信息,同時(shí)用 open_id 在后臺(tái)換取一個(gè)SessionId 用換取的這個(gè)SessionId 存在緩存,做為登錄態(tài)驗(yàn)證。
wx.getUserInfo({
success: function (resuser) {
let userInfo = resuser.userInfo
that.healthApi.login(code, userInfo).then(logindata => { // 這里將微信的請(qǐng)求封裝成Promiese 風(fēng)格
if (logindata.code === 0) {
var sessionId = logindata.data
// 調(diào)用微信wechat.setStorage將換回來(lái)的 SessionId 存在本地緩存
that.wechat.setStorage('sessionId', sessionId).then(() => {
that.globalData.userInfo = userInfo
typeof cb == "function" && cb(that.globalData.userInfo)
})
}
})
},
fail: function () {
wx.showModal({
title: '警告',
content: '您點(diǎn)擊了拒絕授權(quán),將無(wú)法正常使用*****的功能體驗(yàn)。請(qǐng)10分鐘后再次點(diǎn)擊授權(quán),或者刪除小程序重新進(jìn)入。',
success: function (res) {
if (res.confirm) {
console.log('用戶(hù)點(diǎn)擊確定')
}
}
})
}
})
|
這樣我們將登錄態(tài)保存在了 SessionId 中,在每次登錄的時(shí)候我們只需要再調(diào)用一個(gè) 檢查 SessionId的接口就行,檢查不通過(guò)再調(diào)微信登錄接口。此處不做延伸了。
第二種思路:
在3.29微信小程序更新的版本中,加入了這樣一條屬性
withCredentials 字段基礎(chǔ)庫(kù)版本 1.1.0 開(kāi)始支持,低版本需做兼容處理
這個(gè)字段的意思就是調(diào)用 wx.getUserInfo(OBJECT) 是否帶上 登錄態(tài) 的信息。
官方文檔是這樣解釋的:
withCredentials 字段基礎(chǔ)庫(kù)版本 1.1.0 開(kāi)始支持,低版本需做兼容處理
注:當(dāng) withCredentials 為 true 時(shí),要求此前有調(diào)用過(guò) wx.login 且登錄態(tài)尚未過(guò)期,此時(shí)返回的數(shù)據(jù)會(huì)包含 encryptedData, iv 等敏感信息;當(dāng) withCredentials 為 false 時(shí),不要求有登錄態(tài),返回的數(shù)據(jù)不包含 encryptedData, iv 等敏感信息。
success返回參數(shù)說(shuō)明:
| 參數(shù) | 類(lèi)型 | 說(shuō)明 |
|---|---|---|
| userInfo | OBJECT | 用戶(hù)信息對(duì)象,不包含 openid 等敏感信息 |
| rawData | String | 不包括敏感信息的原始數(shù)據(jù)字符串,用于計(jì)算簽名。 |
| signature | String | 使用 sha1( rawData + sessionkey ) 得到字符串,用于校驗(yàn)用戶(hù)信息。 |
| encryptedData | String | 包括敏感數(shù)據(jù)在內(nèi)的完整用戶(hù)信息的加密數(shù)據(jù),詳細(xì)見(jiàn)加密數(shù)據(jù)解密算法 |
| iv | String | 加密算法的初始向量,詳細(xì)見(jiàn)加密數(shù)據(jù)解密算法 |
注:需要兼容微信低版本,向后兼容。
那么利用這個(gè)接口,我們可以直接拿到 登錄狀態(tài),在其他需要驗(yàn)證登錄的地方進(jìn)行提示,而在不需要授權(quán)的地方還可以讓用戶(hù)瀏覽小程序。
回到前面的問(wèn)題,在用戶(hù)點(diǎn)擊拒絕授權(quán)后,在某些操作時(shí)需要驗(yàn)證用戶(hù)是否授權(quán)過(guò),彈出交互信息,那么就利用上面的 SessionId或者 withCredentials 登錄態(tài)進(jìn)行下面的操作:
applyIn: function applyIn() {
if (wx.getStorageSync('sessionId')) { // 根據(jù)儲(chǔ)存的sessionId 進(jìn)行驗(yàn)證
wx.navigateTo({
url: 'familyDoctorApply/familyDoctorApply?Oid=' + this.data.params.Oid + '&title=' + this.data.params.title + '&serviceCity=' + this.data.array[this.data.index].name + '&productPrice=' + this.data.product.productPrice
});
} else {
wx.showModal({
title: '警告',
content: '您點(diǎn)擊了拒絕授權(quán),無(wú)法使用此功能。',
success: function (res) {
if (res.confirm) {
console.log('用戶(hù)點(diǎn)擊確定')
}
}
})
}
|
效果像這樣:

這樣一個(gè)簡(jiǎn)單完整的登錄及授權(quán),登錄態(tài)保存等前端微信小程序解決方案就完成了,還可以繼續(xù)擴(kuò)展到登錄有效期,退出登錄,用戶(hù)權(quán)限等跟多擴(kuò)展的地方。