公眾號H5頁面接入微信登入流程
原始碼地址
https://gitee.com/szxio/h5_weixin
起步
首先建立一個專案,我們採用uni-app來作為我們的前端框架
環境安裝
全域性安裝vue-cli
npm install -g @vue/cli
建立uni-app
使用正式版(對應HBuilderX最新正式版)
vue create -p dcloudio/uni-preset-vue my-project
在安裝過程中選擇預設版本即可
啟動
安裝完成後按照提示進入我們的專案根目錄下執行啟動命令
npm run serve
啟動成功圖
申請測試號
官方文件
申請測試公眾號
這裡我們本地學習,所以可以申請一個測試哈,方便我們快速瞭解微信相關配置。在實際開發中我們會將我們的網站配置在真正的公眾號中。
1.首先登入微信公眾平臺,選擇一個公眾號登入,第一次登入時可能沒有公眾號,我們可以申請註冊一個訂閱號即可。
登入進來後點選下圖示示選單可以申請一個測試號
點選之後我要求我們登入,我們掃碼登入一下即可,然後可以看到如下介面
這裡可以看到我們公眾號的appID
和appsecret
。另外由於我之前設定過相關配置,所以這裡的 介面配置資訊
和 JS介面安全域名
有內容,第一次申請的沒有,不過不影響我們本次教程的後續開發。當我們有需要時可以重新在這個頁面中去設定相關介面資訊
配置授權回撥頁面域名
在測試號管理頁面往下滑可以看到下面的配置項
設定我們專案的啟動地址,由於是測試號,所以這裡可以配置IP地址
注意:測試號可以配置ip地址,正式號只能配置域名
給測試號配置選單
安裝axiox
npm install axios --save
獲取AccessToken
呼叫如下地址即可獲取AccessToken
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
請求如下介面獲取Access token,這個Access token有7200秒的有效期,並且介面每天限制2000次請求,所以一般由後端去請求該介面並儲存起來,並且設定定時重新整理。但是由於現在學習階段,所以我們前端可以直接請求
新建 src\util\getTonken.js
檔案,編寫如下程式碼
import http from "axios"
const APPID = "這裡替換成測試號的APPID"
const APPSECRET = "這裡替換成測試號的APPSECRET"
// 更新tonken
function updateToken() {
return new Promise((resolve, reject) => {
http.get(`/weixin/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`).then(res => {
resolve(res.data.access_token)
}).catch(err => {
reject(err)
})
})
}
// 獲取Tonken
export function getToKen() {
return new Promise(async (resolve, reject) => {
// 從快取中讀取token
let stroagetoken = uni.getStorageSync('accessToken')
// 如果快取中有token,則直接返回快取中的token
if (stroagetoken) {
console.log('快取獲取的token');
// 返回結果
resolve(stroagetoken)
} else {
// 如果快取沒有token,則走介面重新獲取新的token
let token = await updateToken()
// 存入到快取中
uni.setStorageSync('accessToken', token)
// 設定定時任務,每隔7000秒更新一次tonken
setInterval(async () => {
// 獲取新的token
let token = await updateToken()
// 存入到快取中
uni.setStorageSync('accessToken', token)
}, 7000000);
console.log('介面獲取的token');
// 返回結果
resolve(token)
}
})
}
請求微信地址的跨域問題
上面的程式碼中可以看到請求地址是以 /weixin
開頭的,這是因為我們在前端直接請求 https://api.weixin.qq.com
會產生跨域問題,所以我配置了前端代理,配置方式如下:
首先在專案根目錄新建 vue.config.js
檔案,編寫如下程式碼
module.exports = {
publicPath: "./",
devServer: {
disableHostCheck: true, //禁用主機檢查
proxy: {
"/weixin": {
target: "https://api.weixin.qq.com/",
ws: true,
secure: true, // 使用的是http協議則設定為false,https協議則設定為true
changOrigin: true, //開啟代理
pathRewrite: {
"^/weixin": "",
},
}
},
},
};
然後重啟專案,之後在傳送請求時,用 /weixin
開頭去傳送請求,則node會自動幫我們吧請求地址代理到 https://api.weixin.qq.com/
,從而解決跨域問題
建立選單
介面地址
POST(請使用https協議) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
介面引數見官網文件
下面程式碼即可為測試號建立一個普通選單
const ACCESS_TOKEN = uni.getStorageSync("accessToken");
const menuObj = {
button: [
{
type: "view",
name: "測試專案",
url: "http://192.168.60.230:8080/",
},
],
};
// 建立選單
http.post(`/weixin/cgi-bin/menu/create?access_token=${ACCESS_TOKEN}`, menuObj).then((res) => {
console.log(res, "建立選單");
});
程式碼執行後,我們掃描測試號的二維碼,即可看到配置的選單。這裡要保證我們的手機和電腦在同一個區域網下,通俗點就是連著同一個WiFi,這樣我們才能在手機端點選選單進入到我們的專案中
微信網頁授權
授權步驟
- 第一步:使用者同意授權,獲取code
- 第二步:通過code換取網頁授權access_token
- 第三步:重新整理access_token(如果需要)
- 第四步:拉取使用者資訊(需scope為 snsapi_userinfo)
- 附:檢驗授權憑證(access_token)是否有效
引導關注者開發授權頁面
我們可以讓使用者跳轉到授權頁面,如果使用者同意授權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE。
授權地址
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
引數說明
引數 | 是否必須 | 說明 |
---|---|---|
appid | 是 | 公眾號的唯一標識 |
redirect_uri | 是 | 授權後重定向的回撥連結地址, 請使用 urlEncode 對連結進行處理 |
response_type | 是 | 返回型別,請填寫code |
scope | 是 | 應用授權作用域,snsapi_base (不彈出授權頁面,直接跳轉,只能獲取使用者openid),snsapi_userinfo (彈出授權頁面,可通過openid拿到暱稱、性別、所在地。並且, 即使在未關注的情況下,只要使用者授權,也能獲取其資訊 ) |
state | 否 | 重定向後會帶上state引數,開發者可以填寫a-zA-Z0-9的引數值,最多128位元組 |
#wechat_redirect | 是 | 無論直接開啟還是做頁面302重定向時候,必須帶此引數 |
開始編碼
<view>
<button type="info" @click="getUserInfo">獲取授權</button>
</view>
data() {
return {
homeUrl:"http://192.168.60.230:8080/",
};
},
methods: {
// 點選授權按鈕
getUserInfo() {
// 獲取當前頁面地址作為回撥地址,並且對地址進行urlEncode處理
let local = encodeURIComponent(this.homeUrl);
// 獲取公眾號appid
let appid = "wx2188729b190d357d";
// 跳轉到授權頁面
window.location.href =
"https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
appid +
"&redirect_uri=" +
local +
"&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
},
}
點選按鈕跳轉到授權頁面,然後微信會將引數拼接到回撥地址中,我們從地址中獲取code引數來獲取網頁授權的 access token
通過路徑上的code獲取網頁授權token
獲取token的介面地址
GET https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
首先我們封裝一個獲取路徑引數的方法
getUrlCode(name) {
return (
decodeURIComponent(
(new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(
location.href
) || [, ""])[1].replace(/\+/g, "%20")
) || null
);
}
然後再新增一個根據code
獲取token
的方法,這裡的APPID
和APPSECRET
放在了data
中,這裡可以優化成寫一個配置檔案,頁面可以從配置檔案中獲取。
data() {
return {
APPID: "wx2188729b190d357d",
APPSECRET: "d976b0e6262b829ba003e9a24032447c",
};
},
// 根據code獲取網站授權token
getTokenFormCode(code) {
http.get(
`/weixin/sns/oauth2/access_tokenappid=${this.APPID}&secret=${this.APPSECRET}&code=${code}&grant_type=authorization_code`
).then((res) => {
console.log(res.data.access_token,'根據code獲取網站授權token');
console.log(res.data.openid,'獲取到的使用者openid');
});
},
然後在 onLoad
中先判斷路徑上能否獲取到 code 值,如果獲取到後再呼叫介面去獲取網頁授權token
onLoad() {
// 判斷是否有code
let weixinCode = this.getUrlCode("code");
// 當獲取到code後再呼叫獲取token的方法
weixinCode && this.getTokenFormCode(weixinCode);
},
拉取使用者資訊
注意:這個方法需 scope
為 snsapi_userinfo
介面地址
GET https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
編寫方法
// 根據網頁授權token和openid獲取使用者基礎資訊
getAuthorizationInfo(token, openid) {
http.get(`/weixin/sns/userinfo?access_token=${token}&openid=${openid}&lang=zh_CN`).then((res) => {
console.log(res, "使用者基礎資訊");
});
},
改寫 getTokenFormCode
方法,介面呼叫成功後傳遞 token
和 openid
給 getAuthorizationInfo
方法來獲取使用者基本資訊
// 根據code獲取網站授權token
getTokenFormCode(code) {
http.get(
`/weixin/sns/oauth2/access_tokenappid=${this.APPID}&secret=${this.APPSECRET}&code=${code}&grant_type=authorization_code`
).then((res) => {
const { access_token, openid } = res.data;
this.getAuthorizationInfo(access_token, openid);
});
},
介面返回結果
根據介面資料展示頭像和暱稱
在 getAuthorizationInfo
方法中新增如下程式碼,儲存使用者資訊
// 根據code獲取網站授權token
getAuthorizationInfo(token, openid) {
http.get(`/weixin/sns/userinfo?access_token=${token}&openid=${openid}&lang=zh_CN`).then((res) => {
// 解構賦值
const { headimgurl, nickname } = res.data;
this.userInfo = {
// 使用者頭像
headimgurl: headimgurl,
// 使用者微信暱稱
nickname: nickname,
};
});
},
在頁面上展示使用者資訊
<view class="userInfo">
<view>
<image :src="userInfo.headimgurl"></image>
</view>
<view>{{ userInfo.nickname }}</view>
</view>
效果展示