Wechat is a middleware and SDK of Wechat Official Account Admin Platform (mp.weixin.qq.com).
This wechat document is translated by Guo Yu, if you have some understanding problems, please feel free open an issue here.
API details located here
Tips: you'll have to apply
It's a simple demo:
active the reply waiter we setuped before:
if waiter
reply waiter acquires both function and text as a
if user's message is not in waiter's trigger texts. this message will be processd in the![Node.js API Auto-reply robot]()
Codes here
robots can be setup in PAASs like CloudFoundry, appfog or BAE.
wachat 0.6.x supports shorthand methods below:
Tips:

Tips: Business logic in blue lines.

Or:
![]()
This wechat document is translated by Guo Yu, if you have some understanding problems, please feel free open an issue here.
Features
- Auto reply (text, image, videos, music, thumbnails posts are supported)
- CRM message (text, image, videos, music, thumbnails posts are supported)
- Menu settings (CRD are supported)
- QR codes (CR are supported, both temporary and permanent)
- Group settings (CRUD are supported)
- Followers infomation (fetching user's info or followers list)
- Media (upload or download)
- Reply Waiter (good for surveys)
- Sessions
- OAuth API
- Payment (deliver notify and order query)
API details located here
Installation
npm install wechat
Use with Connect/Express
var wechat = require('wechat');
app.use(connect.query()); // Or app.use(express.query());
app.use('/wechat', wechat('some token', function (req, res, next) {
// message is located in req.weixin
var message = req.weixin;
if (message.FromUserName === 'diaosi') {
// reply with text
res.reply('hehe');
} else if (message.FromUserName === 'text') {
// another way to reply with text
res.reply({
content: 'text object',
type: 'text'
});
} else if (message.FromUserName === 'hehe') {
// reply with music
res.reply({
type: "music",
content: {
title: "Just some music",
description: "I have nothing to lose",
musicUrl: "http://mp3.com/xx.mp3",
hqMusicUrl: "http://mp3.com/xx.mp3"
}
});
} else {
// reply with thumbnails posts
res.reply([
{
title: 'Come to fetch me',
description: 'or you want to play in another way ?',
picurl: 'http://nodeapi.cloudfoundry.com/qrcode.jpg',
url: 'http://nodeapi.cloudfoundry.com/'
}
]);
}
}));
Tips: you'll have to apply
token
at Wechat platform (this page is in Chinese)Reply Messages
auto reply a message when your followers send a message to you. also text, image, videos, music, thumbnails posts are supported. details API goes here (official documents)Reply with text
res.reply('Hello world!');
// or
res.reply({type: "text", content: 'Hello world!'});
Reply with Image
res.reply({
type: "image",
content: {
mediaId: 'mediaId'
}
});
Reply with voice
res.reply({
type: "voice",
content: {
mediaId: 'mediaId'
}
});
Reply with Video
res.reply({
type: "video",
content: {
mediaId: 'mediaId',
thumbMediaId: 'thumbMediaId'
}
});
Reply with Music
res.reply({
title: "Just some music",
description: "I have nothing to lose",
musicUrl: "http://mp3.com/xx.mp3",
hqMusicUrl: "http://mp3.com/xx.mp3"
});
Reply with Thumbnails posts
res.reply([
{
title: 'Come to fetch me',
description: 'or you want to play in another way ?',
picurl: 'http://nodeapi.cloudfoundry.com/qrcode.jpg',
url: 'http://nodeapi.cloudfoundry.com/'
}
]);
Reply with social function messages
res.reply({
type: 'hardware',
HardWare:{
MessageView: 'myrank',
MessageAction: 'ranklist'
}
});
transfer user message to wechat customer service
transfer the message sent from wechat users to the Wechat Multi Customer Serviceres.transfer2CustomerService();
Reply with device messages
Specific responses will be made as the message type is devicetext or deviceevent.var wechat = require('wechat');
var config = {
token: 'token',
appid: 'appid',
encodingAESKey: 'encodinAESKey',
checkSignature: true // optional, default value is true. Because WeChat open platform debug tool does not send signature in plaintext mode, if you want to use this debug tool, please set to false
};
app.use(express.query());
app.use('/wechat', wechat(config, function (req, res, next) {
// message is located in req.weixin
var message = req.weixin;
if (message.MsgType === 'device_text') {
// device text
res.reply('This message will be pushed onto the device.');
} else if (message.MsgType === 'device_event') {
if (message.Event === 'subscribe_status' ||
message.Event === 'unsubscribe_status') {
//subscribe or unsubscribe the WIFI device status,the reply should be 1 or 0
res.reply(1);
} else {
res.reply('This message will be pushed onto the device.')
}
}
}));
WXSession
Wechat messages are not communicate like traditional C/S model, therefore nothing Cookies will be store in Wechat client. this WXSession is designed to support access user's infomation viareq.wxsession
, with connect.session
backed.It's a simple demo:
app.use(connect.cookieParser());
app.use(connect.session({secret: 'keyboard cat', cookie: {maxAge: 60000}}));
app.use('/wechat', wechat('some token', wechat.text(function (info, req, res, next) {
if (info.Content === '=') {
var exp = req.wxsession.text.join('');
req.wxsession.text = '';
res.reply(exp);
} else {
req.wxsession.text = req.wxsession.text || [];
req.wxsession.text.push(info.Content);
res.reply('Message got ' + info.Content);
}
})));
req.wxsession
and req.session
shares same store. width redis
as persistence database, across processes sharing are supportd.Reply Waiter
a reply waiter is seems like a telephone menu system. it must be setup before activation. this function is supported upon WXSession.var List = require('wechat').List;
List.add('view', [
['reply {a}', function (info, req, res) {
res.reply('Im Answer A');
}],
['reply {b}', function (info, req, res) {
res.reply('Im Answer B');
}],
['reply {c}', 'Im Answer C (the shorthand method)']
]);
active the reply waiter we setuped before:
var app = connect();
app.use(connect.query());
app.use(connect.cookieParser());
app.use(connect.session({secret: 'keyboard cat', cookie: {maxAge: 60000}}));
app.use('/wechat', wechat('some token', wechat.text(function (info, req, res, next) {
if (info.Content === 'list') {
res.wait('view'); // view is the very waiter we setuped before.
} else {
res.reply('hehe');
// or stop the waiter and quit.
// res.nowait('hehe');
}
})));
if waiter
view
actived, user will receive messages below:reply a
reply b
reply c
reply waiter acquires both function and text as a
callback
actionList.add('view', [
['reply {a}', function (info, req, res, next) {
// we callback as a function
res.reply('Answer A');
}],
// or text as shorthand
['reply {c}', 'Answer C']
]);
if user's message is not in waiter's trigger texts. this message will be processd in the
else
way and can be stoped by res.nowait()
, res.nowait
method actions like reply
method.Show cases
Auto-reply robot based on Node.js
Codes here
robots can be setup in PAASs like CloudFoundry, appfog or BAE.
API details
official document locates here Messages API Guide (in Chinese)。wachat 0.6.x supports shorthand methods below:
app.use('/wechat', wechat('some token', wechat.text(function (message, req, res, next) {
// reply with text
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125035',
// MsgType: 'text',
// Content: 'http',
// MsgId: '5837397576500011341' }
}).image(function (message, req, res, next) {
// message为图片内容
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359124971',
// MsgType: 'image',
// PicUrl: 'http://mmsns.qpic.cn/mmsns/bfc815ygvIWcaaZlEXJV7NzhmA3Y2fc4eBOxLjpPI60Q1Q6ibYicwg/0',
// MediaId: 'media_id',
// MsgId: '5837397301622104395' }
}).voice(function (message, req, res, next) {
// Reply with Voice
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125022',
// MsgType: 'voice',
// MediaId: 'OMYnpghh8fRfzHL8obuboDN9rmLig4s0xdpoNT6a5BoFZWufbE6srbCKc_bxduzS',
// Format: 'amr',
// MsgId: '5837397520665436492' }
}).video(function (message, req, res, next) {
// Reply with Video
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125022',
// MsgType: 'video',
// MediaId: 'OMYnpghh8fRfzHL8obuboDN9rmLig4s0xdpoNT6a5BoFZWufbE6srbCKc_bxduzS',
// ThumbMediaId: 'media_id',
// MsgId: '5837397520665436492' }
}).location(function (message, req, res, next) {
// Reply with Location (geo)
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125311',
// MsgType: 'location',
// Location_X: '30.283950',
// Location_Y: '120.063139',
// Scale: '15',
// Label: {},
// MsgId: '5837398761910985062' }
}).link(function (message, req, res, next) {
// Reply with Link
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125022',
// MsgType: 'link',
// Title: 'A link',
// Description: 'A link has its desc',
// Url: 'http://1024.com/',
// MsgId: '5837397520665436492' }
}).event(function (message, req, res, next) {
// Reply with Event
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125022',
// MsgType: 'event',
// Event: 'LOCATION',
// Latitude: '23.137466',
// Longitude: '113.352425',
// Precision: '119.385040',
// MsgId: '5837397520665436492' }
}).device_text(function (message, req, res, next) {
// Reply with device text.
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125022',
// MsgType: 'device_text',
// DeviceType: 'gh_d3e07d51b513'
// DeviceID: 'dev1234abcd',
// Content: 'd2hvc3lvdXJkYWRkeQ==',
// SessionID: '9394',
// MsgId: '5837397520665436492',
// OpenID: 'oPKu7jgOibOA-De4u8J2RuNKpZRw' }
}).device_event(function (message, req, res, next) {
// Reply with device event.
// { ToUserName: 'gh_d3e07d51b513',
// FromUserName: 'oPKu7jgOibOA-De4u8J2RuNKpZRw',
// CreateTime: '1359125022',
// MsgType: 'device_event',
// Event: 'bind'
// DeviceType: 'gh_d3e07d51b513'
// DeviceID: 'dev1234abcd',
// OpType : 0, //Available as Event is subscribe_status or unsubscribe_status.
// Content: 'd2hvc3lvdXJkYWRkeQ==', //Available as Event is not subscribe_status and unsubscribe_status.
// SessionID: '9394',
// MsgId: '5837397520665436492',
// OpenID: 'oPKu7jgOibOA-De4u8J2RuNKpZRw' }
})));
Tips:
text
, image
, voice
, video
, location
, link
, event
, device_text
, device_event
must be set at least one.More simple APIs
Supported in 0.3.x and above.app.use('/wechat', wechat('some token').text(function (message, req, res, next) {
// TODO
}).image(function (message, req, res, next) {
// TODO
}).voice(function (message, req, res, next) {
// TODO
}).video(function (message, req, res, next) {
// TODO
}).location(function (message, req, res, next) {
// TODO
}).link(function (message, req, res, next) {
// TODO
}).event(function (message, req, res, next) {
// TODO
}).device_text(function (message, req, res, next) {
// TODO
}).device_event(function (message, req, res, next) {
// TODO
}).middlewarify());
Functions Graph

Tips: Business logic in blue lines.
License
The MIT license.Donation
buy me a cup of coffee please.
Or: