wechat 0.7.1 → 0.7.2

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: 24f3a19bb36361d788567cdb400d5a6247753de4
4
- data.tar.gz: eee12cc2791847bb3a0568d57829b348785d10c8
3
+ metadata.gz: bbc60307e8e7d73cfc58fde18740ea50e931399e
4
+ data.tar.gz: 0c56939175b6f0ee07b8b0bd380ac1fa17cd12a4
5
5
  SHA512:
6
- metadata.gz: 742d6ed1dbad1e243aea4fce5e289838aee163f858da65d818c82638069e0ecb5a1afd94cb7a9b2689f30867aa4a6c18a8389fe7bdca8e81cae988fedf6dc04e
7
- data.tar.gz: 8e0f78fedb6bc0cd798d1f8debbab117e3fa8ac642e5c42504d6e2226656b4813fd4ab3685b7092473ebc3ad0964ed416ee5db2b141742b0c70a3839477982a0
6
+ metadata.gz: 726d952d12a6722bd1920c53fa1061e00de1b54b88cf3ed6275411652057e44158be477902be28188efdfad04c20c913c904b564fe94cf357a82533ba9248ed5
7
+ data.tar.gz: 7b97b70b821def7858e908976712f8baec1f30014749ee94cb91eacfeeeb279b35d67da253c0fe06f3894cb19f55473ead516e35e5d68f5fd50c928584ea1b8a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.7.2 (released at 1/18/2016)
4
+
5
+ * Optional session support by @zfben #81, #88, #91
6
+ * Replace after_wechat_response with Rails Nofications facility, by @zfben, original issue is #79
7
+ * New user_batchget API. #89
8
+ * Support Rails 3.2 again after support Rails 5.0. by @guange2015 #87
9
+ * Fetch setting from RAILS_ENV first, then fetch default. by @kikyous #85
10
+ * Warning not support on :scan with regular expression, reason see #84
11
+
3
12
  ## v0.7.1 (released at 1/11/2016)
4
13
 
5
14
  * Fix after using http, upload file function break. #78
@@ -10,6 +19,12 @@
10
19
 
11
20
  * Using [http](https://github.com/httprb/http) instead of rest-client for performance reason. (not support upload file yet)
12
21
 
22
+ ## v0.6.10 (released at 1/17/2016)
23
+
24
+ * Support Rails 3.2 again after support Rails 5.0. by @guange2015 #87
25
+ * Fetch setting from RAILS_ENV first, then fetch default. by @kikyous #85
26
+ * Warning not support on :scan with regular expression. by @kikyous #84
27
+
13
28
  ## v0.6.9 (released at 1/6/2016)
14
29
 
15
30
  * Fix token refresh bug on multi worker. #76
data/README-CN.md CHANGED
@@ -9,6 +9,7 @@ WeChat gem 可以帮助开发者方便地在Rails环境中集成微信[公众平
9
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
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
+ - 回调消息会话(session)记录机制(可选)
12
13
 
13
14
  命令行工具`wechat`可以调用各种无需web环境的API。同时也提供了Rails Controller的responder DSL, 可以帮助开发者方便地在Rails应用中集成微信的消息处理,包括主动推送的和被动响应的消息。
14
15
 
@@ -45,6 +46,15 @@ rails generate wechat:install
45
46
 
46
47
  运行`rails g wechat:install`后会自动生成wechat.yml配置,还有wechat controller及相关路由配置到当前Rails项目。
47
48
 
49
+ 启用session会话记录:
50
+
51
+ ```console
52
+ rails g wechat:session
53
+ rake db:migrate
54
+ ```
55
+
56
+ 运行后会自动启用回调消息会话(session)记录,wechat gem会在Rails项目中生成两个文件,用户可以在*wechat_session*表中添加更多字段或者声明一些关联关系。使用已有的**hash_store**直接保存也是可以的,但对于PostgreSQL用户,使用[hstore](http://guides.rubyonrails.org/active_record_postgresql.html#hstore)或者json格式可能更佳,当然,最佳方案仍然是添加新字段记录数据。
57
+
48
58
 
49
59
  ## 配置
50
60
 
@@ -202,6 +212,7 @@ Wechat commands:
202
212
  wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
203
213
  wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
204
214
  wechat user [OPEN_ID] # 获取用户基本信息
215
+ wechat user_batchget [OPEN_ID_LIST] # 批量获取用户基本信息
205
216
  wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
206
217
  wechat user_group [OPEN_ID] # 查询用户所在分组
207
218
  wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
@@ -522,13 +533,6 @@ class WechatsController < ActionController::Base
522
533
 
523
534
  # 当无任何responder处理用户信息时,使用这个responder处理
524
535
  on :fallback, respond: 'fallback message'
525
-
526
- # 如果你要在微信回复后增加一些操作,可以用 after_wechat_response(req, res)
527
- # private
528
- #
529
- # def after_wechat_response(req, res)
530
- # WechatLog.create req: req, res: res
531
- # end
532
536
  end
533
537
  ```
534
538
 
@@ -570,6 +574,20 @@ end
570
574
 
571
575
  注意设置了[多客服消息转发](http://dkf.qq.com/)后,不能再添加`默认文字信息responder`,否则文字消息将得不到转发。
572
576
 
577
+ ### 通知
578
+
579
+ 现支持以下通知:
580
+
581
+ * `wechat.responder.after_create` data 包含 request<Wechat::Message> 和 response<Wechat::Message>
582
+
583
+ 使用示例:
584
+
585
+ ```ruby
586
+ ActiveSupport::Notifications.subscribe('wechat.responder.after_create') do |name, started, finished, unique_id, data|
587
+ WechatLog.create request: data[:request], response: data[:response]
588
+ end
589
+ ```
590
+
573
591
  ## 已知问题
574
592
 
575
593
  * 企业号接受菜单消息时,Wechat腾讯服务器无法解析部分域名,请使用IP绑定回调URL,用户的普通消息目前不受影响。
data/README.md CHANGED
@@ -13,6 +13,7 @@ WeChat gem trying to helping Rails developer to integrated [enterprise account](
13
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
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
15
  - OAuth 2.0 authentication
16
+ - Record session when received message from user (Optional)
16
17
 
17
18
 
18
19
  `wechat` command share the same API in console, so you can interactive with wechat server quickly, without starting up web environment/code.
@@ -51,12 +52,20 @@ rails generate wechat:install
51
52
 
52
53
  `rails g wechat:install` will generated the initial `wechat.yml` configuration, example wechat controller and corresponding routes.
53
54
 
55
+ Enable session record:
56
+
57
+ ```console
58
+ rails g wechat:session
59
+ rake db:migrate
60
+ ```
61
+
62
+ Enable session record will generate two files in Rails folder, User can add more column fields in *wechat_session* table and add declare to link to users table, it's also possible to store data directly in **hash_store**. if you are using PostgreSQL, using [hstore](http://guides.rubyonrails.org/active_record_postgresql.html#hstore)/json maybe better, but the best way is still add dedicate column to record the data, the Rails way.
54
63
 
55
64
  ## Configuration
56
65
 
57
66
  #### Configure for command line
58
67
 
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.
68
+ To using `wechat` command solely, needs created configure file `~/.wechat.yml` and including below content for public account. the access_token will be write as a file.
60
69
 
61
70
  ```
62
71
  appid: "my_appid"
@@ -216,6 +225,7 @@ Wechat commands:
216
225
  wechat qrcode_download [TICKET, QR_CODE_PIC_PATH] # 通过ticket下载二维码
217
226
  wechat template_message [OPENID, TEMPLATE_YAML_PATH] # 模板消息接口
218
227
  wechat user [OPEN_ID] # 获取用户基本信息
228
+ wechat user_batchget [OPEN_ID_LIST] # 批量获取用户基本信息
219
229
  wechat user_change_group [OPEN_ID, TO_GROUP_ID] # 移动用户分组
220
230
  wechat user_group [OPEN_ID] # 查询用户所在分组
221
231
  wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
@@ -418,7 +428,6 @@ So the ActionController should defined like below:
418
428
  ```ruby
419
429
  class WechatsController < ActionController::Base
420
430
  wechat_responder
421
- wechat_responder
422
431
 
423
432
  # default text responder when no other match
424
433
  on :text do |request, content|
@@ -535,13 +544,6 @@ class WechatsController < ActionController::Base
535
544
 
536
545
  # Any not match above will fail to below
537
546
  on :fallback, respond: 'fallback message'
538
-
539
- # If you need do something after response, you should add after_wechat_response(req, res)
540
- # private
541
- #
542
- # def after_wechat_response(req, res)
543
- # WechatLog.create req: req, res: res
544
- # end
545
547
  end
546
548
  ```
547
549
 
@@ -584,6 +586,17 @@ end
584
586
 
585
587
  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.
586
588
 
589
+ ### Notifications
590
+
591
+ * `wechat.responder.after_create` data include request<Wechat::Message> and response<Wechat::Message>.
592
+
593
+ Example:
594
+
595
+ ```ruby
596
+ ActiveSupport::Notifications.subscribe('wechat.responder.after_create') do |name, started, finished, unique_id, data|
597
+ WechatLog.create request: data[:request], response: data[:response]
598
+ end
599
+ ```
587
600
 
588
601
  ## Known Issue
589
602
 
data/bin/wechat CHANGED
@@ -267,6 +267,11 @@ class App < Thor
267
267
  puts wechat_api.users
268
268
  end
269
269
 
270
+ desc 'user_batchget [OPEN_ID_LIST]', '批量获取用户基本信息'
271
+ def user_batchget(openidlist)
272
+ puts wechat_api.user_batchget(openidlist.split(','))
273
+ end
274
+
270
275
  desc 'qrcode_create_scene [SCENE_ID, EXPIRE_SECONDS]', '请求临时二维码'
271
276
  def qrcode_create_scene(scene_id, expire_seconds = 604800)
272
277
  puts wechat_api.qrcode_create_scene(scene_id, expire_seconds)
@@ -0,0 +1,26 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module Wechat
4
+ module Generators
5
+ class SessionGenerator < Rails::Generators::Base
6
+ include ::Rails::Generators::Migration
7
+
8
+ desc 'Enable wechat session support'
9
+ source_root File.expand_path('../templates', __FILE__)
10
+
11
+ def copy_wechat_sessions_migration
12
+ migration_template 'db/migration.rb', 'db/migrate/create_wechat_sessions.rb'
13
+ end
14
+
15
+ def copy_wechat_session_model
16
+ template 'app/models/wechat_session.rb'
17
+ end
18
+
19
+ private
20
+
21
+ def self.next_migration_number(dirname)
22
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ # Used by wechat gems, do not rename WechatSession to other name,
2
+ # Feel free to inherit from other class like ActiveModel::Model
3
+ class WechatSession < ActiveRecord::Base
4
+ validates :openid, presence: true, uniqueness: true
5
+ serialize :hash_store, Hash
6
+
7
+ # called by wechat gems when user request session
8
+ def self.find_or_initialize_session(request_message)
9
+ find_or_initialize_by(openid: request_message[:from_user_name])
10
+ end
11
+
12
+ # called by wechat gems after response Techent server at controller#create
13
+ def save_session(response_message)
14
+ touch unless new_record? # Always refresh updated_at even no change
15
+ save!
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ class CreateWechatSessions < ActiveRecord::Migration
2
+ def change
3
+ create_table :wechat_sessions do |t|
4
+ t.string :openid, null: false
5
+ t.string :hash_store
6
+ t.timestamps null: false
7
+ end
8
+ add_index :wechat_sessions, :openid, unique: true
9
+ end
10
+ end
data/lib/wechat/api.rb CHANGED
@@ -39,6 +39,10 @@ module Wechat
39
39
  get 'user/info', params: { openid: openid }
40
40
  end
41
41
 
42
+ def user_batchget(openids, lang = 'zh-CN')
43
+ post 'user/info/batchget', JSON.generate(user_list: openids.collect { |v| { openid: v, lang: lang } })
44
+ end
45
+
42
46
  def user_group(openid)
43
47
  post 'groups/getid', JSON.generate(openid: openid)
44
48
  end
@@ -24,6 +24,8 @@ HELP
24
24
  def self.config
25
25
  return @config unless @config.nil?
26
26
  @config ||= loading_config!
27
+ @config.have_session_table = class_exists?('WechatSession') && WechatSession.table_exists?
28
+ @config
27
29
  end
28
30
 
29
31
  private
@@ -48,9 +50,10 @@ HELP
48
50
  rails_config_file = File.join(Dir.getwd, 'config/wechat.yml')
49
51
  home_config_file = File.join(Dir.home, '.wechat.yml')
50
52
  if File.exist?(rails_config_file)
51
- config = YAML.load(ERB.new(File.read(rails_config_file)).result)['default']
53
+ rails_env = ENV['RAILS_ENV'] || 'default'
54
+ config = YAML.load(ERB.new(File.read(rails_config_file)).result)[rails_env]
52
55
  if config.present? && (config['appid'] || config['corpid'])
53
- puts 'Using rails project config/wechat.yml default setting...'
56
+ puts "Using rails project config/wechat.yml #{rails_env} setting..."
54
57
  return config
55
58
  end
56
59
  end
@@ -74,5 +77,11 @@ HELP
74
77
  encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'],
75
78
  jsapi_ticket: ENV['WECHAT_JSAPI_TICKET'] }
76
79
  end
80
+
81
+ def self.class_exists?(class_name)
82
+ return Module.const_get(class_name).present?
83
+ rescue NameError
84
+ return false
85
+ end
77
86
  end
78
87
  end
@@ -36,10 +36,22 @@ module Wechat
36
36
  Message.new(
37
37
  ToUserName: message_hash[:FromUserName],
38
38
  FromUserName: message_hash[:ToUserName],
39
- CreateTime: Time.now.to_i
39
+ CreateTime: Time.now.to_i,
40
+ WechatSession: session
40
41
  )
41
42
  end
42
43
 
44
+ def session
45
+ return nil unless Wechat.config.have_session_table
46
+ @message_hash[:WechatSession] ||= WechatSession.find_or_initialize_session(underscore_hash_keys(message_hash))
47
+ end
48
+
49
+ def save_session
50
+ ws = message_hash.delete(:WechatSession)
51
+ ws.try(:save_session, underscore_hash_keys(message_hash))
52
+ @message_hash[:WechatSession] = ws
53
+ end
54
+
43
55
  def as(type)
44
56
  case type
45
57
  when :text
@@ -116,7 +128,10 @@ module Wechat
116
128
  end
117
129
 
118
130
  def to_xml
119
- message_hash.to_xml(root: 'xml', children: 'item', skip_instruct: true, skip_types: true)
131
+ ws = message_hash.delete(:WechatSession)
132
+ xml = message_hash.to_xml(root: 'xml', children: 'item', skip_instruct: true, skip_types: true)
133
+ @message_hash[:WechatSession] = ws
134
+ xml
120
135
  end
121
136
 
122
137
  TO_JSON_KEY_MAP = {
@@ -177,7 +192,7 @@ module Wechat
177
192
  value = value.collect { |item| item.is_a?(Hash) ? deep_recursive(item, &block) : item }
178
193
  end
179
194
 
180
- key, value = yield(key, value)
195
+ key, value = yield(key, value) unless key == :WechatSession
181
196
  memo.merge!(key => value)
182
197
  end
183
198
  end
@@ -8,7 +8,7 @@ module Wechat
8
8
 
9
9
  included do
10
10
  # Rails 5 remove before_filter and skip_before_filter
11
- if defined?(:skip_before_action)
11
+ if respond_to?(:skip_before_action)
12
12
  # Rails 5 API mode won't define verify_authenticity_token
13
13
  skip_before_action :verify_authenticity_token unless defined?(:verify_authenticity_token)
14
14
  before_action :verify_signature, only: [:show, :create]
@@ -29,7 +29,13 @@ module Wechat
29
29
  if with.present?
30
30
  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)
31
31
  config.merge!(with: with)
32
- self.known_scan_key_lists = with if message_type == :scan
32
+ if message_type == :scan
33
+ if with.is_a?(String)
34
+ self.known_scan_key_lists = with
35
+ else
36
+ fail 'on :scan only support string in parameter with, detail see https://github.com/Eric-Guo/wechat/issues/84'
37
+ end
38
+ end
33
39
  else
34
40
  fail 'Message type click, view, scan and batch_job must specify :with parameters' if [:click, :view, :scan, :batch_job].include?(message_type)
35
41
  end
@@ -41,11 +47,14 @@ module Wechat
41
47
  user_defined_view_responders(with) << config
42
48
  when :batch_job
43
49
  user_defined_batch_job_responders(with) << config
50
+ when :scan
51
+ user_defined_scan_responders << config
44
52
  when :location
45
53
  user_defined_location_responders << config
46
54
  else
47
55
  user_defined_responders(message_type) << config
48
56
  end
57
+
49
58
  config
50
59
  end
51
60
 
@@ -64,6 +73,10 @@ module Wechat
64
73
  @batch_job_responders[with] ||= []
65
74
  end
66
75
 
76
+ def user_defined_scan_responders
77
+ @scan_responders ||= []
78
+ end
79
+
67
80
  def user_defined_location_responders
68
81
  @location_responders ||= []
69
82
  end
@@ -87,8 +100,8 @@ module Wechat
87
100
  yield(* user_defined_view_responders(message[:EventKey]), message[:EventKey])
88
101
  elsif 'click' == message[:Event]
89
102
  yield(* match_responders(responders, message[:EventKey]))
90
- elsif known_scan_key_lists.include?(message[:EventKey])
91
- yield(* known_scan_with_match_responders(user_defined_responders(:scan), message))
103
+ elsif known_scan_key_lists.include?(message[:EventKey]) && %w(scan subscribe scancode_push scancode_waitmsg).include?(message[:Event])
104
+ yield(* known_scan_with_match_responders(user_defined_scan_responders, message))
92
105
  elsif 'batch_job_result' == message[:Event]
93
106
  yield(* user_defined_batch_job_responders(message[:BatchJob][:JobType]), message[:BatchJob])
94
107
  elsif 'location' == message[:Event]
@@ -156,16 +169,18 @@ module Wechat
156
169
  end
157
170
 
158
171
  def create
159
- request = Wechat::Message.from_hash(post_xml)
160
- response = run_responder(request)
172
+ request_msg = Wechat::Message.from_hash(post_xml)
173
+ response_msg = run_responder(request_msg)
161
174
 
162
- if response.respond_to? :to_xml
163
- render plain: process_response(response)
175
+ if response_msg.respond_to? :to_xml
176
+ render plain: process_response(response_msg)
164
177
  else
165
178
  render nothing: true, status: 200, content_type: 'text/html'
166
179
  end
167
180
 
168
- after_wechat_response(request, response) if respond_to?(:after_wechat_response)
181
+ response_msg.save_session if response_msg.is_a?(Wechat::Message) && Wechat.config.have_session_table
182
+
183
+ ActiveSupport::Notifications.instrument 'wechat.responder.after_create', request: request_msg, response: response_msg
169
184
  end
170
185
 
171
186
  private
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.7.1
4
+ version: 0.7.2
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: 2016-01-10 00:00:00.000000000 Z
12
+ date: 2016-01-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -107,7 +107,21 @@ dependencies:
107
107
  - - ">="
108
108
  - !ruby/object:Gem::Version
109
109
  version: '3.2'
110
- description: API and message handling for WeChat in Rails
110
+ - !ruby/object:Gem::Dependency
111
+ name: sqlite3
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ description: API, command and message handling for WeChat in Rails
111
125
  email: eric.guocz@gmail.com
112
126
  executables:
113
127
  - wechat
@@ -122,8 +136,11 @@ files:
122
136
  - bin/wechat
123
137
  - lib/action_controller/wechat_responder.rb
124
138
  - lib/generators/wechat/install_generator.rb
139
+ - lib/generators/wechat/session_generator.rb
125
140
  - lib/generators/wechat/templates/app/controllers/wechats_controller.rb
141
+ - lib/generators/wechat/templates/app/models/wechat_session.rb
126
142
  - lib/generators/wechat/templates/config/wechat.yml
143
+ - lib/generators/wechat/templates/db/migration.rb
127
144
  - lib/wechat.rb
128
145
  - lib/wechat/api.rb
129
146
  - lib/wechat/api_base.rb