wechat 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9f57875f2dee753674602e98333ae19b6a29c4ed
4
- data.tar.gz: e0c6882f86e379bfd8ad74d31a3c6241cd47f0ae
3
+ metadata.gz: 66ecda4306d9d5a9fde71ae0477d99682fd443a0
4
+ data.tar.gz: 13b71709c26cc139d1be233a0449741eb404adbc
5
5
  SHA512:
6
- metadata.gz: 375da3a164458340900ed8d1ab1b4c864ce3b2f645f18ef19be010a67954018ff5a34da7273e12169c1654673d91c237ea99a633ef63b5630d84f04561e887e9
7
- data.tar.gz: 9dba3994255e0cff1de66e7f125f30b9a6f836f81f98a327fab1180fc940e7fc40ed5169c10ff939264a2e314ae9b3412afbb3a9a8b6bda2920237d43799fa0e
6
+ metadata.gz: 85fb0b5a0745542d5c9e9ec09095125c393192da41335592c58561353c6e5d91cc7eeb112a61c2456ac68cda0768391ae33a65a98aa7f05292abd2cfad78a2fc
7
+ data.tar.gz: 09d88487602a96a6bc1d9b3c7dad3a5f9199c1d8df1f40e96d7b5a5ec6692cc894b4fb071de20ac27a1df42f6536cb17fe691651a044c876c4c117bc80602f17
@@ -1,8 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.6.4 (released at 11/16/2015)
4
+
5
+ * Command mode now display different command set based on enterprise/public account setting
6
+ * Move config logic in command/wechat to ApiLoader class
7
+ * Unsubscribe can only reply plain text 'success' #68
8
+ * Fix 404 qrcode download problem, by @huangxiangdan #69
9
+
3
10
  ## v0.6.3 (released at 11/14/2015)
4
11
 
5
- * Official testing and support public encrypt mode, also fix one cipher bug, many thanks to hlltc #67
12
+ * Official testing and support public encrypt mode, also fix one cipher bug, many thanks to @hlltc #67
6
13
  * hlltc report public account FILE_BASE no longer needs, clean code #67
7
14
  * Media command line reflect recent Tecent json schema change. #67
8
15
 
data/README.md CHANGED
@@ -157,6 +157,46 @@ wechat gems 内部不会检查权限。但因公众号类型不同,和微信
157
157
 
158
158
  ## 使用命令行
159
159
 
160
+ 根据企业号和公众号配置不同,wechat提供了的命令行命令。
161
+
162
+ #### 公众号命令行
163
+
164
+ ```
165
+ $ wechat
166
+ Wechat commands:
167
+ wechat callbackip # 获取微信服务器IP地址
168
+ wechat custom_image [OPENID, IMAGE_PATH] # 发送图片客服消息
169
+ wechat custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL] # 发送音乐客服消息
170
+ wechat custom_news [OPENID, NEWS_YAML_PATH] # 发送图文客服消息
171
+ wechat custom_text [OPENID, TEXT_MESSAGE] # 发送文字客服消息
172
+ wechat custom_video [OPENID, VIDEO_PATH] # 发送视频客服消息
173
+ wechat custom_voice [OPENID, VOICE_PATH] # 发送语音客服消息
174
+ wechat group_create [GROUP_NAME] # 创建分组
175
+ wechat group_delete [GROUP_ID] # 删除分组
176
+ wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
177
+ wechat groups # 查询所有分组
178
+ wechat material [MEDIA_ID, PATH] # 永久媒体下载
179
+ wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
180
+ wechat material_count # 获取永久素材总数
181
+ wechat material_delete [MEDIA_ID] # 删除永久素材
182
+ wechat material_list [TYPE, OFFSET, COUNT] # 获取永久素材列表
183
+ wechat media [MEDIA_ID, PATH] # 媒体下载
184
+ wechat media_create [MEDIA_TYPE, PATH] # 媒体上传
185
+ wechat menu # 当前菜单
186
+ wechat menu_create [MENU_YAML_PATH] # 创建菜单
187
+ wechat menu_delete # 删除菜单
188
+ wechat qrcode_create_limit_scene [SCENE_ID_OR_STR] # 请求永久二维码
189
+ wechat qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS] # 请求临时二维码
190
+ wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
191
+ wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
192
+ wechat user [OPEN_ID] # 获取用户基本信息
193
+ wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
194
+ wechat user_group [OPEN_ID] # 查询用户所在分组
195
+ wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
196
+ wechat users # 关注者列表
197
+ ```
198
+
199
+ #### 企业号命令行
160
200
  ```
161
201
  $ wechat
162
202
  Wechat commands:
@@ -177,11 +217,7 @@ Wechat commands:
177
217
  wechat department [DEPARTMENT_ID] # 获取部门列表
178
218
  wechat department_create [NAME, PARENT_ID] # 创建部门
179
219
  wechat department_delete [DEPARTMENT_ID] # 删除部门
180
- wechat department_update [DEPARTMENT_ID, NAME] # 更新部门
181
- wechat group_create [GROUP_NAME] # 创建分组
182
- wechat group_delete [GROUP_ID] # 删除分组
183
- wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
184
- wechat groups # 所有用户分组列表
220
+ wechat department_update [DEPARTMENT_ID, NAME] # 更新部门
185
221
  wechat invite_user [USER_ID] # 邀请成员关注
186
222
  wechat material [MEDIA_ID, PATH] # 永久媒体下载
187
223
  wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
@@ -193,7 +229,7 @@ Wechat commands:
193
229
  wechat menu # 当前菜单
194
230
  wechat menu_create [MENU_YAML_PATH] # 创建菜单
195
231
  wechat menu_delete # 删除菜单
196
- wechat message_send [OPENID, TEXT_MESSAGE] # 发送文字消息(仅企业号)
232
+ wechat message_send [OPENID, TEXT_MESSAGE] # 发送文字消息
197
233
  wechat qrcode_create_limit_scene [SCENE_ID_OR_STR] # 请求永久二维码
198
234
  wechat qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS] # 请求临时二维码
199
235
  wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
@@ -201,21 +237,18 @@ Wechat commands:
201
237
  wechat tag_add_department [TAG_ID, PARTY_IDS] # 增加标签部门
202
238
  wechat tag_add_user [TAG_ID, USER_IDS] # 增加标签成员
203
239
  wechat tag_create [TAGNAME, TAG_ID] # 创建标签
204
- wechat tag_del_user [TAG_ID, USER_IDS] # 删除标签成员
205
240
  wechat tag_del_department [TAG_ID, PARTY_IDS] # 删除标签部门
241
+ wechat tag_del_user [TAG_ID, USER_IDS] # 删除标签成员
206
242
  wechat tag_delete [TAG_ID] # 删除标签
207
243
  wechat tag_update [TAG_ID, TAGNAME] # 更新标签名字
208
244
  wechat tags # 获取标签列表
209
245
  wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
210
246
  wechat user [OPEN_ID] # 获取用户基本信息
211
- wechat user_batchdelete [USER_ID_LIST] # 批量删除成员
212
- wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
247
+ wechat user_batchdelete [USER_ID_LIST] # 批量删除成员
213
248
  wechat user_delete [USER_ID] # 删除成员
214
- wechat user_group [OPEN_ID] # 查询用户所在分组
215
249
  wechat user_list [DEPARTMENT_ID] # 获取部门成员详情
216
250
  wechat user_simplelist [DEPARTMENT_ID] # 获取部门成员
217
251
  wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
218
- wechat users # 关注者列表
219
252
  ```
220
253
 
221
254
  ### 使用场景
@@ -449,7 +482,7 @@ class WechatsController < ApplicationController
449
482
 
450
483
  # 当用户取消关注订阅
451
484
  on :event, with: 'unsubscribe' do |request|
452
- request.reply.text "#{request[:FromUserName]} can not receive this message"
485
+ request.reply.success # user can not receive this message
453
486
  end
454
487
 
455
488
  # 成员进入应用的事件推送
data/bin/wechat CHANGED
@@ -12,316 +12,284 @@ require 'active_support/core_ext'
12
12
  require 'active_support/json'
13
13
  require 'fileutils'
14
14
  require 'yaml'
15
+ require 'wechat/api_loader'
15
16
 
16
17
  class App < Thor
17
- class Helper
18
- def self.with(options)
19
- config = loading_config
20
-
21
- appid = config['appid']
22
- secret = config['secret']
23
- corpid = config['corpid']
24
- corpsecret = config['corpsecret']
25
- token_file = options[:toke_file] || config['access_token'] || '/var/tmp/wechat_access_token'
26
- agentid = config['agentid']
27
- skip_verify_ssl = config['skip_verify_ssl']
28
-
29
- if appid.present? && secret.present? && token_file.present?
30
- Wechat::Api.new(appid, secret, token_file, skip_verify_ssl)
31
- elsif corpid.present? && corpsecret.present? && token_file.present?
32
- Wechat::CorpApi.new(corpid, corpsecret, token_file, agentid, skip_verify_ssl)
33
- else
34
- puts <<-HELP
35
- Need create ~/.wechat.yml with wechat appid and secret
36
- or running at rails root folder so wechat can read config/wechat.yml
37
- HELP
38
- exit 1
39
- end
40
- end
41
-
42
- def self.loading_config
43
- config = {}
44
-
45
- rails_config_file = File.join(Dir.getwd, 'config/wechat.yml')
46
- home_config_file = File.join(Dir.home, '.wechat.yml')
47
-
48
- if File.exist?(rails_config_file)
49
- config = YAML.load(ERB.new(File.read(rails_config_file)).result)['default']
50
- if config.present? && (config['appid'] || config['corpid'])
51
- puts 'Using rails project config/wechat.yml default setting...'
52
- else
53
- config = {}
54
- end
55
- end
18
+ package_name 'Wechat'
19
+ option :toke_file, aliases: '-t', desc: 'File to store access token'
56
20
 
57
- if config.blank? && File.exist?(home_config_file)
58
- config = YAML.load ERB.new(File.read(home_config_file)).result
59
- end
60
- config
21
+ attr_reader :wechat_api_client
22
+ no_commands do
23
+ def wechat_api
24
+ @wechat_api_client ||= Wechat::ApiLoader.with(options)
61
25
  end
62
26
  end
63
27
 
64
- package_name 'Wechat'
65
- option :toke_file, aliases: '-t', desc: 'File to store access token'
66
-
67
28
  desc 'callbackip', '获取微信服务器IP地址'
68
29
  def callbackip
69
- puts Helper.with(options).callbackip
30
+ puts wechat_api.callbackip
70
31
  end
71
32
 
72
33
  desc 'qrcode_download [TICKET, QR_CODE_PIC_PATH]', '通过ticket下载二维码'
73
34
  def qrcode_download(ticket, qr_code_pic_path)
74
- tmp_file = Helper.with(options).qrcode(ticket)
35
+ tmp_file = wechat_api.qrcode(ticket)
75
36
  FileUtils.mv(tmp_file.path, qr_code_pic_path)
76
37
  puts 'File downloaded'
77
38
  end
78
39
 
79
- desc 'groups', '所有用户分组列表'
80
- def groups
81
- puts Helper.with(options).groups
82
- end
83
-
84
- desc 'group_create [GROUP_NAME]', '创建分组'
85
- def group_create(group_name)
86
- puts Helper.with(options).group_create(group_name)
87
- end
88
-
89
- desc 'group_update [GROUP_ID, NEW_GROUP_NAME]', '修改分组名'
90
- def group_update(groupid, new_group_name)
91
- puts Helper.with(options).group_update(groupid, new_group_name)
92
- end
40
+ if Wechat::ApiLoader.with(options).is_a?(Wechat::CorpApi)
41
+ desc 'department_create [NAME, PARENT_ID]', '创建部门'
42
+ method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1'
43
+ def department_create(name)
44
+ api_opts = options.slice(:parentid)
45
+ puts wechat_api.department_create(name, api_opts[:parentid] || '1')
46
+ end
93
47
 
94
- desc 'group_delete [GROUP_ID]', '删除分组'
95
- def group_delete(groupid)
96
- puts Helper.with(options).group_delete(groupid)
97
- end
48
+ desc 'department_delete [DEPARTMENT_ID]', '删除部门'
49
+ def department_delete(departmentid)
50
+ puts wechat_api.department_delete(departmentid)
51
+ end
98
52
 
99
- desc 'department_create [NAME, PARENT_ID]', '创建部门'
100
- method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1'
101
- def department_create(name)
102
- api_opts = options.slice(:parentid)
103
- puts Helper.with(options).department_create(name, api_opts[:parentid] || '1')
104
- end
53
+ desc 'department_update [DEPARTMENT_ID, NAME]', '更新部门'
54
+ method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1', default: nil
55
+ method_option :order, aliases: '-o', desc: '在父部门中的次序值。order值小的排序靠前。', default: nil
56
+ def department_update(departmentid, name)
57
+ api_opts = options.slice(:parentid, :order)
58
+ puts wechat_api.department_update(departmentid, name, api_opts[:parentid], api_opts[:order])
59
+ end
105
60
 
106
- desc 'department_delete [DEPARTMENT_ID]', '删除部门'
107
- def department_delete(departmentid)
108
- puts Helper.with(options).department_delete(departmentid)
109
- end
61
+ desc 'department [DEPARTMENT_ID]', '获取部门列表'
62
+ def department(departmentid = 0)
63
+ r = wechat_api.department(departmentid)
64
+ puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
65
+ puts 'Or# pid id name'
66
+ r['department'].sort_by { |d| d['order'].to_i + d['parentid'].to_i * 1000 } .each do |i|
67
+ puts format('%3d %3d %3d %s', i['order'], i['parentid'], i['id'], i['name'])
68
+ end
69
+ end
110
70
 
111
- desc 'department_update [DEPARTMENT_ID, NAME]', '更新部门'
112
- method_option :parentid, aliases: '-p', desc: '父亲部门id。根部门id为1', default: nil
113
- method_option :order, aliases: '-o', desc: '在父部门中的次序值。order值小的排序靠前。', default: nil
114
- def department_update(departmentid, name)
115
- api_opts = options.slice(:parentid, :order)
116
- puts Helper.with(options).department_update(departmentid, name, api_opts[:parentid], api_opts[:order])
117
- end
71
+ desc 'user_delete [USER_ID]', '删除成员'
72
+ def user_delete(userid)
73
+ puts wechat_api.user_delete(userid)
74
+ end
118
75
 
119
- desc 'department [DEPARTMENT_ID]', '获取部门列表'
120
- def department(departmentid = 0)
121
- r = Helper.with(options).department(departmentid)
122
- puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
123
- puts 'Or# pid id name'
124
- r['department'].sort_by { |d| d['order'].to_i + d['parentid'].to_i * 1000 } .each do |i|
125
- puts format('%3d %3d %3d %s', i['order'], i['parentid'], i['id'], i['name'])
76
+ desc 'user_batchdelete [USER_ID_LIST]', '批量删除成员'
77
+ def user_batchdelete(useridlist)
78
+ puts wechat_api.user_batchdelete(useridlist.split(','))
126
79
  end
127
- end
128
80
 
129
- desc 'user_simplelist [DEPARTMENT_ID]', '获取部门成员'
130
- method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 1
131
- method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0
132
- def user_simplelist(departmentid = 0)
133
- api_opts = options.slice(:fetch_child, :status)
81
+ desc 'user_simplelist [DEPARTMENT_ID]', '获取部门成员'
82
+ method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 1
83
+ method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0
84
+ def user_simplelist(departmentid = 0)
85
+ api_opts = options.slice(:fetch_child, :status)
86
+
87
+ r = wechat_api.user_simplelist(departmentid, api_opts[:fetch_child], api_opts[:status])
88
+ puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
89
+ puts " userid Name #{' ' * 20} department_ids"
90
+ r['userlist'].sort_by { |d| d['userid'] } .each do |i|
91
+ puts format('%7s %-25s %-14s', i['userid'], i['name'], i['department'])
92
+ end
93
+ end
134
94
 
135
- r = Helper.with(options).user_simplelist(departmentid, api_opts[:fetch_child], api_opts[:status])
136
- puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
137
- puts " userid Name #{' ' * 20} department_ids"
138
- r['userlist'].sort_by { |d| d['userid'] } .each do |i|
139
- puts format('%7s %-25s %-14s', i['userid'], i['name'], i['department'])
95
+ desc 'user_list [DEPARTMENT_ID]', '获取部门成员详情'
96
+ method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 0
97
+ method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0
98
+ def user_list(departmentid = 0)
99
+ api_opts = options.slice(:fetch_child, :status)
100
+
101
+ r = wechat_api.user_list(departmentid, api_opts[:fetch_child], api_opts[:status])
102
+ puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
103
+ puts " userid Name #{' ' * 15} department_ids position mobile #{' ' * 5}gender email #{' ' * 10}weixinid status extattr"
104
+ r['userlist'].sort_by { |d| d['userid'] } .each do |i|
105
+ puts format('%7s %-20s %-14s %-8s %-11s %-6s %-15s %-15s %-6s %s',
106
+ i['userid'], i['name'], i['department'], i['position'], i['mobile'],
107
+ i['gender'], i['email'], i['weixinid'], i['status'], i['extattr'])
108
+ end
140
109
  end
141
- end
142
110
 
143
- desc 'user_list [DEPARTMENT_ID]', '获取部门成员详情'
144
- method_option :fetch_child, aliases: '-c', desc: '是否递归获取子部门下面的成员', default: 0
145
- method_option :status, aliases: '-s', desc: '0 获取全部成员,1 获取已关注成员列表,2 获取禁用成员列表,4 获取未关注成员列表。status可叠加', default: 0
146
- def user_list(departmentid = 0)
147
- api_opts = options.slice(:fetch_child, :status)
111
+ desc 'invite_user [USER_ID]', '邀请成员关注'
112
+ def invite_user(userid)
113
+ puts wechat_api.invite_user(userid)
114
+ end
148
115
 
149
- r = Helper.with(options).user_list(departmentid, api_opts[:fetch_child], api_opts[:status])
150
- puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
151
- puts " userid Name #{' ' * 15} department_ids position mobile #{' ' * 5}gender email #{' ' * 10}weixinid status extattr"
152
- r['userlist'].sort_by { |d| d['userid'] } .each do |i|
153
- puts format('%7s %-20s %-14s %-8s %-11s %-6s %-15s %-15s %-6s %s',
154
- i['userid'], i['name'], i['department'], i['position'], i['mobile'],
155
- i['gender'], i['email'], i['weixinid'], i['status'], i['extattr'])
116
+ desc 'tag_create [TAGNAME, TAG_ID]', '创建标签'
117
+ method_option :tagid, aliases: '-id', desc: '整型,指定此参数时新增的标签会生成对应的标签id,不指定时则以目前最大的id自增'
118
+ def tag_create(name)
119
+ api_opts = options.slice(:tagid)
120
+ puts wechat_api.tag_create(name, api_opts[:tagid])
156
121
  end
157
- end
158
122
 
159
- desc 'tag_create [TAGNAME, TAG_ID]', '创建标签'
160
- method_option :tagid, aliases: '-id', desc: '整型,指定此参数时新增的标签会生成对应的标签id,不指定时则以目前最大的id自增'
161
- def tag_create(name)
162
- api_opts = options.slice(:tagid)
163
- puts Helper.with(options).tag_create(name, api_opts[:tagid])
164
- end
123
+ desc 'tag_update [TAG_ID, TAGNAME]', '更新标签名字'
124
+ def tag_update(tagid, tagname)
125
+ puts wechat_api.tag_update(tagid, tagname)
126
+ end
165
127
 
166
- desc 'tag_update [TAG_ID, TAGNAME]', '更新标签名字'
167
- def tag_update(tagid, tagname)
168
- puts Helper.with(options).tag_update(tagid, tagname)
169
- end
128
+ desc 'tag_delete [TAG_ID]', '删除标签'
129
+ def tag_delete(tagid)
130
+ puts wechat_api.tag_delete(tagid)
131
+ end
170
132
 
171
- desc 'tag_delete [TAG_ID]', '删除标签'
172
- def tag_delete(tagid)
173
- puts Helper.with(options).tag_delete(tagid)
174
- end
133
+ desc 'tag [TAG_ID]', '获取标签成员'
134
+ def tag(tagid)
135
+ puts wechat_api.tag(tagid)
136
+ end
175
137
 
176
- desc 'tags', '获取标签列表'
177
- def tags
178
- puts Helper.with(options).tags
179
- end
138
+ desc 'tag_add_user [TAG_ID, USER_IDS]', '增加标签成员'
139
+ def tag_add_user(tagid, userids)
140
+ puts wechat_api.tag_add_user(tagid, userids.split(','))
141
+ end
180
142
 
181
- desc 'tag [TAG_ID]', '获取标签成员'
182
- def tag(tagid)
183
- puts Helper.with(options).tag(tagid)
184
- end
143
+ desc 'tag_add_department [TAG_ID, PARTY_IDS]', '增加标签部门'
144
+ def tag_add_department(tagid, partyids)
145
+ puts wechat_api.tag_add_user(tagid, nil, partyids.split(','))
146
+ end
185
147
 
186
- desc 'tag_add_user [TAG_ID, USER_IDS]', '增加标签成员'
187
- def tag_add_user(tagid, userids)
188
- puts Helper.with(options).tag_add_user(tagid, userids.split(','))
189
- end
148
+ desc 'tag_del_user [TAG_ID, USER_IDS]', '删除标签成员'
149
+ def tag_del_user(tagid, userids)
150
+ puts wechat_api.tag_del_user(tagid, userids.split(','))
151
+ end
190
152
 
191
- desc 'tag_add_department [TAG_ID, PARTY_IDS]', '增加标签部门'
192
- def tag_add_department(tagid, partyids)
193
- puts Helper.with(options).tag_add_user(tagid, nil, partyids.split(','))
194
- end
153
+ desc 'tag_del_department [TAG_ID, PARTY_IDS]', '删除标签部门'
154
+ def tag_del_department(tagid, partyids)
155
+ puts wechat_api.tag_del_user(tagid, nil, partyids.split(','))
156
+ end
195
157
 
196
- desc 'tag_del_user [TAG_ID, USER_IDS]', '删除标签成员'
197
- def tag_del_user(tagid, userids)
198
- puts Helper.with(options).tag_del_user(tagid, userids.split(','))
199
- end
158
+ desc 'tags', '获取标签列表'
159
+ def tags
160
+ puts wechat_api.tags
161
+ end
200
162
 
201
- desc 'tag_del_department [TAG_ID, PARTY_IDS]', '删除标签部门'
202
- def tag_del_department(tagid, partyids)
203
- puts Helper.with(options).tag_del_user(tagid, nil, partyids.split(','))
204
- end
163
+ desc 'batch_job_result [JOB_ID]', '获取异步任务结果'
164
+ def batch_job_result(job_id)
165
+ puts wechat_api.batch_job_result(job_id)
166
+ end
205
167
 
206
- desc 'agent_list', '获取应用概况列表'
207
- def agent_list
208
- r = Helper.with(options).agent_list
209
- puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
210
- puts 'ag# name square_logo_url round_logo_url'
211
- r['agentlist'].sort_by { |d| d['agentid'] } .each do |i|
212
- puts format('%3d %s %s %s', i['agentid'], i['name'], i['square_logo_url'], i['round_logo_url'])
168
+ desc 'batch_replaceparty [BATCH_PARTY_CSV_MEDIA_ID]', '全量覆盖部门'
169
+ def batch_replaceparty(batch_party_csv_media_id)
170
+ puts wechat_api.batch_replaceparty(batch_party_csv_media_id)
213
171
  end
214
- end
215
172
 
216
- desc 'agent [AGENT_ID]', '获取企业号应用详情'
217
- def agent(agentid)
218
- r = Helper.with(options).agent(agentid)
219
- puts "agentid: #{r['agentid']} errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
220
- puts "name: #{r['name']}"
221
- puts "description: #{r['description']}"
222
- puts " square_logo_url: #{r['square_logo_url']}"
223
- puts " round_logo_url: #{r['round_logo_url']}"
224
- puts "allow_userinfos: #{r['allow_userinfos']}"
225
- puts "allow_partys: #{r['allow_partys']}"
226
- puts "allow_tags: #{r['allow_tags']}"
227
- puts "close: #{r['close']} redirect_domain: #{r['redirect_domain']}"
228
- puts "report_location_flag: #{r['report_location_flag']} isreportuser: #{r['isreportuser']} isreportenter: #{r['isreportenter']}"
229
- end
173
+ desc 'batch_syncuser [SYNC_USER_CSV_MEDIA_ID]', '增量更新成员'
174
+ def batch_syncuser(sync_user_csv_media_id)
175
+ puts wechat_api.batch_syncuser(sync_user_csv_media_id)
176
+ end
230
177
 
231
- desc 'users', '关注者列表'
232
- def users
233
- puts Helper.with(options).users
234
- end
178
+ desc 'batch_replaceuser [BATCH_USER_CSV_MEDIA_ID]', '全量覆盖成员'
179
+ def batch_replaceuser(batch_user_csv_media_id)
180
+ puts wechat_api.batch_replaceuser(batch_user_csv_media_id)
181
+ end
235
182
 
236
- desc 'user [OPEN_ID]', '获取用户基本信息'
237
- def user(open_id)
238
- puts Helper.with(options).user(open_id)
239
- end
183
+ desc 'convert_to_openid [USER_ID]', 'userid转换成openid'
184
+ def convert_to_openid(userid)
185
+ puts wechat_api.convert_to_openid(userid)
186
+ end
240
187
 
241
- desc 'convert_to_openid [USER_ID]', 'userid转换成openid'
242
- def convert_to_openid(userid)
243
- puts Helper.with(options).convert_to_openid(userid)
244
- end
188
+ desc 'agent_list', '获取应用概况列表'
189
+ def agent_list
190
+ r = wechat_api.agent_list
191
+ puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
192
+ puts 'ag# name square_logo_url round_logo_url'
193
+ r['agentlist'].sort_by { |d| d['agentid'] } .each do |i|
194
+ puts format('%3d %s %s %s', i['agentid'], i['name'], i['square_logo_url'], i['round_logo_url'])
195
+ end
196
+ end
245
197
 
246
- desc 'invite_user [USER_ID]', '邀请成员关注'
247
- def invite_user(userid)
248
- puts Helper.with(options).invite_user(userid)
249
- end
198
+ desc 'agent [AGENT_ID]', '获取企业号应用详情'
199
+ def agent(agentid)
200
+ r = wechat_api.agent(agentid)
201
+ puts "agentid: #{r['agentid']} errcode: #{r['errcode']} errmsg: #{r['errmsg']}"
202
+ puts "name: #{r['name']}"
203
+ puts "description: #{r['description']}"
204
+ puts " square_logo_url: #{r['square_logo_url']}"
205
+ puts " round_logo_url: #{r['round_logo_url']}"
206
+ puts "allow_userinfos: #{r['allow_userinfos']}"
207
+ puts "allow_partys: #{r['allow_partys']}"
208
+ puts "allow_tags: #{r['allow_tags']}"
209
+ puts "close: #{r['close']} redirect_domain: #{r['redirect_domain']}"
210
+ puts "report_location_flag: #{r['report_location_flag']} isreportuser: #{r['isreportuser']} isreportenter: #{r['isreportenter']}"
211
+ end
250
212
 
251
- desc 'user_delete [USER_ID]', '删除成员'
252
- def user_delete(userid)
253
- puts Helper.with(options).user_delete(userid)
254
- end
213
+ desc 'message_send [OPENID, TEXT_MESSAGE]', '发送文字消息'
214
+ def message_send(openid, text_message)
215
+ puts wechat_api.message_send openid, text_message
216
+ end
217
+ else
218
+ desc 'group_create [GROUP_NAME]', '创建分组'
219
+ def group_create(group_name)
220
+ puts wechat_api.group_create(group_name)
221
+ end
255
222
 
256
- desc 'user_batchdelete [USER_ID_LIST]', '批量删除成员'
257
- def user_batchdelete(useridlist)
258
- puts Helper.with(options).user_batchdelete(useridlist.split(','))
259
- end
223
+ desc 'groups', '查询所有分组'
224
+ def groups
225
+ puts wechat_api.groups
226
+ end
260
227
 
261
- desc 'batch_job_result [JOB_ID]', '获取异步任务结果'
262
- def batch_job_result(job_id)
263
- puts Helper.with(options).batch_job_result(job_id)
264
- end
228
+ desc 'user_group [OPEN_ID]', '查询用户所在分组'
229
+ def user_group(openid)
230
+ puts wechat_api.user_group(openid)
231
+ end
265
232
 
266
- desc 'batch_replaceparty [BATCH_PARTY_CSV_MEDIA_ID]', '全量覆盖部门'
267
- def batch_replaceparty(batch_party_csv_media_id)
268
- puts Helper.with(options).batch_replaceparty(batch_party_csv_media_id)
269
- end
233
+ desc 'group_update [GROUP_ID, NEW_GROUP_NAME]', '修改分组名'
234
+ def group_update(groupid, new_group_name)
235
+ puts wechat_api.group_update(groupid, new_group_name)
236
+ end
270
237
 
271
- desc 'batch_syncuser [SYNC_USER_CSV_MEDIA_ID]', '增量更新成员'
272
- def batch_syncuser(sync_user_csv_media_id)
273
- puts Helper.with(options).batch_syncuser(sync_user_csv_media_id)
274
- end
238
+ desc 'user_change_group [OPEN_ID, TO_GROUP_ID]', '移动用户分组'
239
+ def user_change_group(openid, to_groupid)
240
+ puts wechat_api.user_change_group(openid, to_groupid)
241
+ end
275
242
 
276
- desc 'batch_replaceuser [BATCH_USER_CSV_MEDIA_ID]', '全量覆盖成员'
277
- def batch_replaceuser(batch_user_csv_media_id)
278
- puts Helper.with(options).batch_replaceuser(batch_user_csv_media_id)
279
- end
243
+ desc 'group_delete [GROUP_ID]', '删除分组'
244
+ def group_delete(groupid)
245
+ puts wechat_api.group_delete(groupid)
246
+ end
280
247
 
281
- desc 'user_group [OPEN_ID]', '查询用户所在分组'
282
- def user_group(openid)
283
- puts Helper.with(options).user_group(openid)
248
+ desc 'users', '关注者列表'
249
+ def users
250
+ puts wechat_api.users
251
+ end
284
252
  end
285
253
 
286
- desc 'user_change_group [OPEN_ID, TO_GROUP_ID]', '移动用户分组'
287
- def user_change_group(openid, to_groupid)
288
- puts Helper.with(options).user_change_group(openid, to_groupid)
254
+ desc 'user [OPEN_ID]', '获取用户基本信息'
255
+ def user(open_id)
256
+ puts wechat_api.user(open_id)
289
257
  end
290
258
 
291
259
  desc 'user_update_remark [OPEN_ID, REMARK]', '设置备注名'
292
260
  def user_update_remark(openid, remark)
293
- puts Helper.with(options).user_update_remark(openid, remark)
261
+ puts wechat_api.user_update_remark(openid, remark)
294
262
  end
295
263
 
296
264
  desc 'qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS]', '请求临时二维码'
297
265
  def qrcode_create_scene(scene_id, expire_seconds = 604800)
298
- puts Helper.with(options).qrcode_create_scene(scene_id, expire_seconds)
266
+ puts wechat_api.qrcode_create_scene(scene_id, expire_seconds)
299
267
  end
300
268
 
301
269
  desc 'qrcode_create_limit_scene [SCENE_ID_OR_STR]', '请求永久二维码'
302
270
  def qrcode_create_limit_scene(scene_id_or_str)
303
- puts Helper.with(options).qrcode_create_limit_scene(scene_id_or_str)
271
+ puts wechat_api.qrcode_create_limit_scene(scene_id_or_str)
304
272
  end
305
273
 
306
274
  desc 'menu', '当前菜单'
307
275
  def menu
308
- puts Helper.with(options).menu
276
+ puts wechat_api.menu
309
277
  end
310
278
 
311
279
  desc 'menu_delete', '删除菜单'
312
280
  def menu_delete
313
- puts 'Menu deleted' if Helper.with(options).menu_delete
281
+ puts 'Menu deleted' if wechat_api.menu_delete
314
282
  end
315
283
 
316
284
  desc 'menu_create [MENU_YAML_PATH]', '创建菜单'
317
285
  def menu_create(menu_yaml_path)
318
286
  menu = YAML.load(File.read(menu_yaml_path))
319
- puts 'Menu created' if Helper.with(options).menu_create(menu)
287
+ puts 'Menu created' if wechat_api.menu_create(menu)
320
288
  end
321
289
 
322
290
  desc 'media [MEDIA_ID, PATH]', '媒体下载'
323
291
  def media(media_id, path)
324
- tmp_file = Helper.with(options).media(media_id)
292
+ tmp_file = wechat_api.media(media_id)
325
293
  FileUtils.mv(tmp_file.path, path)
326
294
  puts 'File downloaded'
327
295
  end
@@ -329,12 +297,12 @@ HELP
329
297
  desc 'media_create [MEDIA_TYPE, PATH]', '媒体上传'
330
298
  def media_create(type, path)
331
299
  file = File.new(path)
332
- puts Helper.with(options).media_create(type, file)
300
+ puts wechat_api.media_create(type, file)
333
301
  end
334
302
 
335
303
  desc 'material [MEDIA_ID, PATH]', '永久媒体下载'
336
304
  def material(media_id, path)
337
- tmp_file = Helper.with(options).material(media_id)
305
+ tmp_file = wechat_api.material(media_id)
338
306
  FileUtils.mv(tmp_file.path, path)
339
307
  puts 'File downloaded'
340
308
  end
@@ -342,46 +310,43 @@ HELP
342
310
  desc 'material_add [MEDIA_TYPE, PATH]', '永久媒体上传'
343
311
  def material_add(type, path)
344
312
  file = File.new(path)
345
- puts Helper.with(options).material_add(type, file)
313
+ puts wechat_api.material_add(type, file)
346
314
  end
347
315
 
348
316
  desc 'material_delete [MEDIA_ID]', '删除永久素材'
349
317
  def material_delete(media_id)
350
- puts Helper.with(options).material_delete(media_id)
318
+ puts wechat_api.material_delete(media_id)
351
319
  end
352
320
 
353
321
  desc 'material_count', '获取永久素材总数'
354
322
  def material_count
355
- puts Helper.with(options).material_count
323
+ puts wechat_api.material_count
356
324
  end
357
325
 
358
326
  desc 'material_list [TYPE, OFFSET, COUNT]', '获取永久素材列表'
359
327
  def material_list(type, offset, count)
360
- r = Helper.with(options).material_list(type, offset, count)
328
+ r = wechat_api.material_list(type, offset, count)
361
329
  if %w(image voice video file).include?(type)
362
330
  puts "errcode: #{r['errcode']} errmsg: #{r['errmsg']} total_count: #{r['total_count']} item_count: #{r['item_count']}"
363
- r['item'].each do |i|
364
- puts "#{i['media_id']} #{i['name']} #{Time.at(i['update_time'].to_i)}"
331
+ if wechat_api.is_a?(Wechat::CorpApi)
332
+ r['itemlist'].each { |i| puts "#{i['media_id']} #{i['filename']} #{Time.at(i['update_time'].to_i)}" }
333
+ else
334
+ r['item'].each { |i| puts "#{i['media_id']} #{i['name']} #{Time.at(i['update_time'].to_i)}" }
365
335
  end
366
336
  else
367
337
  puts r
368
338
  end
369
339
  end
370
340
 
371
- desc 'message_send [OPENID, TEXT_MESSAGE]', '发送文字消息(仅企业号)'
372
- def message_send(openid, text_message)
373
- puts Helper.with(options).message_send openid, text_message
374
- end
375
-
376
341
  desc 'custom_text [OPENID, TEXT_MESSAGE]', '发送文字客服消息'
377
342
  def custom_text(openid, text_message)
378
- puts Helper.with(options).custom_message_send Wechat::Message.to(openid).text(text_message)
343
+ puts wechat_api.custom_message_send Wechat::Message.to(openid).text(text_message)
379
344
  end
380
345
 
381
346
  desc 'custom_image [OPENID, IMAGE_PATH]', '发送图片客服消息'
382
347
  def custom_image(openid, image_path)
383
348
  file = File.new(image_path)
384
- api = Helper.with(options)
349
+ api = wechat_api
385
350
 
386
351
  media_id = api.media_create('image', file)['media_id']
387
352
  puts api.custom_message_send Wechat::Message.to(openid).image(media_id)
@@ -390,7 +355,7 @@ HELP
390
355
  desc 'custom_voice [OPENID, VOICE_PATH]', '发送语音客服消息'
391
356
  def custom_voice(openid, voice_path)
392
357
  file = File.new(voice_path)
393
- api = Helper.with(options)
358
+ api = wechat_api
394
359
 
395
360
  media_id = api.media_create('voice', file)['media_id']
396
361
  puts api.custom_message_send Wechat::Message.to(openid).voice(media_id)
@@ -401,7 +366,7 @@ HELP
401
366
  method_option :description, aliases: '-d', desc: '视频描述'
402
367
  def custom_video(openid, video_path)
403
368
  file = File.new(video_path)
404
- api = Helper.with(options)
369
+ api = wechat_api
405
370
 
406
371
  api_opts = options.slice(:title, :description)
407
372
  media_id = api.media_create('video', file)['media_id']
@@ -414,7 +379,7 @@ HELP
414
379
  method_option :HQ_music_url, aliases: '-u', desc: '高质量音乐URL链接'
415
380
  def custom_music(openid, thumbnail_path, music_url)
416
381
  file = File.new(thumbnail_path)
417
- api = Helper.with(options)
382
+ api = wechat_api
418
383
 
419
384
  api_opts = options.slice(:title, :description, :HQ_music_url)
420
385
  thumb_media_id = api.media_create('thumb', file)['thumb_media_id']
@@ -424,13 +389,13 @@ HELP
424
389
  desc 'custom_news [OPENID, NEWS_YAML_PATH]', '发送图文客服消息'
425
390
  def custom_news(openid, news_yaml_path)
426
391
  articles = YAML.load(File.read(news_yaml_path))
427
- puts Helper.with(options).custom_message_send Wechat::Message.to(openid).news(articles['articles'])
392
+ puts wechat_api.custom_message_send Wechat::Message.to(openid).news(articles['articles'])
428
393
  end
429
394
 
430
395
  desc 'template_message [OPENID, TEMPLATE_YAML_PATH]', '模板消息接口'
431
396
  def template_message(openid, template_yaml_path)
432
397
  template = YAML.load(File.read(template_yaml_path))
433
- puts Helper.with(options).template_message_send Wechat::Message.to(openid).template(template['template'])
398
+ puts wechat_api.template_message_send Wechat::Message.to(openid).template(template['template'])
434
399
  end
435
400
  end
436
401
 
@@ -81,7 +81,7 @@ class WechatsController < ApplicationController
81
81
  end
82
82
 
83
83
  on :event, with: 'unsubscribe' do |request|
84
- request.reply.text "#{request[:FromUserName]} can not receive this message"
84
+ request.reply.success # user can not receive this message
85
85
  end
86
86
 
87
87
  # When user enter the app / agent app
@@ -1,3 +1,4 @@
1
+ require 'wechat/api_loader'
1
2
  require 'wechat/api'
2
3
  require 'wechat/corp_api'
3
4
  require 'action_controller/wechat_responder'
@@ -19,18 +20,7 @@ module Wechat
19
20
  attr_reader :config
20
21
 
21
22
  def self.config
22
- @config ||= begin
23
- if defined? Rails
24
- config_file = Rails.root.join('config/wechat.yml')
25
- config = YAML.load(ERB.new(File.new(config_file).read).result)[Rails.env] if File.exist?(config_file)
26
- end
27
-
28
- config ||= config_from_environment
29
- config.symbolize_keys!
30
- config[:access_token] ||= Rails.root.join('tmp/access_token').to_s
31
- config[:jsapi_ticket] ||= Rails.root.join('tmp/jsapi_ticket').to_s
32
- OpenStruct.new(config)
33
- end
23
+ @config ||= ApiLoader.loading_config
34
24
  end
35
25
 
36
26
  def self.api
@@ -40,19 +30,4 @@ module Wechat
40
30
  @api ||= Api.new(config.appid, config.secret, config.access_token, config.skip_verify_ssl, config.jsapi_ticket)
41
31
  end
42
32
  end
43
-
44
- private
45
-
46
- def self.config_from_environment
47
- { appid: ENV['WECHAT_APPID'],
48
- secret: ENV['WECHAT_SECRET'],
49
- corpid: ENV['WECHAT_CORPID'],
50
- corpsecret: ENV['WECHAT_CORPSECRET'],
51
- agentid: ENV['WECHAT_AGENTID'],
52
- token: ENV['WECHAT_TOKEN'],
53
- access_token: ENV['WECHAT_ACCESS_TOKEN'],
54
- encrypt_mode: ENV['WECHAT_ENCRYPT_MODE'],
55
- skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
56
- encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'] }
57
- end
58
33
  end
@@ -1,5 +1,3 @@
1
- require 'cgi'
2
-
3
1
  module Wechat
4
2
  class ApiBase
5
3
  attr_reader :access_token, :client
@@ -11,7 +9,7 @@ module Wechat
11
9
  end
12
10
 
13
11
  def qrcode(ticket)
14
- client.get 'showqrcode', ticket: CGI.escape(ticket), base: MP_BASE, as: :file
12
+ client.get 'showqrcode', params: { ticket: ticket }, base: MP_BASE, as: :file
15
13
  end
16
14
 
17
15
  def media(media_id)
@@ -0,0 +1,65 @@
1
+ module Wechat
2
+ class ApiLoader
3
+ def self.with(options)
4
+ c = loading_config
5
+
6
+ token_file = options[:toke_file] || c.access_token || '/var/tmp/wechat_access_token'
7
+
8
+ if c.appid && c.secret && token_file.present?
9
+ Wechat::Api.new(c.appid, c.secret, token_file, c.skip_verify_ssl)
10
+ elsif c.corpid && c.corpsecret && token_file.present?
11
+ Wechat::CorpApi.new(c.corpid, c.corpsecret, token_file, c.agentid, c.skip_verify_ssl)
12
+ else
13
+ puts <<-HELP
14
+ Need create ~/.wechat.yml with wechat appid and secret
15
+ or running at rails root folder so wechat can read config/wechat.yml
16
+ HELP
17
+ exit 1
18
+ end
19
+ end
20
+
21
+ def self.loading_config
22
+ if defined?(::Rails)
23
+ config_file = Rails.root.join('config/wechat.yml')
24
+ config = YAML.load(ERB.new(File.read(config_file)).result)[Rails.env] if File.exist?(config_file)
25
+ else
26
+ rails_config_file = File.join(Dir.getwd, 'config/wechat.yml')
27
+ home_config_file = File.join(Dir.home, '.wechat.yml')
28
+
29
+ if File.exist?(rails_config_file)
30
+ config = YAML.load(ERB.new(File.read(rails_config_file)).result)['default']
31
+ if config.present? && (config['appid'] || config['corpid'])
32
+ puts 'Using rails project config/wechat.yml default setting...'
33
+ else
34
+ config = {}
35
+ end
36
+ end
37
+
38
+ if config.blank? && File.exist?(home_config_file)
39
+ config = YAML.load ERB.new(File.read(home_config_file)).result
40
+ end
41
+ end
42
+
43
+ config ||= config_from_environment
44
+ if defined?(::Rails)
45
+ config[:access_token] ||= Rails.root.join('tmp/access_token').to_s
46
+ config[:jsapi_ticket] ||= Rails.root.join('tmp/jsapi_ticket').to_s
47
+ end
48
+ config.symbolize_keys!
49
+ OpenStruct.new(config)
50
+ end
51
+
52
+ def self.config_from_environment
53
+ { appid: ENV['WECHAT_APPID'],
54
+ secret: ENV['WECHAT_SECRET'],
55
+ corpid: ENV['WECHAT_CORPID'],
56
+ corpsecret: ENV['WECHAT_CORPSECRET'],
57
+ agentid: ENV['WECHAT_AGENTID'],
58
+ token: ENV['WECHAT_TOKEN'],
59
+ access_token: ENV['WECHAT_ACCESS_TOKEN'],
60
+ encrypt_mode: ENV['WECHAT_ENCRYPT_MODE'],
61
+ skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
62
+ encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'] }
63
+ end
64
+ end
65
+ end
@@ -73,6 +73,10 @@ module Wechat
73
73
  update(MsgType: 'transfer_customer_service')
74
74
  end
75
75
 
76
+ def success
77
+ update(MsgType: 'success')
78
+ end
79
+
76
80
  def image(media_id)
77
81
  update(MsgType: 'image', Image: { MediaId: media_id })
78
82
  end
@@ -200,7 +200,11 @@ module Wechat
200
200
  end
201
201
 
202
202
  def process_response(response)
203
- msg = response.to_xml
203
+ if response[:MsgType] == 'success'
204
+ msg = 'success'
205
+ else
206
+ msg = response.to_xml
207
+ end
204
208
 
205
209
  if self.class.encrypt_mode
206
210
  encrypt = Base64.strict_encode64(encrypt(pack(msg, @app_id), self.class.encoding_aes_key))
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.3
4
+ version: 0.6.4
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-13 00:00:00.000000000 Z
12
+ date: 2015-11-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: 1.6.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: thor
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: rest-client
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -101,6 +115,7 @@ files:
101
115
  - lib/wechat/access_token.rb
102
116
  - lib/wechat/api.rb
103
117
  - lib/wechat/api_base.rb
118
+ - lib/wechat/api_loader.rb
104
119
  - lib/wechat/cipher.rb
105
120
  - lib/wechat/client.rb
106
121
  - lib/wechat/corp_api.rb