當(dāng)準(zhǔn)備工作完成的時(shí)候裙士,先來(lái)一個(gè)簡(jiǎn)單的功能究珊,回復(fù)一個(gè)固定的消息,大致就是當(dāng)用戶(hù)關(guān)注該公眾號(hào)的時(shí)候,公眾號(hào)會(huì)回復(fù)一則文本消息膀钠。
在開(kāi)始之前呢,首先概述一下這篇文章的重點(diǎn)症副,第一启泣,公眾號(hào)的取消、關(guān)注亿蒸、用戶(hù)發(fā)送的內(nèi)容都是POST請(qǐng)求凑兰;第二,公眾號(hào)發(fā)送的內(nèi)容不是json格式边锁,而是xml格式姑食,是不是有點(diǎn)腦殼疼;第三砚蓬,返回給用戶(hù)的消息格式也是xml格式矢门。
在這里,我采用raw-body及xml2js模塊來(lái)將xml數(shù)據(jù)格式轉(zhuǎn)換為json灰蛙。
//g.js部分代碼
const sha1=require('sha1');
const getRawBody=require('raw-body');
const util=require('./util');
module.exports=function(opts){
var wechat=new WeChat(opts);
return async function(ctx){
const signature=ctx.query.signature,
timestamp=ctx.query.timestamp,
nonce=ctx.query.nonce,
token=opts.token;
//字典排序
const str=[token,timestamp,nonce].sort().join('');
const result=sha1(str);
if(result===signature){
if(ctx.request.method==="GET"){
ctx.body=ctx.query.echostr;
}else if(ctx.request.method==="POST"){
try{
var data=await getRawBody(ctx.req,{
length: ctx.request.length,
limit: "1mb",
encoding: ctx.request.charset
});
var content=await util.parseXMLAsync(data);
console.log(content);
}catch(err){
console.log(err);
}
}
}else{
ctx.body={
code:-1,
msg:"fail"
}
}
}
}
//util.js部分代碼
var xml2js=require('xml2js');
exports.parseXMLAsync=function(xml){
return new Promise((resolve,reject)=>{
xml2js.parseString(xml,{trim:true},function(err,content){
if(err){
reject(err);
}
resolve(content);
});
});
}
當(dāng)我關(guān)注公眾號(hào)的時(shí)候祟剔,可以發(fā)現(xiàn)控制臺(tái)打印結(jié)果如下圖所示:
很容易發(fā)現(xiàn)這個(gè)數(shù)據(jù)仍然不是最終想要的json格式,因?yàn)樗拿恳粋€(gè)值都是個(gè)數(shù)組格式摩梧,所以需要再在util.js當(dāng)中增加一個(gè)方法來(lái)將這種數(shù)據(jù)轉(zhuǎn)換為需要的格式物延。
function formatMessage(result){
var message={};
if(typeof result ==='object'){
var keys=Object.keys(result);
for(let i=0;i<keys.length;i++){
var item=result[keys[i]];
var key=keys[i];
if(!(item instanceof Array) || item.length===0){
continue;
}
else if(item.length===1){
var val=item[0];
if(typeof val === 'object'){
messgae[key]=formatMessage(val);
}else{
message[key]=(val || '').trim();
}
}
else{
message[key]=[];
for(var j=0,k=item.length;j<k;j++){
message[key].push(formatMessage(item[j]));
}
}
}
}
return message;
}
exports.formatMessage=formatMessage
最后就是返回消息內(nèi)容了,具體的返回格式可參考公眾號(hào)官方文檔仅父。
if(result===signature){
if(ctx.request.method==="GET"){
ctx.body=ctx.query.echostr;
}else if(ctx.request.method==="POST"){
try{
var data=await getRawBody(ctx.req,{
length: ctx.request.length,
limit: "1mb",
encoding: ctx.request.charset
});
var content=await util.parseXMLAsync(data);
var message=util.formatMessage(content.xml);
if(message.MsgType==='event'){
if(message.Event==='subscribe'){//關(guān)注
var now = Date.parse(new Date())/1000;
ctx.type='application/xml';
var reply=`<xml>
<ToUserName><![CDATA[${message.FromUserName}]]></ToUserName>
<FromUserName><![CDATA[${message.ToUserName}]]></FromUserName>
<CreateTime>${now}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[終于等到你叛薯,還好我沒(méi)放棄浑吟,歡迎關(guān)注lk儒家測(cè)試公眾號(hào)!]]></Content>
</xml>`;
ctx.body=reply;
}
}
}catch(err){
console.log(err);
}
}
}else{
ctx.body={
code:-1,
msg:"fail"
}
}