Nodejs + express 開發微信公眾號模板訊息推送功能
第一步:申請測試號
3.確認登入後,測試號申請成功!
第二步:測試號管理
1.測試號資訊
這裡的appID、appsecret在後面很多介面呼叫中都需要用到
2.介面配置資訊(這裡需要有自己的伺服器和對映成功的域名)
(本人用的是本地node伺服器,用花生殼把本機的8080埠對映到了花生殼提供的二級免費域名的80埠)
url填寫自己的域名,token可以隨意填
填寫完後先不要提交,接下來編寫nodejs服務端程式碼響應微信的提交請求,響應Token驗證結果
server.js
*注意:以下用到的模組大部分需要先安裝,安裝步驟請在本人其他的博文中檢視或自行百度安裝
const express = require('express'); //web服務框架模組
const request = require('request'); //http請求模組
const fs = require('fs'); //檔案系統模組
const path = require('path'); //檔案路徑模組
const sha1 = require('node-sha1'); //加密模組
const urlencode= require('urlencode'); //URL編譯模組
const hostName = '127.0.0.1'; //ip或域名
const port = 8080; //埠
/**
* [開啟跨域便於介面訪問]
*/
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*'); //訪問控制允許來源:所有
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); //訪問控制允許報頭 X-Requested-With: xhr請求
res.header('Access-Control-Allow-Metheds', 'PUT, POST, GET, DELETE, OPTIONS' ); //訪問控制允許方法
res.header('X-Powered-By', 'nodejs'); //自定義頭資訊,表示服務端用nodejs
res.header('Content-Type', 'application/json;charset=utf-8');
next();
});
/**
* [設定驗證微信介面配置引數]
*/
const config = {
token: 'test', //對應測試號介面配置資訊裡填的token
appid: 'xxxxxxxxxxxxxx', //對應測試號資訊裡的appID
secret: 'xxxxxxxxxxxxxxxxxxxx', //對應測試號資訊裡的appsecret
grant_type: 'client_credential' //預設
};
/**
* [驗證微信介面配置資訊,]
*/
app.get('/', function(req, res) {
const token = config.token; //獲取配置的token
const signature = req.query.signature; //獲取微信傳送請求引數signature
const nonce = req.query.nonce; //獲取微信傳送請求引數nonce
const timestamp = req.query.timestamp; //獲取微信傳送請求引數timestamp
const str = [token, timestamp, nonce].sort().join(''); //排序token、timestamp、nonce後轉換為組合字串
const sha = sha1(str); //加密組合字串
//如果加密組合結果等於微信的請求引數signature,驗證通過
if (sha === signature) {
const echostr = req.query.echostr; //獲取微信請求引數echostr
res.send(echostr + ''); //正常返回請求引數echostr
} else {
res.send('驗證失敗');
}
});
app.listen(port, hostName, function() {
console.log(`伺服器執行在http://${hostName}:${port}`);
});
執行server.js啟動node伺服器,保證花生殼成功對映本地伺服器至域名,外網可通過域名正常訪問本地伺服器
然後點選提交,提示“配置成功”表示介面配置完成
3.模板訊息介面
新增測試模板,填寫標題和內容
4.OAuth2.0網頁授權
在網頁服務 > 網頁帳號 > 網頁授權獲取使用者基本資訊 > 修改
回撥域名的填寫自己的域名(注意,域名的格式不包含http://)
5.建立微信網頁授權介面連結
在node伺服器新增授權呼叫介面,在微信中訪問這個介面地址會建立一個可以跳轉到授權頁面的連結
這步操作是為了使回撥的介面得到code引數,因為傳送模板訊息必須要有使用者的openid,而獲取使用者的openid必須要有code引數,code引數需要使用者訪問指定的連結觸發授權後才會產生
繼續在server.js的基礎上增加
/**
* [建立請求微信網頁授權介面連結]
*/
app.get('/authentication', function(req, res) {
const appid = config.appid;
const redirect_uri = urlencode("http://www.xxx.net/code"); //這裡的url需要轉為加密格式,它的作用是訪問微信網頁鑑權介面成功後微信會回撥這個地址,並把code引數帶在回撥地址中
const scope = 'snsapi_userinfo';
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=STATE&connect_redirect=1#wechat_redirect`;
const html =
`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" >
<title>微信鑑權引導</title>
</head>
<body><a href="${url}">跳轉到鑑權頁面</a></body>
</html>`;
res.setHeader('Content-Type', 'text/html');
res.send(html);
});
*注意:每次修改server.js檔案後需要重啟node服務程式碼才會生效
6.下載安裝微信開發者工具除錯
安裝成功後登入開發者工具,訪問剛才建立的介面地址 http://www.xxx.net/authentication,
可以看到鑑權的連結已經建立成功,但目前還沒有寫好獲取code的介面,所以先不要點選
7.獲取到code > 獲取openid > 獲取access_token > 傳送模板訊息
繼續在server.js的基礎上增加
/**
* 網頁授權回撥介面,可以獲取code
*/
app.get('/code', function(req, res) {
const code = req.query.code; //微信回撥這個介面後會把code引數帶過來
getOpenId(code); //把code傳入getOpenId方法
});
/**
* 獲取openid
* @param { string } code [呼叫獲取openid的介面需要code引數]
*/
function getOpenId(code) {
const appid = config.appid;
const secret = config.secret;
const url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appid}&secret=${secret}&code=${code}&grant_type=authorization_code`;
request(url, function(error, response, body) {
if (!error && response.statusCode == 200) {
const openid = body.openid;
getAccessToken(openid); //獲取openid成功後呼叫getAccessToken
}
});
}
/**
* 獲取access_token
* @param { string } openid [傳送模板訊息的介面需要用到openid引數]
*/
function getAccessToken(openid) {
const appid = config.appid;
const secret = config.secret;
const grant_type = config.grant_type;
const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=${grant_type}&appid=${appid}&secret=${secret}`;
request(url, function(error, response, body) {
if (!error && response.statusCode == 200) {
const access_token= JSON.parse(body).access_token;
sendTemplateMsg(openid, access_token); //獲取access_token成功後呼叫傳送模板訊息的方法
} else {
throw 'update access_token error';
}
});
}
/**
* 傳送模板訊息
* @param { string } openid [傳送模板訊息的介面需要用到openid引數]
* @param { string } access_token [傳送模板訊息的介面需要用到access_token引數]
*/
function sendTemplateMsg(openid, access_token) {
const url = `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${access_token}`; //傳送模板訊息的介面
const requestData = { //傳送模板訊息的資料
touser: openid,
template_id: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
url: 'http://weixin.qq.com/download',
data: {
first: {
value: '身份資訊',
color: "#173177"
},
keyword1: {
value: '張三',
color: '#1d1d1d'
},
keyword2: {
value: '男',
color: '#1d1d1d'
},
keyword3: {
value: '45',
color: '#1d1d1d'
},
remark: {
value: '已登記!',
color: '#173177'
}
}
};
request({
url: url,
method: 'post',
body: requestData,
}, function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log('模板訊息推送成功');
}
});
}