Node.js 微信公众号开发小试

申请服务器: 微信公众号的开发需要使用一台用于接收并处理消息的服务器, 此处推荐申请腾讯的免费云主机, 点我去申请吧, 每天九点半开抢, 我选择的服务器镜像是Ubuntu, 关于如何在服务器上配置Node环境, 可参考我另一篇博客使用 Linux 系统开发Web前端. 公众号开发的原理就是通过设置一个接收接口, 一旦开启开发者模式, 微信服务器将转发消息至该接口.

申请服务器

微信公众号的开发需要使用一台用于接收并处理消息的服务器, 此处推荐申请腾讯的免费云主机, 点我去申请吧, 每天九点半开抢, 我选择的服务器镜像是Ubuntu, 关于如何在服务器上配置Node环境, 可参考我另一篇博客使用 Linux 系统开发Web前端. 公众号开发的原理就是通过设置一个接收接口, 一旦开启开发者模式, 微信服务器将转发消息至该接口.

接入开发步骤

填写服务器配置

验证服务器地址的有效性

完成配置后, 服务器将收到来自微信的GET验证请求, 该请求包括如下参数:

  1. signature 微信加密签名, 使用开发者填写的token参数和请求中的timestamp参数、nonce参数进行加密
  2. timestamp 时间戳
  3. nonce 随机数
  4. echostr 随机字符串, 当验证通过时, 返回该字符串给微信服务器, 从而完成验证

验证流程

  1. 将token、timestamp、nonce三个参数进行字典序排序
  2. 将三个参数字符串拼接成一个字符串进行sha1加密
  3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

验证有效性的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
app.get('/wechat', (req, res) => {
var token = "quanru";
var signature = req.query.signature;
var timestamp = req.query.timestamp;
var echostr = req.query.echostr;
var nonce = req.query.nonce;

var oriArray = [nonce, timestamp, token];
oriArray.sort();
var original = oriArray.join('');

var shaObj = new jsSHA(original, 'TEXT');
var scyptoString = shaObj.getHash('SHA-1', 'HEX');
if (signature == scyptoString) {
//验证成功
res.send(echostr);
} else {
//验证失败
res.send(false);
}
});

依据接口文档实现业务逻辑

以文本消息为例, 如下为微信转发至服务器的文本消息:

1
2
3
4
5
6
7
8
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>

消息处理:

1
2
3
4
5
6
7
8
9
10
11
12
  app.post('/wechat', (req, res) => {
res.writeHead(200, {'Content-Type': 'application/xml'});

var content = req.body.xml.content;

turingRobot(encodeURI(content)).then((data) => {
var response = JSON.parse(data);
var resMsg = autoReply(req.body.xml, response.text);
console.log(resMsg);
res.end(resMsg);
});
});

其中turingRobot用于向图灵机器人发送用户消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const request = require('request');
function getTuringResponse(info) {
if(typeof info !== 'string') {
info = info.toString();
}
let options = {
method:'GET',
url: 'http://www.tuling123.com/openapi/api?key=13a74dbd0f6b45d69ac49334e7027742&info='+info
};
return new Promise((resolve, reject) => {
request(options, (err, res, body) => {
if (res) {
resolve(body);
} else {
reject(err);
}
});
})
}
module.exports = getTuringResponse;

自动回复模块autoReply:

1
2
3
4
5
6
7
8
9
10
11
12
13
function autoReply(requestData, info) {
if(requestData.msgtype == 'text') {
var resMsg = '<xml>' +
'<ToUserName><![CDATA[' + requestData.fromusername + ']]></ToUserName>' +
'<FromUserName><![CDATA[' + requestData.tousername + ']]></FromUserName>' +
'<CreateTime>' + parseInt(new Date().valueOf() / 1000) + '</CreateTime>' +
'<MsgType><![CDATA[text]]></MsgType>' +
'<Content><![CDATA['+info+']]></Content>' +
'</xml>';
}
return resMsg;
}
module.exports = autoReply;

One More Thing

使用微信的官方的Node中间件, 可更方便高效地开发公众号
传送门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const turingRobot = require('./turingRobot');
const autoReply = require('./autoReply');
const wechat = require('wechat');

module.exports = function(app) {
//使用中间件
//传入这三个配置, 自动帮你验证
var config = {
token: 'quanru',
appid: 'wxdc6410f1001d787b',
encodingAESKey: 'IJwymet3h2KzGSTPxMnITc25pGiSzSlWCXHUhcvQRzc'
};
app.use('/wechat', wechat(config, (req, res, next) => {
//用户的消息以对象的形式返回到该变量
var message = req.weixin;
var content = message.Content;
turingRobot(encodeURI(content))
.then((data) => {
var response = JSON.parse(data);
//默认回复文本消息, 支持多种格式回复, 如图像, 音乐
res.reply(response.text);
});
}));
}

附上精美PPT地址
附上精美代码地址

参考

nodejs微信开发—自动回复的实现
微信公众平台开发概述—接入指南(需要登录)
使用 Linux 系统开发Web前端

作者

林宜丙

发布于

2016-08-14

更新于

2023-08-30

许可协议