I’ve always wanted to add more travel logs or daily notes to the log, but there are really no entertainment options in winter, and today, with the outbreak of the Novel Coronavirus, the entertainment industry is basically at a standstill, so let’s just keep typing code… In fact, is also the so-called knock code, admire their self-discipline, always unconsciously place to open Steam……
These days, I have been improving and optimizing my public account. Now I can continue to update a development record about the customized passive response.
Official document intercepts
Passive reply User messages are divided into the following six reply types. We need to return the required reply types to the server as fixed strings in accordance with the official API. The following are the different types and their corresponding strings:
- Reply text message
<xml> <ToUserName><! [CDATA[toUser]]></ToUserName> <FromUserName><! [CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><! [CDATA[text]]></MsgType> <Content><! [CDATA[hello]]></Content> </ XML >Copy the code
parameter |
Whether must | describe |
---|---|---|
ToUserName |
is |
Recipient account (OpenID received) |
FromUserName | is |
Developer wechat account |
CreateTime |
is |
Message creation time (integer) |
MsgType |
is |
The message type is text |
Content |
is |
Message content of the reply (line break: line break can be used in content, wechat client supports line break display) |
- Reply to picture message
<xml> <ToUserName><! [CDATA[toUser]]></ToUserName> <FromUserName><! [CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><! [CDATA[image]]></MsgType> <Image> <MediaId><! [CDATA[media_id]]></MediaId> </Image> </xml>Copy the code
parameter |
Whether must | instructions |
---|---|---|
ToUserName |
is |
Recipient account (OpenID received) |
FromUserName | is |
Developer wechat account |
CreateTime |
is |
Message creation time (integer) |
MsgType |
is |
The message type is image |
MediaId |
is |
Id obtained by uploading multimedia files through the interface in the material management |
- Reply to a Voice Message
<xml> <ToUserName><! [CDATA[toUser]]></ToUserName> <FromUserName><! [CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><! [CDATA[voice]]></MsgType> <Voice> <MediaId><! [CDATA[media_id]]></MediaId> </Voice> </xml>Copy the code
parameter |
Whether must | instructions |
---|---|---|
ToUserName |
is |
Recipient account (OpenID received) |
FromUserName | is |
Developer wechat account |
CreateTime |
is |
Message creation timestamp (integer) |
MsgType |
is |
The message type is Voice |
MediaId |
is |
Id obtained by uploading multimedia files through the interface in the material management |
- Reply to video messages
<xml> <ToUserName><! [CDATA[toUser]]></ToUserName> <FromUserName><! [CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><! [CDATA]></MsgType> <Video> <MediaId><! [CDATA[media_id]]></MediaId> <Title><! [CDATA[title]]></Title> <Description><! [CDATA[description]]></Description> </Video> </xml>Copy the code
parameter |
Whether must | instructions |
---|---|---|
ToUserName |
is |
Recipient account (OpenID received) |
FromUserName | is |
Developer wechat account |
CreateTime |
is |
Message creation time (integer) |
MsgType |
is |
The message type is Video |
MediaId |
is |
Id obtained by uploading multimedia files through the interface in the material management |
Title |
no |
Title of the video message |
Description |
no |
Description of the video message |
- Reply to music messages
<xml> <ToUserName><! [CDATA[toUser]]></ToUserName> <FromUserName><! [CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><! [CDATA[music]]></MsgType> <Music> <Title><! [CDATA[TITLE]]></Title> <Description><! [CDATA[DESCRIPTION]]></Description> <MusicUrl><! [CDATA[MUSIC_Url]]></MusicUrl> <HQMusicUrl><! [CDATA[HQ_MUSIC_Url]]></HQMusicUrl> <ThumbMediaId><! [CDATA[media_id]]></ThumbMediaId> </Music> </xml>Copy the code
parameter |
Whether must | instructions |
---|---|---|
ToUserName |
is |
Recipient account (OpenID received) |
FromUserName | is |
Developer wechat account |
CreateTime |
is |
Message creation time (integer) |
MsgType |
is |
The message type is music |
Title |
no |
Music title |
Description |
no |
Music to describe |
MusicURL |
no |
Music links |
HQMusicUrl |
no |
High quality music link, WIFI environment preferentially use this link to play music |
ThumbMediaId | is |
The media ID of the thumbnail, obtained by uploading the multimedia file through the interface in the Material management |
- Reply to graphic message
<xml> <ToUserName><! [CDATA[toUser]]></ToUserName> <FromUserName><! [CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><! [CDATA[news]]></MsgType> <ArticleCount>1</ArticleCount> <Articles> <item> <Title><! [CDATA[title1]]></Title> <Description><! [CDATA[description1]]></Description> <PicUrl><! [CDATA[picurl]]></PicUrl> <Url><! [CDATA[url]]></Url> </item> </Articles> </xml>Copy the code
parameter |
Whether must | instructions |
---|---|---|
ToUserName |
is |
Recipient account (OpenID received) |
FromUserName | is |
Developer wechat account |
CreateTime |
is |
Message creation time (integer) |
MsgType |
is |
The message type is news |
ArticleCount | is |
Number of text and text messages; When a user sends a text message, an image, a video message, a text message, or a location message, the developer can only reply to one text message. In other scenarios, a maximum of eight text messages can be replied |
Articles |
is |
Note that if the number of messages exceeds the limit, only the number of messages within the limit will be sent |
Title |
is |
Text message title |
Description |
is |
Text message description |
PicUrl |
is |
Image link, support JPG, PNG format, better effect for large picture 360200. Small picture 200200 |
Url |
is |
Click the text message jump link |
xml2js
Xml2js is a simple XML-to-javascript object converter that is officially used as follows:
var parseString = require('xml2js').parseString; var xml = "<root>Hello xml2js! </root>" parseString(xml, function (err, result) { console.dir(result); });Copy the code
More usage, also please give walk only www.npmjs.com/package/xml…
Node.js custom passive reply development
First, we need to configure routes to receive requests and data from the server.
App.post ("/", (req,res, next)=> {... })Copy the code
You need to use event listeners to monitor and control data;
App.post ("/", (req,res, next)=> {var buffer = [] req.on('data', (data) => { buffer.push(data) }) req.on('end', Var msgXml = buffer.concat (Buffer).toString(' utF-8 ')})})Copy the code
We first stored the binary data returned by wechat in the buffer array, and processed it into common XML data at the end of the request.
The problem is that Node.js can’t convert XML directly into Javascript objects, so we need the xml2js component to do this for us;
Var reply = require('./reply') req.on('end', () => {// convert data to UTF-8 format var msgXml = buffer.concat (Buffer).tostring (' utF-8 ') // Call parseString method of XML2JS module parseString(msgXml, { explicitArray: false }, (error, If (error) {console.log(error) return} result = result. XML // result. XML is the real data retrieved Reply (result, (resultXml) => {// Invoke the reply function res.send(resultXml)})})})......Copy the code
Result.xml, which contains ToUserName, FromUserName, etc…
There is one pit to watch out for!! Attention!!!!! Attention! Important things three times: The corresponding relationship of ToUserName and FromUserName obtained here is opposite to that of ToUserName and FromUserName in the submitted template. Result.xml. ToUserName should correspond to template data FromUserName, while result.xml.FromUserName corresponds to template data ToUserName.
In addition to the above part that needs to be added into app.js, I made two scripts for processing the reply function separately, namely reply.js and replytype. js. Replytype. js stores all involved templates. Assist reply.js to customize the reply;
Here’s the code in replytype.js:
Var request = require('./request') var request = require('./request') var request = require('./request') content) => { console.log('reply type text ! ') var xmlContent = '<xml><ToUserName><! [CDATA[' + result.FromUserName + ']]></ToUserName>' xmlContent += '<FromUserName><! [CDATA[' + result.ToUserName + ']]></FromUserName>' xmlContent += '<CreateTime>' + new Date().getTime() + '</CreateTime>' xmlContent += '<MsgType><! [CDATA[text]]></MsgType>' xmlContent += '<Content><! [CDATA[' + content + ']]></ content ></ XML >' return xmlContent} // exports.imgMsg = function (result, urlPath) callback) { uploadFile(urlPath, 'image').then((media_id) => { console.log('reply type image ! ', media_id) var xmlContent = '<xml><ToUserName><! [CDATA[' + result.FromUserName + ']]></ToUserName>' xmlContent += '<FromUserName><! [CDATA[' + result.ToUserName + ']]></FromUserName>' xmlContent += '<CreateTime>' + new Date().getTime() + '</CreateTime>' xmlContent += '<MsgType><! [CDATA[image]]></MsgType>' xmlContent += '<Image><MediaId><! [CDATA[' + media_id + ']]></MediaId></Image></ XML >' callback(xmlContent)})} // Echo exports.graphicmsg = (result, contentArr) => { console.log('reply type image and text ! ') var xmlContent = '<xml><ToUserName><! [CDATA[' + result.FromUserName + ']]></ToUserName>' xmlContent += '<FromUserName><! [CDATA[' + result.ToUserName + ']]></FromUserName>' xmlContent += '<CreateTime>' + new Date().getTime() + '</CreateTime>' xmlContent += '<MsgType><! [CDATA[news]]></MsgType>' xmlContent += '<ArticleCount>' + contentArr.length + '</ArticleCount>' xmlContent += '<Articles>' contentArr.map((item, index) => { xmlContent += '<item>' xmlContent += '<Title><! [CDATA[' + item.Title + ']]></Title>' xmlContent += '<Description><! [CDATA[' + item.Description + ']]></Description>' xmlContent += '<PicUrl><! [CDATA[' + item.PicUrl + ']]></PicUrl>' xmlContent += '<Url><! [CDATA[' + item.Url + ']]></Url>' xmlContent += '</item>' }) xmlContent += '</Articles></xml>' return xmlContent }Copy the code
As the image reply template in the above code needs to obtain media_id, it cannot be used independently in the development process. It needs to obtain the permission to use the material of the public account, that is, the uploadFile method in the above code, which I will explain later
All of the above code uses asynchronous functions except for simple text replies, so here we use callback methods to throw the final template to reply.js
Here’s another pitfall, where graphic replies have been restricted for some reason:
- A passive reply can reply to only one text message
- For the development of the public number (not the operation of the public number background operation and maintenance), passive response can not use the big picture, size map contrast figure
Replytype.js introduces the reply.js page as follows:
- The picture reply
Join (__dirname, 'custom image.jpg ') resultXml = replyType.imgMsg(result, urlPath, (resultXml) => { callback(resultXml) })Copy the code
- Text response
TextMsg (result, 'reply content ') callback(resultXml)Copy the code
- By reply
ResultXml = replyType.graphicMsg(result, contentArr) // contentArr is an array objectCopy the code
Use custom replies
Result. XML mentioned above not only contains ToUserName and FromUserName, but also contains user operation information:
result.xml.MsgType === 'event'
Indicates that a user event triggers, such asresult.xml.Event === 'subscribe'
Represents the user pays attentionresult.xml.Event === 'CLICK'
Indicates that the user operates through a custom menu itemresult.xml.EventKey
You can get a custom menukey
attribute
result.xml.MsgType === 'text'
Note The user is triggered by entering keywordsresult.xml.Content
Get the details of what the user entered
—
Upload the material and get the media_id
The materials here can be pictures, voice, etc. The official instructions are as follows:
- Request mode: POST
- Request address: https://api.weixin.qq.com/cgi-bin/media/upload?accesstoken=ACCESSTOKEN&type=TYPE
Media_id function uploadFile (urlPath, type) {return new Promise(resolve, reject) => { fs.readFile('./config.json', 'utf-8', (error, Data) => {if (error) {console.log('uploadFile read accessToken fail', error) return} var form = {// Create form media: fs.createReadStream(urlPath) } var url = 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token=' + JSON.parse(data).setAccessToken.accessToken + '&type=' + type request.post(url, form).then((result) => { resolve(JSON.parse(result).media_id) }) }) }) }Copy the code
My access_token is saved in config.json, so I first get it through fs.readFile, and then join the interface. The type in the interface is the temporary media file type that needs to be created. There are image, voice, video and thumb, which are mainly used for video and music formats.
Fs.createreadstream is used to get the file stream of the media file. Send a public id to the file stream in the form of the requested parameter. The server will return a string that is the media_id of the media file
That’s all for the notes on custom replies.
My data came from my blog site. At first, I used the WP-JSON interface file provided by WordPress, but later I modified the way of obtaining the interface for security reasons. At present, the data of my official account is obtained from the crawl site, and I will share the learning record about the Node crawl site later.
Still hope each guest officer can like!
The article has been synchronized with my personal blog: “Node wechat Public Account Development Custom Menu”.
Related articles:
- Node wechat public account development access public account
- Node wechat public account is developed to encapsulate request and obtain access_token
- Node wechat public account development custom menu
—
Reference:
- [official document of wechat Official Account]
- [wechat public platform interface debugging tool]
- [wechat public platform test account]
- [Node develops wechat public account (1) — access wechat public account]
- [Node develops wechat public account (2) — wechat reply]
- [Node develops wechat public account (3) — wechat menu]
- [Node develops wechat public account (4) — upload material]
This article is published by OpenWrite!