wechat 0.7.1 → 0.7.2

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: 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