wechat 0.11.10 → 0.13.1
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 +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +6 -374
- data/README-CN.md +6 -1
- data/README.md +6 -1
- data/bin/wechat +5 -3
- data/lib/action_controller/wechat_responder.rb +16 -23
- data/lib/generators/wechat/config_generator.rb +1 -1
- data/lib/generators/wechat/session_generator.rb +1 -1
- data/lib/generators/wechat/templates/app/models/wechat_config.rb +1 -1
- data/lib/wechat.rb +27 -12
- data/lib/wechat/api.rb +8 -6
- data/lib/wechat/api_base.rb +2 -1
- data/lib/wechat/api_loader.rb +14 -2
- data/lib/wechat/cipher.rb +3 -3
- data/lib/wechat/concern/common.rb +0 -6
- data/lib/wechat/concern/qcloud.rb +115 -0
- data/lib/wechat/controller_api.rb +3 -3
- data/lib/wechat/corp_api.rb +7 -6
- data/lib/wechat/helpers.rb +1 -7
- data/lib/wechat/http_client.rb +7 -7
- data/lib/wechat/message.rb +5 -4
- data/lib/wechat/mp_api.rb +9 -6
- data/lib/wechat/qcloud/token.rb +66 -0
- data/lib/wechat/responder.rb +13 -43
- data/lib/wechat/ticket/corp_jsapi_ticket.rb +0 -2
- data/lib/wechat/ticket/public_jsapi_ticket.rb +0 -2
- data/lib/wechat/token/corp_access_token.rb +0 -2
- data/lib/wechat/token/public_access_token.rb +0 -2
- metadata +41 -11
- metadata.gz.sig +0 -0
data/lib/wechat/helpers.rb
CHANGED
@@ -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
|
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
|
data/lib/wechat/http_client.rb
CHANGED
@@ -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 =
|
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
|
|
@@ -77,12 +77,12 @@ module Wechat
|
|
77
77
|
def parse_response(response, as_type)
|
78
78
|
content_type = response.headers[:content_type]
|
79
79
|
parse_as = {
|
80
|
-
%r{^application
|
81
|
-
%r{^image
|
82
|
-
%r{^audio
|
83
|
-
%r{^voice
|
84
|
-
%r{^text
|
85
|
-
%r{^text
|
80
|
+
%r{^application/json} => :json,
|
81
|
+
%r{^image/.*} => :file,
|
82
|
+
%r{^audio/.*} => :file,
|
83
|
+
%r{^voice/.*} => :file,
|
84
|
+
%r{^text/html} => :xml,
|
85
|
+
%r{^text/plain} => :probably_json
|
86
86
|
}.each_with_object([]) { |match, memo| memo << match[1] if content_type =~ match[0] }.first || as_type || :text
|
87
87
|
|
88
88
|
# try to parse response as json, fallback to user-specified format or text if failed
|
data/lib/wechat/message.rb
CHANGED
@@ -32,6 +32,7 @@ module Wechat
|
|
32
32
|
|
33
33
|
class ArticleBuilder
|
34
34
|
attr_reader :items
|
35
|
+
|
35
36
|
delegate :count, to: :items
|
36
37
|
def initialize
|
37
38
|
@items = []
|
@@ -40,14 +41,14 @@ module Wechat
|
|
40
41
|
|
41
42
|
class NewsArticleBuilder < ArticleBuilder
|
42
43
|
def item(title: 'title', description: nil, pic_url: nil, url: nil)
|
43
|
-
items << { Title: title, Description: description, PicUrl: pic_url, Url: url }.
|
44
|
+
items << { Title: title, Description: description, PicUrl: pic_url, Url: url }.compact
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
48
|
class MpNewsArticleBuilder < ArticleBuilder
|
48
49
|
def item(thumb_media_id:, title:, content:, author: nil, content_source_url: nil, digest: nil, show_cover_pic: '0')
|
49
50
|
items << { Thumb_Media_ID: thumb_media_id, Author: author, Title: title, ContentSourceUrl: content_source_url,
|
50
|
-
Content: content, Digest: digest, ShowCoverPic: show_cover_pic }.
|
51
|
+
Content: content, Digest: digest, ShowCoverPic: show_cover_pic }.compact
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
@@ -168,7 +169,7 @@ module Wechat
|
|
168
169
|
items = article.items
|
169
170
|
else
|
170
171
|
items = collection.collect do |item|
|
171
|
-
camelize_hash_keys(item.symbolize_keys.slice(:title, :description, :pic_url, :url).
|
172
|
+
camelize_hash_keys(item.symbolize_keys.slice(:title, :description, :pic_url, :url).compact)
|
172
173
|
end
|
173
174
|
end
|
174
175
|
|
@@ -183,7 +184,7 @@ module Wechat
|
|
183
184
|
items = article.items
|
184
185
|
else
|
185
186
|
items = collection.collect do |item|
|
186
|
-
camelize_hash_keys(item.symbolize_keys.slice(:thumb_media_id, :title, :content, :author, :content_source_url, :digest, :show_cover_pic).
|
187
|
+
camelize_hash_keys(item.symbolize_keys.slice(:thumb_media_id, :title, :content, :author, :content_source_url, :digest, :show_cover_pic).compact)
|
187
188
|
end
|
188
189
|
end
|
189
190
|
|
data/lib/wechat/mp_api.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'wechat/api_base'
|
4
|
-
require 'wechat/http_client'
|
5
|
-
require 'wechat/token/public_access_token'
|
6
|
-
require 'wechat/ticket/public_jsapi_ticket'
|
7
|
-
require 'wechat/concern/common'
|
8
|
-
|
9
3
|
module Wechat
|
10
4
|
class MpApi < ApiBase
|
5
|
+
def initialize(appid, secret, token_file, timeout, skip_verify_ssl, jsapi_ticket_file, qcloud_env, qcloud_token_file, qcloud_token_lifespan)
|
6
|
+
super()
|
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
|
+
@qcloud = Qcloud::Token.new(@client, @access_token, qcloud_env, qcloud_token_file, qcloud_token_lifespan)
|
11
|
+
end
|
12
|
+
|
11
13
|
include Concern::Common
|
14
|
+
include Concern::Qcloud
|
12
15
|
|
13
16
|
def template_message_send(message)
|
14
17
|
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
|
data/lib/wechat/responder.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'English'
|
4
|
-
require '
|
4
|
+
require 'rexml/document'
|
5
5
|
|
6
6
|
module Wechat
|
7
7
|
module Responder
|
@@ -10,24 +10,9 @@ module Wechat
|
|
10
10
|
include Cipher
|
11
11
|
|
12
12
|
included do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
skip_before_action :verify_authenticity_token
|
17
|
-
else
|
18
|
-
# Rails 5 API mode won't define verify_authenticity_token
|
19
|
-
# https://github.com/rails/rails/blob/v5.0.0.beta3/actionpack/lib/abstract_controller/callbacks.rb#L66
|
20
|
-
# https://github.com/rails/rails/blob/v5.0.0.beta3/activesupport/lib/active_support/callbacks.rb#L640
|
21
|
-
skip_before_action :verify_authenticity_token, raise: false
|
22
|
-
end
|
23
|
-
|
24
|
-
before_action :config_account, only: %i[show create]
|
25
|
-
before_action :verify_signature, only: %i[show create]
|
26
|
-
else
|
27
|
-
skip_before_filter :verify_authenticity_token
|
28
|
-
before_filter :config_account, only: %i[show create]
|
29
|
-
before_filter :verify_signature, only: %i[show create]
|
30
|
-
end
|
13
|
+
skip_before_action :verify_authenticity_token, raise: false
|
14
|
+
before_action :config_account, only: %i[show create]
|
15
|
+
before_action :verify_signature, only: %i[show create]
|
31
16
|
end
|
32
17
|
|
33
18
|
module ClassMethods
|
@@ -145,9 +130,10 @@ module Wechat
|
|
145
130
|
next
|
146
131
|
end
|
147
132
|
|
148
|
-
|
133
|
+
case condition
|
134
|
+
when Regexp
|
149
135
|
memo[:scoped] ||= [responder] + $LAST_MATCH_INFO.captures if value =~ condition
|
150
|
-
|
136
|
+
when value
|
151
137
|
memo[:scoped] ||= [responder, value]
|
152
138
|
end
|
153
139
|
end
|
@@ -178,15 +164,9 @@ module Wechat
|
|
178
164
|
def show
|
179
165
|
if @we_corpid.present?
|
180
166
|
echostr, _corp_id = unpack(decrypt(Base64.decode64(params[:echostr]), @we_encoding_aes_key))
|
181
|
-
|
182
|
-
render plain: echostr
|
183
|
-
else
|
184
|
-
render text: echostr
|
185
|
-
end
|
186
|
-
elsif Rails::VERSION::MAJOR >= 4
|
187
|
-
render plain: params[:echostr]
|
167
|
+
render plain: echostr
|
188
168
|
else
|
189
|
-
render
|
169
|
+
render plain: params[:echostr]
|
190
170
|
end
|
191
171
|
end
|
192
172
|
|
@@ -195,11 +175,7 @@ module Wechat
|
|
195
175
|
response_msg = run_responder(request_msg)
|
196
176
|
|
197
177
|
if response_msg.respond_to? :to_xml
|
198
|
-
|
199
|
-
render plain: process_response(response_msg)
|
200
|
-
else
|
201
|
-
render text: process_response(response_msg)
|
202
|
-
end
|
178
|
+
render plain: process_response(response_msg)
|
203
179
|
else
|
204
180
|
head :ok, content_type: 'text/html'
|
205
181
|
end
|
@@ -246,15 +222,9 @@ module Wechat
|
|
246
222
|
end
|
247
223
|
|
248
224
|
data_hash = data.fetch('xml', {})
|
249
|
-
if
|
250
|
-
|
251
|
-
|
252
|
-
msg[:Event]&.downcase!
|
253
|
-
end
|
254
|
-
else
|
255
|
-
HashWithIndifferentAccess.new_from_hash_copying_default(data_hash).tap do |msg|
|
256
|
-
msg[:Event]&.downcase!
|
257
|
-
end
|
225
|
+
data_hash = data_hash.to_unsafe_hash if data_hash.instance_of?(ActionController::Parameters)
|
226
|
+
HashWithIndifferentAccess.new(data_hash).tap do |msg|
|
227
|
+
msg[:Event]&.downcase!
|
258
228
|
end
|
259
229
|
end
|
260
230
|
|
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.
|
4
|
+
version: 0.13.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:
|
38
|
+
date: 2021-03-15 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: activesupport
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
46
|
+
version: '6.0'
|
47
47
|
- - "<"
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '7'
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
requirements:
|
54
54
|
- - ">="
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: '
|
56
|
+
version: '6.0'
|
57
57
|
- - "<"
|
58
58
|
- !ruby/object:Gem::Version
|
59
59
|
version: '7'
|
@@ -105,34 +105,62 @@ 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'
|
122
|
+
- !ruby/object:Gem::Dependency
|
123
|
+
name: zeitwerk
|
124
|
+
requirement: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - "~>"
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '2.4'
|
129
|
+
type: :runtime
|
130
|
+
prerelease: false
|
131
|
+
version_requirements: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - "~>"
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '2.4'
|
108
136
|
- !ruby/object:Gem::Dependency
|
109
137
|
name: rubocop
|
110
138
|
requirement: !ruby/object:Gem::Requirement
|
111
139
|
requirements:
|
112
140
|
- - "~>"
|
113
141
|
- !ruby/object:Gem::Version
|
114
|
-
version: '
|
142
|
+
version: '1.9'
|
115
143
|
type: :development
|
116
144
|
prerelease: false
|
117
145
|
version_requirements: !ruby/object:Gem::Requirement
|
118
146
|
requirements:
|
119
147
|
- - "~>"
|
120
148
|
- !ruby/object:Gem::Version
|
121
|
-
version: '
|
149
|
+
version: '1.9'
|
122
150
|
- !ruby/object:Gem::Dependency
|
123
151
|
name: rails
|
124
152
|
requirement: !ruby/object:Gem::Requirement
|
125
153
|
requirements:
|
126
154
|
- - ">="
|
127
155
|
- !ruby/object:Gem::Version
|
128
|
-
version: '
|
156
|
+
version: '6.0'
|
129
157
|
type: :development
|
130
158
|
prerelease: false
|
131
159
|
version_requirements: !ruby/object:Gem::Requirement
|
132
160
|
requirements:
|
133
161
|
- - ">="
|
134
162
|
- !ruby/object:Gem::Version
|
135
|
-
version: '
|
163
|
+
version: '6.0'
|
136
164
|
- !ruby/object:Gem::Dependency
|
137
165
|
name: rspec-rails
|
138
166
|
requirement: !ruby/object:Gem::Requirement
|
@@ -195,12 +223,14 @@ files:
|
|
195
223
|
- lib/wechat/api_loader.rb
|
196
224
|
- lib/wechat/cipher.rb
|
197
225
|
- lib/wechat/concern/common.rb
|
226
|
+
- lib/wechat/concern/qcloud.rb
|
198
227
|
- lib/wechat/controller_api.rb
|
199
228
|
- lib/wechat/corp_api.rb
|
200
229
|
- lib/wechat/helpers.rb
|
201
230
|
- lib/wechat/http_client.rb
|
202
231
|
- lib/wechat/message.rb
|
203
232
|
- lib/wechat/mp_api.rb
|
233
|
+
- lib/wechat/qcloud/token.rb
|
204
234
|
- lib/wechat/responder.rb
|
205
235
|
- lib/wechat/signature.rb
|
206
236
|
- lib/wechat/ticket/corp_jsapi_ticket.rb
|
@@ -219,16 +249,16 @@ require_paths:
|
|
219
249
|
- lib
|
220
250
|
required_ruby_version: !ruby/object:Gem::Requirement
|
221
251
|
requirements:
|
222
|
-
- - "
|
252
|
+
- - ">="
|
223
253
|
- !ruby/object:Gem::Version
|
224
|
-
version: '2.
|
254
|
+
version: '2.6'
|
225
255
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
256
|
requirements:
|
227
257
|
- - ">="
|
228
258
|
- !ruby/object:Gem::Version
|
229
259
|
version: '0'
|
230
260
|
requirements: []
|
231
|
-
rubygems_version: 3.
|
261
|
+
rubygems_version: 3.2.14
|
232
262
|
signing_key:
|
233
263
|
specification_version: 4
|
234
264
|
summary: DSL for wechat message handling and API
|