请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

正在回答 回答被采纳积分+3

10回答

Scott 2016-10-11 16:29:25

这也太没道理了,response.body 是  undefined 说明你用的 request 是比较老一点的版本对吧,把  request 卸载了 npm uninstall request,然后重新装一个 npm install request@latest --save 然后用 response.body 来拿到微信返回的 json 数据,打印出来看看

0 回复 有任何疑惑可以回复我~
Scott 2016-09-29 21:36:01

token 失效了,说明是更新或者获取 token 有问题,最新版的 request 应该是通过 response.body 来获取到 json 数据吧。


把 response[1] 和 response 都改成 var data =response.body 再试试看呢

0 回复 有任何疑惑可以回复我~
  • 提问者 慕神8321268 #1
    修改以后还是会出现错误QAQ,,提示‘Cannot read property 'expires_in' of undefined’
    回复 有任何疑惑可以回复我~ 2016-09-30 14:40:16
  • 提问者 慕神8321268 #2
    我将图附在了最下面,麻烦老师您看看~
    回复 有任何疑惑可以回复我~ 2016-09-30 14:41:49
  • 提问者 慕神8321268 #3
    老师我发现可能不是response的问题,我自己排查了一下在获取access_token生成URL就出现问题了,麻烦您帮我看一下代码,谢谢您~
    回复 有任何疑惑可以回复我~ 2016-09-30 15:54:15
提问者 慕神8321268 2016-10-06 11:11:59

https://img1.sycdn.imooc.com/szimg//57f5c0f10001095f16350952.jpg打印出来的DATA


0 回复 有任何疑惑可以回复我~
提问者 慕神8321268 2016-10-06 11:07:32

wechat.js

'use strict'

var Promise = require('bluebird')
var request=Promise.promisify(require('request'))//promise化 
var util = require('./util')
var fs=require('fs')

var prefix='https://api.weixin.qq.com/cgi-bin/'
var api={
 access_token: prefix + 'token?grant_type=client_credential',
 upload: prefix+'media/upload?'

}
 
function Wechat(opts){
 var that = this
 this.appID=opts.appID
 this.appSecret= opts.appSecret
 this.getAccessToken=opts.getAccessToken
 this.saveAccessToken=opts.saveAccessToken


//promise实现
 this.fetchAccessToken()

}

Wechat.prototype.fetchAccessToken = function(data) {

 var that=this
 //如果有效
 if(this.access_token&&this.expires_in){
  if(this.isValidAccessToken(this)){
   //console.log('data.access_token')
   //console.log(data.access_token)
   return Promise.resolve(this)
  }
 }
    //promise实现
 return this.getAccessToken()
   .then(function(data){
    try{
     
     data=JSON.parse(data)
     console.log('fetch_data::::::')
  console.log(data)
  console.log('fetch_accesstoken::::::'+data.access_token)
    }
    catch(e){
     return that.updateAccessToken()
    }

    if (that.isValidAccessToken(data)) {
     return Promise.resolve(data)
    }
    else{
     return that.updateAccessToken()
    }
   })
   .then(function (data) {

    that.access_token=data.access_token
    that.expires_in=data.expires_in

    //console.log(that.access_token)
    //console.log(that.expires_in)


    that.saveAccessToken(data)
    
    return Promise.resolve(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.access_token+'&appID='+appID+'&secret='+appSecret
    
    return new Promise(function(resolve,reject){
     //向服务器发起get请求
     request({url: url,json:true}).then(function(response){
  var data =response//修改
  


  var now =(new Date().getTime())
  var expires_in=now + (data.expires_in - 20)*1000

  data.expires_in=expires_in
        resolve(data)
 })

    })
 
}


Wechat.prototype.uploadMaterial = function(type,filepath) {//???data
 
    var that=this
 var form={
  media:fs.createReadStream(filepath)
 }
 

 //var appID= this.appID
 //var appSecret= this.appSecret
 
    
    return new Promise(function(resolve,reject){
     that
     .fetchAccessToken()
     .then(function(data){
      //console.log(data)
      //console.log(data.access_token)


      var url=api.upload+'access_token='+data.access_token+'&type='+type 
         console.log(url)
     //向服务器发起get请求
       request({method:'POST',url: url,formData:form,json:true}).then(function(response){
    var _data =response
    //console.log(response[1])
    //console.log("__________________________________________________________")
    //console.log(response.body)
   

    //console.log(_data)
    if(_data){
     resolve(_data)
    }
    else{
     throw new Error('upload material fails') 
    } 
  
  })
     .catch(function(err){
      reject(err)
     })


    })
})

}

Wechat.prototype.reply = function() {
 var content = this.body
 var message = this.weixin
 console.log(content);


 var xml = util.tpl(content,message)

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

module.exports=Wechat


0 回复 有任何疑惑可以回复我~
  • Scott #1
    if(_data){
         resolve(_data)
        }
        else{
         throw new Error('upload material fails') 
        } 
    
    这里写的不对啊,你是要把 data 返回出去,这个 data 是实际的 json 数据,不应该是 response 啊,也就是先 
    
    var data = response.body
    
    再 resolve(data)
    回复 有任何疑惑可以回复我~ 2016-10-06 16:02:31
  • 提问者 慕神8321268 回复 Scott #2
    对这块有问题,但是现在主要问题是能获取data,但拿不到data.access_token。现在把response改为response.body会报错。
    回复 有任何疑惑可以回复我~ 2016-10-09 14:20:22
  • Scott 回复 提问者 慕神8321268 #3
    改成 response.body 会报错,是什么错误,把 response.body 打印出来看看是什么值
    回复 有任何疑惑可以回复我~ 2016-10-10 18:20:56
提问者 慕神8321268 2016-10-05 10:21:16

response[1]部分在横线上方,

response.body 打印结果在横线下

https://img1.sycdn.imooc.com/szimg//57f463480001233b09710917.jpg

0 回复 有任何疑惑可以回复我~
  • Scott #1
    恩,那就是 response.body 是对的,用 response.body 吧,另外,
    
    Wechat.prototype.uploadMaterial = function(type,filepath) 
          console.log(data)
          console.log(data.access_token)
    
    这里的 console 的 data 是对的,但是 data.access_token 是 undefined,你再查查为什么通过 data 获取不到里面的 access_token ,是哪里代码写错了,还是 data 不是一个 json 对象呢
    回复 有任何疑惑可以回复我~ 2016-10-05 21:43:18
  • 提问者 慕神8321268 回复 Scott #2
    老师我一直在排查data的问题,但是还是没法找到,能麻烦您帮忙看看吗?我在最新回复中附上现在的代码。
    回复 有任何疑惑可以回复我~ 2016-10-06 11:06:05
提问者 慕神8321268 2016-09-30 15:52:46

我自己打印了一下,发现uploadMaterial能获取到data,但是无法得到票据access_token,不知道是什么原因,我将wechat的代码贴上来麻烦大神帮我看看~

'use strict'

var Promise = require('bluebird')
var request=Promise.promisify(require('request'))//promise化 
var util = require('./util')
var fs=require('fs')

var prefix='https://api.weixin.qq.com/cgi-bin/'
var api={
 access_token: prefix + 'token?grant_type=client_credential',
 upload: prefix+'media/upload?'

}
 
function Wechat(opts){
 var that = this
 this.appID=opts.appID
 this.appSecret= opts.appSecret
 this.getAccessToken=opts.getAccessToken
 this.saveAccessToken=opts.saveAccessToken


//promise实现
 this.fetchAccessToken()

}

Wechat.prototype.fetchAccessToken = function(data) {

 var that=this
 //如果有效
 if(this.access_token&&this.expires_in){
  if(this.isValidAccessToken(this)){
   return Promise.resolve(this)
  }
 }
    //promise实现
 return this.getAccessToken()
   .then(function(data){
    try{
     data=JSON.parse(data)
    }
    catch(e){
     return that.updateAccessToken()
    }

    if (that.isValidAccessToken(data)) {
     return promise.resolve(data)
    }
    else{
     return that.updateAccessToken()
    }
   })
   .then(function (data) {

    that.access_token=data.access_token
    that.expires_in=data.expires_in

    that.saveAccessToken(data)
    
    return Promise.resolve(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.access_token+'&appID='+appID+'&secret='+appSecret
    
    return new Promise(function(resolve,reject){
     //向服务器发起get请求
     request({url: url,json:true}).then(function(response){
  var data =response//修改
  //console.log(data)

  var now =(new Date().getTime())
  var expires_in=now + (data.expires_in - 20)*1000

  data.expires_in=expires_in
        resolve(data)
 })

    })
 
}


Wechat.prototype.uploadMaterial = function(type,filepath) {//???data
 
    var that=this
 var form={
  media:fs.createReadStream(filepath)
 }
 

 //var appID= this.appID
 //var appSecret= this.appSecret
 
    
    return new Promise(function(resolve,reject){
     that
     .fetchAccessToken()
     .then(function(data){
      console.log(data)
      console.log(data.access_token)


      var url=api.upload+'access_token='+data.access_token+'&type='+type 
         console.log(url)
     //向服务器发起get请求
       request({method:'POST',url: url,formData:form,json:true}).then(function(response){
    var _data =response
   

    //console.log(_data)
    if(_data){
     resolve(_data)
    }
    else{
     throw new Error('upload material fails') 
    }
  
  })
     .catch(function(err){
      reject(err)
     })


    })
})

}

Wechat.prototype.reply = function() {
 var content = this.body
 var message = this.weixin
 console.log(content);


 var xml = util.tpl(content,message)

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

module.exports=Wechat


0 回复 有任何疑惑可以回复我~
  • Scott #1
    return promise.resolve(data)
    
    promise 写成小写了,应该大写
    回复 有任何疑惑可以回复我~ 2016-09-30 17:15:26
  • 提问者 慕神8321268 回复 Scott #2
    谢谢老师~但是改成小写了还是无法获取到access_token.
    然后如果将response写成response.body则会出现" Cannot read property 'expires_in' of undefined"的错误
    回复 有任何疑惑可以回复我~ 2016-10-03 15:32:56
  • Scott 回复 提问者 慕神8321268 #3
    把 response.body 和 response[1] 都打印出来看下返回的数据格式是怎样的,'expires_in' of undefined" 就说明 data 是没有拿到
    回复 有任何疑惑可以回复我~ 2016-10-03 21:16:09
提问者 慕神8321268 2016-09-30 14:41:21

修改response之后出现的错误如图

https://img1.sycdn.imooc.com/szimg//57ee0903000193af08320673.jpg

0 回复 有任何疑惑可以回复我~
提问者 慕神8321268 2016-09-29 19:00:51

tpl.js

'use strict'

var ejs=require('ejs')//模板引擎
var heredoc=require('heredoc')

var tpl=heredoc(function () {/* 
<xml>

<ToUserName><![CDATA[<%= toUserName %>]]></ToUserName>

<FromUserName><![CDATA[<%= fromUserName %>]]></FromUserName>

<CreateTime><%= createTime %></CreateTime>


<MsgType><![CDATA[<%= msgType %>]]></MsgType>
<% if (msgType==='text') { %>

    <Content><![CDATA[<%= content %>]]></Content>
<% } else if (msgType==='image') { %>
  <Image>
    <MediaId><![CDATA[<%= content.mediaId %>]]></MediaId>
    </Image>
<% } else if (msgType==='voice') { %>
    <Voice>
    <MediaId><![CDATA[<%= content.mediaId %>]]></MediaId>
    </Voice>
<% } else if (msgType==='video') { %>
    <Video>
    <MediaId><![CDATA[<%= content.mediaId %>]]></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
}


0 回复 有任何疑惑可以回复我~
提问者 慕神8321268 2016-09-29 19:00:21

wechat.js

'use strict'

var Promise = require('bluebird')
var request=Promise.promisify(require('request'))//promise化 
var util = require('./util')
var fs=require('fs')

var prefix='https://api.weixin.qq.com/cgi-bin/'
var api={
 access_token: prefix + 'token?grant_type=client_credential',
 upload: prefix+'media/upload?'

}
 
function Wechat(opts){
 var that = this
 this.appID=opts.appID
 this.appSecret= opts.appSecret
 this.getAccessToken=opts.getAccessToken
 this.saveAccessToken=opts.saveAccessToken


//promise实现
 this.fetchAccessToken()

}

Wechat.prototype.fetchAccessToken = function(data) {

 var that=this
 //如果有效
 if(this.access_token&&this.expires_in){
  if(this.isValidAccessToken(this)){
   return Promise.resolve(this)
  }
 }
    //promise实现
 return this.getAccessToken()
   .then(function(data){
    try{
     data=JSON.parse(data)
    }
    catch(e){
     return that.updateAccessToken(data)
    }

    if (that.isValidAccessToken(data)) {
     return promise.resolve(data)
    }
    else{
     return that.updateAccessToken()
    }
   })
   .then(function (data) {

    that.access_token=data.access_token
    that.expires_in=data.expires_in

    that.saveAccessToken(data)
    
    return Promise.resolve(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.access_token+'&appID='+appID+'&secret='+appSecret
    
    return new Promise(function(resolve,reject){
     //向服务器发起get请求
     request({url: url,json:true}).then(function(response){
  var data =response//修改
  var now =(new Date().getTime())
  var expires_in=now + (data.expires_in - 20)*1000

  data.expires_in=expires_in
                resolve(data)
 })

    })
 
}


Wechat.prototype.uploadMaterial = function(type,filepath) {//???data
 
    var that=this
 var form={
  media:fs.createReadStream(filepath)
 }
 

 //var appID= this.appID
 //var appSecret= this.appSecret
 
    
    return new Promise(function(resolve,reject){
     that
     .fetchAccessToken()
     .then(function(data){

      var url=api.upload+'access_token='+data.access_token+'&type='+type 
     
     //向服务器发起get请求
       request({method:'POST',url: url,formData:form,json:true}).then(function(response){
    var _data =response[1]

    console.log(_data)
    if(_data){
     resolve(_data)
    }
    else{
     throw new Error('upload material fails') 
    }
  
  })
     .catch(function(err){
      reject(err)
     })

    })
})

}

Wechat.prototype.reply = function() {
 var content = this.body
 var message = this.weixin
 console.log(content);


 var xml = util.tpl(content,message)

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

module.exports=Wechat


0 回复 有任何疑惑可以回复我~
提问者 慕神8321268 2016-09-29 18:59:46

weixin.js

'use strict'

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

var wechatApi=new Wechat(config.wechat)

exports.reply=function*(next){
 var message = this.weixin

 if(message.MsgType==='event'){
  if (message.Event==='subscribe'){
   if(message.EventKey){
    console.log('扫描二维码'+message.EventKey+''+message.Ticket)
   }

   this.body='哈哈,你订阅了这个号\r\n'+'消息ID:'+message.MsgId
  }
  else if(message.Event==='unsubscribe'){
   console.log('无情取关')
   this.body(' ')
  
     }
     else if(message.Event==='LOCATION'){//定位
      this.body='您上报的地理位置是'+message.Latitude+'/'+message.Longitude+'-'+message.Precision
   
     }
     else if(message.Event==='CLICK'){
   this.body='您点了菜单: '+message.EventKey
  }

  else if(message.Event==='SCAN'){
   console.log('关注后扫二维码'+message.EventKey+' '+message.Ticket)
   this.body='看到你扫一下哦'
     }
     else if(message.Event==='VIEW'){
   this.body='您点击了菜单中的链接'+message.EventKey//菜单的URL地址
     }
 }
 else if (message.MsgType==='text'){
  var content=message.Content
  var reply='你说的'+message.Content+'太复杂了'
//回复策略
  if(content==='1'){
   reply='第一没有啊'
  }
  else if(content==='2'){
   reply='第二也没有啊'
  }
  else if(content==='3'){
   reply='第三还没有啊'
  }
  else if(content==='4'){//回复图文
   reply=[{
    title: '技术改变世界',
    description: '只是个描述',
    picUrl: 'http://a0.att.hudong.com/50/85/20300534894500139519859925271.jpg',
    url:'https://console.qcloud.com/cvm'
   }]
  }
  else if(content==='5'){
   var data=yield wechatApi.uploadMaterial('image',__dirname+'/2.jpg')
   reply={
    type:'image',
    mediaId: data.media_id

   }
   //console.log(reply)
  }

  this.body=reply
 }


 yield next
}


0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信