短的答案
- 在微信開放平臺(tái)上注冊(cè)一個(gè)網(wǎng)頁應(yīng)用的賬號(hào), 審批通過之后會(huì)生成一個(gè) AppId 和 AppSecret
- 用戶在網(wǎng)頁上觸發(fā)登錄機(jī)制后, 瀏覽器會(huì)跳轉(zhuǎn)到一個(gè)拼湊出來的的 url 上
例如, 在京東使用微信登錄, 它的 url 是這樣的
https://open.weixin.qq.com/connect/qrconnect?appid=wx827225356b689e24&state=4254CD505A1F4E17DDD96009D4EA2BB860FC6C77A08C92FF3928F27AF381BB92C770127B30BC8487D1703C5878979B10&redirect_uri=https%3A%2F%2Fqq.jd.com%2Fnew%2Fwx%2Fcallback.action%3Fview%3Dnull%26uuid%3Def5652d6750f404399e62e4e7510b066&response_type=code&scope=snsapi_login#wechat_redirect](https://open.weixin.qq.com/connect/qrconnect?appid=wx827225356b689e24&state=4254CD505A1F4E17DDD96009D4EA2BB860FC6C77A08C92FF3928F27AF381BB92C770127B30BC8487D1703C5878979B10&redirect_uri=https%3A%2F%2Fqq.jd.com%2Fnew%2Fwx%2Fcallback.action%3Fview%3Dnull%26uuid%3Def5652d6750f404399e62e4e7510b066&response_type=code&scope=snsapi_login#wechat_redirect)
觀察一下, 這個(gè) url 以 key1=value1&key2=value2 的形式攜帶了一些信息
那么, 當(dāng)用戶跳轉(zhuǎn)到這個(gè) url 上時(shí), 這些信息就以查詢參數(shù)的形式發(fā)送給微信的服務(wù)器, 微信服務(wù)器會(huì)返回一個(gè)頁面, 用戶在掃描微信上的二維碼后, 微信服務(wù)器就會(huì)完成那那一部分的工作, 然后讓用戶端主動(dòng)跳轉(zhuǎn)到我們事先準(zhǔn)備的一個(gè) url 上, 例如 www.xxx.com/authcallback?code=xxxxxxx, 以查詢參數(shù)的形式攜帶一個(gè) code, 這樣我們自己的服務(wù)器就能拿到這個(gè) code - 我們服務(wù)器后臺(tái)根據(jù)這個(gè) code 再去請(qǐng)求微信服務(wù)器, 他會(huì)返回 openid, unionid, userinfo 等信息, 我們的服務(wù)器用 redis 或者其他數(shù)據(jù)庫記錄下這個(gè)信息
- 用 cookie 或類似的手段來給頁面記錄一下身份, 以便下次用戶訪問的時(shí)候會(huì)找到這個(gè)用戶的 openid 等信息, 這樣就完成了一個(gè)第三方登錄的流程
長(zhǎng)的答案(完整代碼)
一. 前端跳轉(zhuǎn)到微信的url上
這里使用的是在當(dāng)前頁面掃碼登錄的方式 (如果想使用類似京東直接跳轉(zhuǎn)的登錄, 可以直接平湊出來一個(gè) url 然后跳轉(zhuǎn)即可 )
- 引入微信登錄的js文件
<script src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
- 調(diào)用微信的接口
var obj = new WxLogin({
id: "login_container",
appid: "wx8725b9a19e0abc0e",
scope: "snsapi_login",
redirect_uri: "https://xxx.com/auth/callback",
state: "",
style: "",
href: ""
})
- 幾個(gè)參數(shù)的含義
- id: 顯示登錄二維碼的容器
- appid: 網(wǎng)站應(yīng)用的id
- scope: 網(wǎng)頁應(yīng)用只用寫 snsapi_login
- redirect_uri: 后端準(zhǔn)備的回調(diào)地址, 用來接收code
- state: 會(huì)原路返回, 可用于防止csrf攻擊, 非必須
- style: 二維碼的樣式, 提供"black", "white", 非必需
- href: 自定義樣式鏈接
二. 后端接收 code
后端使用的是 express 的寫法
同時(shí)也使用了由樸靈大神寫的庫 wechat-oauth, 它內(nèi)部封裝了獲取用戶信息的方法, 讓我們不必糾結(jié)于這些細(xì)節(jié)
只需要知道它做了什么: 發(fā)送 code 到微信的服務(wù)器, 然后微信返回了用戶的信息
可以命令行運(yùn)行 npm i wechat-oauth
下載
代碼如下
const OAuth = require('wechat-oauth')
const router = express.Router()
// 使用網(wǎng)頁應(yīng)用的 appid 和 secret 去初始化 wechat-oauth 的方法
const wxPcClient = new OAuth(WX_APP_ID, WX_APP_SECRET)
router.get('/callback', (req, res) => {
// 這里接收前端的 redirect_url 傳遞的 code
const { code } = req.query
wxPcClient.getAccessToken(code, (err, result) => {
if (!err) {
const accessToken = result.data.access_token
const openId = result.data.openid
const unionId = result.data.unionid
// 這里生成一個(gè) sessionid
const sessionId = generateSessionId()
wxPcClient.getUser(openId, (err, result) => {
// 這里獲取到了用戶的信息, 可以存儲(chǔ)在數(shù)據(jù)庫中
const {nickname, sex, city, province, country, headimgurl} = result
// 設(shè)置一個(gè) cookie 用于標(biāo)記這個(gè)用戶
res.cookie('wxsessionid', sessionId, { maxAge: 84600000, httpOnly: true })
// 登錄成功后做一個(gè)跳轉(zhuǎn), 也可以不做
res.redirect('https://xxx.com/yyy.html')
})
}
})
})