我們發(fā)現(xiàn)大部分小程序都會(huì)使用 wx.getUserInfo 接口,來獲取用戶信息。原本設(shè)計(jì)這個(gè)接口時(shí),我們希望開發(fā)者在真正需要用戶信息的情況下才去調(diào)取這個(gè)接口,但很多開發(fā)者會(huì)直接調(diào)用這個(gè)接口,導(dǎo)致用戶在使用小程序的時(shí)候產(chǎn)生困擾,歸結(jié)起來有幾點(diǎn):
此外,我們發(fā)現(xiàn)開發(fā)者默認(rèn)將 wx.login 和 wx.getUserInfo 綁定使用,這個(gè)是由于我們一開始的設(shè)計(jì)缺陷和實(shí)例代碼導(dǎo)致的(wx.getUserInfo 必須通過 wx.login 在后臺(tái)生成 session_key后才能調(diào)用)。同時(shí),我們收到開發(fā)者的反饋,希望用戶進(jìn)入小程序首頁便能獲取到用戶的 unionId,以便識(shí)別到用戶是否以前關(guān)注了同主體公眾號(hào)或使用過同主體的App 。
為了解決以上問題,針對(duì)獲取用戶信息我們更新了三個(gè)能力:
1.使用組件來獲取用戶信息
2.若用戶滿足一定條件,則可以用wx.login 獲取到的code直接換到unionId
3.wx.getUserInfo 不需要依賴 wx.login 就能調(diào)用得到數(shù)據(jù)
獲取用戶信息組件介紹
<button/> 組件變化:
示例:
<button open-type="getUserInfo" bindgetuserinfo="userInfoHandler"> Click me </button>
和 wx.getUserInfo 不同之處在于:
1.API wx.getUserInfo 只會(huì)彈一次框,用戶拒絕授權(quán)之后,再次調(diào)用將不會(huì)彈框;
2.組件 <button open-type="getUserInfo"> 由于是用戶主動(dòng)觸發(fā),不受彈框次數(shù)限制,只要用戶沒有授權(quán),都會(huì)再次彈框。
通過獲取用戶信息的組件,就可以解決用戶再次授權(quán)的問題。
開發(fā)者申請(qǐng) userinfo 授權(quán)主要為了獲取 unionid,我們鼓勵(lì)開發(fā)者在不騷擾用戶的情況下合理獲得unionid,而僅在必要時(shí)才向用戶彈窗申請(qǐng)使用昵稱頭像。為此,凡使用“獲取用戶信息組件”獲取用戶昵稱頭像的小程序,在滿足以下全部條件時(shí),將可以靜默獲得 unionid:
1.在微信開放平臺(tái)下存在同主體的App、公眾號(hào)、小程序。
2.用戶關(guān)注了某個(gè)相同主體公眾號(hào),或曾經(jīng)在某個(gè)相同主體App、公眾號(hào)上進(jìn)行過微信登錄授權(quán)。
這樣可讓其他同主體的App、公眾號(hào)、小程序的開發(fā)者快速獲得已有用戶的數(shù)據(jù)。
某些工具類的輕量小程序不需要登錄行為,但是也想獲取用戶信息,那么就可以在 wx.getUserInfo 的時(shí)候加一個(gè)參數(shù) withCredentials: false 直接獲取到用戶信息,可以少一次網(wǎng)絡(luò)請(qǐng)求。
這樣可以在不給用戶彈窗授權(quán)的情況下直接展示用戶的信息。
最佳實(shí)踐
1.調(diào)用 wx.login 獲取 code,然后從微信后端換取到 session_key,用于解密 getUserInfo返回的敏感數(shù)據(jù)。
2.使用 wx.getSetting 獲取用戶的授權(quán)情況
1) 如果用戶已經(jīng)授權(quán),直接調(diào)用 API wx.getUserInfo 獲取用戶最新的信息;
2) 用戶未授權(quán),在界面中顯示一個(gè)按鈕提示用戶登入,當(dāng)用戶點(diǎn)擊并授權(quán)后就獲取到用戶的最新信息。
3.獲取到用戶數(shù)據(jù)后可以進(jìn)行展示或者發(fā)送給自己的后端。
One More Thing
除了獲取用戶方案介紹之外,再聊一聊很多初次接觸微信小程序的開發(fā)者所不容易理解的一些概念:
1.關(guān)于OpenId和UnionId
OpenId 是一個(gè)用戶對(duì)于一個(gè)小程序/公眾號(hào)的標(biāo)識(shí),開發(fā)者可以通過這個(gè)標(biāo)識(shí)識(shí)別出用戶。
UnionId 是一個(gè)用戶對(duì)于同主體微信小程序/公眾號(hào)/APP的標(biāo)識(shí),開發(fā)者需要在微信開放平臺(tái)下綁定相同賬號(hào)的主體。開發(fā)者可通過UnionId,實(shí)現(xiàn)多個(gè)小程序、公眾號(hào)、甚至APP 之間的數(shù)據(jù)互通了。
同一個(gè)用戶的這兩個(gè) ID 對(duì)于同一個(gè)小程序來說是永久不變的,就算用戶刪了小程序,下次用戶進(jìn)入小程序,開發(fā)者依舊可以通過后臺(tái)的記錄標(biāo)識(shí)出來。
2.關(guān)于 getUserInfo 和 login
很多開發(fā)者會(huì)把 login 和 getUserInfo 捆綁調(diào)用當(dāng)成登錄使用,其實(shí) login 已經(jīng)可以完成登錄,getUserInfo 只是獲取額外的用戶信息。
在 login 獲取到 code 后,會(huì)發(fā)送到開發(fā)者后端,開發(fā)者后端通過接口去微信后端換取到 openid 和sessionKey(現(xiàn)在會(huì)將 unionid 也一并返回)后,把自定義登錄態(tài) 3rd_session返回給前端,就已經(jīng)完成登錄行為了。而 login 行為是靜默,不必授權(quán)的,用戶不會(huì)察覺。
getUserInfo 只是為了提供更優(yōu)質(zhì)的服務(wù)而存在,比如展示頭像昵稱,判斷性別,開發(fā)者可通過 unionId 和其他公眾號(hào)上已有的用戶畫像結(jié)合來提供歷史數(shù)據(jù)。因此開發(fā)者不必在用戶剛剛進(jìn)入小程序的時(shí)候就強(qiáng)制要求授權(quán)。
可以在官方的文檔中看到 login 的最佳實(shí)踐:
Q & A
Q1: 為什么 login 的時(shí)候不直接返回 openid,而是要用這么復(fù)雜的方式來經(jīng)過后臺(tái)好幾層處理之后才能拿到?
A: 為了防止壞人在網(wǎng)絡(luò)鏈路上做手腳,所以小程序端請(qǐng)求開發(fā)者服務(wù)器的的請(qǐng)求都需要二次驗(yàn)證才是可信的。因?yàn)槲覀儾扇×诵〕绦蚨酥唤o code ,由服務(wù)器端拿著 code 和 AppSecrect 去微信服務(wù)器請(qǐng)求的方式,才會(huì)給到開發(fā)者對(duì)應(yīng)的openId 和用于加解密的 session_key。
Q2: 既然用戶的openId 是永遠(yuǎn)不變的,那么開發(fā)者可以使用openId 作為用戶的登錄態(tài)么?
A: 不行,這是非常危險(xiǎn)的行為。因?yàn)?openId 是不變的,如果有壞人拿著別人的 openId 來進(jìn)行請(qǐng)求,那么就會(huì)出現(xiàn)冒充的情況。所以我們建議開發(fā)者可以自己在后臺(tái)生成一個(gè)擁有有效期的 第三方session 來做登錄態(tài),用戶每隔一段時(shí)間都需要進(jìn)行更新以保障數(shù)據(jù)的安全性。
Q3: 是不是用戶每次打開小程序都需要重新login?
A: 不必,可以將登錄態(tài)存入storage中,用戶再次登錄就可以拿storage 里的登錄態(tài)做正常的業(yè)務(wù)請(qǐng)求,只有當(dāng)?shù)卿洃B(tài)過期了之后才需要重新login 。這樣子做一則可以減少用戶等待時(shí)間,二則可以減少網(wǎng)絡(luò)帶寬。
目前微信的session_key 有效期是三天,所以建議開發(fā)者設(shè)置的登錄態(tài)有效期要小于這個(gè)值。
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)