wechat 0.6.5 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e173474b91515c5b98160ebcf2e88c307b7a0c7
4
- data.tar.gz: 24e1eeb02200389eb39fe1aa89a0e6dd87cfeda8
3
+ metadata.gz: 38d17166a10c49de46d4e87c787b0869163e13d3
4
+ data.tar.gz: 3c80f22d8adc8219c4e0b32824d2df63269a6aa6
5
5
  SHA512:
6
- metadata.gz: deff7d137bfcf8e9ff9c9e5102fae2639289edb58c5a3d426d32190df1e1e860d83a9a9faec2e858cdb7258580408dd0d38824416735ea7ce22ae7fb0d0ea9fa
7
- data.tar.gz: 88485947385312824105e5d4a1a444fb45b8ddfdb377d24283ef463d848c96e0c9dda87c1998f57dea91ca934c4fd70ff2f3f2826d1c35d9554279987842be5d
6
+ metadata.gz: bf6b9c04a09cc228db3366c6b311731404af1a2e01581c5602d96897be3a3ddb3b52d9e0c3e4013c6307bc135f3ba8db7b85ecfa3f8880f3b9a5179e8c933619
7
+ data.tar.gz: d1091b3c0c44c974c42c9e88a16eadcf256d00c4108c527dc9b3969e24f22e4b7d24a559cf3f61779a09a5bbee90cdd744aa60f4d9522ee5ecb33e4239caa732
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.6.6 (released at 12/15/2015)
4
+
5
+ * Add jsapi_ticket support for Enterprise Account
6
+ * Default generated WechatsController < ActionController::Base, as many Rails application may having #authenticate_user or #set_current_user in ApplicationController, so easily affect the first time using experience.
7
+ * New syntax `on :view, with: 'VIEW_URL'` support.
8
+ * New command `upload_replaceparty` which combine three sub command to make uploading department easier.
9
+ * New command `upload_replaceuser` which combine three sub command to make uploading user easier.
10
+
3
11
  ## v0.6.5 (released at 11/24/2015)
4
12
 
5
13
  * Handle 48001 error if token is expire/not valid, close #71
data/README.md CHANGED
@@ -10,7 +10,11 @@ WeChat gem 可以帮助开发者方便地在Rails环境中集成微信[公众平
10
10
  - [微信JS-SDK](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BE%AE%E4%BF%A1JS%E6%8E%A5%E5%8F%A3) config接口注入权限验证
11
11
  - OAuth 2.0认证机制
12
12
 
13
- 命令行工具`wechat`可以调用各种无需web环境的API。同时也提供了Rails Controller的responder DSL, 可以帮助开发者方便地在Rails应用中集成微信的消息处理机制。如果你的App还需要集成微信OAuth2.0, 你可以考虑[omniauth-wechat-oauth2](https://github.com/skinnyworm/omniauth-wechat-oauth2), 以便和devise集成,提供完整的用户认证。
13
+ 命令行工具`wechat`可以调用各种无需web环境的API。同时也提供了Rails Controller的responder DSL, 可以帮助开发者方便地在Rails应用中集成微信的消息处理机制。
14
+
15
+ 如果你的App还需要集成微信OAuth2.0, 你可以考虑[omniauth-wechat-oauth2](https://github.com/skinnyworm/omniauth-wechat-oauth2), 以便和devise集成,提供完整的用户认证。
16
+
17
+ 如果你对如何制作微信网页UI没有灵感,可以参考官方的[weui](https://github.com/weui/weui),针对Rails的Gem是[weui-rails](https://github.com/Eric-Guo/weui-rails)。
14
18
 
15
19
 
16
20
  ## 安装
@@ -106,6 +110,7 @@ default: &default
106
110
  access_token: "C:/Users/[user_name]/wechat_access_token"
107
111
  token: ""
108
112
  encoding_aes_key: ""
113
+ jsapi_ticket: "C:/Users/[user_name]/wechat_jsapi_ticket"
109
114
 
110
115
  production:
111
116
  corpid: <%= ENV['WECHAT_CORPID'] %>
@@ -115,6 +120,7 @@ production:
115
120
  token: <%= ENV['WECHAT_TOKEN'] %>
116
121
  skip_verify_ssl: false
117
122
  encoding_aes_key: <%= ENV['WECHAT_ENCODING_AES_KEY'] %>
123
+ jsapi_ticket: <%= ENV['WECHAT_JSAPI_TICKET'] %>
118
124
 
119
125
  development:
120
126
  <<: *default
@@ -136,7 +142,7 @@ Wechat服务器有报道曾出现[RestClient::SSLCertificateNotVerified](http://
136
142
  在个别情况下,单个Rails应用可能需要处理来自多个账号的消息,此时可以配置多个responder controller。
137
143
 
138
144
  ```ruby
139
- class WechatFirstController < ApplicationController
145
+ class WechatFirstController < ActionController::Base
140
146
  wechat_responder appid: "app1", secret: "secret1", token: "token1", access_token: Rails.root.join("tmp/access_token1")
141
147
 
142
148
  on :text, with:"help", respond: "help content"
@@ -230,8 +236,6 @@ Wechat commands:
230
236
  wechat menu_create [MENU_YAML_PATH] # 创建菜单
231
237
  wechat menu_delete # 删除菜单
232
238
  wechat message_send [OPENID, TEXT_MESSAGE] # 发送文字消息
233
- wechat qrcode_create_limit_scene [SCENE_ID_OR_STR] # 请求永久二维码
234
- wechat qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS] # 请求临时二维码
235
239
  wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
236
240
  wechat tag [TAG_ID] # 获取标签成员
237
241
  wechat tag_add_department [TAG_ID, PARTY_IDS] # 增加标签部门
@@ -243,6 +247,8 @@ Wechat commands:
243
247
  wechat tag_update [TAG_ID, TAGNAME] # 更新标签名字
244
248
  wechat tags # 获取标签列表
245
249
  wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
250
+ wechat upload_replaceparty [BATCH_PARTY_CSV_PATH] # 上传文件方式全量覆盖部门
251
+ wechat upload_replaceuser [BATCH_USER_CSV_PATH] # 上传文件方式全量覆盖成员
246
252
  wechat user [OPEN_ID] # 获取用户基本信息
247
253
  wechat user_batchdelete [USER_ID_LIST] # 批量删除成员
248
254
  wechat user_delete [USER_ID] # 删除成员
@@ -398,7 +404,7 @@ $ wechat template_message oCfEht9oM*********** template.yml
398
404
  然后创建Controller class, 例如
399
405
 
400
406
  ```ruby
401
- class WechatsController < ApplicationController
407
+ class WechatsController < ActionController::Base
402
408
  wechat_responder
403
409
 
404
410
  # 默认文字信息responder
@@ -459,6 +465,11 @@ class WechatsController < ApplicationController
459
465
  request.reply.text "User: #{request[:FromUserName]} click #{key}"
460
466
  end
461
467
 
468
+ # 当用户点击菜单时
469
+ on :view, with: 'http://wechat.somewhere.com/view_url' do |request, view|
470
+ request.reply.text "#{request[:FromUserName]} view #{view}"
471
+ end
472
+
462
473
  # 处理图片信息
463
474
  on :image do |request|
464
475
  request.reply.image(request[:MediaId]) #直接将图片返回给用户
@@ -533,7 +544,8 @@ end
533
544
  - :video 响应视频消息
534
545
  - :link 响应链接消息
535
546
  - :event 响应事件消息, 可以用`:with`参数来匹配事件类型
536
- - :click 虚拟响应事件消息, 微信仍然传入:event,但gem内部会单独处理
547
+ - :click 虚拟响应事件消息, 微信传入:event,但gem内部会单独处理
548
+ - :view 虚拟响应事件消息, 微信传入:event,但gem内部会单独处理
537
549
  - :scan 虚拟响应事件消息
538
550
  - :batch_job 虚拟响应事件消息
539
551
  - :location 虚拟响应上报地理位置事件消息
@@ -542,7 +554,7 @@ end
542
554
  ### 多客服消息转发
543
555
 
544
556
  ```ruby
545
- class WechatsController < ApplicationController
557
+ class WechatsController < ActionController::Base
546
558
  # 当无任何responder处理用户信息时,转发至客服处理。
547
559
  on :fallback do |message|
548
560
  message.reply.transfer_customer_service
data/bin/wechat CHANGED
@@ -16,7 +16,7 @@ require 'wechat/api_loader'
16
16
 
17
17
  class App < Thor
18
18
  package_name 'Wechat'
19
- option :toke_file, aliases: '-t', desc: 'File to store access token'
19
+ option :token_file, aliases: '-t', desc: 'File to store access token'
20
20
 
21
21
  attr_reader :wechat_api_client
22
22
  no_commands do
@@ -170,6 +170,15 @@ class App < Thor
170
170
  puts wechat_api.batch_replaceparty(batch_party_csv_media_id)
171
171
  end
172
172
 
173
+ desc 'upload_replaceparty [BATCH_PARTY_CSV_PATH]', '上传文件方式全量覆盖部门'
174
+ def upload_replaceparty(batch_party_csv_path)
175
+ file = File.new(batch_party_csv_path)
176
+ media_id = wechat_api.media_create('file', file)['media_id']
177
+ job_id = wechat_api.batch_replaceparty(media_id)['jobid']
178
+ puts "running job_id: #{job_id}"
179
+ puts wechat_api.batch_job_result(job_id)
180
+ end
181
+
173
182
  desc 'batch_syncuser [SYNC_USER_CSV_MEDIA_ID]', '增量更新成员'
174
183
  def batch_syncuser(sync_user_csv_media_id)
175
184
  puts wechat_api.batch_syncuser(sync_user_csv_media_id)
@@ -180,6 +189,15 @@ class App < Thor
180
189
  puts wechat_api.batch_replaceuser(batch_user_csv_media_id)
181
190
  end
182
191
 
192
+ desc 'upload_replaceuser [BATCH_USER_CSV_PATH]', '上传文件方式全量覆盖成员'
193
+ def upload_replaceuser(batch_user_csv_path)
194
+ file = File.new(batch_user_csv_path)
195
+ media_id = wechat_api.media_create('file', file)['media_id']
196
+ job_id = wechat_api.batch_replaceuser(media_id)['jobid']
197
+ puts "running job_id: #{job_id}"
198
+ puts wechat_api.batch_job_result(job_id)
199
+ end
200
+
183
201
  desc 'convert_to_openid [USER_ID]', 'userid转换成openid'
184
202
  def convert_to_openid(userid)
185
203
  puts wechat_api.convert_to_openid(userid)
@@ -14,7 +14,7 @@ module ActionController
14
14
  self.wechat = Wechat.api
15
15
  else
16
16
  if corpid.present?
17
- self.wechat = Wechat::CorpApi.new(corpid, opts[:corpsecret], opts[:access_token], agentid, skip_verify_ssl)
17
+ self.wechat = Wechat::CorpApi.new(corpid, opts[:corpsecret], opts[:access_token], agentid, skip_verify_ssl, opts[:jsapi_ticket])
18
18
  else
19
19
  self.wechat = Wechat::Api.new(opts[:appid], opts[:secret], opts[:access_token], skip_verify_ssl, opts[:jsapi_ticket])
20
20
  end
@@ -1,4 +1,8 @@
1
+ <% if defined? ActionController::API -%>
1
2
  class WechatsController < ApplicationController
3
+ <% else -%>
4
+ class WechatsController < ActionController::Base
5
+ <% end -%>
2
6
  wechat_responder
3
7
 
4
8
  # default text responder when no other match
@@ -59,6 +63,11 @@ class WechatsController < ApplicationController
59
63
  request.reply.text "User: #{request[:FromUserName]} click #{key}"
60
64
  end
61
65
 
66
+ # When user view URL in the menu button
67
+ on :view, with: 'http://wechat.somewhere.com/view_url' do |request, view|
68
+ request.reply.text "#{request[:FromUserName]} view #{view}"
69
+ end
70
+
62
71
  # When user sent the imsage
63
72
  on :image do |request|
64
73
  request.reply.image(request[:MediaId]) # Echo the sent image to user
@@ -9,6 +9,7 @@ default: &default
9
9
  access_token: "C:/Users/[username]/wechat_access_token"
10
10
  encrypt_mode: false # if true must fill encoding_aes_key
11
11
  encoding_aes_key: "my_encoding_aes_key"
12
+ jsapi_ticket: "C:/Users/[user_name]/wechat_jsapi_ticket"
12
13
 
13
14
  production:
14
15
  corpid: <%%= ENV['WECHAT_CORPID'] %>
@@ -21,6 +22,7 @@ production:
21
22
  access_token: <%%= ENV['WECHAT_ACCESS_TOKEN'] %>
22
23
  encrypt_mode: false # if true must fill encoding_aes_key
23
24
  encoding_aes_key: <%%= ENV['WECHAT_ENCODING_AES_KEY'] %>
25
+ jsapi_ticket: <%= ENV['WECHAT_JSAPI_TICKET'] %>
24
26
 
25
27
  development:
26
28
  <<: *default
@@ -22,6 +22,6 @@ module Wechat
22
22
  end
23
23
 
24
24
  def self.api
25
- ApiLoader.api
25
+ @wechat_api ||= ApiLoader.with({})
26
26
  end
27
27
  end
@@ -5,12 +5,10 @@ require 'wechat/jsapi_ticket'
5
5
 
6
6
  module Wechat
7
7
  class Api < ApiBase
8
- attr_reader :jsapi_ticket
9
-
10
8
  API_BASE = 'https://api.weixin.qq.com/cgi-bin/'
11
9
  OAUTH2_BASE = 'https://api.weixin.qq.com/sns/oauth2/'
12
10
 
13
- def initialize(appid, secret, token_file, skip_verify_ssl, jsapi_ticket_file = '/var/tmp/wechat_jsapi_ticket')
11
+ def initialize(appid, secret, token_file, skip_verify_ssl, jsapi_ticket_file)
14
12
  @client = Client.new(API_BASE, skip_verify_ssl)
15
13
  @access_token = AccessToken.new(@client, appid, secret, token_file)
16
14
  @jsapi_ticket = JsapiTicket.new(@client, @access_token, jsapi_ticket_file)
@@ -1,6 +1,6 @@
1
1
  module Wechat
2
2
  class ApiBase
3
- attr_reader :access_token, :client
3
+ attr_reader :access_token, :client, :jsapi_ticket
4
4
 
5
5
  MP_BASE = 'https://mp.weixin.qq.com/cgi-bin/'
6
6
 
@@ -1,23 +1,15 @@
1
1
  module Wechat
2
2
  module ApiLoader
3
- def self.api
4
- c = ApiLoader.config
5
- if c.corpid.present?
6
- @api ||= CorpApi.new(c.corpid, c.corpsecret, c.access_token, c.agentid, c.skip_verify_ssl)
7
- else
8
- @api ||= Api.new(c.appid, c.secret, c.access_token, c.skip_verify_ssl, c.jsapi_ticket)
9
- end
10
- end
11
-
12
3
  def self.with(options)
13
- c = config
4
+ c = ApiLoader.config
14
5
 
15
- token_file = options[:toke_file] || c.access_token || '/var/tmp/wechat_access_token'
6
+ token_file = options[:token_file] || c.access_token || '/var/tmp/wechat_access_token'
7
+ js_token_file = options[:js_token_file] || c.jsapi_ticket || '/var/tmp/wechat_jsapi_ticket'
16
8
 
17
9
  if c.appid && c.secret && token_file.present?
18
- Wechat::Api.new(c.appid, c.secret, token_file, c.skip_verify_ssl)
10
+ Wechat::Api.new(c.appid, c.secret, token_file, c.skip_verify_ssl, js_token_file)
19
11
  elsif c.corpid && c.corpsecret && token_file.present?
20
- Wechat::CorpApi.new(c.corpid, c.corpsecret, token_file, c.agentid, c.skip_verify_ssl)
12
+ Wechat::CorpApi.new(c.corpid, c.corpsecret, token_file, c.agentid, c.skip_verify_ssl, js_token_file)
21
13
  else
22
14
  puts <<-HELP
23
15
  Need create ~/.wechat.yml with wechat appid and secret
@@ -77,7 +69,8 @@ HELP
77
69
  access_token: ENV['WECHAT_ACCESS_TOKEN'],
78
70
  encrypt_mode: ENV['WECHAT_ENCRYPT_MODE'],
79
71
  skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
80
- encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'] }
72
+ encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'],
73
+ jsapi_ticket: ENV['WECHAT_JSAPI_TICKET'] }
81
74
  end
82
75
  end
83
76
  end
@@ -1,6 +1,7 @@
1
1
  require 'wechat/api_base'
2
2
  require 'wechat/client'
3
3
  require 'wechat/access_token'
4
+ require 'wechat/corp_jsapi_ticket'
4
5
 
5
6
  module Wechat
6
7
  class CorpAccessToken < AccessToken
@@ -17,10 +18,11 @@ module Wechat
17
18
 
18
19
  API_BASE = 'https://qyapi.weixin.qq.com/cgi-bin/'
19
20
 
20
- def initialize(appid, secret, token_file, agentid, skip_verify_ssl)
21
+ def initialize(appid, secret, token_file, agentid, skip_verify_ssl, jsapi_ticket_file)
21
22
  @client = Client.new(API_BASE, skip_verify_ssl)
22
23
  @access_token = CorpAccessToken.new(@client, appid, secret, token_file)
23
24
  @agentid = agentid
25
+ @jsapi_ticket = CorpJsapiTicket.new(@client, @access_token, jsapi_ticket_file)
24
26
  end
25
27
 
26
28
  def agent_list
@@ -0,0 +1,13 @@
1
+ require 'wechat/jsapi_base'
2
+
3
+ module Wechat
4
+ class CorpJsapiTicket < JsapiBase
5
+ # refresh jsapi ticket
6
+ def refresh
7
+ data = client.get('get_jsapi_ticket', params: { access_token: access_token.token })
8
+ data.merge!('created_at'.freeze => Time.now.to_i)
9
+ File.open(jsapi_ticket_file, 'w') { |f| f.write(data.to_json) } if valid_ticket(data)
10
+ @jsapi_ticket_data = data
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+ require 'digest/sha1'
3
+
4
+ module Wechat
5
+ class JsapiBase
6
+ attr_reader :client, :access_token, :jsapi_ticket_file, :jsapi_ticket_data
7
+
8
+ def initialize(client, access_token, jsapi_ticket_file)
9
+ @client = client
10
+ @access_token = access_token
11
+ @jsapi_ticket_file = jsapi_ticket_file
12
+ end
13
+
14
+ # 获取微信 jssdk 签名所需的 jsapi_ticket, 返回具有如下结构的 hash:
15
+ # {
16
+ # "errcode":0,
17
+ # "errmsg":"ok",
18
+ # "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
19
+ # "expires_in":7200
20
+ # }
21
+ def ticket
22
+ begin
23
+ @jsapi_ticket_data ||= JSON.parse(File.read(jsapi_ticket_file))
24
+ created_at = jsapi_ticket_data['created_at'].to_i
25
+ expires_in = jsapi_ticket_data['expires_in'].to_i
26
+ if Time.now.to_i - created_at >= expires_in - 3 * 60
27
+ fail 'jsapi_ticket may be expired'
28
+ end
29
+ rescue
30
+ refresh
31
+ end
32
+ valid_ticket(@jsapi_ticket_data)
33
+ end
34
+
35
+ # 获取 jssdk 签名及注册所需其他参数, 返回具有如下结构的 hash:
36
+ # params = {
37
+ # noncestr: noncestr,
38
+ # timestamp: timestamp,
39
+ # jsapi_ticket: ticket,
40
+ # url: url,
41
+ # signature: signature
42
+ # }
43
+ def signature(url)
44
+ timestamp = Time.now.to_i
45
+ noncestr = SecureRandom.base64(16)
46
+ params = {
47
+ noncestr: noncestr,
48
+ timestamp: timestamp,
49
+ jsapi_ticket: ticket,
50
+ url: url
51
+ }
52
+ pairs = params.keys.sort.map do |key|
53
+ "#{key}=#{params[key]}"
54
+ end
55
+ result = Digest::SHA1.hexdigest pairs.join('&')
56
+ params.merge(signature: result)
57
+ end
58
+
59
+ protected
60
+
61
+ def valid_ticket(jsapi_ticket_data)
62
+ ticket = jsapi_ticket_data['ticket'] || jsapi_ticket_data[:ticket]
63
+ fail "Response didn't have ticket" if ticket.blank?
64
+ ticket
65
+ end
66
+ end
67
+ end
@@ -1,75 +1,13 @@
1
- # coding: utf-8
2
- require 'digest/sha1'
1
+ require 'wechat/jsapi_base'
3
2
 
4
3
  module Wechat
5
- class JsapiTicket
6
- attr_reader :client, :access_token, :jsapi_ticket_file, :jsapi_ticket_data
7
-
8
- def initialize(client, access_token, jsapi_ticket_file)
9
- @client = client
10
- @access_token = access_token
11
- @jsapi_ticket_file = jsapi_ticket_file
12
- end
13
-
14
- # 获取微信 jssdk 签名所需的 jsapi_ticket, 返回具有如下结构的 hash:
15
- # {
16
- # "errcode":0,
17
- # "errmsg":"ok",
18
- # "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
19
- # "expires_in":7200
20
- # }
21
- def ticket
22
- begin
23
- @jsapi_ticket_data ||= JSON.parse(File.read(jsapi_ticket_file))
24
- created_at = jsapi_ticket_data['created_at'].to_i
25
- expires_in = jsapi_ticket_data['expires_in'].to_i
26
- if Time.now.to_i - created_at >= expires_in - 3 * 60
27
- fail 'jsapi_ticket may be expired'
28
- end
29
- rescue
30
- refresh
31
- end
32
- valid_ticket(@jsapi_ticket_data)
33
- end
34
-
35
- # 刷新 jsapi_ticket
4
+ class JsapiTicket < JsapiBase
5
+ # refresh jsapi ticket
36
6
  def refresh
37
7
  data = client.get('ticket/getticket', params: { access_token: access_token.token, type: 'jsapi' })
38
8
  data.merge!('created_at'.freeze => Time.now.to_i)
39
9
  File.open(jsapi_ticket_file, 'w') { |f| f.write(data.to_json) } if valid_ticket(data)
40
10
  @jsapi_ticket_data = data
41
11
  end
42
-
43
- # 获取 jssdk 签名及注册所需其他参数, 返回具有如下结构的 hash:
44
- # params = {
45
- # noncestr: noncestr,
46
- # timestamp: timestamp,
47
- # jsapi_ticket: ticket,
48
- # url: url,
49
- # signature: signature
50
- # }
51
- def signature(url)
52
- timestamp = Time.now.to_i
53
- noncestr = SecureRandom.base64(16)
54
- params = {
55
- noncestr: noncestr,
56
- timestamp: timestamp,
57
- jsapi_ticket: ticket,
58
- url: url
59
- }
60
- pairs = params.keys.sort.map do |key|
61
- "#{key}=#{params[key]}"
62
- end
63
- result = Digest::SHA1.hexdigest pairs.join('&')
64
- params.merge(signature: result)
65
- end
66
-
67
- private
68
-
69
- def valid_ticket(jsapi_ticket_data)
70
- ticket = jsapi_ticket_data['ticket'] || jsapi_ticket_data[:ticket]
71
- fail "Response didn't have ticket" if ticket.blank?
72
- ticket
73
- end
74
12
  end
75
13
  end
@@ -15,21 +15,23 @@ module Wechat
15
15
  attr_accessor :wechat, :token, :corpid, :agentid, :encrypt_mode, :skip_verify_ssl, :encoding_aes_key
16
16
 
17
17
  def on(message_type, with: nil, respond: nil, &block)
18
- fail 'Unknow message type' unless [:text, :image, :voice, :video, :link, :event, :click, :scan, :batch_job, :location, :fallback].include?(message_type)
18
+ fail 'Unknow message type' unless [:text, :image, :voice, :video, :link, :event, :click, :view, :scan, :batch_job, :location, :fallback].include?(message_type)
19
19
  config = respond.nil? ? {} : { respond: respond }
20
20
  config.merge!(proc: block) if block_given?
21
21
 
22
22
  if with.present?
23
- fail 'Only text, event, click, scan and batch_job can having :with parameters' unless [:text, :event, :click, :scan, :batch_job].include?(message_type)
23
+ fail 'Only text, event, click, view, scan and batch_job can having :with parameters' unless [:text, :event, :click, :view, :scan, :batch_job].include?(message_type)
24
24
  config.merge!(with: with)
25
25
  self.known_scan_key_lists = with if message_type == :scan
26
26
  else
27
- fail 'Message type click, scan and batch_job must specify :with parameters' if [:click, :scan, :batch_job].include?(message_type)
27
+ fail 'Message type click, view, scan and batch_job must specify :with parameters' if [:click, :view, :scan, :batch_job].include?(message_type)
28
28
  end
29
29
 
30
30
  case message_type
31
31
  when :click
32
32
  user_defined_click_responders(with) << config
33
+ when :view
34
+ user_defined_view_responders(with) << config
33
35
  when :batch_job
34
36
  user_defined_batch_job_responders(with) << config
35
37
  when :location
@@ -45,6 +47,11 @@ module Wechat
45
47
  @click_responders[with] ||= []
46
48
  end
47
49
 
50
+ def user_defined_view_responders(with)
51
+ @view_responders ||= {}
52
+ @view_responders[with] ||= []
53
+ end
54
+
48
55
  def user_defined_batch_job_responders(with)
49
56
  @batch_job_responders ||= {}
50
57
  @batch_job_responders[with] ||= []
@@ -69,6 +76,8 @@ module Wechat
69
76
  when :event
70
77
  if 'click' == message[:Event] && !user_defined_click_responders(message[:EventKey]).empty?
71
78
  yield(* user_defined_click_responders(message[:EventKey]), message[:EventKey])
79
+ elsif 'view' == message[:Event] && !user_defined_view_responders(message[:EventKey]).empty?
80
+ yield(* user_defined_view_responders(message[:EventKey]), message[:EventKey])
72
81
  elsif 'click' == message[:Event]
73
82
  yield(* match_responders(responders, message[:EventKey]))
74
83
  elsif known_scan_key_lists.include?(message[:EventKey])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skinnyworm
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-24 00:00:00.000000000 Z
12
+ date: 2015-12-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -73,14 +73,14 @@ dependencies:
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '3.3'
76
+ version: '3.4'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: '3.3'
83
+ version: '3.4'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: rails
86
86
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +119,8 @@ files:
119
119
  - lib/wechat/cipher.rb
120
120
  - lib/wechat/client.rb
121
121
  - lib/wechat/corp_api.rb
122
+ - lib/wechat/corp_jsapi_ticket.rb
123
+ - lib/wechat/jsapi_base.rb
122
124
  - lib/wechat/jsapi_ticket.rb
123
125
  - lib/wechat/message.rb
124
126
  - lib/wechat/responder.rb