请稍等 ...
×

采纳答案成功!

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

正在回答 回答被采纳积分+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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
'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的代码贴上来麻烦大神帮我看看~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
'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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
'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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
'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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
'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下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号