PC端微信掃碼登錄流程:
為什么要微信登錄:
如果用戶在微信客戶端中訪問第三方網(wǎng)頁蠢挡,公眾號可以通過微信網(wǎng)頁授權(quán)機(jī)制逊脯,來獲取用戶基本信息,進(jìn)而實現(xiàn)業(yè)務(wù)邏輯置谦。微信擁有龐大且穩(wěn)定活躍的用戶基數(shù)放坏,直接將我們的app接入到微信的生態(tài)可以免去復(fù)雜的新用戶注冊流程咙咽,使用戶體驗更良好。
微信登錄的幾種情況:
-
PC端:
PC端微信瀏覽器 -> 直接調(diào)用微信授權(quán)(不掃碼淤年,使用微信服務(wù)號的appid和appsecret)
PC端其他瀏覽器 -> 跳轉(zhuǎn)微信的掃碼登錄頁面(需要掃碼钧敞,使用微信開放平臺注冊的PC應(yīng)用appid和appsecret)
-
移動端:
微信客戶端打開 -> 直接調(diào)用微信授權(quán)(不掃碼,使用微信服務(wù)號的appid和appsecret)
其他手機(jī)瀏覽器打開 -> 跳轉(zhuǎn)微信的掃碼登錄頁面(需要掃碼互亮,使用微信開放平臺注冊的PC應(yīng)用appid和appsecret)
區(qū)分是否是PC環(huán)境的方法:
判斷是PC環(huán)境還是移動環(huán)境是為了相應(yīng)切換應(yīng)用的布局犁享,目前采用css媒體查詢來做判斷:
/* 屏幕寬度小于等于1070像素時識別為移動端(1070像素是使推薦頁常用情報站欄不現(xiàn)實滾動條的最小寬度) */
@media screen and (max-width: 1070px) {
/* 移動端布局css樣式 */
}
/* 屏幕寬度大于1071像素識別為PC端 */
@media screen and (min-width: 1071px) {
/* PC端布局樣式 */
}
這里目前的設(shè)計是將判斷UI樣式和判斷登錄邏輯區(qū)分開的,兩個功能分別獨(dú)立判斷
區(qū)分微信登錄的幾種情況的方法:
- 前端在登錄時獲取用戶設(shè)備信息(userAgent)
let UA = navigator.userAgent.toLocaleLowerCase()
// UA的格式可能因設(shè)備不同而采用不同的大小寫格式這里我們先統(tǒng)一為小寫方便下一步判斷
UA.indexOf("micromessenger") != -1
// 通過indexOf方法來判斷字符串里是否有要查詢的字段
前端操作
1 獲取code(此步驟由前端完成)
首先要在微信開放平臺里申請創(chuàng)建一個web應(yīng)用豹休,填寫完基本信息之后提交審核炊昆,最長7個工作日,一般兩天就能下來威根。審核通過以后可以得到web應(yīng)用的AppID和AppSecret凤巨,稍后請求微信登錄的二維碼。
在得到web應(yīng)用的AppID以后前端需要配置請求登錄二維碼的url:
// 前端使用appid和回調(diào)域名來獲取微信登陸二維碼
window.location.replace(
"https://open.weixin.qq.com/connect/qrconnect?" +
"appid=" + APP_id + "&" +
"redirect_uri=" + encodeURIComponent('http://wx.digitwonder.com') + "&" +
"scope=snsapi_login#wechat_redirect" )
這個配置中AppID字段是向后臺傳微信開放平臺的web應(yīng)用AppID洛搀,回調(diào)地址也是在開放平臺注冊時留的地址敢茁,而且這個回調(diào)地址的uri需要經(jīng)過encode編碼加密以后拼接到請求的。'scope'字段表示請求的作用域留美,微信掃碼登錄時scope字段固定寫'snsapi_login'彰檬。將這個地址拼接好以后就可以將路由定向到微信的二維碼頁面了。
參數(shù)說明
參數(shù) | 是否必須 | 說明 |
---|---|---|
appid | 是 | 應(yīng)用唯一標(biāo)識(前面認(rèn)證網(wǎng)頁應(yīng)用中獲得) |
redirect_uri | 是 | 重定向地址谎砾,需要進(jìn)行UrlEncode(前面認(rèn)證網(wǎng)頁應(yīng)用中獲得) |
response_type | 是 | 填code |
scope | 是 | 應(yīng)用授權(quán)作用域逢倍,擁有多個作用域用逗號(,)分隔,網(wǎng)頁應(yīng)用目前僅填寫snsapi_login即可 |
state | 是 | 用于保持請求和回調(diào)的狀態(tài)景图,授權(quán)請求后原樣帶回給第三方较雕。該參數(shù)可用于防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該參數(shù)挚币,可設(shè)置為簡單的隨機(jī)數(shù)加session進(jìn)行校驗 |
- 在頁面定位到微信二維碼頁面以后掃碼確認(rèn)亮蒋,頁面會被定向到之前配置的回調(diào)頁面地址并且將請求來的code拼接到url上一并返回,我們在微信確認(rèn)登陸以后回到url拼接有code的頁面獲取到code之后向后臺發(fā)送登陸請求妆毕。
// 聲明變量flag用來存儲微信回調(diào)頁面的code信息
let flag = flag.split("&")[0];
// 重定向該頁面的路由(清除url中的code) - 避免發(fā)送code請求
this.$router.replace({
path: "/login",
query: {
redirect: this.$route.query.redirect
}
});
this.request({
url: "/biz/login/wx", // 后臺接收code的接口
method: "POST", // 使用HTTP的POST方法傳回code
data: {
code: flag // 將頁面存儲code的flag變量以code字段傳給后臺
// 此處區(qū)分登錄方式的字段待定
}
}).then(res => {
// 前端本地獲取用戶信息后的方法
})
后端操作
接口結(jié)構(gòu)
接口: (post)/biz/login/wx
參數(shù): browser(取值為 wx,other)
返回數(shù)據(jù)(json):
// 登錄成功時返回
{
"code": 1,
"msg": "SUCCESS",
"data": {
"nick": "用戶昵稱",
"role_id": 2,
"mobile": "手機(jī)號",
"avatar": "用戶頭像",
"birthday": 1578909982972,
"gender": 2,
"location": "地區(qū)",
"summary": "用戶簡介",
"eval": true,
"status": "Complete",
"last_login": 1578909982972,
"id": "id",
"create_time": 1571755690000,
"update_time": 1578885503000
}
}
// 登錄失敗時返回
{
"code": 0,
"msg": "FAILURE"
}
1 獲取access_token
收到登錄請求后首先通過code向微信服務(wù)器換取access_token慎玖。
根據(jù)不同的瀏覽器類型使用相應(yīng)的appid和secret
// 請求url(Get)
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
參數(shù)說明
參數(shù) | 是否必須 | 說明 |
---|---|---|
appid | 是 | 應(yīng)用唯一標(biāo)識 |
secret | 是 | 應(yīng)用密鑰AppSecret |
code | 是 | 填寫第一步獲取的code參數(shù) |
grant_type | 是 | 填authorization_code |
微信瀏覽器登錄時使用公眾號appid和secret, 其他瀏覽器登錄使用網(wǎng)站應(yīng)用appid和secret
返回數(shù)據(jù)說明
名稱 | 類型 | 說明 |
---|---|---|
access_token | String | access_token |
expires_in | int | access_token有效時間 |
refresh_token | String | refresh_token |
openid | String | open_id |
scope | String | 授權(quán)作用域 |
當(dāng)獲取數(shù)據(jù)出錯時,返回結(jié)果中包含"errCode"字段, 登錄失敗
2 拉取用戶信息
通過第一步中獲取到的access_token和openid拉取user_info
// 請求url(Get)
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
參數(shù)說明
參數(shù) | 是否必須 | 說明 |
---|---|---|
access_token | 是 | 上一步中獲取到的access_token |
openid | 是 | 微信用戶唯一標(biāo)識,上一步中獲取到的openid |
返回數(shù)據(jù)說明
名稱 | 類型 | 說明 |
---|---|---|
openid | String | open_id |
unionid | String | union_id |
nickname | String | 用戶昵稱 |
sex | int | 性別 |
province | String | 省 |
city | String | 城市 |
country | String | 國家 |
headimgurl | String | 用戶頭像 |
privilege | Array | 用戶權(quán)限 |
當(dāng)獲取數(shù)據(jù)出錯時,返回結(jié)果中包含"errCode"字段, 登錄失敗
3 生成或獲取本地用戶
- 通過union_id獲取第三方平臺賬號
- 第三方平臺賬號存在時通過uid獲取用戶數(shù)據(jù),否則繼續(xù)
- 使用微信登錄的賬戶需要將其用戶數(shù)據(jù)轉(zhuǎn)換成本地用戶并存儲
- 添加用戶緩存
- 創(chuàng)建或更新用戶Auth數(shù)據(jù)
- 更新ES(UserIndex)
- 創(chuàng)建用戶媒體
4 返回用戶數(shù)據(jù)
將用戶數(shù)據(jù)返回到前臺