wechat 0.6.7 → 0.6.8

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: eee061e4522d5960256e017183c61f615ef94a0d
4
- data.tar.gz: 510a350df936a6d4d9465997ba253b4ef3e78634
3
+ metadata.gz: eda1d074591c670445ef8e73291eb2131e0a595c
4
+ data.tar.gz: 576db68d3550ab9ac86c392e2ca6757184e0b114
5
5
  SHA512:
6
- metadata.gz: f21668a1dc3cbb3fac9336e57d214a4d9d99a1814e30e1474b1a0e9d12dd47c47bc69c5f6af02c4b6bb89f09ab76ade708ebaebfb838eba4110268730ac69688
7
- data.tar.gz: efa6851ddb7f3f948daccdc148c412f8a73e2211c123c4417ddd3e7195cdeb3030e8f046162328e3c11ded6b96cf3c5143e35d92757fe6770f530ef18ed876a4
6
+ metadata.gz: 70af013d27c8a9a144012c564da1d02927d865fcc64837d1bfb371f525503527d830ac80cb53a512927980e717780a8e88d31f15853a4210eb70780d5a7c716e
7
+ data.tar.gz: c38169bac4eca6015b9be377d95b3b4ae44511ed3df80ae379d76d3b23077e44867da3c98a15437fb447b6a99757479a4e501cc393e2e87bfda8b5279eb4e9e8
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.6.8 (released at 12/25/2015)
4
+
5
+ * Support Rails 5.0.0.beta1.
6
+ * English README available
7
+ * Fix oauth2_url calling error, fix #75
8
+
3
9
  ## v0.6.7 (released at 12/18/2015)
4
10
 
5
11
  * Add timeout configuration option, close #74
@@ -0,0 +1,584 @@
1
+ WeChat [![Gem Version][version-badge]][rubygems] [![Build Status][travis-badge]][travis] [![Code Climate][codeclimate-badge]][codeclimate] [![Code Coverage][codecoverage-badge]][codecoverage]
2
+ ======
3
+
4
+ [![Join the chat][gitter-badge]][gitter] [![Issue Stats][issue-badge]][issuestats] [![PR Stats][pr-badge]][issuestats]
5
+
6
+ WeChat gem 可以帮助开发者方便地在Rails环境中集成微信[公众平台](https://mp.weixin.qq.com/)和[企业平台](https://qy.weixin.qq.com)提供的服务,包括:
7
+
8
+ - 微信公众/企业平台[主动消息](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF)API(命令行和Web环境都可以使用)
9
+ - [回调消息](http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E4%B8%8E%E4%BA%8B%E4%BB%B6)(必须运行Web服务器)
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
+ - OAuth 2.0认证机制
12
+
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)。
18
+
19
+
20
+ ## 安装
21
+
22
+ Using `gem install`
23
+
24
+ ```
25
+ gem install "wechat"
26
+ ```
27
+
28
+ Or add to your app's `Gemfile`:
29
+
30
+ ```
31
+ gem 'wechat'
32
+ ```
33
+
34
+ Run the following command to install it:
35
+
36
+ ```console
37
+ bundle install
38
+ ```
39
+
40
+ Run the generator:
41
+
42
+ ```console
43
+ rails generate wechat:install
44
+ ```
45
+
46
+ 运行`rails g wechat:install`后会自动生成wechat.yml配置,还有wechat controller及相关路由配置到当前Rails项目。
47
+
48
+
49
+ ## 配置
50
+
51
+ #### 命令行程序的配置
52
+
53
+ 要使用命令行程序,需要在home目录中创建一个`~/.wechat.yml`,包含以下内容。其中`access_token`是存放access_token的文件位置。
54
+
55
+ ```
56
+ appid: "my_appid"
57
+ secret: "my_secret"
58
+ access_token: "/var/tmp/wechat_access_token"
59
+ ```
60
+
61
+ Windows或者使用企业号,需要存放在`C:/Users/[user_name]/`下,其中corpid和corpsecret可以从企业号管理界面的设置->权限管理,通过新建任意一个管理组后获取。
62
+
63
+ ```
64
+ corpid: "my_appid"
65
+ corpsecret: "my_secret"
66
+ agentid: 1 # 企业应用的id,整型。可在应用的设置页面查看
67
+ access_token: "C:/Users/[user_name]/wechat_access_token"
68
+ ```
69
+
70
+ #### Rails 全局配置
71
+ Rails应用程序中,需要将配置文件放在`config/wechat.yml`,可以为不同environment创建不同的配置。
72
+
73
+ 公众号配置示例:
74
+
75
+ ```
76
+ default: &default
77
+ appid: "app_id"
78
+ secret: "app_secret"
79
+ token: "app_token"
80
+ access_token: "/var/tmp/wechat_access_token"
81
+
82
+ production:
83
+ appid: <%= ENV['WECHAT_APPID'] %>
84
+ secret: <%= ENV['WECHAT_APP_SECRET'] %>
85
+ token: <%= ENV['WECHAT_TOKEN'] %>
86
+ access_token: <%= ENV['WECHAT_ACCESS_TOKEN'] %>
87
+
88
+ development:
89
+ <<: *default
90
+
91
+ test:
92
+ <<: *default
93
+ ```
94
+
95
+ 公众号可选安全模式(加密模式),通过添加如下配置可开启加密模式。
96
+
97
+ ```
98
+ default: &default
99
+ encrypt_mode: true
100
+ encoding_aes_key: "my_encoding_aes_key"
101
+ ```
102
+
103
+ 企业号配置下必须使用加密模式,其中token和encoding_aes_key可以从企业号管理界面的应用中心->某个应用->模式选择,选择回调模式后获得。
104
+
105
+ ```
106
+ default: &default
107
+ corpid: "corpid"
108
+ corpsecret: "corpsecret"
109
+ agentid: 1
110
+ access_token: "C:/Users/[user_name]/wechat_access_token"
111
+ token: ""
112
+ encoding_aes_key: ""
113
+ jsapi_ticket: "C:/Users/[user_name]/wechat_jsapi_ticket"
114
+
115
+ production:
116
+ corpid: <%= ENV['WECHAT_CORPID'] %>
117
+ corpsecret: <%= ENV['WECHAT_CORPSECRET'] %>
118
+ agentid: <%= ENV['WECHAT_AGENTID'] %>
119
+ access_token: <%= ENV['WECHAT_ACCESS_TOKEN'] %>
120
+ token: <%= ENV['WECHAT_TOKEN'] %>
121
+ timeout: 30,
122
+ skip_verify_ssl: true
123
+ encoding_aes_key: <%= ENV['WECHAT_ENCODING_AES_KEY'] %>
124
+ jsapi_ticket: <%= ENV['WECHAT_JSAPI_TICKET'] %>
125
+
126
+ development:
127
+ <<: *default
128
+
129
+ test:
130
+ <<: *default
131
+ ```
132
+
133
+ ##### 配置优先级
134
+
135
+ 注意在Rails项目根目录下运行`wechat`命令行工具会优先使用`config/wechat.yml`中的`default`配置,如果失败则使用`~\.wechat.yml`中的配置,以便于在生产环境下管理多个微信账号应用。
136
+
137
+ ##### 配置微信服务器超时
138
+
139
+ 微信服务器有时请求会花很长时间,如果不配置,默认为20秒,可视情况配置。
140
+
141
+ ##### 配置跳过SSL认证
142
+
143
+ Wechat服务器有报道曾出现[RestClient::SSLCertificateNotVerified](http://qydev.weixin.qq.com/qa/index.php?qa=11037)错误,此时可以选择关闭SSL验证。`skip_verify_ssl: true`
144
+
145
+ #### 为每个Responder配置不同的appid和secret
146
+
147
+ 在个别情况下,单个Rails应用可能需要处理来自多个账号的消息,此时可以配置多个responder controller。
148
+
149
+ ```ruby
150
+ class WechatFirstController < ActionController::Base
151
+ wechat_responder appid: "app1", secret: "secret1", token: "token1", access_token: Rails.root.join("tmp/access_token1")
152
+
153
+ on :text, with:"help", respond: "help content"
154
+ end
155
+ ```
156
+
157
+ #### jssdk 支持
158
+
159
+ jssdk 使用前需通过config接口注入权限验证配置, 所需参数可以通过 signature 方法获取:
160
+
161
+ ```ruby
162
+ WechatsController.wechat.jsapi_ticket.signature(request.original_url)
163
+ ```
164
+
165
+ ## 关于接口权限
166
+
167
+ wechat gems 内部不会检查权限。但因公众号类型不同,和微信服务器端通讯时,可能会被拒绝,详细权限控制可参考[官方文档](http://mp.weixin.qq.com/wiki/7/2d301d4b757dedc333b9a9854b457b47.html)。
168
+
169
+ ## 使用命令行
170
+
171
+ 根据企业号和公众号配置不同,wechat提供了的命令行命令。
172
+
173
+ #### 公众号命令行
174
+
175
+ ```
176
+ $ wechat
177
+ Wechat commands:
178
+ wechat callbackip # 获取微信服务器IP地址
179
+ wechat custom_image [OPENID, IMAGE_PATH] # 发送图片客服消息
180
+ wechat custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL] # 发送音乐客服消息
181
+ wechat custom_news [OPENID, NEWS_YAML_PATH] # 发送图文客服消息
182
+ wechat custom_text [OPENID, TEXT_MESSAGE] # 发送文字客服消息
183
+ wechat custom_video [OPENID, VIDEO_PATH] # 发送视频客服消息
184
+ wechat custom_voice [OPENID, VOICE_PATH] # 发送语音客服消息
185
+ wechat group_create [GROUP_NAME] # 创建分组
186
+ wechat group_delete [GROUP_ID] # 删除分组
187
+ wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
188
+ wechat groups # 查询所有分组
189
+ wechat material [MEDIA_ID, PATH] # 永久媒体下载
190
+ wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
191
+ wechat material_count # 获取永久素材总数
192
+ wechat material_delete [MEDIA_ID] # 删除永久素材
193
+ wechat material_list [TYPE, OFFSET, COUNT] # 获取永久素材列表
194
+ wechat media [MEDIA_ID, PATH] # 媒体下载
195
+ wechat media_create [MEDIA_TYPE, PATH] # 媒体上传
196
+ wechat menu # 当前菜单
197
+ wechat menu_create [MENU_YAML_PATH] # 创建菜单
198
+ wechat menu_delete # 删除菜单
199
+ wechat oauth2_url [REDIRECT_URI] # 生成OAuth2.0验证URL
200
+ wechat qrcode_create_limit_scene [SCENE_ID_OR_STR] # 请求永久二维码
201
+ wechat qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS] # 请求临时二维码
202
+ wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
203
+ wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
204
+ wechat user [OPEN_ID] # 获取用户基本信息
205
+ wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
206
+ wechat user_group [OPEN_ID] # 查询用户所在分组
207
+ wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
208
+ wechat users # 关注者列表
209
+ ```
210
+
211
+ #### 企业号命令行
212
+ ```
213
+ $ wechat
214
+ Wechat commands:
215
+ wechat agent [AGENT_ID] # 获取企业号应用详情
216
+ wechat agent_list # 获取应用概况列表
217
+ wechat batch_job_result [JOB_ID] # 获取异步任务结果
218
+ wechat batch_replaceparty [BATCH_PARTY_CSV_MEDIA_ID] # 全量覆盖部门
219
+ wechat batch_replaceuser [BATCH_USER_CSV_MEDIA_ID] # 全量覆盖成员
220
+ wechat batch_syncuser [SYNC_USER_CSV_MEDIA_ID] # 增量更新成员
221
+ wechat callbackip # 获取微信服务器IP地址
222
+ wechat convert_to_openid [USER_ID] # userid转换成openid
223
+ wechat custom_image [OPENID, IMAGE_PATH] # 发送图片客服消息
224
+ wechat custom_music [OPENID, THUMBNAIL_PATH, MUSIC_URL] # 发送音乐客服消息
225
+ wechat custom_news [OPENID, NEWS_YAML_PATH] # 发送图文客服消息
226
+ wechat custom_text [OPENID, TEXT_MESSAGE] # 发送文字客服消息
227
+ wechat custom_video [OPENID, VIDEO_PATH] # 发送视频客服消息
228
+ wechat custom_voice [OPENID, VOICE_PATH] # 发送语音客服消息
229
+ wechat department [DEPARTMENT_ID] # 获取部门列表
230
+ wechat department_create [NAME, PARENT_ID] # 创建部门
231
+ wechat department_delete [DEPARTMENT_ID] # 删除部门
232
+ wechat department_update [DEPARTMENT_ID, NAME] # 更新部门
233
+ wechat invite_user [USER_ID] # 邀请成员关注
234
+ wechat material [MEDIA_ID, PATH] # 永久媒体下载
235
+ wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
236
+ wechat material_count # 获取永久素材总数
237
+ wechat material_delete [MEDIA_ID] # 删除永久素材
238
+ wechat material_list [TYPE, OFFSET, COUNT] # 获取永久素材列表
239
+ wechat media [MEDIA_ID, PATH] # 媒体下载
240
+ wechat media_create [MEDIA_TYPE, PATH] # 媒体上传
241
+ wechat menu # 当前菜单
242
+ wechat menu_create [MENU_YAML_PATH] # 创建菜单
243
+ wechat menu_delete # 删除菜单
244
+ wechat message_send [OPENID, TEXT_MESSAGE] # 发送文字消息
245
+ wechat oauth2_url [REDIRECT_URI] # 生成OAuth2.0验证URL
246
+ wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
247
+ wechat tag [TAG_ID] # 获取标签成员
248
+ wechat tag_add_department [TAG_ID, PARTY_IDS] # 增加标签部门
249
+ wechat tag_add_user [TAG_ID, USER_IDS] # 增加标签成员
250
+ wechat tag_create [TAGNAME, TAG_ID] # 创建标签
251
+ wechat tag_del_department [TAG_ID, PARTY_IDS] # 删除标签部门
252
+ wechat tag_del_user [TAG_ID, USER_IDS] # 删除标签成员
253
+ wechat tag_delete [TAG_ID] # 删除标签
254
+ wechat tag_update [TAG_ID, TAGNAME] # 更新标签名字
255
+ wechat tags # 获取标签列表
256
+ wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
257
+ wechat upload_replaceparty [BATCH_PARTY_CSV_PATH] # 上传文件方式全量覆盖部门
258
+ wechat upload_replaceuser [BATCH_USER_CSV_PATH] # 上传文件方式全量覆盖成员
259
+ wechat user [OPEN_ID] # 获取用户基本信息
260
+ wechat user_batchdelete [USER_ID_LIST] # 批量删除成员
261
+ wechat user_delete [USER_ID] # 删除成员
262
+ wechat user_list [DEPARTMENT_ID] # 获取部门成员详情
263
+ wechat user_simplelist [DEPARTMENT_ID] # 获取部门成员
264
+ wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
265
+ ```
266
+
267
+ ### 使用场景
268
+ 以下是几种典型场景的使用方法
269
+
270
+ #####获取所有用户的OPENID
271
+
272
+ ```
273
+ $ wechat users
274
+
275
+ {"total"=>4, "count"=>4, "data"=>{"openid"=>["oCfEht9***********", "oCfEhtwqa***********", "oCfEht9oMCqGo***********", "oCfEht_81H5o2***********"]}, "next_openid"=>"oCfEht_81H5o2***********"}
276
+
277
+ ```
278
+
279
+ #####获取用户的信息
280
+
281
+ ```
282
+ $ wechat user "oCfEht9***********"
283
+
284
+ {"subscribe"=>1, "openid"=>"oCfEht9***********", "nickname"=>"Nickname", "sex"=>1, "language"=>"zh_CN", "city"=>"徐汇", "province"=>"上海", "country"=>"中国", "headimgurl"=>"http://wx.qlogo.cn/mmopen/ajNVdqHZLLBd0SG8NjV3UpXZuiaGGPDcaKHebTKiaTyof*********/0", "subscribe_time"=>1395715239}
285
+
286
+ ```
287
+
288
+ ##### 获取当前菜单
289
+ ```
290
+ $ wechat menu
291
+
292
+ {"menu"=>{"button"=>[{"type"=>"view", "name"=>"保护的", "url"=>"http://***/protected", "sub_button"=>[]}, {"type"=>"view", "name"=>"公开的", "url"=>"http://***", "sub_button"=>[]}]}}
293
+
294
+ ```
295
+
296
+ ##### 创建菜单
297
+ 创建菜单需要一个定义菜单内容的yaml文件,比如
298
+ menu.yaml
299
+
300
+ ```
301
+ button:
302
+ -
303
+ name: "我要"
304
+ sub_button:
305
+ -
306
+ type: "scancode_waitmsg"
307
+ name: "绑定用餐二维码"
308
+ key: "BINDING_QR_CODE"
309
+ -
310
+ type: "click"
311
+ name: "预订午餐"
312
+ key: "BOOK_LUNCH"
313
+ -
314
+ type: "click"
315
+ name: "预订晚餐"
316
+ key: "BOOK_DINNER"
317
+ -
318
+ name: "查询"
319
+ sub_button:
320
+ -
321
+ type: "click"
322
+ name: "进出记录"
323
+ key: "BADGE_IN_OUT"
324
+ -
325
+ type: "click"
326
+ name: "年假余额"
327
+ key: "ANNUAL_LEAVE"
328
+ -
329
+ type: "view"
330
+ name: "关于"
331
+ url: "http://blog.cloud-mes.com/"
332
+ ```
333
+
334
+ 然后执行命令行,需确保设置,权限管理中有对此应用的管理权限,否则会报[60011](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E)错。
335
+
336
+ ```
337
+ $ wechat menu_create menu.yaml
338
+
339
+ ```
340
+
341
+ ##### 发送客服图文消息
342
+ 需定义一个图文消息内容的yaml文件,比如
343
+ articles.yaml
344
+
345
+ ```
346
+ articles:
347
+ -
348
+ title: "习近平在布鲁日欧洲学院演讲"
349
+ description: "新华网比利时布鲁日4月1日电 国家主席习近平1日在比利时布鲁日欧洲学院发表重要演讲"
350
+ url: "http://news.sina.com.cn/c/2014-04-01/232629843387.shtml"
351
+ pic_url: "http://i3.sinaimg.cn/dy/c/2014-04-01/1396366518_bYays1.jpg"
352
+ ```
353
+
354
+ 然后执行命令行
355
+
356
+ ```
357
+ $ wechat custom_news oCfEht9oM*********** articles.yml
358
+
359
+ ```
360
+
361
+ ##### 发送模板消息
362
+ 需定义一个模板消息内容的yaml文件,比如
363
+ template.yml
364
+
365
+ ```
366
+ template:
367
+ template_id: "o64KQ62_xxxxxxxxxxxxxxx-Qz-MlNcRKteq8"
368
+ url: "http://weixin.qq.com/download"
369
+ topcolor: "#FF0000"
370
+ data:
371
+ first:
372
+ value: "你好,你已报名成功"
373
+ color: "#0A0A0A"
374
+ keynote1:
375
+ value: "XX活动"
376
+ color: "#CCCCCC"
377
+ keynote2:
378
+ value: "2014年9月16日"
379
+ color: "#CCCCCC"
380
+ keynote3:
381
+ value: "上海徐家汇xxx城"
382
+ color: "#CCCCCC"
383
+ remark:
384
+ value: "欢迎再次使用。"
385
+ color: "#173177"
386
+
387
+ ```
388
+
389
+ 然后执行命令行
390
+
391
+ ```
392
+ $ wechat template_message oCfEht9oM*********** template.yml
393
+ ```
394
+
395
+ ## Rails Responder Controller DSL
396
+
397
+ 为了在Rails app中响应用户的消息,开发者需要创建一个wechat responder controller. 首先在router中定义
398
+
399
+ ```ruby
400
+ resource :wechat, only:[:show, :create]
401
+ ```
402
+
403
+ 然后创建Controller class, 例如
404
+
405
+ ```ruby
406
+ class WechatsController < ActionController::Base
407
+ wechat_responder
408
+
409
+ # 默认文字信息responder
410
+ on :text do |request, content|
411
+ request.reply.text "echo: #{content}" #Just echo
412
+ end
413
+
414
+ # 当请求的文字信息内容为'help'时, 使用这个responder处理
415
+ on :text, with: 'help' do |request|
416
+ request.reply.text 'help content' #回复帮助信息
417
+ end
418
+
419
+ # 当请求的文字信息内容为'<n>条新闻'时, 使用这个responder处理, 并将n作为第二个参数
420
+ on :text, with: /^(\d+)条新闻$/ do |request, count|
421
+ # 微信最多显示10条新闻,大于10条将只取前10条
422
+ news = (1..count.to_i).each_with_object([]) { |n, memo| memo << { title: '新闻标题', content: "第#{n}条新闻的内容#{n.hash}" } }
423
+ request.reply.news(news) do |article, n, index| # 回复"articles"
424
+ article.item title: "#{index} #{n[:title]}", description: n[:content], pic_url: 'http://www.baidu.com/img/bdlogo.gif', url: 'http://www.baidu.com/'
425
+ end
426
+ end
427
+
428
+ # 当用户加关注
429
+ on :event, with: 'subscribe' do |request|
430
+ request.reply.text "User #{request[:FromUserName]} subscribe now"
431
+ end
432
+
433
+ # 公众号收到未关注用户扫描qrscene_xxxxxx二维码时。注意此次扫描事件将不再引发上条的用户加关注事件
434
+ on :scan, with: 'qrscene_xxxxxx' do |request, ticket|
435
+ request.reply.text "Unsubscribe user #{request[:FromUserName]} Ticket #{ticket}"
436
+ end
437
+
438
+ # 公众号收到已关注用户扫描创建二维码的scene_id事件时
439
+ on :scan, with: 'scene_id' do |request, ticket|
440
+ request.reply.text "Subscribe user #{request[:FromUserName]} Ticket #{ticket}"
441
+ end
442
+
443
+ # 当没有任何on :scan事件处理已关注用户扫描的scene_id时
444
+ on :event, with: 'scan' do |request|
445
+ if request[:EventKey].present?
446
+ request.reply.text "event scan got EventKey #{request[:EventKey]} Ticket #{request[:Ticket]}"
447
+ end
448
+ end
449
+
450
+ # 企业号收到EventKey 为二维码扫描结果事件时
451
+ on :scan, with: 'BINDING_QR_CODE' do |request, scan_result, scan_type|
452
+ request.reply.text "User #{request[:FromUserName]} ScanResult #{scan_result} ScanType #{scan_type}"
453
+ end
454
+
455
+ # 企业号收到EventKey 为CODE 39码扫描结果事件时
456
+ on :scan, with: 'BINDING_BARCODE' do |message, scan_result|
457
+ if scan_result.start_with? 'CODE_39,'
458
+ message.reply.text "User: #{message[:FromUserName]} scan barcode, result is #{scan_result.split(',')[1]}"
459
+ end
460
+ end
461
+
462
+ # 当用户点击菜单时
463
+ on :click, with: 'BOOK_LUNCH' do |request, key|
464
+ request.reply.text "User: #{request[:FromUserName]} click #{key}"
465
+ end
466
+
467
+ # 当用户点击菜单时
468
+ on :view, with: 'http://wechat.somewhere.com/view_url' do |request, view|
469
+ request.reply.text "#{request[:FromUserName]} view #{view}"
470
+ end
471
+
472
+ # 处理图片信息
473
+ on :image do |request|
474
+ request.reply.image(request[:MediaId]) #直接将图片返回给用户
475
+ end
476
+
477
+ # 处理语音信息
478
+ on :voice do |request|
479
+ request.reply.voice(request[:MediaId]) #直接语音音返回给用户
480
+ end
481
+
482
+ # 处理视频信息
483
+ on :video do |request|
484
+ nickname = wechat.user(request[:FromUserName])['nickname'] #调用 api 获得发送者的nickname
485
+ request.reply.video(request[:MediaId], title: '回声', description: "#{nickname}发来的视频请求") #直接视频返回给用户
486
+ end
487
+
488
+ # 处理上报地理位置事件
489
+ on :location do |request|
490
+ request.reply.text("Latitude: #{message[:Latitude]} Longitude: #{message[:Longitude]} Precision: #{message[:Precision]}")
491
+ end
492
+
493
+ # 当用户取消关注订阅
494
+ on :event, with: 'unsubscribe' do |request|
495
+ request.reply.success # user can not receive this message
496
+ end
497
+
498
+ # 成员进入应用的事件推送
499
+ on :event, with: 'enter_agent' do |request|
500
+ request.reply.text "#{request[:FromUserName]} enter agent app now"
501
+ end
502
+
503
+ # 当异步任务增量更新成员完成时推送
504
+ on :batch_job, with: 'sync_user' do |request, batch_job|
505
+ request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
506
+ end
507
+
508
+ # 当异步任务全量覆盖成员完成时推送
509
+ on :batch_job, with: 'replace_user' do |request, batch_job|
510
+ request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
511
+ end
512
+
513
+ # 当异步任务邀请成员关注完成时推送
514
+ on :batch_job, with: 'invite_user' do |request, batch_job|
515
+ request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
516
+ end
517
+
518
+ # 当异步任务全量覆盖部门完成时推送
519
+ on :batch_job, with: 'replace_party' do |request, batch_job|
520
+ request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
521
+ end
522
+
523
+ # 当无任何responder处理用户信息时,使用这个responder处理
524
+ on :fallback, respond: 'fallback message'
525
+ end
526
+ ```
527
+
528
+ 在controller中使用`wechat_responder`引入Responder DSL, 之后可以用
529
+
530
+ ```
531
+ on <message_type> do |message|
532
+ message.reply.text "some text"
533
+ end
534
+ ```
535
+
536
+ 来响应用户信息。
537
+
538
+ 目前支持的message_type有如下几种
539
+
540
+ - :text 响应文字消息,可以用`:with`参数来匹配文本内容 `on(:text, with:'help'){|message, content| ...}`
541
+ - :image 响应图片消息
542
+ - :voice 响应语音消息
543
+ - :video 响应视频消息
544
+ - :link 响应链接消息
545
+ - :event 响应事件消息, 可以用`:with`参数来匹配事件类型
546
+ - :click 虚拟响应事件消息, 微信传入:event,但gem内部会单独处理
547
+ - :view 虚拟响应事件消息, 微信传入:event,但gem内部会单独处理
548
+ - :scan 虚拟响应事件消息
549
+ - :batch_job 虚拟响应事件消息
550
+ - :location 虚拟响应上报地理位置事件消息
551
+ - :fallback 默认响应,当收到的消息无法被其他responder响应时,会使用这个responder.
552
+
553
+ ### 多客服消息转发
554
+
555
+ ```ruby
556
+ class WechatsController < ActionController::Base
557
+ # 当无任何responder处理用户信息时,转发至客服处理。
558
+ on :fallback do |message|
559
+ message.reply.transfer_customer_service
560
+ end
561
+ end
562
+ ```
563
+
564
+ 注意设置了[多客服消息转发](http://dkf.qq.com/)后,不能再添加`默认文字信息responder`,否则文字消息将得不到转发。
565
+
566
+ ## 已知问题
567
+
568
+ * 企业号接受菜单消息时,Wechat腾讯服务器无法解析部分域名,请使用IP绑定回调URL,用户的普通消息目前不受影响。
569
+ * 企业号全量覆盖成员使用的csv通讯录格式,直接将下载的模板导入[是不工作的](http://qydev.weixin.qq.com/qa/index.php?qa=13978),必须使用Excel打开,然后另存为csv格式才会变成合法格式。
570
+
571
+
572
+ [version-badge]: https://badge.fury.io/rb/wechat.svg
573
+ [rubygems]: https://rubygems.org/gems/wechat
574
+ [travis-badge]: https://travis-ci.org/Eric-Guo/wechat.svg
575
+ [travis]: https://travis-ci.org/Eric-Guo/wechat
576
+ [codeclimate-badge]: https://codeclimate.com/github/Eric-Guo/wechat.png
577
+ [codeclimate]: https://codeclimate.com/github/Eric-Guo/wechat
578
+ [codecoverage-badge]: https://codeclimate.com/github/Eric-Guo/wechat/coverage.png
579
+ [codecoverage]: https://codeclimate.com/github/Eric-Guo/wechat/coverage
580
+ [gitter-badge]: https://badges.gitter.im/Join%20Chat.svg
581
+ [gitter]: https://gitter.im/Eric-Guo/wechat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
582
+ [issue-badge]: http://issuestats.com/github/Eric-Guo/wechat/badge/issue
583
+ [pr-badge]: http://issuestats.com/github/Eric-Guo/wechat/badge/pr
584
+ [issuestats]: http://issuestats.com/github/Eric-Guo/wechat
data/README.md CHANGED
@@ -3,21 +3,27 @@ WeChat [![Gem Version][version-badge]][rubygems] [![Build Status][travis-badge]]
3
3
 
4
4
  [![Join the chat][gitter-badge]][gitter] [![Issue Stats][issue-badge]][issuestats] [![PR Stats][pr-badge]][issuestats]
5
5
 
6
- WeChat gem 可以帮助开发者方便地在Rails环境中集成微信[公众平台](https://mp.weixin.qq.com/)和[企业平台](https://qy.weixin.qq.com)提供的服务,包括:
6
+ [中文文档 Chinese document](/README-CN.md)
7
7
 
8
- - 微信公众/企业平台[主动消息](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF)API(命令行和Web环境都可以使用)
9
- - [回调消息](http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E4%B8%8E%E4%BA%8B%E4%BB%B6)(必须运行Web服务器)
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
- - OAuth 2.0认证机制
8
+ [Wechat](http://www.wechat.com/) is a free messaging and calling app developed by [Tencent](http://tencent.com/en-us/index.shtml), after linked billion people, Wechat become a platform of application
12
9
 
13
- 命令行工具`wechat`可以调用各种无需web环境的API。同时也提供了Rails Controller的responder DSL, 可以帮助开发者方便地在Rails应用中集成微信的消息处理机制。
10
+ WeChat gem trying to helping Rails developer to integrated [enterprise account](https://qy.weixin.qq.com) / [public account](https://mp.weixin.qq.com/) easily. Below feature is ready and no need writing adapter code talking to wechat server directly.
14
11
 
15
- 如果你的App还需要集成微信OAuth2.0, 你可以考虑[omniauth-wechat-oauth2](https://github.com/skinnyworm/omniauth-wechat-oauth2), 以便和devise集成,提供完整的用户认证。
12
+ - [Sending message](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF) API(Can access via console or in rails)
13
+ - [Receiving message](http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E4%B8%8E%E4%BA%8B%E4%BB%B6)(You must running on rails server to receiving message)
14
+ - [Wechat JS-SDK](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%BE%AE%E4%BF%A1JS%E6%8E%A5%E5%8F%A3) config signature
15
+ - OAuth 2.0 authentication
16
16
 
17
- 如果你对如何制作微信网页UI没有灵感,可以参考官方的[weui](https://github.com/weui/weui),针对Rails的Gem是[weui-rails](https://github.com/Eric-Guo/weui-rails)。
18
17
 
18
+ `wechat` command share the same API in console, so you can interactive with wechat server quickly, without starting up web environment/code.
19
19
 
20
- ## 安装
20
+ A responder DSL can used in Rails controller, so giving a event based interface to handler message sent by end user from wechat server.
21
+
22
+ Wechat provide OAuth2.0 as authentication service and possible to intergrated with devise/other authorization gems, [omniauth-wechat-oauth2](https://github.com/skinnyworm/omniauth-wechat-oauth2) is a good start
23
+
24
+ There is official [weui](https://github.com/weui/weui), which corresponding Rails gems called [weui-rails](https://github.com/Eric-Guo/weui-rails) available, if you prefer following the same UI design as wechat.
25
+
26
+ ## Installation
21
27
 
22
28
  Using `gem install`
23
29
 
@@ -43,14 +49,14 @@ Run the generator:
43
49
  rails generate wechat:install
44
50
  ```
45
51
 
46
- 运行`rails g wechat:install`后会自动生成wechat.yml配置,还有wechat controller及相关路由配置到当前Rails项目。
52
+ `rails g wechat:install` will generated the initial `wechat.yml` configuration, example wechat controller and corresponding routes.
47
53
 
48
54
 
49
- ## 配置
55
+ ## Configuration
50
56
 
51
- #### 命令行程序的配置
57
+ #### Configure for command line
52
58
 
53
- 要使用命令行程序,需要在home目录中创建一个`~/.wechat.yml`,包含以下内容。其中`access_token`是存放access_token的文件位置。
59
+ You can using `wechat` command solely, you need created configure file `~/.wechat.yml` and including below content for public account. the access_token will be write as a file.
54
60
 
55
61
  ```
56
62
  appid: "my_appid"
@@ -58,19 +64,22 @@ secret: "my_secret"
58
64
  access_token: "/var/tmp/wechat_access_token"
59
65
  ```
60
66
 
61
- Windows或者使用企业号,需要存放在`C:/Users/[user_name]/`下,其中corpidcorpsecret可以从企业号管理界面的设置->权限管理,通过新建任意一个管理组后获取。
67
+ For enterprise account, need using `corpid` instead of `appid` as enterprise account support multiply application (Tencent called agent) in one enterprise account. Obtain the `corpsecret` is a little tricky, must created at management mode->privilege setting and create any of management group to obtain. Due to Tencent currently only provide Chinese interface for they management console, it's highly recommend you find a college knowing Mandarin to help you to obtain.
68
+
69
+ Windows user need store `.wechat.yml` at `C:/Users/[user_name]/` (replace your user name), also be caution the direction of folder separator.
62
70
 
63
71
  ```
64
72
  corpid: "my_appid"
65
73
  corpsecret: "my_secret"
66
- agentid: 1 # 企业应用的id,整型。可在应用的设置页面查看
74
+ agentid: 1 # Integer, which can be obtain from application, settings
67
75
  access_token: "C:/Users/[user_name]/wechat_access_token"
68
76
  ```
69
77
 
70
- #### Rails 全局配置
71
- Rails应用程序中,需要将配置文件放在`config/wechat.yml`,可以为不同environment创建不同的配置。
78
+ #### Configure for Rails
72
79
 
73
- 公众号配置示例:
80
+ Rails configuration files support different environment similar to database.yml, after running `rails generate wechat:install` you can find configuration files at `config/wechat.yml`
81
+
82
+ Public account congfigure example:
74
83
 
75
84
  ```
76
85
  default: &default
@@ -92,7 +101,8 @@ test:
92
101
  <<: *default
93
102
  ```
94
103
 
95
- 公众号可选安全模式(加密模式),通过添加如下配置可开启加密模式。
104
+ Although it's optional for public account, but highly recommend to enable encrypt mode by add below two items to `wechat.yml`
105
+
96
106
 
97
107
  ```
98
108
  default: &default
@@ -100,7 +110,9 @@ default: &default
100
110
  encoding_aes_key: "my_encoding_aes_key"
101
111
  ```
102
112
 
103
- 企业号配置下必须使用加密模式,其中token和encoding_aes_key可以从企业号管理界面的应用中心->某个应用->模式选择,选择回调模式后获得。
113
+ Enterprise account must using encrypt mode (`encrypt_mode: true` is default on, no need configure).
114
+
115
+ The `token` and `encoding_aes_key` can be obtain from management console -> one of the agent application -> Mode selection, select callback mode and get/set.
104
116
 
105
117
  ```
106
118
  default: &default
@@ -119,7 +131,7 @@ production:
119
131
  access_token: <%= ENV['WECHAT_ACCESS_TOKEN'] %>
120
132
  token: <%= ENV['WECHAT_TOKEN'] %>
121
133
  timeout: 30,
122
- skip_verify_ssl: true
134
+ skip_verify_ssl: true # not recommend
123
135
  encoding_aes_key: <%= ENV['WECHAT_ENCODING_AES_KEY'] %>
124
136
  jsapi_ticket: <%= ENV['WECHAT_JSAPI_TICKET'] %>
125
137
 
@@ -130,21 +142,21 @@ test:
130
142
  <<: *default
131
143
  ```
132
144
 
133
- ##### 配置优先级
145
+ ##### Configure priority
134
146
 
135
- 注意在Rails项目根目录下运行`wechat`命令行工具会优先使用`config/wechat.yml`中的`default`配置,如果失败则使用`~\.wechat.yml`中的配置,以便于在生产环境下管理多个微信账号应用。
147
+ Running `wechat` command in the root folder of Rails application will using the Rails configuration first (`default` section), if can not find it, will relay on `~\.wechat.yml`, such behavior enable manage more wechat public account and enterprise account without changing your home `~\.wechat.yml` file.
136
148
 
137
- ##### 配置微信服务器超时
149
+ ##### Wechat server timeout setting
138
150
 
139
- 微信服务器有时请求会花很长时间,如果不配置,默认为20秒,可视情况配置。
151
+ Stability various even for Tencent wechat server, so setting a long timeout may needed, default is 20 seconds if not set.
140
152
 
141
- ##### 配置跳过SSL认证
153
+ ##### Skip the SSL verification
142
154
 
143
- Wechat服务器有报道曾出现[RestClient::SSLCertificateNotVerified](http://qydev.weixin.qq.com/qa/index.php?qa=11037)错误,此时可以选择关闭SSL验证。`skip_verify_ssl: true`
155
+ SSL Certification can also be corrupted by some reason in China, [it's reported](http://qydev.weixin.qq.com/qa/index.php?qa=11037) and if it's happen to you, can setting `skip_verify_ssl: true`. (not recommend)
144
156
 
145
- #### 为每个Responder配置不同的appid和secret
157
+ #### Configure individual responder with different appid
146
158
 
147
- 在个别情况下,单个Rails应用可能需要处理来自多个账号的消息,此时可以配置多个responder controller。
159
+ Rare case, you may want to hosting more than one wechat enterprise/public account in one Rails application, so you can given those configuration info when calling `wechat_responder`
148
160
 
149
161
  ```ruby
150
162
  class WechatFirstController < ActionController::Base
@@ -154,23 +166,25 @@ class WechatFirstController < ActionController::Base
154
166
  end
155
167
  ```
156
168
 
157
- #### jssdk 支持
169
+ #### JS-SDK helper
158
170
 
159
- jssdk 使用前需通过config接口注入权限验证配置, 所需参数可以通过 signature 方法获取:
171
+ JS-SDK enable you control wechat behavior in your web page, but need inject a config with signature methods first, you can obtain those signature hash via below
160
172
 
161
173
  ```ruby
162
174
  WechatsController.wechat.jsapi_ticket.signature(request.original_url)
163
175
  ```
164
176
 
165
- ## 关于接口权限
177
+ ## The API privilege
166
178
 
167
- wechat gems 内部不会检查权限。但因公众号类型不同,和微信服务器端通讯时,可能会被拒绝,详细权限控制可参考[官方文档](http://mp.weixin.qq.com/wiki/7/2d301d4b757dedc333b9a9854b457b47.html)
179
+ wechat gems won't handle any privilege exception. (except token time out, but it's not important to you as it's auto retry/recovery in gems internally), but Tencent will control a lot of privilege based on your public account type and certification, more info, please reference [official document](http://mp.weixin.qq.com/wiki/7/2d301d4b757dedc333b9a9854b457b47.html).
168
180
 
169
- ## 使用命令行
181
+ ## Command line mode
170
182
 
171
- 根据企业号和公众号配置不同,wechat提供了的命令行命令。
183
+ The available API is different between public account and enterprise account, so wechat gems provide different set of command.
172
184
 
173
- #### 公众号命令行
185
+ Feel safe if you can not read Chinese in the comments, it's keep there in order to copy & find in official document more easier.
186
+
187
+ #### Public account command line
174
188
 
175
189
  ```
176
190
  $ wechat
@@ -208,7 +222,7 @@ Wechat commands:
208
222
  wechat users # 关注者列表
209
223
  ```
210
224
 
211
- #### 企业号命令行
225
+ #### Enterprise account command line
212
226
  ```
213
227
  $ wechat
214
228
  Wechat commands:
@@ -264,10 +278,9 @@ Wechat commands:
264
278
  wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
265
279
  ```
266
280
 
267
- ### 使用场景
268
- 以下是几种典型场景的使用方法
281
+ ### Command line usage demo (partially)
269
282
 
270
- #####获取所有用户的OPENID
283
+ ##### Fetch all users open id
271
284
 
272
285
  ```
273
286
  $ wechat users
@@ -276,7 +289,7 @@ $ wechat users
276
289
 
277
290
  ```
278
291
 
279
- #####获取用户的信息
292
+ ##### Fetch user info
280
293
 
281
294
  ```
282
295
  $ wechat user "oCfEht9***********"
@@ -285,15 +298,7 @@ $ wechat user "oCfEht9***********"
285
298
 
286
299
  ```
287
300
 
288
- #####获取用户的信息
289
-
290
- ```
291
- $ wechat user "oCfEht9***********"
292
-
293
- {"subscribe"=>1, "openid"=>"oCfEht9***********", "nickname"=>"Nickname", "sex"=>1, "language"=>"zh_CN", "city"=>"徐汇", "province"=>"上海", "country"=>"中国", "headimgurl"=>"http://wx.qlogo.cn/mmopen/ajNVdqHZLLBd0SG8NjV3UpXZuiaGGPDcaKHebTKiaTyof*********/0", "subscribe_time"=>1395715239}
294
- ```
295
-
296
- ##### 获取当前菜单
301
+ ##### Fetch menu
297
302
  ```
298
303
  $ wechat menu
299
304
 
@@ -301,14 +306,14 @@ $ wechat menu
301
306
 
302
307
  ```
303
308
 
304
- ##### 创建菜单
305
- 创建菜单需要一个定义菜单内容的yaml文件,比如
306
- menu.yaml
309
+ ##### Menu create
310
+
311
+ menu content for a wechat application can be defined as a yaml files, like `menu.yaml`
307
312
 
308
313
  ```
309
314
  button:
310
315
  -
311
- name: "我要"
316
+ name: "Want"
312
317
  sub_button:
313
318
  -
314
319
  type: "scancode_waitmsg"
@@ -323,7 +328,7 @@ button:
323
328
  name: "预订晚餐"
324
329
  key: "BOOK_DINNER"
325
330
  -
326
- name: "查询"
331
+ name: "Query"
327
332
  sub_button:
328
333
  -
329
334
  type: "click"
@@ -335,20 +340,20 @@ button:
335
340
  key: "ANNUAL_LEAVE"
336
341
  -
337
342
  type: "view"
338
- name: "关于"
343
+ name: "About"
339
344
  url: "http://blog.cloud-mes.com/"
340
345
  ```
341
346
 
342
- 然后执行命令行,需确保设置,权限管理中有对此应用的管理权限,否则会报[60011](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E)错。
347
+ Caution: make sure you having management privilege for those application below running below command, other will got [60011](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E) error.
343
348
 
344
349
  ```
345
350
  $ wechat menu_create menu.yaml
346
-
347
351
  ```
348
352
 
349
- ##### 发送客服图文消息
350
- 需定义一个图文消息内容的yaml文件,比如
351
- articles.yaml
353
+ ##### Sent custom news
354
+
355
+
356
+ Sending custom_news should also defined as a yaml file, like `articles.yaml`
352
357
 
353
358
  ```
354
359
  articles:
@@ -359,16 +364,16 @@ articles:
359
364
  pic_url: "http://i3.sinaimg.cn/dy/c/2014-04-01/1396366518_bYays1.jpg"
360
365
  ```
361
366
 
362
- 然后执行命令行
367
+ After that, can running command:
363
368
 
364
369
  ```
365
370
  $ wechat custom_news oCfEht9oM*********** articles.yml
366
371
 
367
372
  ```
368
373
 
369
- ##### 发送模板消息
370
- 需定义一个模板消息内容的yaml文件,比如
371
- template.yml
374
+ ##### Sent template message
375
+
376
+ Sending template message via yaml file similar too, defined `template.yml` and content is just the template content.
372
377
 
373
378
  ```
374
379
  template:
@@ -377,24 +382,24 @@ template:
377
382
  topcolor: "#FF0000"
378
383
  data:
379
384
  first:
380
- value: "你好,你已报名成功"
385
+ value: "Hello, you successfully registed"
381
386
  color: "#0A0A0A"
382
387
  keynote1:
383
- value: "XX活动"
388
+ value: "5km Health Running"
384
389
  color: "#CCCCCC"
385
390
  keynote2:
386
- value: "2014年9月16"
391
+ value: "2014-09-16"
387
392
  color: "#CCCCCC"
388
393
  keynote3:
389
- value: "上海徐家汇xxx城"
394
+ value: "Centry Park, Pudong, Shanghai"
390
395
  color: "#CCCCCC"
391
396
  remark:
392
- value: "欢迎再次使用。"
397
+ value: "Welcome back"
393
398
  color: "#173177"
394
399
 
395
400
  ```
396
401
 
397
- 然后执行命令行
402
+ After that, can running command:
398
403
 
399
404
  ```
400
405
  $ wechat template_message oCfEht9oM*********** template.yml
@@ -402,138 +407,138 @@ $ wechat template_message oCfEht9oM*********** template.yml
402
407
 
403
408
  ## Rails Responder Controller DSL
404
409
 
405
- 为了在Rails app中响应用户的消息,开发者需要创建一个wechat responder controller. 首先在router中定义
410
+ In order to responding the message user sent, Rails developer need create a wechat responder controller and defined the routing in `routes.rb`
406
411
 
407
412
  ```ruby
408
413
  resource :wechat, only:[:show, :create]
409
414
  ```
410
415
 
411
- 然后创建Controller class, 例如
416
+ So the ActionController should defined like below:
412
417
 
413
418
  ```ruby
414
419
  class WechatsController < ActionController::Base
415
420
  wechat_responder
416
-
417
- # 默认文字信息responder
421
+ wechat_responder
422
+
423
+ # default text responder when no other match
418
424
  on :text do |request, content|
419
- request.reply.text "echo: #{content}" #Just echo
425
+ request.reply.text "echo: #{content}" # Just echo
420
426
  end
421
427
 
422
- # 当请求的文字信息内容为'help'时, 使用这个responder处理
428
+ # When receive 'help', will trigger this responder
423
429
  on :text, with: 'help' do |request|
424
- request.reply.text 'help content' #回复帮助信息
430
+ request.reply.text 'help content'
425
431
  end
426
432
 
427
- # 当请求的文字信息内容为'<n>条新闻'时, 使用这个responder处理, 并将n作为第二个参数
428
- on :text, with: /^(\d+)条新闻$/ do |request, count|
429
- # 微信最多显示10条新闻,大于10条将只取前10条
430
- news = (1..count.to_i).each_with_object([]) { |n, memo| memo << { title: '新闻标题', content: "第#{n}条新闻的内容#{n.hash}" } }
431
- request.reply.news(news) do |article, n, index| # 回复"articles"
433
+ # When receive '<n>news', will match and will got count as <n> as parameter
434
+ on :text, with: /^(\d+) news$/ do |request, count|
435
+ # Wechat article can only contain max 10 items, large than 10 will dropped.
436
+ news = (1..count.to_i).each_with_object([]) { |n, memo| memo << { title: 'News title', content: "No. #{n} news content" } }
437
+ request.reply.news(news) do |article, n, index| # article is return object
432
438
  article.item title: "#{index} #{n[:title]}", description: n[:content], pic_url: 'http://www.baidu.com/img/bdlogo.gif', url: 'http://www.baidu.com/'
433
439
  end
434
440
  end
435
441
 
436
- # 当用户加关注
437
442
  on :event, with: 'subscribe' do |request|
438
- request.reply.text "User #{request[:FromUserName]} subscribe now"
443
+ request.reply.text "#{request[:FromUserName]} subscribe now"
439
444
  end
440
445
 
441
- # 公众号收到未关注用户扫描qrscene_xxxxxx二维码时。注意此次扫描事件将不再引发上条的用户加关注事件
446
+ # When unsubscribe user scan qrcode qrscene_xxxxxx to subscribe in public account
447
+ # notice user will subscribe public account at same time, so wechat won't trigger subscribe event any more
442
448
  on :scan, with: 'qrscene_xxxxxx' do |request, ticket|
443
449
  request.reply.text "Unsubscribe user #{request[:FromUserName]} Ticket #{ticket}"
444
450
  end
445
451
 
446
- # 公众号收到已关注用户扫描创建二维码的scene_id事件时
452
+ # When subscribe user scan scene_id in public account
447
453
  on :scan, with: 'scene_id' do |request, ticket|
448
454
  request.reply.text "Subscribe user #{request[:FromUserName]} Ticket #{ticket}"
449
455
  end
450
456
 
451
- # 当没有任何on :scan事件处理已关注用户扫描的scene_id
457
+ # When no any on :scan responder can match subscribe user scaned scene_id
452
458
  on :event, with: 'scan' do |request|
453
459
  if request[:EventKey].present?
454
460
  request.reply.text "event scan got EventKey #{request[:EventKey]} Ticket #{request[:Ticket]}"
455
461
  end
456
462
  end
457
463
 
458
- # 企业号收到EventKey 为二维码扫描结果事件时
464
+ # When enterprise user press menu BINDING_QR_CODE and success to scan bar code
459
465
  on :scan, with: 'BINDING_QR_CODE' do |request, scan_result, scan_type|
460
466
  request.reply.text "User #{request[:FromUserName]} ScanResult #{scan_result} ScanType #{scan_type}"
461
467
  end
462
468
 
463
- # 企业号收到EventKey 为CODE 39码扫描结果事件时
469
+ # Except QR code, wechat can also scan CODE_39 bar code in enterprise account
464
470
  on :scan, with: 'BINDING_BARCODE' do |message, scan_result|
465
471
  if scan_result.start_with? 'CODE_39,'
466
472
  message.reply.text "User: #{message[:FromUserName]} scan barcode, result is #{scan_result.split(',')[1]}"
467
473
  end
468
474
  end
469
475
 
470
- # 当用户点击菜单时
476
+ # When user click the menu button
471
477
  on :click, with: 'BOOK_LUNCH' do |request, key|
472
478
  request.reply.text "User: #{request[:FromUserName]} click #{key}"
473
479
  end
474
480
 
475
- # 当用户点击菜单时
481
+ # When user view URL in the menu button
476
482
  on :view, with: 'http://wechat.somewhere.com/view_url' do |request, view|
477
483
  request.reply.text "#{request[:FromUserName]} view #{view}"
478
484
  end
479
485
 
480
- # 处理图片信息
486
+ # When user sent the imsage
481
487
  on :image do |request|
482
- request.reply.image(request[:MediaId]) #直接将图片返回给用户
488
+ request.reply.image(request[:MediaId]) # Echo the sent image to user
483
489
  end
484
490
 
485
- # 处理语音信息
491
+ # When user sent the voice
486
492
  on :voice do |request|
487
- request.reply.voice(request[:MediaId]) #直接语音音返回给用户
493
+ request.reply.voice(request[:MediaId]) # Echo the sent voice to user
488
494
  end
489
495
 
490
- # 处理视频信息
496
+ # When user sent the video
491
497
  on :video do |request|
492
- nickname = wechat.user(request[:FromUserName])['nickname'] #调用 api 获得发送者的nickname
493
- request.reply.video(request[:MediaId], title: '回声', description: "#{nickname}发来的视频请求") #直接视频返回给用户
498
+ nickname = wechat.user(request[:FromUserName])['nickname'] # Call wechat api to get sender nickname
499
+ request.reply.video(request[:MediaId], title: 'Echo', description: "Got #{nickname} sent video") # Echo the sent video to user
494
500
  end
495
501
 
496
- # 处理上报地理位置事件
502
+ # When user sent location
497
503
  on :location do |request|
498
504
  request.reply.text("Latitude: #{message[:Latitude]} Longitude: #{message[:Longitude]} Precision: #{message[:Precision]}")
499
505
  end
500
506
 
501
- # 当用户取消关注订阅
502
507
  on :event, with: 'unsubscribe' do |request|
503
508
  request.reply.success # user can not receive this message
504
509
  end
505
510
 
506
- # 成员进入应用的事件推送
511
+ # When user enter the app / agent app
507
512
  on :event, with: 'enter_agent' do |request|
508
513
  request.reply.text "#{request[:FromUserName]} enter agent app now"
509
514
  end
510
515
 
511
- # 当异步任务增量更新成员完成时推送
516
+ # When batch job create/update user (incremental) finished.
512
517
  on :batch_job, with: 'sync_user' do |request, batch_job|
513
- request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
518
+ request.reply.text "sync_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
514
519
  end
515
520
 
516
- # 当异步任务全量覆盖成员完成时推送
521
+ # When batch job replace user (full sync) finished.
517
522
  on :batch_job, with: 'replace_user' do |request, batch_job|
518
- request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
523
+ request.reply.text "replace_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
519
524
  end
520
525
 
521
- # 当异步任务邀请成员关注完成时推送
526
+ # When batch job invent user finished.
522
527
  on :batch_job, with: 'invite_user' do |request, batch_job|
523
- request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
528
+ request.reply.text "invite_user job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
524
529
  end
525
530
 
526
- # 当异步任务全量覆盖部门完成时推送
531
+ # When batch job replace department (full sync) finished.
527
532
  on :batch_job, with: 'replace_party' do |request, batch_job|
528
- request.reply.text "job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
533
+ request.reply.text "replace_party job #{batch_job[:JobId]} finished, return code #{batch_job[:ErrCode]}, return message #{batch_job[:ErrMsg]}"
529
534
  end
530
535
 
531
- # 当无任何responder处理用户信息时,使用这个responder处理
536
+ # Any not match above will fail to below
532
537
  on :fallback, respond: 'fallback message'
533
538
  end
534
539
  ```
535
540
 
536
- 在controller中使用`wechat_responder`引入Responder DSL, 之后可以用
541
+ So the importent statement is only `wechat_responder`, all other is just a DSL:
537
542
 
538
543
  ```
539
544
  on <message_type> do |message|
@@ -541,46 +546,42 @@ on <message_type> do |message|
541
546
  end
542
547
  ```
543
548
 
544
- 来响应用户信息。
549
+ The block code will be running to responding user's message.
545
550
 
546
- 目前支持的message_type有如下几种
547
551
 
548
- - :text 响应文字消息,可以用`:with`参数来匹配文本内容 `on(:text, with:'help'){|message, content| ...}`
549
- - :image 响应图片消息
550
- - :voice 响应语音消息
551
- - :video 响应视频消息
552
- - :link 响应链接消息
553
- - :event 响应事件消息, 可以用`:with`参数来匹配事件类型
554
- - :click 虚拟响应事件消息, 微信传入:event,但gem内部会单独处理
555
- - :view 虚拟响应事件消息, 微信传入:event,但gem内部会单独处理
556
- - :scan 虚拟响应事件消息
557
- - :batch_job 虚拟响应事件消息
558
- - :location 虚拟响应上报地理位置事件消息
559
- - :fallback 默认响应,当收到的消息无法被其他responder响应时,会使用这个responder.
552
+ Below is current supported message_type:
560
553
 
561
- ### 多客服消息转发
554
+ - :text text message, using `:with` to match text content like `on(:text, with:'help'){|message, content| ...}`
555
+ - :image image message
556
+ - :voice voice message
557
+ - :video video message
558
+ - :link link message
559
+ - :event event message, using `:with` to match particular event
560
+ - :click virtual event message, wechat still sent event message,but gems will mapping to menu click event.
561
+ - :view virtual view message, wechat still sent event message,but gems will mapping to menu view page event.
562
+ - :scan virtual scan message, wechat still sent event message, but gems will mapping on scan event
563
+ - :batch_job virtual batch job message
564
+ - :location virtual location message
565
+ - :fallback default message, when no other responder can handle incoming messsage, will using fallback to handle
566
+
567
+ ### Transfer to customer service
562
568
 
563
569
  ```ruby
564
570
  class WechatsController < ActionController::Base
565
- # 当无任何responder处理用户信息时,转发至客服处理。
571
+ # When no other responder can handle incoming message, will transfer to human customer service.
566
572
  on :fallback do |message|
567
- message.reply.transfer_customer_service
573
+ message.reply.transfer_customer_service
568
574
  end
569
575
  end
570
576
  ```
571
577
 
572
- 注意设置了[多客服消息转发](http://dkf.qq.com/)后,不能再添加`默认文字信息responder`,否则文字消息将得不到转发。
573
-
574
- ## Message DSL
575
-
576
- Wechat 的核心是一个Message DSL,帮助开发者构建各种类型的消息,包括主动推送的和被动响应的。
577
- ....
578
+ Caution: do not setting default text responder if you want to using [multiply human customer service](http://dkf.qq.com/), other will lead text message can not transfer.
578
579
 
579
580
 
580
- ## 已知问题
581
+ ## Known Issue
581
582
 
582
- * 企业号接受菜单消息时,Wechat腾讯服务器无法解析部分域名,请使用IP绑定回调URL,用户的普通消息目前不受影响。
583
- * 企业号全量覆盖成员使用的csv通讯录格式,直接将下载的模板导入[是不工作的](http://qydev.weixin.qq.com/qa/index.php?qa=13978),必须使用Excel打开,然后另存为csv格式才会变成合法格式。
583
+ * Sometime, enterprise account can not receive the menu message due to Tencent server can not resolved the DNS, so using IP as a callback URL more stable, but it's never happen for user sent text message.
584
+ * Enterprise batch replace users using a CSV format file, but if you using the download template directly, it's [not working](http://qydev.weixin.qq.com/qa/index.php?qa=13978), must open the CSV file in excel first, then save as CSV format again, seems Tencent only support Excel save as CSV file format.
584
585
 
585
586
 
586
587
  [version-badge]: https://badge.fury.io/rb/wechat.svg
data/bin/wechat CHANGED
@@ -288,7 +288,7 @@ class App < Thor
288
288
  desc 'oauth2_url [REDIRECT_URI]', '生成OAuth2.0验证URL'
289
289
  def oauth2_url(redirect_uri)
290
290
  appid = Wechat.config.corpid || Wechat.config.appid
291
- puts oauth2_url(redirect_uri, appid)
291
+ puts wechat_api.oauth2_url(redirect_uri, appid)
292
292
  end
293
293
 
294
294
  desc 'user_update_remark [OPEN_ID, REMARK]', '设置备注名'
@@ -7,8 +7,15 @@ module Wechat
7
7
  include Cipher
8
8
 
9
9
  included do
10
- skip_before_filter :verify_authenticity_token
11
- before_filter :verify_signature, only: [:show, :create]
10
+ # Rails 5 remove before_filter and skip_before_filter
11
+ if defined?(:skip_before_action)
12
+ # Rails 5 API mode won't define verify_authenticity_token
13
+ skip_before_action :verify_authenticity_token unless defined?(:verify_authenticity_token)
14
+ before_action :verify_signature, only: [:show, :create]
15
+ else
16
+ skip_before_filter :verify_authenticity_token
17
+ before_filter :verify_signature, only: [:show, :create]
18
+ end
12
19
  end
13
20
 
14
21
  module ClassMethods
@@ -153,7 +160,7 @@ module Wechat
153
160
  response = run_responder(request)
154
161
 
155
162
  if response.respond_to? :to_xml
156
- render xml: process_response(response)
163
+ render plain: process_response(response)
157
164
  else
158
165
  render nothing: true, status: 200, content_type: 'text/html'
159
166
  end
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.7
4
+ version: 0.6.8
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-12-18 00:00:00.000000000 Z
12
+ date: 2015-12-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -18,6 +18,9 @@ dependencies:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: '3.2'
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: 5.1.x
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -25,6 +28,9 @@ dependencies:
25
28
  - - ">="
26
29
  - !ruby/object:Gem::Version
27
30
  version: '3.2'
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: 5.1.x
28
34
  - !ruby/object:Gem::Dependency
29
35
  name: nokogiri
30
36
  requirement: !ruby/object:Gem::Requirement
@@ -104,6 +110,7 @@ extra_rdoc_files: []
104
110
  files:
105
111
  - CHANGELOG.md
106
112
  - LICENSE
113
+ - README-CN.md
107
114
  - README.md
108
115
  - Rakefile
109
116
  - bin/wechat