前言
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
其實官方已經有文檔,這里記錄一下實現的過程,以及其中一些細節。
准備工作
1、去微信開放平台申請賬號
https://open.weixin.qq.com/
2、賬號申請完成之后,進行開發者資質認證,認證一次就好,不需要像公眾號那樣年審。
3、創建網站應用,如果是APP的則創建移動應用
審核通過之后,就默認獲得了微信登陸的接口能力,接下來就是實現微信登陸的過程了。
實現
請求code
微信登陸支持兩種方式獲取code,第一種是跳轉新的頁面,第二種是內嵌iframe,就體驗來說,優先選擇第二種,這里也主要介紹第二種。
先上代碼,用的是vuejs
<Button @click="wxLogin" type="success" long>微信登錄</Button>
<div v-show="isShowWxLogin" id="wx_login_modal">
wxLogin() {
console.log("微信登錄");
new WxLogin({
id: "wx_login_modal",
appid: "wx692f8f2a*********",
scope: "snsapi_login",
redirect_uri: encodeURI("https://*******/"),
state: "null",
style: "white",
href: "https://********/css/wechat_login.css"
});
this.isShowWxLogin = true;
}
記得要先在頁面中先引入如下JS文件(支持https):
http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js
然后在需要使用微信登錄的地方實例以下WxLogin對象:
參數 | 是否必須 |
說明
|
---|---|---|
self_redirect
|
否
|
true:手機點擊確認登錄后可以在 iframe 內跳轉到 redirect_uri,false:手機點擊確認登錄后可以在 top window 跳轉到 redirect_uri。默認為 false。
|
id
|
是
|
第三方頁面顯示二維碼的容器id
|
appid
|
是
|
應用唯一標識,在微信開放平台提交應用審核通過后獲得
|
scope
|
是
|
應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即可
|
redirect_uri
|
是
|
重定向地址,需要進行UrlEncode
|
state
|
否
|
用於保持請求和回調的狀態,授權請求后原樣帶回給第三方。該參數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該參數,可設置為簡單的隨機數加session進行校驗
|
style
|
否
|
提供"black"、"white"可選,默認為黑色文字描述。詳見文檔底部FAQ
|
href
|
否
|
自定義樣式鏈接,第三方可根據實際需求覆蓋默認樣式。詳見文檔底部FAQ
|
其中,可以在調用wxLogin方法之前,預請求服務器生成一個偽隨機數,返回附到state里進行校驗,或者附帶一些附加的參數。
href用於自定義樣式,可以先不填,用chrome調試樣式並記錄好css,保存成文件上傳服務器再填css地址。
redirect_uri需要預先UrlEncode,若登錄成功,會附帶code和state重定向到該地址。
通過code獲取access_token
參數 | 是否必須 | 說明 |
---|---|---|
appid
|
是
|
應用唯一標識,在微信開放平台提交應用審核通過后獲得
|
secret
|
是
|
應用密鑰AppSecret,在微信開放平台提交應用審核通過后獲得
|
code
|
是
|
填寫第一步獲取的code參數
|
grant_type
|
是
|
填authorization_code
|
正確的返回:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
需要注意的是同一個微信開放平台賬戶下的移動應用、網站應用和公眾賬號(包括小程序),用戶的UnionID是唯一的。
我們應該優先采用unionid作為關聯微信賬戶體系的id。
由於系統要做到前后端分離,通過無狀態接口調用,所以會重定向到前端的地址,由前端負責識別出code和state后進行調用后端提供的接口,返回jwt以及相關信息。
下面是后端php代碼:
function wechatLogin()
{
$code = request()->get('code');
$appid = "wx692f8f2******";
$secret = "c272e97be6573729********";
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
$res = file_get_contents($url);
$res = json_decode($res, true);
……處理邏輯,返回jwt
}
通過access_token調用接口
一般獲取到unionid之后進行綁定就結束了,下次用戶再掃碼匹配unionid即可,也可以用access_token獲取用戶信息進行保存,見
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Authorized_Interface_Calling_UnionID.html
授權作用域(scope) | 接口 | 接口說明 |
---|---|---|
snsapi_base
|
/sns/oauth2/access_token
|
通過code換取access_token、refresh_token和已授權scope
|
snsapi_base
|
/sns/oauth2/refresh_token
|
刷新或續期access_token使用
|
snsapi_base
|
/sns/auth
|
檢查access_token有效性
|
snsapi_userinfo
|
/sns/userinfo
|
獲取用戶個人信息
|
首次登錄
如果平台不采用微信賬號體系,也就是原本存在賬號密碼登陸,手機號登陸等,
那么用戶第一次使用微信登陸時,需要進行一次賬號綁定。
1、判斷unionid是否綁定
2、若未綁定,則臨時保存unionid,彈出注冊/登錄頁面
3、提交時候,附帶上unionid,直接綁定。
也也可以在用戶中心里提供微信綁定按鈕,下次登錄的時候就沒那么麻煩了。
總結
微信登陸方便了用戶一鍵掃碼登陸,除了官方的方案,還有另外2種,這里僅提供思路。
(1)實現關注公眾號登錄,需要認證的服務號,因為要生成帶參二維碼。
1、用戶點擊微信登陸,生成一個隨機數參數,用於生成帶參數的二維碼,供前端顯示
https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
2、用戶掃碼,關注公眾號,在關注事件消息里獲取用戶信息,識別出隨機數參數作為緩存key,用戶信息作為value,保存緩存。
3、前端每隔3秒附帶隨機數參數輪詢接口,查詢是否有該隨機數參數緩存,若存在則判斷是否綁定。
4、若綁定則返回用戶信息,沒有則提示注冊或登錄。
(2)實現掃碼登陸,需要認證的公眾號。
與上面不同的是,這里二維碼自己生成即可,然后通過網頁授權的方式獲取用戶信息,其余邏輯大同小異。