wechat 0.11.4 → 0.11.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +5 -1
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +5 -0
  5. data/lib/action_controller/wechat_responder.rb +7 -5
  6. data/lib/generators/wechat/config_generator.rb +14 -10
  7. data/lib/generators/wechat/install_generator.rb +3 -1
  8. data/lib/generators/wechat/menu_generator.rb +3 -1
  9. data/lib/generators/wechat/redis_store_generator.rb +3 -1
  10. data/lib/generators/wechat/session_generator.rb +14 -10
  11. data/lib/generators/wechat/templates/app/models/wechat_config.rb +8 -13
  12. data/lib/generators/wechat/templates/app/models/wechat_session.rb +2 -0
  13. data/lib/generators/wechat/templates/config/initializers/wechat_redis_store.rb +5 -3
  14. data/lib/wechat.rb +5 -3
  15. data/lib/wechat/api.rb +2 -0
  16. data/lib/wechat/api_base.rb +8 -6
  17. data/lib/wechat/api_loader.rb +48 -49
  18. data/lib/wechat/cipher.rb +4 -2
  19. data/lib/wechat/concern/common.rb +2 -0
  20. data/lib/wechat/controller_api.rb +13 -10
  21. data/lib/wechat/corp_api.rb +2 -0
  22. data/lib/wechat/helpers.rb +14 -12
  23. data/lib/wechat/http_client.rb +21 -16
  24. data/lib/wechat/message.rb +17 -14
  25. data/lib/wechat/mp_api.rb +2 -0
  26. data/lib/wechat/responder.rb +37 -38
  27. data/lib/wechat/signature.rb +2 -0
  28. data/lib/wechat/ticket/corp_jsapi_ticket.rb +2 -0
  29. data/lib/wechat/ticket/jsapi_base.rb +4 -2
  30. data/lib/wechat/ticket/public_jsapi_ticket.rb +2 -0
  31. data/lib/wechat/token/access_token_base.rb +4 -2
  32. data/lib/wechat/token/corp_access_token.rb +2 -0
  33. data/lib/wechat/token/public_access_token.rb +2 -0
  34. metadata +42 -28
  35. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df10ca6f78d2d0546495b798889545656fe4e40f8f06cd8267b60ce26a1d1d9a
4
- data.tar.gz: c78e07d9b619a950887bd2de8e6e751f5d280db52f9458aa78456aa9aa305cc5
3
+ metadata.gz: 332ed5cc2f20211d70e994fc4549534748c9400074ece51debd7e4d147b4a1fd
4
+ data.tar.gz: 6cb347a738b602628c6dadae3ef2d90cddb9c1baff68e7e66b9bc88cc14a8643
5
5
  SHA512:
6
- metadata.gz: b528307cd3d452bd6e0733aa6a1663eae1ac4569b3e1d64f98dac8174a14276bfb7125476da1d219a02893287a693143c45bafa8ba5f164a1eaec6139f9d64ae
7
- data.tar.gz: d1205df3d31f15261fcde43b734d7abd79c99059c0a5339d9b98bbe69709ba814b7e7cbb14bd320c898b0f3c82235055dc7fde5d1cad33f5f0792b67e2a6872c
6
+ metadata.gz: 3b293b5f93fcc0f304af98f7664c73469595028b4bc38d14c60bf2506243c288d59964e17acaea563c7922493b39e67bc56ede37e638fecaf4f83c332dbb60ca
7
+ data.tar.gz: 640d2a2b5fc743189f03f680c03404cc991ff6b5e50f84f802c520eed10d7df1690080ae11ac9f1b22ada9b4f45a5f1c6a8ba5e8f01a9043026ce20ed39569ee
@@ -1 +1,5 @@
1
- }(nFS�e�n�9{��S!�<��C�p>t��t��I�ǔ���I@�nK�:��m���K^a�\j���P{:���0�>��1�^�[SSi�=z[�}Z�e.G��M�Ð���sΔ
1
+ o����6TK
2
+ [|%��)��֜��xʰJ���.�����"9?
3
+ �m�БF�XBq���:�D^��w���v|����ͿO�pn�+���a�����껅�h"�����)��1��p�A��5��C0� ���AWp��u�ˑ�\�x��ub�X�_S{N�F$%�a\�ZU��۟-�N
4
+ �曵.���k�����X�PI�ج��P�q�WT{ɷHRK�=q#��
5
+ � BKT$'��ck�V�6 Ѧ̈́*��Cl�[f�,,�v����8��#HD���P��|��C� �j�Dz�_
data.tar.gz.sig CHANGED
Binary file
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.11.5 (released at 08/30/2019)
4
+
5
+ * Add rubocop check in CI by @hophacker #267
6
+ * Support Rails 6 and Windows at #266
7
+
3
8
  ## v0.11.4 (released at 08/15/2019)
4
9
 
5
10
  * rails 6 redirect_to use allow_other_host: true by @Chen-George-Zhen #263
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionController
2
4
  module WechatResponder
3
5
  def wechat_api(opts = {})
@@ -36,11 +38,11 @@ module ActionController
36
38
  self.trusted_domain_fullname = opts[:trusted_domain_fullname] || cfg.trusted_domain_fullname
37
39
  self.oauth2_cookie_duration = opts[:oauth2_cookie_duration] || cfg.oauth2_cookie_duration.to_i.seconds
38
40
  self.timeout = opts[:timeout] || cfg.timeout
39
- if opts.key?(:skip_verify_ssl)
40
- self.skip_verify_ssl = opts[:skip_verify_ssl]
41
- else
42
- self.skip_verify_ssl = cfg.skip_verify_ssl
43
- end
41
+ self.skip_verify_ssl = if opts.key?(:skip_verify_ssl)
42
+ opts[:skip_verify_ssl]
43
+ else
44
+ cfg.skip_verify_ssl
45
+ end
44
46
 
45
47
  return Wechat.api if account == :default && opts.empty?
46
48
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/generators/active_record'
2
4
 
3
5
  module Wechat
@@ -6,13 +8,13 @@ module Wechat
6
8
  include ::Rails::Generators::Migration
7
9
 
8
10
  desc 'Generate wechat configs in database'
9
- source_root File.expand_path('../templates', __FILE__)
11
+ source_root File.expand_path('templates', __dir__)
10
12
 
11
13
  def copy_wechat_config_migration
12
14
  migration_template(
13
- 'db/config_migration.rb.erb',
14
- 'db/migrate/create_wechat_configs.rb',
15
- {migration_version: migration_version}
15
+ 'db/config_migration.rb.erb',
16
+ 'db/migrate/create_wechat_configs.rb',
17
+ migration_version: migration_version
16
18
  )
17
19
  end
18
20
 
@@ -20,16 +22,18 @@ module Wechat
20
22
  template 'app/models/wechat_config.rb'
21
23
  end
22
24
 
23
- private
25
+ class << self
26
+ private
24
27
 
25
- def self.next_migration_number(dirname)
26
- ::ActiveRecord::Generators::Base.next_migration_number(dirname)
28
+ def next_migration_number(dirname)
29
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
30
+ end
27
31
  end
28
32
 
33
+ private
34
+
29
35
  def migration_version
30
- if Rails.version >= '5.0.0'
31
- "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
32
- end
36
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]" if Rails.version >= '5.0.0'
33
37
  end
34
38
  end
35
39
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Generators
3
5
  class InstallGenerator < Rails::Generators::Base
4
6
  desc 'Install Wechat support files'
5
- source_root File.expand_path('../templates', __FILE__)
7
+ source_root File.expand_path('templates', __dir__)
6
8
 
7
9
  def copy_config
8
10
  template 'config/wechat.yml'
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Generators
3
5
  class MenuGenerator < Rails::Generators::Base
4
6
  desc 'Generate wechat menu'
5
- source_root File.expand_path('../templates', __FILE__)
7
+ source_root File.expand_path('templates', __dir__)
6
8
  class_option :conditional, desc: 'Generate conditional menu', type: :boolean, default: false
7
9
 
8
10
  def copy_menu
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Generators
3
5
  class RedisStoreGenerator < Rails::Generators::Base
4
6
  desc 'Using redis as token/ticket store'
5
- source_root File.expand_path('../templates', __FILE__)
7
+ source_root File.expand_path('templates', __dir__)
6
8
 
7
9
  def copy_wechat_redis_initializer
8
10
  template 'config/initializers/wechat_redis_store.rb'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/generators/active_record'
2
4
 
3
5
  module Wechat
@@ -6,13 +8,13 @@ module Wechat
6
8
  include ::Rails::Generators::Migration
7
9
 
8
10
  desc 'Enable wechat session support'
9
- source_root File.expand_path('../templates', __FILE__)
11
+ source_root File.expand_path('templates', __dir__)
10
12
 
11
13
  def copy_wechat_sessions_migration
12
14
  migration_template(
13
- 'db/session_migration.rb.erb',
14
- 'db/migrate/create_wechat_sessions.rb',
15
- {migration_version: migration_version}
15
+ 'db/session_migration.rb.erb',
16
+ 'db/migrate/create_wechat_sessions.rb',
17
+ migration_version: migration_version
16
18
  )
17
19
  end
18
20
 
@@ -20,16 +22,18 @@ module Wechat
20
22
  template 'app/models/wechat_session.rb'
21
23
  end
22
24
 
23
- private
25
+ class << self
26
+ private
24
27
 
25
- def self.next_migration_number(dirname)
26
- ::ActiveRecord::Generators::Base.next_migration_number(dirname)
28
+ def next_migration_number(dirname)
29
+ ::ActiveRecord::Generators::Base.next_migration_number(dirname)
30
+ end
27
31
  end
28
32
 
33
+ private
34
+
29
35
  def migration_version
30
- if Rails.version >= '5.0.0'
31
- "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
32
- end
36
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]" if Rails.version >= '5.0.0'
33
37
  end
34
38
  end
35
39
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Used by wechat gems, do not rename WechatConfig to other name,
2
4
  # Feel free to inherit from other class like ActiveModel::Model
3
5
  class WechatConfig < ActiveRecord::Base
@@ -10,17 +12,16 @@ class WechatConfig < ActiveRecord::Base
10
12
 
11
13
  validate :app_config_is_valid
12
14
 
13
- ATTRIBUTES_TO_REMOVE = %w(environment account created_at updated_at enabled)
15
+ ATTRIBUTES_TO_REMOVE = %w[environment account created_at updated_at enabled].freeze
14
16
 
15
17
  def self.get_all_configs(environment)
16
- WechatConfig.where(environment: environment, enabled: true).inject({}) do |hash, config|
18
+ WechatConfig.where(environment: environment, enabled: true).each_with_object({}) do |config, hash|
17
19
  hash[config.account] = config.build_config_hash
18
- hash
19
20
  end
20
21
  end
21
22
 
22
23
  def build_config_hash
23
- self.as_json(except: ATTRIBUTES_TO_REMOVE)
24
+ as_json(except: ATTRIBUTES_TO_REMOVE)
24
25
  end
25
26
 
26
27
  private
@@ -28,17 +29,11 @@ class WechatConfig < ActiveRecord::Base
28
29
  def app_config_is_valid
29
30
  if self[:appid].present?
30
31
  # public account
31
- if self[:secret].blank?
32
- errors.add(:secret, 'cannot be nil when appid is set')
33
- end
32
+ errors.add(:secret, 'cannot be nil when appid is set') if self[:secret].blank?
34
33
  elsif self[:corpid].present?
35
34
  # corp account
36
- if self[:corpsecret].blank?
37
- errors.add(:corpsecret, 'cannot be nil when corpid is set')
38
- end
39
- if self[:agentid].blank?
40
- errors.add(:agentid, 'cannot be nil when corpid is set')
41
- end
35
+ errors.add(:corpsecret, 'cannot be nil when corpid is set') if self[:corpsecret].blank?
36
+ errors.add(:agentid, 'cannot be nil when corpid is set') if self[:agentid].blank?
42
37
  else
43
38
  errors[:base] << 'Either appid or corpid must be set'
44
39
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Used by wechat gems, do not rename WechatSession to other name,
2
4
  # Feel free to inherit from other class like ActiveModel::Model
3
5
  class WechatSession < ActiveRecord::Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  def self.redis
3
5
  # You can reuse existing redis connection and remove this method if require
@@ -17,7 +19,7 @@ module Wechat
17
19
  private
18
20
 
19
21
  def redis_key
20
- "my_app_wechat_token_#{self.secret}"
22
+ "my_app_wechat_token_#{secret}"
21
23
  end
22
24
  end
23
25
  end
@@ -25,7 +27,7 @@ module Wechat
25
27
  module Ticket
26
28
  class JsapiBase
27
29
  def read_ticket
28
- JSON.parse(Wechat.redis.get(redis_key)) || {}
30
+ JSON.parse(Wechat.redis.get(redis_key)) || {}
29
31
  end
30
32
 
31
33
  def write_ticket(ticket_hash)
@@ -35,7 +37,7 @@ module Wechat
35
37
  private
36
38
 
37
39
  def redis_key
38
- "my_app_wechat_ticket_#{self.access_token.secret}"
40
+ "my_app_wechat_ticket_#{access_token.secret}"
39
41
  end
40
42
  end
41
43
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'base64'
2
4
  require 'openssl/cipher'
3
5
  require 'wechat/api_loader'
@@ -36,15 +38,15 @@ module Wechat
36
38
  ApiLoader.reload_config!
37
39
  end
38
40
 
39
- def self.decrypt(encrypted_data, session_key, iv)
41
+ def self.decrypt(encrypted_data, session_key, ivector)
40
42
  cipher = OpenSSL::Cipher.new('AES-128-CBC')
41
43
  cipher.decrypt
42
44
 
43
45
  cipher.key = Base64.decode64(session_key)
44
- cipher.iv = Base64.decode64(iv)
46
+ cipher.iv = Base64.decode64(ivector)
45
47
  decrypted_data = Base64.decode64(encrypted_data)
46
48
  JSON.parse(cipher.update(decrypted_data) + cipher.final)
47
- rescue Exception => e
49
+ rescue StandardError => e
48
50
  { 'errcode': 41003, 'errmsg': e.message }
49
51
  end
50
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wechat/api_base'
2
4
  require 'wechat/http_client'
3
5
  require 'wechat/token/public_access_token'
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  class ApiBase
3
5
  attr_reader :access_token, :client, :jsapi_ticket
4
6
 
5
- API_BASE = 'https://api.weixin.qq.com/cgi-bin/'.freeze
6
- MP_BASE = 'https://mp.weixin.qq.com/cgi-bin/'.freeze
7
- WXA_BASE = 'https://api.weixin.qq.com/wxa/'.freeze
8
- OAUTH2_BASE = 'https://api.weixin.qq.com/sns/'.freeze
9
- DATACUBE_BASE = 'https://api.weixin.qq.com/datacube/'.freeze
10
- QYAPI_BASE = 'https://qyapi.weixin.qq.com/cgi-bin/'.freeze
7
+ API_BASE = 'https://api.weixin.qq.com/cgi-bin/'
8
+ MP_BASE = 'https://mp.weixin.qq.com/cgi-bin/'
9
+ WXA_BASE = 'https://api.weixin.qq.com/wxa/'
10
+ OAUTH2_BASE = 'https://api.weixin.qq.com/sns/'
11
+ DATACUBE_BASE = 'https://api.weixin.qq.com/datacube/'
12
+ QYAPI_BASE = 'https://qyapi.weixin.qq.com/cgi-bin/'
11
13
 
12
14
  def callbackip
13
15
  get 'getcallbackip'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module ApiLoader
3
5
  def self.with(options)
@@ -8,12 +10,12 @@ module Wechat
8
10
  js_token_file = options[:js_token_file] || c.jsapi_ticket.presence || '/var/tmp/wechat_jsapi_ticket'
9
11
  type = options[:type] || c.type
10
12
  if c.appid && c.secret && token_file.present?
11
- wx_class = (type == 'mp') ? Wechat::MpApi : Wechat::Api
13
+ wx_class = type == 'mp' ? Wechat::MpApi : Wechat::Api
12
14
  wx_class.new(c.appid, c.secret, token_file, c.timeout, c.skip_verify_ssl, js_token_file)
13
15
  elsif c.corpid && c.corpsecret && token_file.present?
14
16
  Wechat::CorpApi.new(c.corpid, c.corpsecret, token_file, c.agentid, c.timeout, c.skip_verify_ssl, js_token_file)
15
17
  else
16
- raise "Need create ~/.wechat.yml with wechat appid and secret or running at rails root folder so wechat can read config/wechat.yml"
18
+ raise 'Need create ~/.wechat.yml with wechat appid and secret or running at rails root folder so wechat can read config/wechat.yml'
17
19
  end
18
20
  end
19
21
 
@@ -35,11 +37,9 @@ module Wechat
35
37
 
36
38
  configs.symbolize_keys!
37
39
  configs.each do |key, cfg|
38
- if cfg.is_a?(Hash)
39
- cfg.symbolize_keys!
40
- else
41
- raise "wrong wechat configuration format for #{key}"
42
- end
40
+ raise "wrong wechat configuration format for #{key}" unless cfg.is_a?(Hash)
41
+
42
+ cfg.symbolize_keys!
43
43
  end
44
44
 
45
45
  if defined?(::Rails)
@@ -64,9 +64,7 @@ module Wechat
64
64
  end
65
65
 
66
66
  private_class_method def self.config_from_db
67
- unless class_exists?('WechatConfig')
68
- return {}
69
- end
67
+ return {} unless class_exists?('WechatConfig')
70
68
 
71
69
  environment = defined?(::Rails) ? Rails.env.to_s : ENV['RAILS_ENV'] || 'development'
72
70
  WechatConfig.get_all_configs(environment)
@@ -74,11 +72,11 @@ module Wechat
74
72
 
75
73
  private_class_method def self.config_from_file
76
74
  if defined?(::Rails)
77
- config_file = ENV['WECHAT_CONF_FILE'] || Rails.root.join('config/wechat.yml')
78
- return resovle_config_file(config_file, Rails.env.to_s)
75
+ config_file = ENV['WECHAT_CONF_FILE'] || Rails.root.join('config', 'wechat.yml')
76
+ resolve_config_file(config_file, Rails.env.to_s)
79
77
  else
80
- rails_config_file = ENV['WECHAT_CONF_FILE'] || File.join(Dir.getwd, 'config/wechat.yml')
81
- application_config_file = File.join(Dir.getwd, 'config/application.yml')
78
+ rails_config_file = ENV['WECHAT_CONF_FILE'] || File.join(Dir.getwd, 'config', 'wechat.yml')
79
+ application_config_file = File.join(Dir.getwd, 'config', 'application.yml')
82
80
  home_config_file = File.join(Dir.home, '.wechat.yml')
83
81
  if File.exist?(rails_config_file)
84
82
  rails_env = ENV['RAILS_ENV'] || 'development'
@@ -86,54 +84,55 @@ module Wechat
86
84
  require 'figaro'
87
85
  Figaro::Application.new(path: application_config_file, environment: rails_env).load
88
86
  end
89
- config = resovle_config_file(rails_config_file, rails_env)
90
- if config.present? && (default = config[:default]) && (default['appid'] || default['corpid'])
91
- puts "Using rails project #{ENV['WECHAT_CONF_FILE'] || "config/wechat.yml"} #{rails_env} setting..."
87
+ config = resolve_config_file(rails_config_file, rails_env)
88
+ if config.present? && (default = config[:default]) && (default['appid'] || default['corpid'])
89
+ puts "Using rails project #{ENV['WECHAT_CONF_FILE'] || 'config/wechat.yml'} #{rails_env} setting..."
92
90
  return config
93
91
  end
94
92
  end
95
- if File.exist?(home_config_file)
96
- return resovle_config_file(home_config_file, nil)
97
- end
93
+ return resolve_config_file(home_config_file, nil) if File.exist?(home_config_file)
98
94
  end
99
95
  end
100
96
 
101
- private_class_method def self.resovle_config_file(config_file, env)
102
- if File.exist?(config_file)
103
- raw_data = YAML.load(ERB.new(File.read(config_file)).result)
104
- configs = {}
105
- if env
106
- # Process multiple accounts when env is given
107
- raw_data.each do |key, value|
108
- if key == env
109
- configs[:default] = value
110
- elsif m = /(.*?)_#{env}$/.match(key)
111
- configs[m[1].to_sym] = value
112
- end
97
+ private_class_method def self.resolve_config_file(config_file, env)
98
+ return unless File.exist?(config_file)
99
+
100
+ # rubocop:disable Security/YAMLLoad
101
+ raw_data = YAML.load(ERB.new(File.read(config_file)).result)
102
+ # rubocop:enable Security/YAMLLoad
103
+ configs = {}
104
+ if env
105
+ # Process multiple accounts when env is given
106
+ raw_data.each do |key, value|
107
+ if key == env
108
+ configs[:default] = value
109
+ else
110
+ m = /(.*?)_#{env}$/.match(key)
111
+ configs[m[1].to_sym] = value if m
113
112
  end
114
- else
115
- # Treat is as one account when env is omitted
116
- configs[:default] = raw_data
117
113
  end
118
- configs
114
+ else
115
+ # Treat is as one account when env is omitted
116
+ configs[:default] = raw_data
119
117
  end
118
+ configs
120
119
  end
121
120
 
122
121
  private_class_method def self.config_from_environment
123
122
  value = { appid: ENV['WECHAT_APPID'],
124
- secret: ENV['WECHAT_SECRET'],
125
- corpid: ENV['WECHAT_CORPID'],
126
- corpsecret: ENV['WECHAT_CORPSECRET'],
127
- agentid: ENV['WECHAT_AGENTID'],
128
- token: ENV['WECHAT_TOKEN'],
129
- access_token: ENV['WECHAT_ACCESS_TOKEN'],
130
- encrypt_mode: ENV['WECHAT_ENCRYPT_MODE'],
131
- timeout: ENV['WECHAT_TIMEOUT'],
132
- skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
133
- encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'],
134
- jsapi_ticket: ENV['WECHAT_JSAPI_TICKET'],
135
- trusted_domain_fullname: ENV['WECHAT_TRUSTED_DOMAIN_FULLNAME'] }
136
- {default: value}
123
+ secret: ENV['WECHAT_SECRET'],
124
+ corpid: ENV['WECHAT_CORPID'],
125
+ corpsecret: ENV['WECHAT_CORPSECRET'],
126
+ agentid: ENV['WECHAT_AGENTID'],
127
+ token: ENV['WECHAT_TOKEN'],
128
+ access_token: ENV['WECHAT_ACCESS_TOKEN'],
129
+ encrypt_mode: ENV['WECHAT_ENCRYPT_MODE'],
130
+ timeout: ENV['WECHAT_TIMEOUT'],
131
+ skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
132
+ encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'],
133
+ jsapi_ticket: ENV['WECHAT_JSAPI_TICKET'],
134
+ trusted_domain_fullname: ENV['WECHAT_TRUSTED_DOMAIN_FULLNAME'] }
135
+ { default: value }
137
136
  end
138
137
 
139
138
  private_class_method def self.class_exists?(class_name)
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Cipher
3
5
  BLOCK_SIZE = 32
4
- CIPHER = 'AES-256-CBC'.freeze
6
+ CIPHER = 'AES-256-CBC'
5
7
 
6
8
  def encrypt(plain, encoding_aes_key)
7
9
  cipher = OpenSSL::Cipher.new(CIPHER)
@@ -51,7 +53,7 @@ module Wechat
51
53
  def encode_padding(data)
52
54
  length = data.bytes.length
53
55
  amount_to_pad = BLOCK_SIZE - (length % BLOCK_SIZE)
54
- amount_to_pad = BLOCK_SIZE if amount_to_pad == 0
56
+ amount_to_pad = BLOCK_SIZE if amount_to_pad.zero?
55
57
  padding = ([amount_to_pad].pack('c') * amount_to_pad)
56
58
  data + padding
57
59
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Concern
3
5
  module Common
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module ControllerApi
3
5
  extend ActiveSupport::Concern
@@ -20,10 +22,10 @@ module Wechat
20
22
  if account
21
23
  config = Wechat.config(account)
22
24
  appid = config.corpid || config.appid
23
- is_crop_account = !!config.corpid
25
+ is_crop_account = config.corpid.present?
24
26
  else
25
27
  appid = self.class.corpid || self.class.appid
26
- is_crop_account = !!self.class.corpid
28
+ is_crop_account = self.class.corpid.present?
27
29
  end
28
30
 
29
31
  raise 'Can not get corpid or appid, so please configure it first to using wechat_oauth2' if appid.blank?
@@ -37,6 +39,7 @@ module Wechat
37
39
  }
38
40
 
39
41
  return generate_oauth2_url(oauth2_params) unless block_given?
42
+
40
43
  is_crop_account ? wechat_corp_oauth2(oauth2_params, account, &block) : wechat_public_oauth2(oauth2_params, account, &block)
41
44
  end
42
45
 
@@ -47,7 +50,7 @@ module Wechat
47
50
  unionid = cookies.signed_or_encrypted[:we_unionid]
48
51
  we_token = cookies.signed_or_encrypted[:we_access_token]
49
52
  if openid.present?
50
- yield openid, { 'openid' => openid, 'unionid' => unionid, 'access_token' => we_token}
53
+ yield openid, { 'openid' => openid, 'unionid' => unionid, 'access_token' => we_token }
51
54
  elsif params[:code].present? && params[:state] == oauth2_params[:state]
52
55
  access_info = wechat(account).web_access_token(params[:code])
53
56
  cookies.signed_or_encrypted[:we_openid] = { value: access_info['openid'], expires: self.class.oauth2_cookie_duration.from_now }
@@ -55,7 +58,7 @@ module Wechat
55
58
  cookies.signed_or_encrypted[:we_access_token] = { value: access_info['access_token'], expires: self.class.oauth2_cookie_duration.from_now }
56
59
  yield access_info['openid'], access_info
57
60
  else
58
- (Rails::VERSION::MAJOR >= 6) ? (redirect_to generate_oauth2_url(oauth2_params), allow_other_host: true) : (redirect_to generate_oauth2_url(oauth2_params))
61
+ Rails::VERSION::MAJOR >= 6 ? (redirect_to generate_oauth2_url(oauth2_params), allow_other_host: true) : (redirect_to generate_oauth2_url(oauth2_params))
59
62
  end
60
63
  end
61
64
 
@@ -70,18 +73,18 @@ module Wechat
70
73
  cookies.signed_or_encrypted[:we_deviceid] = { value: userinfo['DeviceId'], expires: self.class.oauth2_cookie_duration.from_now }
71
74
  yield userinfo['UserId'], userinfo
72
75
  else
73
- (Rails::VERSION::MAJOR >= 6) ? (redirect_to generate_oauth2_url(oauth2_params), allow_other_host: true) : (redirect_to generate_oauth2_url(oauth2_params))
76
+ Rails::VERSION::MAJOR >= 6 ? (redirect_to generate_oauth2_url(oauth2_params), allow_other_host: true) : (redirect_to generate_oauth2_url(oauth2_params))
74
77
  end
75
78
  end
76
79
 
77
80
  def generate_redirect_uri(account = nil)
78
81
  domain_name = if account
79
- Wechat.config(account).trusted_domain_fullname
80
- else
81
- self.class.trusted_domain_fullname
82
- end
82
+ Wechat.config(account).trusted_domain_fullname
83
+ else
84
+ self.class.trusted_domain_fullname
85
+ end
83
86
  page_url = domain_name ? "#{domain_name}#{request.original_fullpath}" : request.original_url
84
- safe_query = request.query_parameters.reject { |k, _| %w(code state access_token).include? k }.to_query
87
+ safe_query = request.query_parameters.reject { |k, _| %w[code state access_token].include? k }.to_query
85
88
  page_url.sub(request.query_string, safe_query)
86
89
  end
87
90
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wechat/api_base'
2
4
  require 'wechat/http_client'
3
5
  require 'wechat/token/corp_access_token'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Helpers
3
5
  def wechat_config_js(config_options = {})
@@ -22,25 +24,25 @@ module Wechat
22
24
  else
23
25
  controller.request.original_url
24
26
  end
25
- page_url = page_url.split('#').first if is_ios?
27
+ page_url = page_url.split('#').first if ios?
26
28
  js_hash = api.jsapi_ticket.signature(page_url)
27
29
 
28
- config_js = <<-WECHAT_CONFIG_JS
29
- wx.config({
30
- debug: #{config_options[:debug]},
31
- appId: "#{app_id}",
32
- timestamp: "#{js_hash[:timestamp]}",
33
- nonceStr: "#{js_hash[:noncestr]}",
34
- signature: "#{js_hash[:signature]}",
35
- jsApiList: ['#{config_options[:api].join("','")}']
36
- });
37
- WECHAT_CONFIG_JS
30
+ config_js = <<~WECHAT_CONFIG_JS
31
+ wx.config({
32
+ debug: #{config_options[:debug]},
33
+ appId: "#{app_id}",
34
+ timestamp: "#{js_hash[:timestamp]}",
35
+ nonceStr: "#{js_hash[:noncestr]}",
36
+ signature: "#{js_hash[:signature]}",
37
+ jsApiList: ['#{config_options[:api].join("','")}']
38
+ });
39
+ WECHAT_CONFIG_JS
38
40
  javascript_tag config_js, type: 'application/javascript'
39
41
  end
40
42
 
41
43
  private
42
44
 
43
- def is_ios?
45
+ def ios?
44
46
  controller.request.user_agent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
45
47
  end
46
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'http'
2
4
 
3
5
  module Wechat
@@ -35,10 +37,10 @@ module Wechat
35
37
  params = header.delete(:params)
36
38
  form_file = file.is_a?(HTTP::FormData::File) ? file : HTTP::FormData::File.new(file)
37
39
  httprb.headers(header)
38
- .post(url, params: params,
39
- form: { media: form_file,
40
- hack: 'X' }, # Existing here for http-form_data 1.0.1 handle single param improperly
41
- ssl_context: ssl_context)
40
+ .post(url, params: params,
41
+ form: { media: form_file,
42
+ hack: 'X' }, # Existing here for http-form_data 1.0.1 handle single param improperly
43
+ ssl_context: ssl_context)
42
44
  end
43
45
  end
44
46
 
@@ -51,6 +53,7 @@ module Wechat
51
53
  response = yield("#{url_base}#{path}", header)
52
54
 
53
55
  raise "Request not OK, response status #{response.status}" if response.status != 200
56
+
54
57
  parse_response(response, as || :json) do |parse_as, data|
55
58
  break data unless parse_as == :json && data['errcode'].present?
56
59
 
@@ -71,25 +74,27 @@ module Wechat
71
74
  end
72
75
  end
73
76
 
74
- def parse_response(response, as)
77
+ def parse_response(response, as_type)
75
78
  content_type = response.headers[:content_type]
76
79
  parse_as = {
77
80
  %r{^application\/json} => :json,
78
- %r{^image\/.*} => :file,
79
- %r{^audio\/.*} => :file,
80
- %r{^voice\/.*} => :file,
81
- %r{^text\/html} => :xml,
82
- %r{^text\/plain} => :probably_json
83
- }.each_with_object([]) { |match, memo| memo << match[1] if content_type =~ match[0] }.first || as || :text
81
+ %r{^image\/.*} => :file,
82
+ %r{^audio\/.*} => :file,
83
+ %r{^voice\/.*} => :file,
84
+ %r{^text\/html} => :xml,
85
+ %r{^text\/plain} => :probably_json
86
+ }.each_with_object([]) { |match, memo| memo << match[1] if content_type =~ match[0] }.first || as_type || :text
84
87
 
85
88
  # try to parse response as json, fallback to user-specified format or text if failed
86
89
  if parse_as == :probably_json
87
- data = JSON.parse response.body.to_s.gsub(/[\u0000-\u001f]+/, '') rescue nil
88
- if data
89
- return yield(:json, data)
90
- else
91
- parse_as = as || :text
90
+ begin
91
+ data = JSON.parse response.body.to_s.gsub(/[\u0000-\u001f]+/, '')
92
+ rescue StandardError
93
+ nil
92
94
  end
95
+ return yield(:json, data) if data
96
+
97
+ parse_as = as_type || :text
93
98
  end
94
99
 
95
100
  case parse_as
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  class Message
3
5
  class << self
@@ -70,6 +72,7 @@ module Wechat
70
72
 
71
73
  def session
72
74
  return nil unless Wechat.config.have_session_class
75
+
73
76
  @message_hash[:WechatSession] ||= WechatSession.find_or_initialize_session(underscore_hash_keys(message_hash))
74
77
  end
75
78
 
@@ -120,8 +123,8 @@ module Wechat
120
123
 
121
124
  def markdown(content)
122
125
  update(MsgType: 'markdown', Markdown: {
123
- content: content
124
- })
126
+ content: content
127
+ })
125
128
  end
126
129
 
127
130
  def transfer_customer_service(kf_account = nil)
@@ -207,25 +210,25 @@ module Wechat
207
210
  end
208
211
 
209
212
  TO_JSON_KEY_MAP = {
210
- 'TextCard' => 'textcard',
211
- 'Markdown' => 'markdown',
212
- 'ToUserName' => 'touser',
213
- 'ToPartyName' => 'toparty',
214
- 'ToWxName' => 'towxname',
215
- 'MediaId' => 'media_id',
216
- 'MpNews' => 'mpnews',
217
- 'ThumbMediaId' => 'thumb_media_id',
218
- 'TemplateId' => 'template_id',
219
- 'FormId' => 'form_id',
213
+ 'TextCard' => 'textcard',
214
+ 'Markdown' => 'markdown',
215
+ 'ToUserName' => 'touser',
216
+ 'ToPartyName' => 'toparty',
217
+ 'ToWxName' => 'towxname',
218
+ 'MediaId' => 'media_id',
219
+ 'MpNews' => 'mpnews',
220
+ 'ThumbMediaId' => 'thumb_media_id',
221
+ 'TemplateId' => 'template_id',
222
+ 'FormId' => 'form_id',
220
223
  'ContentSourceUrl' => 'content_source_url',
221
- 'ShowCoverPic' => 'show_cover_pic'
224
+ 'ShowCoverPic' => 'show_cover_pic'
222
225
  }.freeze
223
226
 
224
227
  TO_JSON_ALLOWED = %w[touser toparty msgtype content image voice video file textcard markdown
225
228
  music news articles template agentid filter
226
229
  send_ignore_reprint mpnews towxname].freeze
227
230
 
228
- def to_json
231
+ def to_json(*_args)
229
232
  keep_camel_case_key = message_hash[:MsgType] == 'template'
230
233
  json_hash = deep_recursive(message_hash) do |key, value|
231
234
  key = key.to_s
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wechat/api_base'
2
4
  require 'wechat/http_client'
3
5
  require 'wechat/token/public_access_token'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'English'
2
4
  require 'wechat/signature'
3
5
 
@@ -19,12 +21,12 @@ module Wechat
19
21
  skip_before_action :verify_authenticity_token, raise: false
20
22
  end
21
23
 
22
- before_action :config_account, only: [:show, :create]
23
- before_action :verify_signature, only: [:show, :create]
24
+ before_action :config_account, only: %i[show create]
25
+ before_action :verify_signature, only: %i[show create]
24
26
  else
25
27
  skip_before_filter :verify_authenticity_token
26
- before_filter :config_account, only: [:show, :create]
27
- before_filter :verify_signature, only: [:show, :create]
28
+ before_filter :config_account, only: %i[show create]
29
+ before_filter :verify_signature, only: %i[show create]
28
30
  end
29
31
  end
30
32
 
@@ -32,22 +34,22 @@ module Wechat
32
34
  attr_accessor :account_from_request
33
35
 
34
36
  def on(message_type, with: nil, respond: nil, &block)
35
- raise 'Unknow message type' unless [:text, :image, :voice, :video, :shortvideo, :link, :event, :click, :view, :scan, :batch_job, :location, :label_location, :fallback].include?(message_type)
37
+ raise 'Unknow message type' unless %i[text image voice video shortvideo link event click view scan batch_job location label_location fallback].include?(message_type)
38
+
36
39
  config = respond.nil? ? {} : { respond: respond }
37
40
  config[:proc] = block if block_given?
38
41
 
39
42
  if with.present?
40
- raise 'Only text, event, click, view, scan and batch_job can having :with parameters' unless [:text, :event, :click, :view, :scan, :batch_job].include?(message_type)
43
+ raise 'Only text, event, click, view, scan and batch_job can having :with parameters' unless %i[text event click view scan batch_job].include?(message_type)
44
+
41
45
  config[:with] = with
42
46
  if message_type == :scan
43
- if with.is_a?(String)
44
- self.known_scan_key_lists = with
45
- else
46
- raise 'on :scan only support string in parameter with, detail see https://github.com/Eric-Guo/wechat/issues/84'
47
- end
47
+ raise 'on :scan only support string in parameter with, detail see https://github.com/Eric-Guo/wechat/issues/84' unless with.is_a?(String)
48
+
49
+ self.known_scan_key_lists = with
48
50
  end
49
- else
50
- raise 'Message type click, view, scan and batch_job must specify :with parameters' if [:click, :view, :scan, :batch_job].include?(message_type)
51
+ elsif %i[click view scan batch_job].include?(message_type)
52
+ raise 'Message type click, view, scan and batch_job must specify :with parameters'
51
53
  end
52
54
 
53
55
  case message_type
@@ -86,15 +88,15 @@ module Wechat
86
88
  end
87
89
 
88
90
  def user_defined_scan_responders
89
- @scan_responders ||= []
91
+ @user_defined_scan_responders ||= []
90
92
  end
91
93
 
92
94
  def user_defined_location_responders
93
- @location_responders ||= []
95
+ @user_defined_location_responders ||= []
94
96
  end
95
97
 
96
98
  def user_defined_label_location_responders
97
- @label_location_responders ||= []
99
+ @user_defined_label_location_responders ||= []
98
100
  end
99
101
 
100
102
  def user_defined_responders(type)
@@ -110,17 +112,17 @@ module Wechat
110
112
  when :text
111
113
  yield(* match_responders(responders, message[:Content]))
112
114
  when :event
113
- if 'click' == message[:Event] && !user_defined_click_responders(message[:EventKey]).empty?
115
+ if message[:Event] == 'click' && !user_defined_click_responders(message[:EventKey]).empty?
114
116
  yield(* user_defined_click_responders(message[:EventKey]), message[:EventKey])
115
- elsif 'view' == message[:Event] && !user_defined_view_responders(message[:EventKey]).empty?
117
+ elsif message[:Event] == 'view' && !user_defined_view_responders(message[:EventKey]).empty?
116
118
  yield(* user_defined_view_responders(message[:EventKey]), message[:EventKey])
117
- elsif 'click' == message[:Event]
119
+ elsif message[:Event] == 'click'
118
120
  yield(* match_responders(responders, message[:EventKey]))
119
- elsif known_scan_key_lists.include?(message[:EventKey]) && %w(scan subscribe scancode_push scancode_waitmsg).freeze.include?(message[:Event])
121
+ elsif known_scan_key_lists.include?(message[:EventKey]) && %w[scan subscribe scancode_push scancode_waitmsg].freeze.include?(message[:Event])
120
122
  yield(* known_scan_with_match_responders(user_defined_scan_responders, message))
121
- elsif 'batch_job_result' == message[:Event]
123
+ elsif message[:Event] == 'batch_job_result'
122
124
  yield(* user_defined_batch_job_responders(message[:BatchJob][:JobType]), message[:BatchJob])
123
- elsif 'location' == message[:Event]
125
+ elsif message[:Event] == 'location'
124
126
  yield(* user_defined_location_responders, message)
125
127
  else
126
128
  yield(* match_responders(responders, message[:Event]))
@@ -145,8 +147,8 @@ module Wechat
145
147
 
146
148
  if condition.is_a? Regexp
147
149
  memo[:scoped] ||= [responder] + $LAST_MATCH_INFO.captures if value =~ condition
148
- else
149
- memo[:scoped] ||= [responder, value] if value == condition
150
+ elsif value == condition
151
+ memo[:scoped] ||= [responder, value]
150
152
  end
151
153
  end
152
154
  matched[:scoped] || matched[:general]
@@ -154,9 +156,9 @@ module Wechat
154
156
 
155
157
  def known_scan_with_match_responders(responders, message)
156
158
  matched = responders.each_with_object({}) do |responder, memo|
157
- if %w(scan subscribe).freeze.include?(message[:Event]) && message[:EventKey] == responder[:with]
159
+ if %w[scan subscribe].freeze.include?(message[:Event]) && message[:EventKey] == responder[:with]
158
160
  memo[:scaned] ||= [responder, message[:Ticket]]
159
- elsif %w(scancode_push scancode_waitmsg).freeze.include?(message[:Event]) && message[:EventKey] == responder[:with]
161
+ elsif %w[scancode_push scancode_waitmsg].freeze.include?(message[:Event]) && message[:EventKey] == responder[:with]
160
162
  memo[:scaned] ||= [responder, message[:ScanCodeInfo][:ScanResult], message[:ScanCodeInfo][:ScanType]]
161
163
  end
162
164
  end
@@ -181,12 +183,10 @@ module Wechat
181
183
  else
182
184
  render text: echostr
183
185
  end
186
+ elsif Rails::VERSION::MAJOR >= 4
187
+ render plain: params[:echostr]
184
188
  else
185
- if Rails::VERSION::MAJOR >= 4
186
- render plain: params[:echostr]
187
- else
188
- render text: params[:echostr]
189
- end
189
+ render text: params[:echostr]
190
190
  end
191
191
  end
192
192
 
@@ -249,11 +249,11 @@ module Wechat
249
249
  if Rails::VERSION::MAJOR >= 5
250
250
  data_hash = data_hash.to_unsafe_hash if data_hash.instance_of?(ActionController::Parameters)
251
251
  HashWithIndifferentAccess.new(data_hash).tap do |msg|
252
- msg[:Event].downcase! if msg[:Event]
252
+ msg[:Event]&.downcase!
253
253
  end
254
254
  else
255
255
  HashWithIndifferentAccess.new_from_hash_copying_default(data_hash).tap do |msg|
256
- msg[:Event].downcase! if msg[:Event]
256
+ msg[:Event]&.downcase!
257
257
  end
258
258
  end
259
259
  end
@@ -263,10 +263,10 @@ module Wechat
263
263
  responder ||= self.class.user_defined_responders(:fallback).first
264
264
 
265
265
  next if responder.nil?
266
- case
267
- when responder[:respond]
266
+
267
+ if responder[:respond]
268
268
  request.reply.text responder[:respond]
269
- when responder[:proc]
269
+ elsif responder[:proc]
270
270
  define_singleton_method :process, responder[:proc]
271
271
  number_of_block_parameter = responder[:proc].arity
272
272
  send(:process, *args.unshift(request).take(number_of_block_parameter))
@@ -293,8 +293,7 @@ module Wechat
293
293
  { Encrypt: encrypt,
294
294
  MsgSignature: msg_sign,
295
295
  TimeStamp: timestamp,
296
- Nonce: nonce
297
- }.to_xml(root: 'xml', children: 'item', skip_instruct: true, skip_types: true)
296
+ Nonce: nonce }.to_xml(root: 'xml', children: 'item', skip_instruct: true, skip_types: true)
298
297
  end
299
298
 
300
299
  def request_encrypt_content
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Signature
3
5
  def self.hexdigest(token, timestamp, nonce, msg_encrypt)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wechat/ticket/jsapi_base'
2
4
 
3
5
  module Wechat
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'digest/sha1'
2
4
  require 'securerandom'
3
5
 
@@ -63,8 +65,8 @@ module Wechat
63
65
  end
64
66
 
65
67
  def write_ticket_to_store(ticket_hash)
66
- ticket_hash['got_ticket_at'.freeze] = Time.now.to_i
67
- ticket_hash['ticket_expires_in'.freeze] = ticket_hash.delete('expires_in')
68
+ ticket_hash['got_ticket_at'] = Time.now.to_i
69
+ ticket_hash['ticket_expires_in'] = ticket_hash.delete('expires_in')
68
70
  write_ticket(ticket_hash)
69
71
  end
70
72
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wechat/ticket/jsapi_base'
2
4
 
3
5
  module Wechat
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Wechat
2
4
  module Token
3
5
  class AccessTokenBase
@@ -32,8 +34,8 @@ module Wechat
32
34
  def write_token_to_store(token_hash)
33
35
  raise InvalidCredentialError unless token_hash.is_a?(Hash) && token_hash['access_token']
34
36
 
35
- token_hash['got_token_at'.freeze] = Time.now.to_i
36
- token_hash['token_expires_in'.freeze] = token_hash.delete('expires_in')
37
+ token_hash['got_token_at'] = Time.now.to_i
38
+ token_hash['token_expires_in'] = token_hash.delete('expires_in')
37
39
  write_token(token_hash)
38
40
  end
39
41
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wechat/token/access_token_base'
2
4
 
3
5
  module Wechat
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wechat/token/access_token_base'
2
4
 
3
5
  module Wechat
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.11.4
4
+ version: 0.11.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skinnyworm
@@ -12,30 +12,30 @@ cert_chain:
12
12
  - |
13
13
  -----BEGIN CERTIFICATE-----
14
14
  MIIEQDCCAqigAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBplcmlj
15
- Lmd1b2N6L0RDPWdtYWlsL0RDPWNvbTAeFw0xODA4MjcxMDM0MjBaFw0xOTA4Mjcx
16
- MDM0MjBaMCUxIzAhBgNVBAMMGmVyaWMuZ3VvY3ovREM9Z21haWwvREM9Y29tMIIB
17
- ojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvvuL8SAQjsNR1ij4IEo3u63M
18
- OST173hPCWPwvznHnDsphHMPY9erDkWWMC4Rx9Rq0mfQoONIbr7hgVMO2+ixsMuC
19
- c/sW8X3GY0WxiqCOXP7hIPycboRsb+h+dbbrzOGGsdN7jp8GQVlse75kDulGm2tz
20
- c+2uzj7qx+kAvlX1M+gAtoXwBte0BNYmqszOaHNxoiAd4MiTwxvhxmVrpd6V+oP1
21
- tNbZRQxRjDj3gJn/kV4qYQYUt5S7p7fIAnZ7JZicXsiffMSQGNcwijeMOQVyppl/
22
- DrRNnRkZLn5yge2oclPZetbeTOGMTURv5ktuykCqSlydq3+bC7uLzPTHFM9882y4
23
- +xcmWO3Ho9voGn3XtGKB5yJ+eUYTQ/Tm7bAICgi9R/0NFG01riq3RyFTFrCqmXgl
24
- PC6yn7KpelWPKRQ6oKu4vweUjgZlHa3eyAgQwTcVfS4ZOM1qXgsRtVHzUlSkiZt0
25
- 5Rp973RN1w5ZYmC9X4IqvazoWZq+uw/Tnp4bEZwRAgMBAAGjezB5MAkGA1UdEwQC
26
- MAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQGmgb/xHA1sOvdHsW8OZ0ID7cR3jAf
15
+ Lmd1b2N6L0RDPWdtYWlsL0RDPWNvbTAeFw0xOTA4MzAwODIzMTVaFw0yMDA4Mjkw
16
+ ODIzMTVaMCUxIzAhBgNVBAMMGmVyaWMuZ3VvY3ovREM9Z21haWwvREM9Y29tMIIB
17
+ ojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA2ZlFyUImo53jN4+1Kk6cyGts
18
+ LcT2x+i3G4mvZeqrZFCyhgWHJ04oAsfKBLCLRmspRsUuDQ3GQ8P5tH9oTduu55qy
19
+ ohflwuuffJHwsJYJEQ4hykJSCQ8gd4qj8WrhAmNo15ujq6mjGXPRBtZltR142kKE
20
+ o1tUYtc4Fr3oIAh65m62ZC2kJ5GATLYQ+U3JiiHWga8iJ8KSHbrzhM4N3ppaeYxD
21
+ wk6Lwk2OyppO9Iiv9Ad2BEFFd2s7mvYtaMGPWYK2fYTUuq6yKupg3CppX3ttq+bN
22
+ Ejx6dXn4RwYmATfc/Iv4aVU8lZS9HABqmProgkmi5vE2AAW1rQihm2ACm9VGlX+B
23
+ J2uIIWFJC56+TmkyqcBM87ztRxFlNLJe1G2S2TZ/qhAyWfoSEDA9eW6OUsb6qvnz
24
+ PHFPo/Vgq9BEoYMItUsEoJHdmLBjzhiccQx2XWAhZrBREpH20jIC/ereVGRpAeVf
25
+ kYdFgW84K+lL9XTt9QJNM08YM/mFcpaGq4/2YbbLAgMBAAGjezB5MAkGA1UdEwQC
26
+ MAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQdvlZDewUSWN/OWf9bTuDHHc5r+TAf
27
27
  BgNVHREEGDAWgRRlcmljLmd1b2N6QGdtYWlsLmNvbTAfBgNVHRIEGDAWgRRlcmlj
28
- Lmd1b2N6QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAp7iNDlqk1L5zrTmD
29
- E0QAEYo0wiKZ/x29kaXuG3j0hUkkwKFbhUHjsTEl307sO8yQRg/6DuVrQhUBwS9G
30
- g749ybsn7pfOL+lCVUGGxWFJ8qsICQ4ECjtnKVXdQowDUzSeb5/IPaeN+RB4Rh7D
31
- 2msnkJhsf0IQbNNUt53tkE5KhwAkHGdY5solSLPwtUmmdW1kNt7OfGBTi5CjXwFg
32
- Jh+lbxasy+KwHA6+9O5b8Qm2QSBN5bJGd2a63QE5p8cjRBnaRuiKn4wkmqMj/C0Z
33
- OyM5lSs5iGML+eVE/dCsV+YFmSr6Ue8vokmKdrBDjtAkHwmVA0TpqHVmT+9bVUPn
34
- Jl+EzvEfsjriqcj9+WGPo4R7XDQQnseHqzlXNedkrLFX/nTnEs5RKBZ6Ter1KRU6
35
- ivoox98/nhOs6bHcSFPsxXdxUihcCfCzj+zcaHNEqpvTI/36Bnl2XW6dUJNaFQDc
36
- oWOyq5ZkxqnYrYXactjW0+vcPv6WHoHXmjv4dF7iFp8r0mvK
28
+ Lmd1b2N6QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAkS8q1uex/jWTHtYi
29
+ 6Rgv8hZugwpFCwGPb9i4VgSSA1qkfsFhNxQji1xcpo8hYlH6zW9L6CGC9BU4n9R2
30
+ iyuuvtHVnxt5i6u39fIw0dIHJdtswSXZ6Kq58RP1Lg1nbmXX0zHz1fXp+DXL7NoJ
31
+ bBHL9Oy6jps/Lz8fIanPIZ6iT/akA7Mts94v1F9dyeA3IIJVptvmuGFC9PexX4TJ
32
+ fZ/qmk93C6KEOGEQ0zJzjnKjRZT0KOnJxbpB6/4Xvr+SrTb0yx20s+YWWa28pb0C
33
+ gNr4HHRfhmqxoTKvM4Mm9oJSBO/ENi5zfLwvwOWRuriMuDGYmKCdwmn4Y9asgYS4
34
+ 2febpVoh2LTA7GDc1VJOKhxisQ2OtYpcTR503eGyIrnS4NGs+B0rXOB7pEX+VOju
35
+ 2Gz/SZ1dgCkJpJU45GNrhatKx3kyg8eC5IHekNrEvJNJqPl0VdRIs/GtUkQyk+np
36
+ 3kTPkfLMsAZznXo3bzMe0V5TB4+a7pFEK1nN/htWrOVkIi/3
37
37
  -----END CERTIFICATE-----
38
- date: 2019-08-15 00:00:00.000000000 Z
38
+ date: 2019-08-30 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: activesupport
@@ -46,7 +46,7 @@ dependencies:
46
46
  version: '3.2'
47
47
  - - "<"
48
48
  - !ruby/object:Gem::Version
49
- version: '6'
49
+ version: '7'
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
@@ -56,7 +56,7 @@ dependencies:
56
56
  version: '3.2'
57
57
  - - "<"
58
58
  - !ruby/object:Gem::Version
59
- version: '6'
59
+ version: '7'
60
60
  - !ruby/object:Gem::Dependency
61
61
  name: http
62
62
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +105,20 @@ dependencies:
105
105
  - - ">="
106
106
  - !ruby/object:Gem::Version
107
107
  version: '0'
108
+ - !ruby/object:Gem::Dependency
109
+ name: rubocop
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - "~>"
113
+ - !ruby/object:Gem::Version
114
+ version: '0.74'
115
+ type: :development
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: '0.74'
108
122
  - !ruby/object:Gem::Dependency
109
123
  name: rails
110
124
  requirement: !ruby/object:Gem::Requirement
@@ -139,14 +153,14 @@ dependencies:
139
153
  requirements:
140
154
  - - "~>"
141
155
  - !ruby/object:Gem::Version
142
- version: 1.3.13
156
+ version: '1.4'
143
157
  type: :development
144
158
  prerelease: false
145
159
  version_requirements: !ruby/object:Gem::Requirement
146
160
  requirements:
147
161
  - - "~>"
148
162
  - !ruby/object:Gem::Version
149
- version: 1.3.13
163
+ version: '1.4'
150
164
  description: API, command and message handling for WeChat in Rails
151
165
  email: eric.guocz@gmail.com
152
166
  executables:
@@ -214,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
228
  - !ruby/object:Gem::Version
215
229
  version: '0'
216
230
  requirements: []
217
- rubygems_version: 3.0.4
231
+ rubygems_version: 3.0.6
218
232
  signing_key:
219
233
  specification_version: 4
220
234
  summary: DSL for wechat message handling and API
metadata.gz.sig CHANGED
Binary file