1. 程式人生 > >Nodejs + express 開發微信公眾號模板訊息推送功能

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('模板訊息推送成功'); 
            }
        });
    }

介面依賴關係圖

這裡寫圖片描述