关注回复失败,命令行没有出现什么报错,但就是无法自动回复

来源:4-3 第四天 自动回复各种消息

落叶无痕

2016-07-24

appjs

var Koa=require('koa');
var path=require('path')
var wechat=require('./g');
var util=require('./util')
var wechat_file=path.join(__dirname,'./wechat.txt')
var config=require('./config')
var weixin=require('./weixin')
var app=new Koa();
app.use(wechat(config.wechat,weixin.reply));
app.listen(3000);

g.js

'use strict'
var getRawBody=require('raw-body');
var sha1=require('sha1');
var Wechat=require('./wechat')
var xmlopr=require('./xmlopr')
module.exports=function(opts){
		var wechat=new Wechat(opts)
		return function *(next){
			var that=this
			var token=opts.token
			var signature=this.query.signature
			var nonce=this.query.nonce
			var timestamp=this.query.timestamp
			var echostr=this.query.echostr
			var str=[token,timestamp,nonce].sort().join('')
			var sha=sha1(str)
			if(this.method==='GET'){
				if(sha===signature){
					this.body=echostr+""
				}else{
					this.body="cuode"
				}
			}
			else if(this.method==='POST'){
				if(sha!==signature){
					this.body="cuode"
					return false
				}
			var data=yield getRawBody(this.req,{
				length:this.length,
				limit:'1mb',
				encoding:this.charset
			})
			var content=yield xmlopr.parseXMLAsync(data)
			console.log(content);
			var message=xmlopr.formatMessage(content.xml);
			console.log(message);
			// if(message.MsgType==='event'){
			// 	if(message.Event==='subscribe'){
			// 		var now=new Date().getTime()
			// 		that.status=200
			// 		that.type='application/xml'
			// 		that.body=xml
					
			// 	}
			// }
			this.weixin=message;
			yield handler.call(this,next)
			wechat.reply.call(this)
			}

			
	}
}

wechat.js

'use strict'
var Promise=require('bluebird')
var request=Promise.promisify(require('request'))
var xmlopr=require('./xmlopr')
var prefix='https://api.weixin.qq.com/cgi-bin/'
var api={
	accessToken:prefix+'token?grant_type=client_credential'
}
function Wechat(opts){
	var  that=this
	this.appID=opts.appID
	this.appSecret=opts.appSecret
	this.getAccessToken=opts.getAccessToken
	this.saveAccessToken=opts.saveAccessToken

	return this.getAccessToken()
	.then(function(data){
		try{
			data=JSON.parse(data)
		}
		catch(e){
			return that.updateAccessToken()
		}
		if(that.isValidAccessToken){
			return Promise.resolve(data)
		}
		else{
			return that.updateAccessToken()
		}
	})
	.then(function(data){
		that.getAccessToken=data.access_token
		that.expires_in=data.expires_in
		that.saveAccessToken(data)
	})
}
Wechat.prototype.isValidAccessToken=function(data){
	if(!data||!data.access_token||!data.expires_in){
		return false
	}
	var access_token=data.access_token
	var expires_in=data.expires_in
	var now=(new Date().getTime())
	if(now<expires_in){
		return true
	}else{
		return false
	}
}
Wechat.prototype.updateAccessToken=function(data){
	var appID=this.appID
	var appSecret=this.appSecret
	var url=api.accessToken+'&appid='+appID+'&secret='+appSecret
   	return new Promise(function(resolve,reject){
   		request({url:url,json:true}).then(function(response){
   		var data=response.body
   		var now=(new Date().getTime())
   		var expires_in=now+(data.expires_in-20)*1000
   		data.expires_in=expires_in
   		resolve(data)
   })
   })
}
Wechat.prototype.reply=function(){
	var content=this.body;
	var message=this.weixin;
	var xml=xmlopr.tpl(content,message);
	this.status=200;
	this.type='application/xml';
	this.body=xml;

}
module.exports=Wechat;

tpl.js

'use strict'
var ejs=require('ejs');
var heredoc=require('heredoc');
var tpl=heredoc(function(){	/*
	<xml>
	<ToUserName><![CDATA[<%=toUserName %>]]></ToUserName>
	<FromUserName><![CDATA[<%= romUserName %>]]></FromUserName>
	<CreateTime><%=createTime %></CreateTime>
	<MsgType><![CDATA[<%=msgType %>]]></MsgType>
	<% if(msgType==='text'){%>
		<Content><![CDATA[<%=content%>]]></Content>
	<%}else if(msgType==='image'){%>
		<Image>
		<MediaId><![CDATA[<%=content.media_id %>]]></MediaId>
		</Image>
	<%}else if(msgType==='voice'){%>
		<Voice>
		<MediaId><![CDATA[<%= content.media_id %>]]></MediaId>
		</Voice>
	<%}else if(msgType==='video'){%>
		<Video>
		<MediaId><![CDATA[<%= content.media_id %>]]></MediaId>
		<Title><![CDATA[<%= content.title %>]]></Title>
		<Description><![CDATA[<%= content.description %>]]></Description>
		</Video> 
	<% } else if (msgType=== 'music') {%>
    <Music>
        <Title><![CDATA[<%= content.title %>]]></Title>
        <Description><![CDATA[<%= content.description %>]]></Description>
        <MusicUrl><![CDATA[<%= content.musicUrl %>]]></MusicUrl>
        <HQMusicUrl><![CDATA[<%= content.hqMusicUrl %>]]></HQMusicUrl>
        <ThumbMediaId><![CDATA[<%= content.thumbMediaId %>]]></ThumbMediaId>
    </Music>
	<%}else if(msgType==='news'){%>
		<ArticleCount><%=content.length %></ArticleCount>
		<Articles>
			<% content.forEach(function(item){%>
			<item>
			<Title><![CDATA[<%= item.title %>]]></Title> 
			<Description><![CDATA[<%= item.description %>]]></Description>
			<PicUrl><![CDATA[<% item.picurl %>]]></PicUrl>
			<Url><![CDATA[<%= item.url %>]]></Url>
			</item>
			<%})%>
		</Articles>
		<%}%>
	</xml>
	*/})
var compiled=ejs.compile(tpl);
exports=module.exports={
	compiled:compiled
}

xmlopr.js

'use strict'
var xml2js=require('xml2js')
var Promise=require('bluebird')
var tpl=require('./tpl')
exports.parseXMLAsync=function(xml){
	return new Promise(function(resolve,reject){
		xml2js.parseString(xml,{trim:true},function(err,content){
			if(err) reject(err)
			else resolve(content)
		})
	})

}
function formatMessage(result){
	var message={};
	if(typeof result==='object'){
		var keys=Object.keys(result);
		for(var i=0;i<keys.length;i++){
			var item=result[keys[i]];
			var key=keys[i];
			if(!(item instanceof Array)||item.length===0){
				continue
			}
			if(item.length==1){
				var val=item[0];
				if(typeof val==='object'){
					message[key]=formatMessage(val);
				}else{
					message[key]=(val||'').trim(); //拿掉首尾的空格
				}
			}else{
				message[key]=[];
				for(var f=0;f<item.length;f++){
					message[key].push(formatMessage(item[f]))
				}
			}
		}
	}
	return message;
}
exports.formatMessage=function(xml){
	return new Promise(function(resolve,reject){
		xml2js.parseString(xml,{trim:true},function(err,content){
			if(err) reject(err)
			else resolve(content)
		})
	})

}
exports.tpl=function(content,message){
	var info={};
	var type='text';
	var fromUserName=message.FromUserName;
	var toUserName=message.ToUserName;
	if(Array.isArray(content)){
		type='news'
	}
	type=content.type||type;
	info.content=content;
	info.createTime=new Date().getTime();
	info.msgType=type;
	info.toUserName=fromUserName;
	info.fromUserName=toUserName;
	return tpl.compiled(info)
}
exports.formatMessage=formatMessage;

weixin.js

'use strict'
exports.reply=function *(next){
	var message=this.weixin;
	console.log(message);
	if(message.MsgType==='event'){
		if(message.Event==='subscribe'){
			if(message.EventKey){
				console.log("扫二维码进来");
			}
			this.body='哈哈哈';
		}
		else if(message.Event==='unsubscribe'){
			console.log('取消关注');
			this.body='取消关注';
		}
	}else{

	}
	yield next;
}


写回答

4回答

五月君

2016-12-25

把你的xml 打印出来看看 应该是ejs模板那块没显示出来

1
0

落叶无痕

提问者

2016-07-25

这个有点奇怪,昨天是没有报错的,但是今天一运行昨天的代码就报错了,修改了几个地方就可以正常回复了


1
2
elewei
修改哪个地方 ?
2017-08-01
共2条回复

落叶无痕

提问者

2016-08-15

直接修改了一下端口号,一运行,就有报错的信息出来,修改一下就可以了。不知道你们可不可以。

0
0

PaulDing

2016-08-15

我也遇到一样的问题,解决了吗?求教

0
0

7天搞定Node.js微信公众号

Koa框架、ES2015新特性、MongoDB,开发微信公众号

1742 学习 · 787 问题

查看课程