我們一般都是先獲取到微信的 unionid,然后再通過 unionid 去登錄自己的網(wǎng)站,就可以關(guān)聯(lián)到用戶在自己網(wǎng)站上的 user_id,但是在小程序登錄中,有時(shí)候可以獲取到 unionid,有時(shí)候獲取不到,在獲取不到 unionid 的情況下,用戶無法正常登錄網(wǎng)站。
UnionID機(jī)制說明:
如果開發(fā)者擁有多個(gè)移動(dòng)應(yīng)用、網(wǎng)站應(yīng)用、和公眾帳號(hào)(包括小程序),可通過 unionid 來區(qū)分用戶的唯一性,因?yàn)橹灰峭粋€(gè)微信開放平臺(tái)帳號(hào)下的移動(dòng)應(yīng)用、網(wǎng)站應(yīng)用和公眾帳號(hào)(包括小程序),用戶的 unionid 是唯一的。換句話說,同一用戶,對(duì)同一個(gè)微信開放平臺(tái)下的不同應(yīng)用,unionid 是相同的。
同一個(gè)微信開放平臺(tái)下的相同主體的 App、公眾號(hào)、小程序,如果用戶已經(jīng)關(guān)注公眾號(hào),或者曾經(jīng)登錄過App或公眾號(hào),則用戶打開小程序時(shí),開發(fā)者可以直接通過
獲取到該用戶UnionID,無須用戶再次授權(quán)。(解讀:用戶如果沒有登錄過app,也沒有登錄過公眾號(hào),也沒有關(guān)注過公眾號(hào)的情況下,小程序中通過 是獲取不到 unionid的)簡而言之,微信針對(duì)不同的用戶在不同的應(yīng)用下都有唯一的一個(gè) openId, 但是要想確定用戶是不是同一個(gè)用戶,就需要靠 unionid 來區(qū)分。
通常自己的后臺(tái)都會(huì)有自己的一個(gè)用戶表,每個(gè)用戶有不同的 userid。也就是說同一個(gè)用戶在同一個(gè)微信開放平臺(tái)下的相同主體的應(yīng)用對(duì)應(yīng)著相同的 userid, unionid 以及不同的 openid。所以在用戶登錄進(jìn)來的時(shí)候,我們只能靠微信返回給我們的 unionid 去判斷是不是同一個(gè)用戶,再去關(guān)聯(lián)我們的用戶表,拿到對(duì)應(yīng)的 user_id。
一般情況下(即在登錄小程序之前,已經(jīng)關(guān)注過公眾號(hào)或已經(jīng)登錄過公眾號(hào)或已經(jīng)使用微信登錄的方式登錄過app),用戶通過以下兩步就正常成功登錄網(wǎng)站。
1. 獲取code(登錄憑證,用來換取openid及session_key等) ({ success: function(res){ if(){ (); }else{ ('獲取用戶登錄態(tài)失??!'+); } } }) 2. 獲取用戶信息(利用返回的code獲取用戶的信息) getNeededUserInfo: function(code){ ({ url: '', method: 'POST', data: { code: code // 后端通過這個(gè)code去調(diào)用微信的接口(https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code),傳入?yún)?shù)code、appid、appsecret后獲取到微信返回的unionid、openid及session_key等。(然后后端可以直接利用微信返回的信息去關(guān)聯(lián)用戶在自己網(wǎng)站的user_id) }, success: function(res){ // 可以返回前端需要的用戶信息(包括unionid、openid、user_id等) } }) }
二般情況下(即在登錄小程序之前,既沒有關(guān)注過公眾號(hào),也沒有登錄過公眾號(hào),更沒有使用微信登錄的方式登錄過app),通過 的到的 code 換不回 unionid 及 openid 等信息。
解決思路:通過帶登錄態(tài)的
獲取到用戶的加密數(shù)據(jù) encryptedData 和加密算法的初始向量iv,然后將 encryptdata、iv 以及 code傳給后端,后端再去通過接收到的encryptedData、iv以、code 以及之前的 session_key 解密出用戶的 openid、unionid 等。加密數(shù)據(jù)解密算法以下是具體實(shí)現(xiàn)步驟:
1. 獲取code(登錄憑證,用來換取openid及session_key等) ({ success: function(res){ if(){ (); }else{ ('獲取用戶登錄態(tài)失??!'+); } } }) 2. 獲取加密數(shù)據(jù)和加密算法初始向量 舊版本基礎(chǔ)庫調(diào)取()可以直接獲取到微信返回的encryptdata等完整數(shù)據(jù),基礎(chǔ)庫更新之后,需要增加withCredentials屬性,并將屬性值設(shè)置為true時(shí)才可以獲取到除用戶基本信息之外的encryptedData以及iv等數(shù)據(jù)。 需要注意的是:當(dāng)withCredentials值為true時(shí),要求此前有調(diào)用過且登錄態(tài)尚未過期。 getEncData: function(){ ({ withCredentials: true, success: function(res){ ( code, res.encryptedData, res.encryptedData ); } }) } 3. 獲取用戶信息(利用返回的code獲取用戶的信息) getNeededUserInfo: function(code, enc, iv){ ({ url: '', method: 'POST', data: { code: code, encryptedData: enc, iv: iv }, success: function(res){ // 可以返回前端需要的用戶信息(包括unionid、openid、user_id等) } }) }
實(shí)際項(xiàng)目中需要將以上兩種情況整合以后使用。
思路有兩種:
第一種:( 前端判斷是否有 unionid )在向后端上傳 code 并且后端返回?cái)?shù)據(jù)以后,前端判斷返回值中是否有 unionid 或者 unionid 是否為 null,null 的情況下去調(diào)用帶有用戶登錄態(tài)的(),然后再將微信返回的 encryptedData 和 iv 返回給后端,后端解密出相應(yīng)的信息后再返回給前端;
第二種:( 后端判斷是否有 unionid )前端在調(diào)用 () 時(shí)候帶著登錄態(tài),然后不管后臺(tái)能不能拿到 unionid,都把 encryptedData 和 iv 返回給后端,后端在拿到前端 code 之后去請(qǐng)求微信的接口拿 unionid,如果返回的 unionid 為空,再拿前端傳的 encryptedData、iv以及之前的 session_key 解密出 unionid。
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)