NodeJS实现微信公众号关注后自动回复功能
一实先自动回复功能的逻辑步骤
1处理POST类型的控制逻辑,接收XML的数据包;
2解析XML数据包(获得数据包的消息类型或者是事件类型);
3拼装我们定义好的消息;
4包装成XML格式;
5在5秒内返回回去
二代码实操
本节代码参照上节课继续修改和完善,目录结构跟之前相同,新引入的模块raw-body使用npminstall安装一下即可,app.js启动文件和util.js不做变动,主要修改一下generator.js文件,以及在generator.js同级目录下新建wechat.js文件和tools.js文件。
wechat.js文件是将前一节generator.js文件中票据部分的代码抽离出来单独放在一个文件中,具体代码如下:
'usestrict';
//引入模块
varPromise=require('bluebird');
varrequest=Promise.promisify(require('request'));
//增加url配置项
varprefix='https://api.weixin.qq.com/cgi-bin/';
varapi={
accessToken:prefix+'token?grant_type=client_credential'
};
//利用构造函数生成实例完成票据存储逻辑
functionweChat(opts){
varthat=this;
this.appID=opts.appID;
this.appSecret=opts.appSecret;
this.getAccessToken=opts.getAccessToken;
this.saveAccessToken=opts.saveAccessToken;
//获取票据的方法
this.getAccessToken()
.then(function(data){
//从静态文件获取票据,JSON化数据,如果有异常,则尝试更新票据
try{
data=JSON.parse(data);
}catch(e){
returnthat.updateAccessToken();
}
//判断票据是否在有效期内,如果合法,向下传递票据,如果不合法,更新票据
if(that.isValidAccessToken(data)){
Promise.resolve(data);
}else{
returnthat.updateAccessToken();
}
})
//将拿到的票据信息和有效期信息存储起来
.then(function(data){
//console.log(data);
that.access_token=data.access_token;
that.expires_in=data.expires_in;
that.saveAccessToken(data);
})
};
//在weChat的原型链上增加验证有效期的方法
weChat.prototype.isValidAccessToken=function(data){
//进行判断,如果票据不合法,返回false
if(!data||!data.access_token||!data.expires_in){
returnfalse;
}
//拿到票据和过期时间的数据
varaccess_token=data.access_token;
varexpires_in=data.expires_in;
//获取当前时间
varnow=(newDate().getTime());
//如果当前时间小于票据过期时间,返回true,否则返回false
if(now
generator.js文件进行精简后,添加判断对xml数据的格式化方法以及判断事件,添加关注事件测试信息,具体代码如下:
'usestrict';
//引入模块
varsha1=require('sha1');
vargetRawBody=require('raw-body');
varweChat=require('./wechat');
vartools=require('./tools');
//建立中间件函数并暴露出去
module.exports=function(opts){
//实例化weChat()函数
//varwechat=newweChat(opts);
returnfunction*(next){
//console.log(this.query);
varthat=this;
vartoken=opts.token;
varsignature=this.query.signature;
varnonce=this.query.nonce;
vartimestamp=this.query.timestamp;
varechostr=this.query.echostr;
//进行字典排序
varstr=[token,timestamp,nonce].sort().join('');
//进行加密
varsha=sha1(str);
//使用this.method对请求方法进行判断
if(this.method==='GET'){
//如果是get请求判断加密后的值是否等于签名值
if(sha===signature){
this.body=echostr+'';
}else{
this.body='wrong';
};
}elseif(this.method==='POST'){
//如果是post请求也是先判断签名是否合法如果不合法直接返回wrong
if(sha!==signature){
this.body='wrong';
returnfalse;
};
//通过raw-body模块可以把把this上的request对象也就是http模块中的request对象去拼装它的数据最终拿到一个buffer的xml数据
//通过yield关键字获取到post过来的原始的XML数据
vardata=yieldgetRawBody(this.req,{
length:this.length,
limit:'1mb',
encoding:this.charset
});
//console.log(data.toString());打印XML数据(当微信公众号有操作的时候终端可以看到返回的XML数据)
//tools为处理XML数据的工具包使用tools工具包的parseXMLAsync方法把XML数据转化成数组对象
varcontent=yieldtools.parseXMLAsync(data);
//console.log(content);打印转化后的数组对象
//格式化content数据为json对象
varmessage=tools.formatMessage(content.xml);
console.log(message);
//打印message
//判断message的MsgType如果是event则是一个事件
if(message.MsgType==='event'){
//如果是订阅事件
if(message.Event==='subscribe'){
//获取当前时间戳
varnow=newDate().getTime();
//设置回复状态是200
that.status=200;
//设置回复的类型是xml格式
that.type='application/xml';
//设置回复的主体
that.body=''+
' '+
' '+
''+now+' '+
' '+
' '+
' ';
return;
}
}
}
}
};
tools.js是处理XML数据的工具文件:
'usestrict';
//引入模块
varxml2js=require('xml2js');
varPromise=require('bluebird');
//导出解析XML的方法
exports.parseXMLAsync=function(xml){
returnnewPromise(function(resolve,reject){
xml2js.parseString(xml,{trim:true},function(err,content){
if(err){
reject(err);
}else{
resolve(content);
};
});
});
};
//因为value值可能是嵌套多层的所以先对value值进行遍历
functionformatMessage(result){
//声明空对象message
varmessage={};
//对result类型进行判断
if(typeofresult==='object'){
//如果是object类型通过Object.keys()方法拿到result所有的key并存入keys变量中
varkeys=Object.keys(result);
//对keys进行循环遍历
for(vari=0;i
完成这节的代码后,当关注微信测试公众号的时候,会自动回复『你好,同学!』的提示信息。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。