介紹
在很多微信H5應用裡,當使用者訪問第三方應用時就需要進行微信網頁授權,並且很多涉及安全的操作我們必須要先獲取使用者資訊才能繼續,本文章簡單介紹了微信授權流程,並通過申請微信測試賬號來模擬網頁授權,使用者在授權頁點選確定登入後獲取使用者資訊並顯示在前端頁面,最後效果如下圖
工具及開發準備
1. 微信開發者工具及微信測試號
因為是微信授權,所以必須要在微信環境下使用,首先我們要在這裡安裝微信開發者工具,因為我們沒有自己的應用,所以還需要在微信公眾平臺申請一個介面測試號,這個介面測試號就相當於我們的第三方應用。
2. 引數設定
登陸測試號後可以檢視到自己的appId和appsecret資訊,將體驗介面許可權表裡的網頁服務的網頁授權獲取使用者基本資訊修改為127.0.0.1:8800,該地址就是使用者確認授權後回撥的地址即我們應用的後臺處理地址,如下圖
最後拿出自己微信掃碼關注該測試號即可,如下圖所示
微信授權流程介紹
具體流程及詳細介紹大家可以到官網微信公眾平臺技術文件檢視,大致分為四步:
1. 引導使用者進入授權頁面同意授權,此時會呼叫微信api獲取code
2. 授權通過後會帶上code引數請求回撥地址
3. 後臺獲取code,再次呼叫微信介面換取網頁授權access_token和openid
4. 通過網頁授權access_token和openid獲取使用者基本資訊(如果有unionid還會獲取到unionid引數)
正式開始
詳細程式碼可以在github上下載,地址https://github.com/wangfengyuan/wxAuthorize
1. 原始程式碼
let express = require("express");const https = require('https');
let app = express();
//appIDlet
appID = `wxec6fa9e9bc03d885`;
//appsecretlet
appSerect = `4c8a0d14cff08959b4e17334cabf9cf0`;
//點選授權後重定向url地址
let redirectUrl = `/getUserInfo`;
let host = `http://127.0.0.1:3000`;
//微信授權api,介面返回code,點選授權後跳轉到重定向地址並帶上code引數
let authorizeUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appID}&redirect_uri=` + `${host}${redirectUrl}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`
app.get("/login", function(req, res) {
res.sendFile(path.resolve(__dirname,'login.html'));
});
app.get("/auth", function(req, res) {
res.writeHead(302, {
'Location': authorizeUrl
});
res.end();
});
app.get("/getUserInfo", function(req, res) {
let code = req.query.code;
let getaccess = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=` + `${appID}&secret=${appSerect}&code=${code}&grant_type=authorization_code`;
//通過拿到的code和appID、app_serect獲取access_token和open_id
https.get(getaccess, (resText) => {
var ddd = "";
resText.on('data', (d) => {
ddd += d;
});
resText.on('end', () => {
// console.log(ddd);
var obj = JSON.parse(ddd);
var access_token = obj.access_token;
var open_id = obj.openid;
//通過上一步獲取的access_token和open_id獲取userInfo即使用者資訊
let getUserUrl = `https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${open_id}&lang=zh_CN`;
https.get(getUserUrl, (resText) => {
user = "";
resText.on('data', (d) => {
user += d;
});
resText.on('end', () => {
console.log(user);
var userobj = JSON.parse(user);
res.send(userobj);
console.log(userobj);
});
}) });
}).on('error', (e) => {
console.error(e);
});
app.listen(3000);複製程式碼
具體使用時要將appID和appSerect換成你對應的引數即可,因為我們的請求是要按一定順序的,但是node傳送請求是非同步的,所以我們的請求巢狀了三層,程式碼很難看,所以這裡可以採用ES6的async和await解決非同步回撥地獄。
2. 使用ES6的async和await的改進程式碼
async function wxAuth(req, res) {
//解析querystring獲取URL中的code值
let code = req.query.code;
//通過拿到的code和appID、app_serect獲取返回資訊
let resObj = await getAccessToken(code);
//解析得到access_token和open_id
let access_token = resObj.access_token;
let open_id = resObj.openid;
//通過上一步獲取的access_token和open_id獲取userInfo即使用者資訊
let userObj = await getUserInfo(access_token, open_id);
console.log(userObj);
res.render(path.resolve(__dirname,'userInfo.ejs'), {userObj: userObj});
// res.send(userObj);}
//通過拿到的code和appID、app_serect獲取access_token和open_id
function getAccessToken(code) {
return new Promise( (resolve, reject) => {
let getAccessUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=` + `${appID}&secret=${appSerect}&code=${code}&grant_type=authorization_code`;
https.get(getAccessUrl, (res) => {
var resText = "";
res.on('data', (d) => {
resText += d;
});
res.on('end', () => {
var resObj = JSON.parse(resText);
resolve(resObj);
});
}).on('error', (e) => {
console.error(e);
});
});
}
//通過上一步獲取的access_token和open_id獲取userInfo即使用者資訊
function getUserInfo(access_token, open_id) {
return new Promise( (resolve, reject) => {
let getUserUrl = `https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${open_id}&lang=zh_CN`;
https.get(getUserUrl, (res) => {
var resText = "";
res.on('data', (d) => {
resText += d;
});
res.on('end', () => {
var userObj = JSON.parse(resText);
resolve(userObj);
});
}).on('error', (e) => {
console.error(e);
});
})}複製程式碼
修改後程式碼流程清晰了很多,最後點選確認登陸後將獲取到的userObj通過ejs模板渲染在前端頁面,就能看到文章最開始展現的效果圖。
寫在最後
我前端剛入門沒多久,最近在公司實習,受到身邊同事影響,所以也開始寫文章來記錄自己的學習心得,這是我第一次寫文章,所以可能寫的不太好,大家對文章和程式碼有什麼建議歡迎提出來一起交流,謝謝!