回复图片失败

来源:

oog

2016-10-13

老师你好,我感觉我每部都做对了,但是图片在微信客户端就是接受不到。 现在我图文,一般的消息都能成功回复出去,就是5的图不行。输出结果如下图

upload url:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=BOYIN9M57YLPbIgQEwM8M1tvnYfAvlxAVtHlJS-SAvrRoZ0q9TI35GBBA423G_rljKOgWf_64o7mAKSQQDOK_CTcXwzdd4UYZnweDcpC9S8eX0Yc8SQlnk11Zj9inRcCTFWcACAXJA&type=image
upload success:{"statusCode":200,"body":{"type":"image","media_id":"KMCavjDjR2piKM8Hk7QSXkKPLUttNdy1Vk5Dt5rk6u7gk2sWuy61rpHT_bB8mzRH","created_at":1476290700},"headers":{"connection":"close","content-type":"text/plain","date":"Wed, 12 Oct 2016 16:45:00 GMT","content-length":"118"},"request":{"uri":{"protocol":"https:","slashes":true,"auth":null,"host":"api.weixin.qq.com","port":443,"hostname":"api.weixin.qq.com","hash":null,"search":"?access_token=BOYIN9M57YLPbIgQEwM8M1tvnYfAvlxAVtHlJS-SAvrRoZ0q9TI35GBBA423G_rljKOgWf_64o7mAKSQQDOK_CTcXwzdd4UYZnweDcpC9S8eX0Yc8SQlnk11Zj9inRcCTFWcACAXJA&type=image","query":"access_token=BOYIN9M57YLPbIgQEwM8M1tvnYfAvlxAVtHlJS-SAvrRoZ0q9TI35GBBA423G_rljKOgWf_64o7mAKSQQDOK_CTcXwzdd4UYZnweDcpC9S8eX0Yc8SQlnk11Zj9inRcCTFWcACAXJA&type=image","pathname":"/cgi-bin/media/upload","path":"/cgi-bin/media/upload?access_token=BOYIN9M57YLPbIgQEwM8M1tvnYfAvlxAVtHlJS-SAvrRoZ0q9TI35GBBA423G_rljKOgWf_64o7mAKSQQDOK_CTcXwzdd4UYZnweDcpC9S8eX0Yc8SQlnk11Zj9inRcCTFWcACAXJA&type=image","href":"https://api.weixin.qq.com/cgi-bin/media/upload?access_token=BOYIN9M57YLPbIgQEwM8M1tvnYfAvlxAVtHlJS-SAvrRoZ0q9TI35GBBA423G_rljKOgWf_64o7mAKSQQDOK_CTcXwzdd4UYZnweDcpC9S8eX0Yc8SQlnk11Zj9inRcCTFWcACAXJA&type=image"},"method":"Post","headers":{"accept":"application/json","content-type":"multipart/form-data; boundary=--------------------------178037158051642397238963","content-length":443239}}}
here?
reply content:<xml>
<ToUserName><![CDATA[oxk0wvwjhJ-UhGr2CGND-VYrgIt0]]></ToUserName>
<FromUserName><![CDATA[gh_0628f885df72]]></FromUserName>
<CreateTime>1476290700742</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[KMCavjDjR2piKM8Hk7QSXkKPLUttNdy1Vk5Dt5rk6u7gk2sWuy61rpHT_bB8mzRH]]></MediaId>
</Image>
</xml>

基于以上您可以看到,我上传是图片是成功的,返回的body中也包含了和上传一样的mediaid,并且返回的数据也和微信接口要求的一样。

这边还请您给予指导

下面是wechat.js

'use strict'


var Promise = require('bluebird');
var request = Promise.promisify(require('request'));
var util = require('../lib/util');
var fs = require('fs');
var prefix = 'https://api.weixin.qq.com/cgi-bin/';
var grant_type = 'client_credential';


//grant_type=client_credential&appid=APPID&secret=APPSECRET
function Wechat(opts){
	var that = this;
	this.appID = opts.appID;
	this.appsecret = opts.appsecret;
	this.getAccessToken = opts.getAccessToken;
	this.saveAccessToken = opts.saveAccessToken;  
	//初始化的过程中就去把token拿到
	this.fetchAccessToken()
}

//取得Access token
Wechat.prototype.fetchAccessToken = function (data){
	var that = this;
	//console.log('fetch this:'+that)
	//先检查有没有合法的token,如果有的话直接返回
   if (this.access_token && this.expires_in){
        if (this.validateAccessToken(this)){
            return Promise.resolve(this.access_token)
        }
    }



	// if(this.validateAccessToken(that)){
	// 	console.log('valid')
	// 	return  Promise.resolve(that.access_token);
	// }
	//console.log('should valid')
		//get 方法是去读写在本地的token,如果本地的不好使了,那么调用update方法去微信服务器交换
	return that.getAccessToken()
			 .then(function(data){
				try{
					data = JSON.parse(data);
				}
				catch(e){
					return that.updateAccessToken();
				}
				if(that.validateAccessToken(data)){
					console.log('data:2'+some)
					return Promise.resolve(data);
				}
				else{
					//var some = JSON.stringify(data);
					//console.log('data:2'+some)
					return that.updateAccessToken();
				}
			}).then( function(data){
				that.access_token = data.access_token;
				that.expires_in = data.expires_in;
				that.saveAccessToken(data);
				//返回token
				return Promise.resolve(data.access_token);
			})
	
}

Wechat.prototype.validateAccessToken = function (data){
	var some = JSON.stringify(data);
	console.log("some"+some);

	if(!data || !data.access_token || data.expires_in){
		return false
	}
	console.log("what");
	var access_token = data.access_token;
	var expires_in = data.expires_in;
	var curTime = (new Date().getTime());
	//console.log("time"+curTime);
	//1476293619539
	if(curTime < expires_in){
		return true;
	}else{
		return false;
	}
}

//上传材料
Wechat.prototype.uploadMaterial = function (type,filePath){
	var that  = this
	//console.log('this1:'+this)
	console.log('readfile path:'+filePath)
	var formData = {
			media: fs.createReadStream(filePath)	
		}
	return new Promise(function (resolve, reject){
		//console.log('this2:'+this)
		 that
		.fetchAccessToken()
		.then(function(data){
			//console.log('that:'+data)
			var method = 'upload';
			var access_token = data;
			var type = type;


			var url = prefix+'media/'+method+'?'+'access_token='+access_token+'&type='+'image';
			console.log('upload url:'+url);

			request({method: 'Post',url: url,formData: formData,json: true })
				.then( function(response){
				//response contains full response of request
				//console.log(response);
				//console.log('request success:'+response.created_at);

				var uploadc = JSON.stringify(response)
				console.log('upload success:'+uploadc);

				var _data = response;
				//console.log(data);
				if(_data){
					resolve(_data);
				}else{
					throw new Error('upload uploadMaterial failed')
				}
			})
			.catch(function(err){
				reject(err);
			})
		})
	})
}


Wechat.prototype.updateAccessToken = function (){
	//console.log('upade')
	var url = prefix+'token?'+'grant_type='+grant_type+'&appid='+this.appID+'&secret='+this.appsecret;

	return new Promise(function (resolve, reject){

		request({url:url, json: true }).then( function(response){
			//response contains full response of request
			//console.log(response);
			var data = response;
			var result = {
				access_token:'',
				expires_in:'',
			}
			//console.log(data);
			var curTime = (new Date().getTime());
			var expires_in = curTime + (data.body.expires_in - 20) * 1000;
			result.expires_in = expires_in;
			result.access_token = data.body.access_token;

			resolve(result);
		})
	})
}

Wechat.prototype.reply = function (){
	
		var content = this.body;
		var message = this.weixinData;
		//提取模板处理数据
		var xml = util.tplM(content, message);

		console.log('reply content:'+xml);

		this.status = 200 
		this.type ='application/xml'
		this.body = xml
}


module.exports = Wechat;


我reply里面打印出来了输出消息包,正如你在shell输出里面看到的,消息没问题。

下面是回复的js

'use strict'

//实现微信的依据状况的 -- 消息路由

var config = require('../config/config')
var Wechat = require('../wechat/wechat')

var wechatApi = new Wechat(config.wechat);
var path = require('path')

exports.reply = function *(next){

	 var message = this.weixinData;

	 //console.log('message:'+message.Event);	 
	  //console.log('message event EventKey:'+message.EventKey);	
	 if(message.MsgType ==='event'){
	 	if(message.Event ==='subscribe'){
	 		if(message.EventKey){
	 			console.log('扫描二维码而来:'+message.Eventkey+''+message.ticket)
	 		}
	 		this.body = '宝贝你好,请输入:1,2,3,4其中之一 ';
	 	}else if(message.Event ==='unsubscribe'){
	 			console.log('撒有哪啦');
	 		this.body ='无情取消关注'
	 	}else if(message.Event ==='LOCATION'){
	 		this.body = '你的位置是:'+ message.Latitude+'/'+message.Longtitude+'-'+message.EventKey;

	 	}else if(message.Event ==='CLICK'){
	 		this.body = '您点击了菜单:'+message.EventKey;

	 	}else if(message.Event ==='SCAN'){
	 		this.body = '谢谢扫描';
	 	}

	 }else if (message.MsgType === 'text') {
	 		var content = message.Content;
	 		var reply = '你说的太复杂了:'+message.Content;

	 		if(content ==='1'){
	 			reply ='陆总你好'
	 		}else if(content == '2'){
	 			reply = '陆总你好2'
	 		}else if(content == '3'){
	 			reply = '陆总我睡了'
	 		}
	 		else if(content == '4'){
	 			reply = [{
	 				title:'电音之王',
	 				description:'欢迎来到电音之王的世界',
	 				picUrl:'http://img.xiami.net/images/collect/772/72/42220772_1425550553_vLXZ.jpg',
	 				url:'www.baidu.com'
	 			},{
	 				title:'你好陆总',
	 				description:'欢迎来到电音之王的世界哈哈',
	 				picUrl:'http://img.xiami.net/images/collect/772/72/42220772_1425550553_vLXZ.jpg',
	 				url:'www.baidu.com'
	 			}]
	 		}
	 		else if(content == '5'){
	 			//console.log('5+0')
	 			var newpath = path.join(__dirname,'../config/aimage.jpg')
	 			var uploadImage = yield wechatApi.uploadMaterial('image',newpath)
	 			//console.log('5+1')
	 			//console.log("id:"+show);
	 			reply = {
	 				type: 'image',
	 				mediaId: uploadImage.body.media_id
	 			}
	 		}
	 		
	 		this.body = reply
	 }
	 //console.log('A')
	 yield next
	 // console.log('B')
}

再下面是g.js

'use strict'


var sha1 = require('sha1');
var Promise = require('bluebird');
//var request = Promise.promisify(require('request'));
var Wechat = require('./wechat');
var getRawBody = require('raw-body');
var util = require('../lib/util');

module.exports = function(opts, handler){
	//实例化一个和wechat交互的对象
	var wechat = new Wechat(opts);

	return function *(next){//这个地方怎么用的还需要继续学习


		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(sha === signature){
			if(this.method === 'GET'){
				this.body = echostr +'';
				//console.log('this is a get method');
			}else if(this.method === 'POST'){
				var data  = yield getRawBody(this.req, {
					length: this.length,
					limit: '1mb',
					encoding:this.charset
				})
				 data = yield util.parseXMLAsync(data);
				// console.log(data);
				 //console.log('data.xml:'+data.xml)
				// console.log('G')
				 data = yield util.formatMessage(data.xml);
				 //console.log(data);

				 this.weixinData = data;

				 //用外面传进来的weixinhandler处理具体的回复内容

				 //这个地方传入 next的目的?
				 //console.log('D')
				 yield handler.reply.call(this, next); 

				 wechat.reply.call(this);
				 //解析请求,回复完毕后,处理回复的路由

				 
			}
		}else{
			this.body = 'wrong';
		}
	}

}


写回答

2回答

Scott

2016-10-13

好神奇,看代码,也没看出毛病。


打印出来的 xml 看着也没问题,但是这个 xml 应该是没有被正确回复给微信公众号,比如再发请求的时候断了,或者是测试公众号服务异常,或者是图片 id 不合法,或者是临时素材上传拿到的 id 服务器识别有问题,好吧,这大概是我能想到的可能性了,你切换到手机 4G 用笔记本连上手机 4G,在测试看看呢

0
2
oog
非常感谢!
2016-10-22
共2条回复

oog

提问者

2016-10-13

对了微信中显示 该公众号暂时无法提供服务,请稍后再试

0
4
oog
回复
Scott
老师见楼上
2016-10-13
共4条回复

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

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

1742 学习 · 787 问题

查看课程