最近做需求要對(duì)接微信公眾號(hào)悬而,看了兩天文檔函喉,基本算是理清楚了避归,在這里做下記錄。
準(zhǔn)備工作
了解公眾號(hào)類型和接口權(quán)限
微信公眾號(hào)分為訂閱號(hào)
和服務(wù)號(hào)
管呵,兩種賬號(hào)都可以進(jìn)行微信認(rèn)證以獲取更多接口權(quán)限(個(gè)人注冊(cè)的訂閱號(hào)不能進(jìn)行微信認(rèn)證)梳毙。
具體接口權(quán)限見:官方文檔 >>
獲取微信公眾平臺(tái)測(cè)試號(hào)
如果沒有申請(qǐng)好的公眾號(hào),可以使用官方提供的測(cè)試賬號(hào)捐下,使用自己微信號(hào)掃描登錄即可账锹。
登錄地址:微信公眾平臺(tái)測(cè)試號(hào) >>
網(wǎng)頁授權(quán)回調(diào)域名設(shè)置
我們要想在我們的網(wǎng)頁中獲取用戶信息萌业,就必須通過網(wǎng)頁授權(quán)來實(shí)現(xiàn)。網(wǎng)頁回調(diào)域名是指獲取用戶信息后需要跳轉(zhuǎn)的域名地址奸柬,因?yàn)楂@取用戶信息是微信提供的鏈接生年,獲取后需要再重定向到我們自己的頁面。
使用之前需要到公眾號(hào)里把我們的域名設(shè)置成網(wǎng)頁授權(quán)域名廓奕。
設(shè)置方法:登錄微信公眾平臺(tái) > 設(shè)置 > 公眾號(hào)設(shè)置 > 功能設(shè)置 > 網(wǎng)頁授權(quán)域名
配置規(guī)范為全域名(不需要加
http://
或https://
)抱婉,設(shè)置后可以在該域名下所有的頁面使用,但不能在該域名的二級(jí)域名下使用桌粉。
如:設(shè)置了
www.raydom.wang
蒸绩,http://www.raydom.wang/index.html
中可以使用,但http://note.raydom.wang
中不能使用铃肯。
后臺(tái)環(huán)境搭建
為了安全起見患亿,微信的接口調(diào)用都需要放到后臺(tái)進(jìn)行。這里使用的是基于node環(huán)境的koa2服務(wù)環(huán)境押逼。
開始
第一步:用戶同意授權(quán)窍育,獲取code
引導(dǎo)用戶打開如下鏈接:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
參數(shù)說明:
參數(shù) | 必填 | 說明 |
---|---|---|
appid | 是 | 公眾號(hào)的唯一標(biāo)識(shí) |
redirect_uri | 是 | 授權(quán)后重定向的回調(diào)鏈接地址, 請(qǐng)使用 urlEncode 對(duì)鏈接進(jìn)行處理 |
response_type | 是 | 返回類型宴胧,請(qǐng)?zhí)顚慶ode |
scope | 是 | 應(yīng)用授權(quán)作用域漱抓,snsapi_base (不彈出授權(quán)頁面,直接跳轉(zhuǎn)恕齐,只能獲取用戶openid)乞娄,snsapi_userinfo (彈出授權(quán)頁面,可通過openid拿到昵稱显歧、性別仪或、所在地。并且士骤, 即使在未關(guān)注的情況下范删,只要用戶授權(quán),也能獲取其信息 ) |
state | 否 | 重定向后會(huì)帶上state參數(shù)拷肌,開發(fā)者可以填寫a-zA-Z0-9的參數(shù)值到旦,最多128字節(jié) |
#wechat_redirect | 是 | 無論直接打開還是做頁面302重定向時(shí)候,必須帶此參數(shù) |
注意:redirect_uri 的值需要經(jīng)過 urlEncode 處理巨缘。
js中沒有提供原生方法添忘,可以使用工具處理以后使用: urlEncode處理工具 >>
如果用戶關(guān)注了公眾號(hào),
scope
使用snsapi_userinfo
獲取用戶信息時(shí)若锁,也不會(huì)彈出授權(quán)框(測(cè)試公眾號(hào)每次都會(huì)彈)
第二步:通過code獲取用戶信息
跳轉(zhuǎn)到我們自己的頁面以后搁骑,url中會(huì)自動(dòng)添加code。
示例:http://test.raydom.wang/?code=081tRRYX1Bk2IT0JNqVX16RAYX1tRRYT&state=123
獲取url中的code到后臺(tái)
前端代碼示例:
// 獲取url中的參數(shù)
function GetQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
// 這里使用的axios進(jìn)行ajax請(qǐng)求
axios.get("http://testapi.raydom.wang/login", {
params: {
code: GetQueryString("code")
}
})
.then((res) => {
console.log(res)
})
- 在后臺(tái)用拿到的
code
獲取ACCESS_TOKEN
、openid
和更多信息
后臺(tái)代碼示例:
const router = require('koa-router')() // 引入router
const superagent = require('superagent') // 一個(gè)node環(huán)境http(s)請(qǐng)求中間件
const cache = require('memory-cache') // 緩存處理中間件
const appid = "xxxxxxxxxxxxxxx" // appid
const appsecret = "xxxxxxxxxxxxxxxxxxx" // appsecret
router.get("/login", async(ctx, next) => {
let ACCESS_TOKEN = "",
openid = "";
// 使用code獲取openid和access_token
await superagent
.get("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +
appid + "&secret=" +
appsecret + "&code=" +
ctx.query.code + "&grant_type=authorization_code")
.then(res => {
// 此處本來應(yīng)該用res.body獲取返回的json數(shù)據(jù)仲器,但總是獲取不到煤率,只能用text代替
let result = JSON.parse(res.text)
ACCESS_TOKEN = result.access_token
openid = result.openid
})
.catch(res => {
console.log(res)
})
// 使用ACCESS_TOKEN和openid
await superagent
.get("https://api.weixin.qq.com/sns/userinfo?access_token=" +
access_token + "&openid=" + openid + "&lang=zh_CN")
.then(res => {
console.log(JSON.parse(res.text))
ctx.body = {
state: 1,
msg: '獲取access_token成功!'
}
})
.catch(res => {
console.log(res)
})
})
- 刷新access_token(如果需要)
由于access_token擁有較短的有效期乏冀,當(dāng)access_token超時(shí)后蝶糯,可以使用refresh_token進(jìn)行刷新,refresh_token有效期為30天煤辨,當(dāng)refresh_token失效之后裳涛,需要用戶重新授權(quán)。
請(qǐng)求方法:
獲取第二步的refresh_token后众辨,請(qǐng)求以下鏈接獲取access_token:https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
返回結(jié)果:
參數(shù) | 描述 |
---|---|
access_token | 網(wǎng)頁授權(quán)接口調(diào)用憑證,注意:此access_token與基礎(chǔ)支持的access_token不同 |
expires_in | access_token接口調(diào)用憑證超時(shí)時(shí)間端三,單位(秒) |
refresh_token | 用戶刷新access_token |
openid | 用戶唯一標(biāo)識(shí) |
scope | 用戶授權(quán)的作用域,使用逗號(hào)(,)分隔 |
關(guān)于UnionID機(jī)制(測(cè)試賬號(hào)無法獲染槌埂)
如果開發(fā)者擁有多個(gè)移動(dòng)應(yīng)用郊闯、網(wǎng)站應(yīng)用和公眾帳號(hào),可通過獲取用戶基本信息中的unionid來區(qū)分用戶的唯一性蛛株,因?yàn)橥挥脩敉帕蓿瑢?duì)同一個(gè)微信開放平臺(tái)下的不同應(yīng)用(移動(dòng)應(yīng)用、網(wǎng)站應(yīng)用和公眾帳號(hào))谨履,unionid是相同的欢摄。
獲取
unionid
需要scope
使用snsapi_userinfo
。
檢驗(yàn)授權(quán)憑證(access_token)是否有效
請(qǐng)求接口:http:GET(請(qǐng)使用https協(xié)議) https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID
有效返回的JSON結(jié)果:
{ "errcode":0,"errmsg":"ok"}
錯(cuò)誤時(shí)的JSON返回示例:
{ "errcode":40003,"errmsg":"invalid openid"}