wechat 0.11.4 → 0.11.5
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 +4 -4
- checksums.yaml.gz.sig +5 -1
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +5 -0
- data/lib/action_controller/wechat_responder.rb +7 -5
- data/lib/generators/wechat/config_generator.rb +14 -10
- data/lib/generators/wechat/install_generator.rb +3 -1
- data/lib/generators/wechat/menu_generator.rb +3 -1
- data/lib/generators/wechat/redis_store_generator.rb +3 -1
- data/lib/generators/wechat/session_generator.rb +14 -10
- data/lib/generators/wechat/templates/app/models/wechat_config.rb +8 -13
- data/lib/generators/wechat/templates/app/models/wechat_session.rb +2 -0
- data/lib/generators/wechat/templates/config/initializers/wechat_redis_store.rb +5 -3
- data/lib/wechat.rb +5 -3
- data/lib/wechat/api.rb +2 -0
- data/lib/wechat/api_base.rb +8 -6
- data/lib/wechat/api_loader.rb +48 -49
- data/lib/wechat/cipher.rb +4 -2
- data/lib/wechat/concern/common.rb +2 -0
- data/lib/wechat/controller_api.rb +13 -10
- data/lib/wechat/corp_api.rb +2 -0
- data/lib/wechat/helpers.rb +14 -12
- data/lib/wechat/http_client.rb +21 -16
- data/lib/wechat/message.rb +17 -14
- data/lib/wechat/mp_api.rb +2 -0
- data/lib/wechat/responder.rb +37 -38
- data/lib/wechat/signature.rb +2 -0
- data/lib/wechat/ticket/corp_jsapi_ticket.rb +2 -0
- data/lib/wechat/ticket/jsapi_base.rb +4 -2
- data/lib/wechat/ticket/public_jsapi_ticket.rb +2 -0
- data/lib/wechat/token/access_token_base.rb +4 -2
- data/lib/wechat/token/corp_access_token.rb +2 -0
- data/lib/wechat/token/public_access_token.rb +2 -0
- metadata +42 -28
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 332ed5cc2f20211d70e994fc4549534748c9400074ece51debd7e4d147b4a1fd
|
|
4
|
+
data.tar.gz: 6cb347a738b602628c6dadae3ef2d90cddb9c1baff68e7e66b9bc88cc14a8643
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b293b5f93fcc0f304af98f7664c73469595028b4bc38d14c60bf2506243c288d59964e17acaea563c7922493b39e67bc56ede37e638fecaf4f83c332dbb60ca
|
|
7
|
+
data.tar.gz: 640d2a2b5fc743189f03f680c03404cc991ff6b5e50f84f802c520eed10d7df1690080ae11ac9f1b22ada9b4f45a5f1c6a8ba5e8f01a9043026ce20ed39569ee
|
checksums.yaml.gz.sig
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
�o����6�TK
|
|
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
|
data/CHANGELOG.md
CHANGED
|
@@ -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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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('
|
|
11
|
+
source_root File.expand_path('templates', __dir__)
|
|
10
12
|
|
|
11
13
|
def copy_wechat_config_migration
|
|
12
14
|
migration_template(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
25
|
+
class << self
|
|
26
|
+
private
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
11
|
+
source_root File.expand_path('templates', __dir__)
|
|
10
12
|
|
|
11
13
|
def copy_wechat_sessions_migration
|
|
12
14
|
migration_template(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
25
|
+
class << self
|
|
26
|
+
private
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
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).
|
|
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
|
-
|
|
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
|
-
|
|
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
|
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_#{
|
|
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_#{
|
|
40
|
+
"my_app_wechat_ticket_#{access_token.secret}"
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
end
|
data/lib/wechat.rb
CHANGED
|
@@ -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,
|
|
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(
|
|
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
|
|
49
|
+
rescue StandardError => e
|
|
48
50
|
{ 'errcode': 41003, 'errmsg': e.message }
|
|
49
51
|
end
|
|
50
52
|
end
|
data/lib/wechat/api.rb
CHANGED
data/lib/wechat/api_base.rb
CHANGED
|
@@ -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
|
|
6
|
-
MP_BASE = 'https://mp.weixin.qq.com/cgi-bin/'
|
|
7
|
-
WXA_BASE = 'https://api.weixin.qq.com/wxa/'
|
|
8
|
-
OAUTH2_BASE = 'https://api.weixin.qq.com/sns/'
|
|
9
|
-
DATACUBE_BASE = 'https://api.weixin.qq.com/datacube/'
|
|
10
|
-
QYAPI_BASE = 'https://qyapi.weixin.qq.com/cgi-bin/'
|
|
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'
|
data/lib/wechat/api_loader.rb
CHANGED
|
@@ -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 =
|
|
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
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
78
|
-
|
|
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
|
|
81
|
-
application_config_file = File.join(Dir.getwd, 'config
|
|
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 =
|
|
90
|
-
if config.present? && (default = config[:default])
|
|
91
|
-
puts "Using rails project #{ENV['WECHAT_CONF_FILE'] ||
|
|
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.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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)
|
data/lib/wechat/cipher.rb
CHANGED
|
@@ -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'
|
|
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
|
|
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 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 =
|
|
25
|
+
is_crop_account = config.corpid.present?
|
|
24
26
|
else
|
|
25
27
|
appid = self.class.corpid || self.class.appid
|
|
26
|
-
is_crop_account =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
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
|
|
data/lib/wechat/corp_api.rb
CHANGED
data/lib/wechat/helpers.rb
CHANGED
|
@@ -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
|
|
27
|
+
page_url = page_url.split('#').first if ios?
|
|
26
28
|
js_hash = api.jsapi_ticket.signature(page_url)
|
|
27
29
|
|
|
28
|
-
config_js =
|
|
29
|
-
wx.config({
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
45
|
+
def ios?
|
|
44
46
|
controller.request.user_agent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
|
|
45
47
|
end
|
|
46
48
|
end
|
data/lib/wechat/http_client.rb
CHANGED
|
@@ -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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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,
|
|
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\/.*}
|
|
79
|
-
%r{^audio\/.*}
|
|
80
|
-
%r{^voice\/.*}
|
|
81
|
-
%r{^text\/html}
|
|
82
|
-
%r{^text\/plain}
|
|
83
|
-
}.each_with_object([]) { |match, memo| memo << match[1] if content_type =~ match[0] }.first ||
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
data/lib/wechat/message.rb
CHANGED
|
@@ -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
|
-
|
|
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'
|
|
211
|
-
'Markdown'
|
|
212
|
-
'ToUserName'
|
|
213
|
-
'ToPartyName'
|
|
214
|
-
'ToWxName'
|
|
215
|
-
'MediaId'
|
|
216
|
-
'MpNews'
|
|
217
|
-
'ThumbMediaId'
|
|
218
|
-
'TemplateId'
|
|
219
|
-
'FormId'
|
|
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'
|
|
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
|
data/lib/wechat/mp_api.rb
CHANGED
data/lib/wechat/responder.rb
CHANGED
|
@@ -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: [
|
|
23
|
-
before_action :verify_signature, only: [
|
|
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: [
|
|
27
|
-
before_filter :verify_signature, only: [
|
|
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 [
|
|
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 [
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
50
|
-
raise 'Message type click, view, scan and batch_job must specify :with parameters'
|
|
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
|
-
@
|
|
91
|
+
@user_defined_scan_responders ||= []
|
|
90
92
|
end
|
|
91
93
|
|
|
92
94
|
def user_defined_location_responders
|
|
93
|
-
@
|
|
95
|
+
@user_defined_location_responders ||= []
|
|
94
96
|
end
|
|
95
97
|
|
|
96
98
|
def user_defined_label_location_responders
|
|
97
|
-
@
|
|
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
|
|
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
|
|
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
|
|
119
|
+
elsif message[:Event] == 'click'
|
|
118
120
|
yield(* match_responders(responders, message[:EventKey]))
|
|
119
|
-
elsif known_scan_key_lists.include?(message[:EventKey]) && %w
|
|
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
|
|
123
|
+
elsif message[:Event] == 'batch_job_result'
|
|
122
124
|
yield(* user_defined_batch_job_responders(message[:BatchJob][:JobType]), message[:BatchJob])
|
|
123
|
-
elsif
|
|
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
|
-
|
|
149
|
-
memo[:scoped] ||= [responder, value]
|
|
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
|
|
159
|
+
if %w[scan subscribe].freeze.include?(message[:Event]) && message[:EventKey] == responder[:with]
|
|
158
160
|
memo[:scaned] ||= [responder, message[:Ticket]]
|
|
159
|
-
elsif %w
|
|
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
|
-
|
|
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]
|
|
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]
|
|
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
|
-
|
|
267
|
-
|
|
266
|
+
|
|
267
|
+
if responder[:respond]
|
|
268
268
|
request.reply.text responder[:respond]
|
|
269
|
-
|
|
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
|
data/lib/wechat/signature.rb
CHANGED
|
@@ -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'
|
|
67
|
-
ticket_hash['ticket_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
|
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'
|
|
36
|
-
token_hash['token_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
|
|
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
|
+
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
+
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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-
|
|
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: '
|
|
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: '
|
|
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.
|
|
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.
|
|
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.
|
|
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
|