wechat 0.11.11 → 0.12.1

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
  SHA256:
3
- metadata.gz: 0f0bb39391f507bdd4855e02eb9d56a1e7b110c6c9fd8c16b65a984af1d376f1
4
- data.tar.gz: 673b26d9e77bf7d652fd0bfa30fdddf9516fc7b0a15bdf8b53e471fdb4db606c
3
+ metadata.gz: f7dfe45f7c68aafa5b96a2a3178ae2108f9989bb5594b6ae35d1e7dcc358219a
4
+ data.tar.gz: 25a51c65de855682ec12ee332241d9acd47c8cc8c2376995c8d8f0512825e899
5
5
  SHA512:
6
- metadata.gz: 841297efa8f80c68801a9348c253b7666b501f0cec535f39e42d268d6e5188c9c0f551c3d1af72282194cc97e9c65bcb1e30a9359b208d345a8a5e237c46858e
7
- data.tar.gz: 31a0a90843b8ca7357563fc9cbf53cf795a1ef58d7292bae725caaf4b5868997975176b0cf26b9b2259c5378d04eee28053d3e91d6d26a057bdab5aaf29b39f9
6
+ metadata.gz: '080ada4dbb3191ed4d10d51d4cef85de0cfc469af61f636ee99b03be92e487060fa454a37ef54a8386d77d1ebede360d2819c64d59f0d1ca2a202ba199e1a31e'
7
+ data.tar.gz: f3482024b4e35f91924c384ca27819748341444047c135362552b460ccf15243fcd5fd1c896e0c15eb00e392aa73ce1c750854b78e6e0c52af0176482e4939cb
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.12.1 (released at 28/12/2020)
4
+
5
+ * Support Ruby 3.0.
6
+ * Qcloud_token support.
7
+ * CRUD of tencent cloud DB for miniapp
8
+ * TCB storage API support.
9
+ * Set default branch to *main*.
10
+
3
11
  ## v0.11.11 (released at 09/13/2020)
4
12
 
5
13
  * FIX: fix_load_controller_wechat not support MP type, by @Msms-NJ #281
@@ -38,27 +38,28 @@ module ActionController
38
38
  self.trusted_domain_fullname = opts[:trusted_domain_fullname] || cfg.trusted_domain_fullname
39
39
  self.oauth2_cookie_duration = opts[:oauth2_cookie_duration] || cfg.oauth2_cookie_duration.to_i.seconds
40
40
  self.timeout = opts[:timeout] || cfg.timeout
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
41
+ self.qcloud_token_lifespan = opts[:qcloud_token_lifespan] || cfg.qcloud_token_lifespan
42
+ self.skip_verify_ssl = opts.key?(:skip_verify_ssl) ? opts[:skip_verify_ssl] : cfg.skip_verify_ssl
46
43
 
47
44
  return Wechat.api if account == :default && opts.empty?
48
45
 
49
46
  access_token = opts[:access_token] || cfg.access_token
50
47
  jsapi_ticket = opts[:jsapi_ticket] || cfg.jsapi_ticket
48
+ qcloud_token = opts[:qcloud_token] || cfg.qcloud_token
51
49
 
52
- if corpid.present?
53
- corpsecret = opts[:corpsecret] || cfg.corpsecret
54
- Wechat::CorpApi.new(corpid, corpsecret, access_token, \
55
- agentid, timeout, skip_verify_ssl, jsapi_ticket)
50
+ api_type = opts[:type] || cfg.type
51
+ secret = corpid.present? ? opts[:corpsecret] || cfg.corpsecret : opts[:secret] || cfg.secret
52
+
53
+ get_wechat_api(api_type, corpid, appid, secret, access_token, agentid, timeout, skip_verify_ssl, jsapi_ticket, qcloud_token, qcloud_token_lifespan)
54
+ end
55
+
56
+ def get_wechat_api(api_type, corpid, appid, secret, access_token, agentid, timeout, skip_verify_ssl, jsapi_ticket, qcloud_token, qcloud_token_lifespan)
57
+ if api_type && api_type.to_sym == :mp
58
+ Wechat::MpApi.new(appid, secret, access_token, timeout, skip_verify_ssl, jsapi_ticket, qcloud_token, qcloud_token_lifespan)
59
+ elsif corpid.present?
60
+ Wechat::CorpApi.new(corpid, secret, access_token, agentid, timeout, skip_verify_ssl, jsapi_ticket)
56
61
  else
57
- type = opts[:type] || cfg.type
58
- secret = opts[:secret] || cfg.secret
59
- wechat_api_class = (type && type.to_sym == :mp ? Wechat::MpApi : Wechat::Api)
60
- wechat_api_class.new(appid, secret, access_token, \
61
- timeout, skip_verify_ssl, jsapi_ticket)
62
+ Wechat::Api.new(appid, secret, access_token, timeout, skip_verify_ssl, jsapi_ticket)
62
63
  end
63
64
  end
64
65
  end
@@ -35,7 +35,7 @@ class WechatConfig < ActiveRecord::Base
35
35
  errors.add(:corpsecret, 'cannot be nil when corpid is set') if self[:corpsecret].blank?
36
36
  errors.add(:agentid, 'cannot be nil when corpid is set') if self[:agentid].blank?
37
37
  else
38
- errors[:base] << 'Either appid or corpid must be set'
38
+ errors.add(:base, 'Either appid or corpid must be set')
39
39
  end
40
40
  end
41
41
  end
@@ -16,7 +16,9 @@ module Wechat
16
16
  autoload :ControllerApi, 'wechat/controller_api'
17
17
 
18
18
  class AccessTokenExpiredError < StandardError; end
19
+
19
20
  class InvalidCredentialError < StandardError; end
21
+
20
22
  class ResponseError < StandardError
21
23
  attr_reader :error_code
22
24
 
@@ -8,6 +8,14 @@ require 'wechat/concern/common'
8
8
 
9
9
  module Wechat
10
10
  class Api < ApiBase
11
+ def initialize(appid, secret, token_file, timeout, skip_verify_ssl, jsapi_ticket_file)
12
+ super()
13
+ @client = HttpClient.new(Wechat::Api::API_BASE, timeout, skip_verify_ssl)
14
+ @access_token = Token::PublicAccessToken.new(@client, appid, secret, token_file)
15
+ @jsapi_ticket = Ticket::PublicJsapiTicket.new(@client, @access_token, jsapi_ticket_file)
16
+ @qcloud = nil
17
+ end
18
+
11
19
  include Concern::Common
12
20
 
13
21
  def template_message_send(message)
@@ -2,13 +2,14 @@
2
2
 
3
3
  module Wechat
4
4
  class ApiBase
5
- attr_reader :access_token, :client, :jsapi_ticket
5
+ attr_reader :access_token, :client, :jsapi_ticket, :qcloud
6
6
 
7
7
  API_BASE = 'https://api.weixin.qq.com/cgi-bin/'
8
8
  MP_BASE = 'https://mp.weixin.qq.com/cgi-bin/'
9
9
  WXA_BASE = 'https://api.weixin.qq.com/wxa/'
10
10
  OAUTH2_BASE = 'https://api.weixin.qq.com/sns/'
11
11
  DATACUBE_BASE = 'https://api.weixin.qq.com/datacube/'
12
+ TCB_BASE = 'https://api.weixin.qq.com/tcb/'
12
13
  QYAPI_BASE = 'https://qyapi.weixin.qq.com/cgi-bin/'
13
14
 
14
15
  def callbackip
@@ -9,9 +9,16 @@ module Wechat
9
9
  token_file = options[:token_file] || c.access_token.presence || '/var/tmp/wechat_access_token'
10
10
  js_token_file = options[:js_token_file] || c.jsapi_ticket.presence || '/var/tmp/wechat_jsapi_ticket'
11
11
  type = options[:type] || c.type
12
+
12
13
  if c.appid && c.secret && token_file.present?
13
- wx_class = type == 'mp' ? Wechat::MpApi : Wechat::Api
14
- wx_class.new(c.appid, c.secret, token_file, c.timeout, c.skip_verify_ssl, js_token_file)
14
+ if type == 'mp'
15
+ qcloud_env = options[:qcloud_env] || c.qcloud_env
16
+ qcloud_token_file = options[:qcloud_token_file] || c.qcloud_token_file.presence || '/var/tmp/qcloud_access_token'
17
+ qcloud_token_lifespan = options[:qcloud_token_lifespan] || c.qcloud_token_lifespan
18
+ Wechat::MpApi.new(c.appid, c.secret, token_file, c.timeout, c.skip_verify_ssl, js_token_file, qcloud_env, qcloud_token_file, qcloud_token_lifespan)
19
+ else
20
+ Wechat::Api.new(c.appid, c.secret, token_file, c.timeout, c.skip_verify_ssl, js_token_file)
21
+ end
15
22
  elsif c.corpid && c.corpsecret && token_file.present?
16
23
  Wechat::CorpApi.new(c.corpid, c.corpsecret, token_file, c.agentid, c.timeout, c.skip_verify_ssl, js_token_file)
17
24
  else
@@ -46,11 +53,13 @@ module Wechat
46
53
  configs.each do |_, cfg|
47
54
  cfg[:access_token] ||= Rails.root.try(:join, 'tmp/access_token').try(:to_path)
48
55
  cfg[:jsapi_ticket] ||= Rails.root.try(:join, 'tmp/jsapi_ticket').try(:to_path)
56
+ cfg[:qcloud_token] ||= Rails.root.try(:join, 'tmp/qcloud_token').try(:to_path)
49
57
  end
50
58
  end
51
59
 
52
60
  configs.each do |_, cfg|
53
61
  cfg[:timeout] ||= 20
62
+ cfg[:qcloud_token_lifespan] ||= 7200
54
63
  cfg[:have_session_class] = class_exists?('WechatSession')
55
64
  cfg[:oauth2_cookie_duration] ||= 1.hour
56
65
  end
@@ -135,6 +144,9 @@ module Wechat
135
144
  skip_verify_ssl: ENV['WECHAT_SKIP_VERIFY_SSL'],
136
145
  encoding_aes_key: ENV['WECHAT_ENCODING_AES_KEY'],
137
146
  jsapi_ticket: ENV['WECHAT_JSAPI_TICKET'],
147
+ qcloud_env: ENV['WECHAT_QCLOUD_ENV'],
148
+ qcloud_token_file: ENV['WECHAT_QCLOUD_TOKEN'],
149
+ qcloud_token_lifespan: ENV['WECHAT_QCLOUD_TOKEN_LIFESPAN'],
138
150
  trusted_domain_fullname: ENV['WECHAT_TRUSTED_DOMAIN_FULLNAME'] }
139
151
  { default: value }
140
152
  end
@@ -3,12 +3,6 @@
3
3
  module Wechat
4
4
  module Concern
5
5
  module Common
6
- def initialize(appid, secret, token_file, timeout, skip_verify_ssl, jsapi_ticket_file)
7
- @client = HttpClient.new(Wechat::Api::API_BASE, timeout, skip_verify_ssl)
8
- @access_token = Token::PublicAccessToken.new(@client, appid, secret, token_file)
9
- @jsapi_ticket = Ticket::PublicJsapiTicket.new(@client, @access_token, jsapi_ticket_file)
10
- end
11
-
12
6
  def groups
13
7
  get 'groups/get'
14
8
  end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wechat
4
+ module Concern
5
+ module Qcloud
6
+ def invoke_cloud_function(function_name, post_body_params)
7
+ post 'invokecloudfunction', JSON.generate(post_body_params), params: { env: qcloud.qcloud_env, name: function_name }, base: Wechat::Api::TCB_BASE
8
+ end
9
+
10
+ def qdb_migrate_import(collection_name, file_path, file_type: Wechat::Qcloud::FILE_TYPE_JSON, stop_on_error: false, conflict_mode: Wechat::Qcloud::CONFLICT_MODE_UPSERT)
11
+ import_params_hash = { env: qcloud.qcloud_env,
12
+ collection_name: collection_name,
13
+ file_path: file_path,
14
+ file_type: file_type,
15
+ stop_on_error: stop_on_error,
16
+ conflict_mode: conflict_mode }
17
+ post 'databasemigrateimport', JSON.generate(import_params_hash), base: Wechat::Api::TCB_BASE
18
+ end
19
+
20
+ def qdb_migrate_export(query, file_path, file_type: Wechat::Qcloud::FILE_TYPE_JSON)
21
+ export_params_hash = { env: qcloud.qcloud_env,
22
+ file_path: file_path,
23
+ file_type: file_type,
24
+ query: query }
25
+ post 'databasemigrateexport', JSON.generate(export_params_hash), base: Wechat::Api::TCB_BASE
26
+ end
27
+
28
+ def qdb_migrate_query(job_id)
29
+ query_info_hash = { env: qcloud.qcloud_env,
30
+ job_id: job_id }
31
+
32
+ post 'databasemigratequeryinfo', JSON.generate(query_info_hash), base: Wechat::Api::TCB_BASE
33
+ end
34
+
35
+ def qdb_update_index(collection_name, create_indexes: [], drop_indexes: [])
36
+ update_index_params_hash = { env: qcloud.qcloud_env,
37
+ collection_name: collection_name,
38
+ create_indexes: create_indexes,
39
+ drop_indexes: drop_indexes }
40
+ post 'updateindex', JSON.generate(update_index_params_hash), base: Wechat::Api::TCB_BASE
41
+ end
42
+
43
+ def qdb_collection_add(collection_name)
44
+ collection_add_params_hash = { env: qcloud.qcloud_env,
45
+ collection_name: collection_name }
46
+ post 'databasecollectionadd', JSON.generate(collection_add_params_hash), base: Wechat::Api::TCB_BASE
47
+ end
48
+
49
+ def qdb_collection_delete(collection_name)
50
+ collection_delete_params_hash = { env: qcloud.qcloud_env,
51
+ collection_name: collection_name }
52
+ post 'databasecollectiondelete', JSON.generate(collection_delete_params_hash), base: Wechat::Api::TCB_BASE
53
+ end
54
+
55
+ def qdb_collections(limit: 10, offset: 0)
56
+ get_collections_params_hash = { env: qcloud.qcloud_env,
57
+ limit: limit,
58
+ offset: offset }
59
+ post 'databasecollectionget', JSON.generate(get_collections_params_hash), base: Wechat::Api::TCB_BASE
60
+ end
61
+
62
+ def qdb_add(add_query)
63
+ post 'databaseadd', JSON.generate(env: qcloud.qcloud_env, query: add_query), base: Wechat::Api::TCB_BASE
64
+ end
65
+
66
+ def qdb_delete(delete_query)
67
+ post 'databasedelete', JSON.generate(env: qcloud.qcloud_env, query: delete_query), base: Wechat::Api::TCB_BASE
68
+ end
69
+
70
+ def qdb_update(update_query)
71
+ post 'databaseupdate', JSON.generate(env: qcloud.qcloud_env, query: update_query), base: Wechat::Api::TCB_BASE
72
+ end
73
+
74
+ def qdb_query(query)
75
+ post 'databasequery', JSON.generate(env: qcloud.qcloud_env, query: query), base: Wechat::Api::TCB_BASE
76
+ end
77
+
78
+ def qdb_aggregate(aggregate_query)
79
+ post 'databaseaggregate', JSON.generate(env: qcloud.qcloud_env, query: aggregate_query), base: Wechat::Api::TCB_BASE
80
+ end
81
+
82
+ def qdb_count(count_query)
83
+ post 'databasecount', JSON.generate(env: qcloud.qcloud_env, query: count_query), base: Wechat::Api::TCB_BASE
84
+ end
85
+
86
+ def tcb_delete_files(fileid_list)
87
+ post 'batchdeletefile', JSON.generate(env: qcloud.qcloud_env, fileid_list: fileid_list), base: Wechat::Api::TCB_BASE
88
+ end
89
+
90
+ def tcb_download_files(file_list)
91
+ post 'batchdownloadfile', JSON.generate(env: qcloud.qcloud_env, file_list: file_list), base: Wechat::Api::TCB_BASE
92
+ end
93
+
94
+ def tcb_preflight_upload_file(q_path)
95
+ post 'uploadfile', JSON.generate(env: qcloud.qcloud_env, path: q_path), base: Wechat::Api::TCB_BASE
96
+ end
97
+
98
+ def tcb_do_upload_file(q_path, upload_url, signature, x_cos_security_token, x_cos_meta_fileid, file)
99
+ form_file = file.is_a?(HTTP::FormData::File) ? file : HTTP::FormData::File.new(file)
100
+ form_data = HTTP::FormData.create({ key: q_path,
101
+ Signature: signature,
102
+ "x-cos-security-token": x_cos_security_token,
103
+ 'x-cos-meta-fileid': x_cos_meta_fileid,
104
+ file: form_file })
105
+ client.httprb.post(upload_url, form: form_data, ssl_context: client.ssl_context)
106
+ end
107
+
108
+ def tcb_upload_file(q_path, file)
109
+ res = tcb_preflight_upload_file(q_path)
110
+ tcb_do_upload_file(q_path, res['url'], res['authorization'], res['token'], res['cos_file_id'], file)
111
+ res
112
+ end
113
+ end
114
+ end
115
+ end
@@ -5,7 +5,7 @@ module Wechat
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  module ClassMethods
8
- attr_accessor :wechat_api_client, :wechat_cfg_account, :token, :appid, :corpid, :agentid, :encrypt_mode, :timeout,
8
+ attr_accessor :wechat_api_client, :wechat_cfg_account, :token, :appid, :corpid, :agentid, :encrypt_mode, :timeout, :qcloud_token_lifespan,
9
9
  :skip_verify_ssl, :encoding_aes_key, :trusted_domain_fullname, :oauth2_cookie_duration
10
10
  end
11
11
 
@@ -15,6 +15,7 @@ module Wechat
15
15
  @access_token = Token::CorpAccessToken.new(@client, appid, secret, token_file)
16
16
  @agentid = agentid
17
17
  @jsapi_ticket = Ticket::CorpJsapiTicket.new(@client, @access_token, jsapi_ticket_file)
18
+ @qcloud = nil
18
19
  end
19
20
 
20
21
  def agent_list
@@ -91,7 +92,7 @@ module Wechat
91
92
  end
92
93
 
93
94
  def department_update(departmentid, name = nil, parentid = nil, order = nil)
94
- post 'department/update', JSON.generate({ id: departmentid, name: name, parentid: parentid, order: order }.reject { |_k, v| v.nil? })
95
+ post 'department/update', JSON.generate({ id: departmentid, name: name, parentid: parentid, order: order }.compact)
95
96
  end
96
97
 
97
98
  def department(departmentid = 1)
@@ -24,7 +24,7 @@ module Wechat
24
24
  else
25
25
  controller.request.original_url
26
26
  end
27
- page_url = page_url.split('#').first if ios?
27
+ page_url = page_url.split('#').first
28
28
  js_hash = api.jsapi_ticket.signature(page_url)
29
29
 
30
30
  config_js = <<~WECHAT_CONFIG_JS
@@ -39,11 +39,5 @@ module Wechat
39
39
  WECHAT_CONFIG_JS
40
40
  javascript_tag config_js, type: 'application/javascript'
41
41
  end
42
-
43
- private
44
-
45
- def ios?
46
- controller.request.user_agent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
47
- end
48
42
  end
49
43
  end
@@ -14,7 +14,7 @@ module Wechat
14
14
  HTTP.timeout(:global, write: timeout, connect: timeout, read: timeout)
15
15
  end
16
16
  @ssl_context = OpenSSL::SSL::SSLContext.new
17
- @ssl_context.ssl_version = :TLSv1_2
17
+ @ssl_context.ssl_version = 'TLSv1_2'
18
18
  @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE if skip_verify_ssl
19
19
  end
20
20
 
@@ -41,14 +41,14 @@ module Wechat
41
41
 
42
42
  class NewsArticleBuilder < ArticleBuilder
43
43
  def item(title: 'title', description: nil, pic_url: nil, url: nil)
44
- items << { Title: title, Description: description, PicUrl: pic_url, Url: url }.reject { |_k, v| v.nil? }
44
+ items << { Title: title, Description: description, PicUrl: pic_url, Url: url }.compact
45
45
  end
46
46
  end
47
47
 
48
48
  class MpNewsArticleBuilder < ArticleBuilder
49
49
  def item(thumb_media_id:, title:, content:, author: nil, content_source_url: nil, digest: nil, show_cover_pic: '0')
50
50
  items << { Thumb_Media_ID: thumb_media_id, Author: author, Title: title, ContentSourceUrl: content_source_url,
51
- Content: content, Digest: digest, ShowCoverPic: show_cover_pic }.reject { |_k, v| v.nil? }
51
+ Content: content, Digest: digest, ShowCoverPic: show_cover_pic }.compact
52
52
  end
53
53
  end
54
54
 
@@ -169,7 +169,7 @@ module Wechat
169
169
  items = article.items
170
170
  else
171
171
  items = collection.collect do |item|
172
- camelize_hash_keys(item.symbolize_keys.slice(:title, :description, :pic_url, :url).reject { |_k, v| v.nil? })
172
+ camelize_hash_keys(item.symbolize_keys.slice(:title, :description, :pic_url, :url).compact)
173
173
  end
174
174
  end
175
175
 
@@ -184,7 +184,7 @@ module Wechat
184
184
  items = article.items
185
185
  else
186
186
  items = collection.collect do |item|
187
- camelize_hash_keys(item.symbolize_keys.slice(:thumb_media_id, :title, :content, :author, :content_source_url, :digest, :show_cover_pic).reject { |_k, v| v.nil? })
187
+ camelize_hash_keys(item.symbolize_keys.slice(:thumb_media_id, :title, :content, :author, :content_source_url, :digest, :show_cover_pic).compact)
188
188
  end
189
189
  end
190
190
 
@@ -4,11 +4,22 @@ require 'wechat/api_base'
4
4
  require 'wechat/http_client'
5
5
  require 'wechat/token/public_access_token'
6
6
  require 'wechat/ticket/public_jsapi_ticket'
7
+ require 'wechat/qcloud/token'
7
8
  require 'wechat/concern/common'
9
+ require 'wechat/concern/qcloud'
8
10
 
9
11
  module Wechat
10
12
  class MpApi < ApiBase
13
+ def initialize(appid, secret, token_file, timeout, skip_verify_ssl, jsapi_ticket_file, qcloud_env, qcloud_token_file, qcloud_token_lifespan)
14
+ super()
15
+ @client = HttpClient.new(Wechat::Api::API_BASE, timeout, skip_verify_ssl)
16
+ @access_token = Token::PublicAccessToken.new(@client, appid, secret, token_file)
17
+ @jsapi_ticket = Ticket::PublicJsapiTicket.new(@client, @access_token, jsapi_ticket_file)
18
+ @qcloud = Qcloud::Token.new(@client, @access_token, qcloud_env, qcloud_token_file, qcloud_token_lifespan)
19
+ end
20
+
11
21
  include Concern::Common
22
+ include Concern::Qcloud
12
23
 
13
24
  def template_message_send(message)
14
25
  post 'message/wxopen/template/send', message.to_json, content_type: :json
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wechat
4
+ module Qcloud
5
+ FILE_TYPE_JSON = 1
6
+ FILE_TYPE_CSV = 2
7
+ CONFLICT_MODE_INSERT = 1
8
+ CONFLICT_MODE_UPSERT = 2
9
+
10
+ class Token
11
+ attr_reader :client, :access_token, :qcloud_env, :qcloud_token_file, :qcloud_token_lifespan, :qcloud_token, :qcloud_token_expired_time
12
+
13
+ def initialize(client, access_token, qcloud_env, qcloud_token_file, lifespan)
14
+ @client = client
15
+ @access_token = access_token
16
+ @qcloud_env = qcloud_env
17
+ @qcloud_token_file = qcloud_token_file
18
+ @qcloud_token_lifespan = lifespan
19
+ @random_generator = Random.new
20
+ end
21
+
22
+ def token(tries = 2)
23
+ # Possible two worker running, one worker refresh ticket, other unaware, so must read every time
24
+ read_qcloud_token_from_store
25
+ refresh if remain_life_seconds < @random_generator.rand(30..3 * 60)
26
+ qcloud_token
27
+ rescue AccessTokenExpiredError
28
+ access_token.refresh
29
+ retry unless (tries -= 1).zero?
30
+ end
31
+
32
+ def refresh
33
+ data = client.post('getqcloudtoken', JSON.generate(lifespan: qcloud_token_lifespan), base: ::Wechat::ApiBase::TCB_BASE, params: { access_token: access_token.token })
34
+ write_qcloud_token_to_store(data)
35
+ read_qcloud_token_from_store
36
+ end
37
+
38
+ protected
39
+
40
+ def read_qcloud_token_from_store
41
+ td = read_qcloud_token
42
+ @qcloud_token_expired_time = td.fetch('qcloud_token_expired_time').to_i
43
+ @qcloud_token = td.fetch('token') # return qcloud_token same time
44
+ rescue JSON::ParserError, Errno::ENOENT, KeyError, TypeError
45
+ refresh
46
+ end
47
+
48
+ def write_qcloud_token_to_store(qcloud_token_hash)
49
+ qcloud_token_hash['qcloud_token_expired_time'] = qcloud_token_hash.delete('expired_time')
50
+ write_qcloud_token(qcloud_token_hash)
51
+ end
52
+
53
+ def read_qcloud_token
54
+ JSON.parse(File.read(qcloud_token_file))
55
+ end
56
+
57
+ def write_qcloud_token(qcloud_token_hash)
58
+ File.write(qcloud_token_file, qcloud_token_hash.to_json)
59
+ end
60
+
61
+ def remain_life_seconds
62
+ qcloud_token_expired_time - Time.now.to_i
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'English'
4
+ require 'rexml/document'
4
5
  require 'wechat/signature'
5
6
 
6
7
  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.11
4
+ version: 0.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skinnyworm
@@ -35,7 +35,7 @@ cert_chain:
35
35
  spvOK5/LPXWX6ZGc2SR8SH/s7ftYH2EkeM1VUbtemow08NdgCwJ4IG+fRQ9dcrJ+
36
36
  L9TbpLHvVrCe1w8duMqNeUmqj+M1iC/5Zst2vIe14QcOTuAh
37
37
  -----END CERTIFICATE-----
38
- date: 2020-09-13 00:00:00.000000000 Z
38
+ date: 2020-12-28 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: activesupport
@@ -105,20 +105,34 @@ dependencies:
105
105
  - - ">="
106
106
  - !ruby/object:Gem::Version
107
107
  version: '0'
108
+ - !ruby/object:Gem::Dependency
109
+ name: rexml
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ type: :runtime
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
108
122
  - !ruby/object:Gem::Dependency
109
123
  name: rubocop
110
124
  requirement: !ruby/object:Gem::Requirement
111
125
  requirements:
112
126
  - - "~>"
113
127
  - !ruby/object:Gem::Version
114
- version: '0.74'
128
+ version: '1.0'
115
129
  type: :development
116
130
  prerelease: false
117
131
  version_requirements: !ruby/object:Gem::Requirement
118
132
  requirements:
119
133
  - - "~>"
120
134
  - !ruby/object:Gem::Version
121
- version: '0.74'
135
+ version: '1.0'
122
136
  - !ruby/object:Gem::Dependency
123
137
  name: rails
124
138
  requirement: !ruby/object:Gem::Requirement
@@ -195,12 +209,14 @@ files:
195
209
  - lib/wechat/api_loader.rb
196
210
  - lib/wechat/cipher.rb
197
211
  - lib/wechat/concern/common.rb
212
+ - lib/wechat/concern/qcloud.rb
198
213
  - lib/wechat/controller_api.rb
199
214
  - lib/wechat/corp_api.rb
200
215
  - lib/wechat/helpers.rb
201
216
  - lib/wechat/http_client.rb
202
217
  - lib/wechat/message.rb
203
218
  - lib/wechat/mp_api.rb
219
+ - lib/wechat/qcloud/token.rb
204
220
  - lib/wechat/responder.rb
205
221
  - lib/wechat/signature.rb
206
222
  - lib/wechat/ticket/corp_jsapi_ticket.rb
@@ -219,7 +235,7 @@ require_paths:
219
235
  - lib
220
236
  required_ruby_version: !ruby/object:Gem::Requirement
221
237
  requirements:
222
- - - "~>"
238
+ - - ">="
223
239
  - !ruby/object:Gem::Version
224
240
  version: '2.4'
225
241
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -228,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
228
244
  - !ruby/object:Gem::Version
229
245
  version: '0'
230
246
  requirements: []
231
- rubygems_version: 3.1.4
247
+ rubygems_version: 3.2.3
232
248
  signing_key:
233
249
  specification_version: 4
234
250
  summary: DSL for wechat message handling and API
metadata.gz.sig CHANGED
Binary file