前言
做微信小程序或公眾號開發,有時我們為了管理用戶,需要獲取用戶的openid,unionId等信息。這時會用到微信提供的接口:code2Session。
code2Session接口以code ( code是前端調用wx.login接口獲取的 ) 為參數之一,調用成功可返回openid和session_key。openid是小程序用戶的唯一標識;session_key可作為秘鑰,對wx.getUserInfo接口獲取的加密數據進行解密,解密之后可以獲取到用戶的unionId,unionId是同主體 ( 綁定了同一個開放平臺賬號)下微信用戶的唯一標識。
在實際開發中,相信很多人在調接口時都遇到過這種錯誤:invalid code或code been used。歸根結底是沒搞清楚微信的登錄機制,在代碼邏輯上出了問題。前端頻繁調用wx.login接口或后端頻繁調用code2Session接口都有可能導致這些錯誤。
什么是登錄狀態?
當用戶進入小程序是有 登錄狀態一說的,在登錄狀態有效期內什么是不變的呢?session_key!
登錄狀態有效期內,session_key是不會變化的,即使你重新調用wx.login接口獲取新的code,用新code傳給后臺去獲取session_key,你會發現獲取的 session_key跟上次是一樣的。
我們可以在后臺保存session_key,在登錄狀態有效期內,就無需再次調用code2Session接口去獲取session_key了。
那么,如何檢測登錄狀態是否有效?
前端調用wx.checkSession接口,可查詢用戶當前登錄狀態是否有效。
wx.checkSession({
success() { // 登錄狀態有效回調
},
fail() { // 登錄狀態失效回調
}
})
什么情況下會報code been used(40163)?
在登錄狀態有效期內,后臺用同一個code,多次調用code2Session接口就會報code been used(40163)錯誤。
什么情況下會報invalid code(40029)?
前端每次調用wx.login接口會導致code刷新,若后臺沒有及時獲取到新的code,用老的code去調接口,會報錯。
后臺代碼邏輯問題:誤改了前端傳過來的code,會報錯。
如何正確的處理代碼邏輯?
前端可以頻繁的調用wx.login接口,但每次調用要及時通知后端。這樣后端也可以頻繁的調用code2Session接口,只要用的最新code就不會報錯。但既然我們知道了在登錄有效期這個說法,為什么要頻繁調接口呢?可以參考下面這種方式,也是筆者在實際項目中的鑒權機制: unionId+token雙重校驗 ↓
1、 假設用戶第一次進小程序,調用wx.checkSession檢測必然為登錄狀態失效,我們可以用valid這個參數表示登錄狀態。調用wx.login接口獲取code,調用getUserInfo接口獲取加密數據,并把如下參數傳給后臺:{code:—,encryptedData:—,iv—,valid:false},后臺發現valid為false的時候,就通過code獲取session_key,再通過session_key解密出unionId,校驗unionId是不是合法用戶,如果合法,就用這個unionId生成一個token返回給前端,前端將token存入緩存。
2、 校驗成功,小程序就可以進入主頁面了,后續的業務接口都把token放在請求頭里,后臺校驗token是否合法。若發現token無效,就給前端返回你們協商好的錯誤碼,前端跳轉至登錄頁面(帶參跳轉:tokenInvalid:1),登錄頁面發現帶有參數tokenInvalid時,即使wx.checkSession檢查登錄狀態有效,我們也要重新獲取code,加密數據,并把valid強制設為false,讓后端重新校驗,類似步驟1。這個邏輯就是處理token失效的情況的。(token是我們自定義的,后臺可以對其設置有效期,比如1個月。)