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