wechat 0.11.7 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +25 -0
- data/README-CN.md +3 -2
- data/README.md +3 -2
- data/bin/wechat +8 -3
- data/lib/action_controller/wechat_responder.rb +15 -12
- data/lib/generators/wechat/templates/app/models/wechat_config.rb +1 -1
- data/lib/wechat.rb +3 -0
- data/lib/wechat/api.rb +8 -0
- data/lib/wechat/api_base.rb +3 -2
- data/lib/wechat/api_loader.rb +14 -2
- data/lib/wechat/cipher.rb +3 -3
- data/lib/wechat/concern/common.rb +11 -7
- data/lib/wechat/concern/qcloud.rb +115 -0
- data/lib/wechat/controller_api.rb +1 -1
- data/lib/wechat/corp_api.rb +18 -2
- 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 +11 -0
- data/lib/wechat/qcloud/token.rb +66 -0
- data/lib/wechat/responder.rb +4 -2
- metadata +49 -33
- 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: f7dfe45f7c68aafa5b96a2a3178ae2108f9989bb5594b6ae35d1e7dcc358219a
|
4
|
+
data.tar.gz: 25a51c65de855682ec12ee332241d9acd47c8cc8c2376995c8d8f0512825e899
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '080ada4dbb3191ed4d10d51d4cef85de0cfc469af61f636ee99b03be92e487060fa454a37ef54a8386d77d1ebede360d2819c64d59f0d1ca2a202ba199e1a31e'
|
7
|
+
data.tar.gz: f3482024b4e35f91924c384ca27819748341444047c135362552b460ccf15243fcd5fd1c896e0c15eb00e392aa73ce1c750854b78e6e0c52af0176482e4939cb
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,30 @@
|
|
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
|
+
|
11
|
+
## v0.11.11 (released at 09/13/2020)
|
12
|
+
|
13
|
+
* FIX: fix_load_controller_wechat not support MP type, by @Msms-NJ #281
|
14
|
+
|
15
|
+
## v0.11.10 (released at 09/02/2020)
|
16
|
+
|
17
|
+
* ADD: Wechat::MpApi.wxa_msg_sec_check.
|
18
|
+
|
19
|
+
## v0.11.9 (released at 04/29/2020)
|
20
|
+
|
21
|
+
* CHG: upgrade ssl_version to 1.2 by @paicha #276
|
22
|
+
|
23
|
+
## v0.11.8 (released at 03/09/2020)
|
24
|
+
|
25
|
+
* ADD: Wechat::CorpApi.news_message_send
|
26
|
+
* FIX: Wechat API Change material/get_material. reported by @0000sir #275
|
27
|
+
|
3
28
|
## v0.11.7 (released at 11/15/2019)
|
4
29
|
|
5
30
|
* ADD: Wechat::MpApi.subscribe_message_send. by @paicha #271
|
data/README-CN.md
CHANGED
@@ -3,7 +3,7 @@ WeChat [![Gem Version](https://badge.fury.io/rb/wechat.svg)](https://rubygems.or
|
|
3
3
|
|
4
4
|
[![Join the chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Eric-Guo/wechat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
5
|
|
6
|
-
WeChat gem帮助开发者方便地在Rails环境中集成[微信公众平台](https://
|
6
|
+
WeChat gem帮助开发者方便地在Rails环境中集成[微信公众平台](https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html)、[企业微信](https://work.weixin.qq.com/api/doc)和[小程序](https://developers.weixin.qq.com/miniprogram/dev/framework/),包括功能:
|
7
7
|
|
8
8
|
- 微信公众平台/企业微信[发送消息](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF)API(命令行和Web环境都可以使用)
|
9
9
|
- [接收消息](http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E4%B8%8E%E4%BA%8B%E4%BB%B6)(必须运行Web服务器)
|
@@ -360,7 +360,7 @@ Wechat Public Account commands:
|
|
360
360
|
wechat group_delete [GROUP_ID] # 删除分组
|
361
361
|
wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
|
362
362
|
wechat groups # 查询所有分组
|
363
|
-
wechat
|
363
|
+
wechat material_get [MEDIA_ID, PATH] # 永久媒体下载
|
364
364
|
wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
|
365
365
|
wechat material_count # 获取永久素材总数
|
366
366
|
wechat material_delete [MEDIA_ID] # 删除永久素材
|
@@ -399,6 +399,7 @@ Wechat Public Account commands:
|
|
399
399
|
wechat user_group [OPEN_ID] # 查询用户所在分组
|
400
400
|
wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
|
401
401
|
wechat users # 关注者列表
|
402
|
+
wechat wxa_msg_sec_check [CONTENT] # 检查一段文本是否含有违法违规内容。
|
402
403
|
wechat wxacode_download [WXA_CODE_PIC_PATH, PATH, WIDTH] # 下载小程序码
|
403
404
|
```
|
404
405
|
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ WeChat [![Gem Version](https://badge.fury.io/rb/wechat.svg)](https://rubygems.or
|
|
7
7
|
|
8
8
|
[Wechat](http://www.wechat.com/) is a Chinese multi-purpose messaging, social media and mobile payment app developed by Tencent. It was first released in 2011, and by 2018 it was one of the world's largest standalone mobile apps by monthly active users, with over 1 billion monthly active users (902 million daily active users). (According to [wiki](https://en.wikipedia.org/wiki/WeChat))
|
9
9
|
|
10
|
-
WeChat gem helps Rails developers integrate [WeChat Official Accounts Platform](https://
|
10
|
+
WeChat gem helps Rails developers integrate [WeChat Official Accounts Platform](https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html) or [Wechat mini program](https://developers.weixin.qq.com/miniprogram/dev/framework/) easily, including features:
|
11
11
|
|
12
12
|
- [Sending message](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF) API(can be both accessed via console or rails server)
|
13
13
|
- [Receiving message](http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E6%B6%88%E6%81%AF%E4%B8%8E%E4%BA%8B%E4%BB%B6)(rails server is required to be running)
|
@@ -391,7 +391,7 @@ Wechat Public Account commands:
|
|
391
391
|
wechat group_delete [GROUP_ID] # 删除分组
|
392
392
|
wechat group_update [GROUP_ID, NEW_GROUP_NAME] # 修改分组名
|
393
393
|
wechat groups # 查询所有分组
|
394
|
-
wechat
|
394
|
+
wechat material_get [MEDIA_ID, PATH] # 永久媒体下载
|
395
395
|
wechat material_add [MEDIA_TYPE, PATH] # 永久媒体上传
|
396
396
|
wechat material_count # 获取永久素材总数
|
397
397
|
wechat material_delete [MEDIA_ID] # 删除永久素材
|
@@ -430,6 +430,7 @@ Wechat Public Account commands:
|
|
430
430
|
wechat user_group [OPEN_ID] # 查询用户所在分组
|
431
431
|
wechat user_update_remark [OPEN_ID, REMARK] # 设置备注名
|
432
432
|
wechat users # 关注者列表
|
433
|
+
wechat wxa_msg_sec_check [CONTENT] # 检查一段文本是否含有违法违规内容。
|
433
434
|
wechat wxacode_download [WXA_CODE_PIC_PATH, PATH, WIDTH] # 下载小程序码
|
434
435
|
wechat clear_quota # 接口调用次数清零
|
435
436
|
```
|
data/bin/wechat
CHANGED
@@ -225,6 +225,11 @@ class App < Thor
|
|
225
225
|
puts 'WXA Code File downloaded'
|
226
226
|
end
|
227
227
|
|
228
|
+
desc 'wxa_msg_sec_check [CONTENT]', '检查一段文本是否含有违法违规内容。'
|
229
|
+
def wxa_msg_sec_check(content)
|
230
|
+
puts wechat_api.wxa_msg_sec_check(content)
|
231
|
+
end
|
232
|
+
|
228
233
|
desc 'media_uploadnews [MPNEWS_YAML_PATH]', '上传图文消息素材'
|
229
234
|
def media_uploadnews(mpnews_yaml_path)
|
230
235
|
mpnew = YAML.load(File.read(mpnews_yaml_path))
|
@@ -389,9 +394,9 @@ class App < Thor
|
|
389
394
|
puts wechat_api.media_uploadimg(image_path)
|
390
395
|
end
|
391
396
|
|
392
|
-
desc '
|
393
|
-
def
|
394
|
-
tmp_file = wechat_api.
|
397
|
+
desc 'material_get [MEDIA_ID, PATH]', '永久媒体下载'
|
398
|
+
def material_get(media_id, path)
|
399
|
+
tmp_file = wechat_api.get_material(media_id)
|
395
400
|
FileUtils.mv(tmp_file.path, path)
|
396
401
|
puts 'File downloaded'
|
397
402
|
end
|
@@ -38,25 +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.
|
42
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
secret
|
58
|
-
Wechat::Api.new(appid, secret, access_token, \
|
59
|
-
timeout, skip_verify_ssl, jsapi_ticket)
|
62
|
+
Wechat::Api.new(appid, secret, access_token, timeout, skip_verify_ssl, jsapi_ticket)
|
60
63
|
end
|
61
64
|
end
|
62
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
|
38
|
+
errors.add(:base, 'Either appid or corpid must be set')
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
data/lib/wechat.rb
CHANGED
@@ -16,9 +16,12 @@ 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
|
24
|
+
|
22
25
|
def initialize(errcode, errmsg)
|
23
26
|
@error_code = errcode
|
24
27
|
super "#{errmsg}(#{error_code})"
|
data/lib/wechat/api.rb
CHANGED
@@ -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)
|
data/lib/wechat/api_base.rb
CHANGED
@@ -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
|
-
WXA_BASE
|
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
|
data/lib/wechat/api_loader.rb
CHANGED
@@ -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
|
-
|
14
|
-
|
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
|
data/lib/wechat/cipher.rb
CHANGED
@@ -10,7 +10,7 @@ module Wechat
|
|
10
10
|
cipher.encrypt
|
11
11
|
|
12
12
|
cipher.padding = 0
|
13
|
-
key_data = Base64.decode64(encoding_aes_key
|
13
|
+
key_data = Base64.decode64("#{encoding_aes_key}=")
|
14
14
|
cipher.key = key_data
|
15
15
|
cipher.iv = [key_data].pack('H*')
|
16
16
|
|
@@ -22,7 +22,7 @@ module Wechat
|
|
22
22
|
cipher.decrypt
|
23
23
|
|
24
24
|
cipher.padding = 0
|
25
|
-
key_data = Base64.decode64(encoding_aes_key
|
25
|
+
key_data = Base64.decode64("#{encoding_aes_key}=")
|
26
26
|
cipher.key = key_data
|
27
27
|
cipher.iv = [key_data].pack('H*')
|
28
28
|
|
@@ -41,7 +41,7 @@ module Wechat
|
|
41
41
|
|
42
42
|
def unpack(msg)
|
43
43
|
msg = decode_padding(msg)
|
44
|
-
msg_len = msg[16, 4].reverse.
|
44
|
+
msg_len = msg[16, 4].reverse.unpack1('V')
|
45
45
|
content = msg[20, msg_len]
|
46
46
|
app_id = msg[(20 + msg_len)..-1]
|
47
47
|
|
@@ -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
|
@@ -106,6 +100,10 @@ module Wechat
|
|
106
100
|
post 'wxaapp/createwxaqrcode', JSON.generate(path: path, width: width)
|
107
101
|
end
|
108
102
|
|
103
|
+
def wxa_msg_sec_check(content)
|
104
|
+
post 'msg_sec_check', JSON.generate(content: content), base: Wechat::Api::WXA_BASE
|
105
|
+
end
|
106
|
+
|
109
107
|
def menu
|
110
108
|
get 'menu/get'
|
111
109
|
end
|
@@ -133,7 +131,13 @@ module Wechat
|
|
133
131
|
end
|
134
132
|
|
135
133
|
def material(media_id)
|
136
|
-
|
134
|
+
ActiveSupport::Deprecation.warn('material is deprecated. use get_material instead.')
|
135
|
+
|
136
|
+
post 'material/get_material', JSON.generate(media_id: media_id), as: :file
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_material(media_id)
|
140
|
+
post 'material/get_material', JSON.generate(media_id: media_id), as: :file
|
137
141
|
end
|
138
142
|
|
139
143
|
def material_count
|
@@ -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
|
|
data/lib/wechat/corp_api.rb
CHANGED
@@ -10,10 +10,12 @@ module Wechat
|
|
10
10
|
attr_reader :agentid
|
11
11
|
|
12
12
|
def initialize(appid, secret, token_file, agentid, timeout, skip_verify_ssl, jsapi_ticket_file)
|
13
|
+
super()
|
13
14
|
@client = HttpClient.new(QYAPI_BASE, timeout, skip_verify_ssl)
|
14
15
|
@access_token = Token::CorpAccessToken.new(@client, appid, secret, token_file)
|
15
16
|
@agentid = agentid
|
16
17
|
@jsapi_ticket = Ticket::CorpJsapiTicket.new(@client, @access_token, jsapi_ticket_file)
|
18
|
+
@qcloud = nil
|
17
19
|
end
|
18
20
|
|
19
21
|
def agent_list
|
@@ -90,7 +92,7 @@ module Wechat
|
|
90
92
|
end
|
91
93
|
|
92
94
|
def department_update(departmentid, name = nil, parentid = nil, order = nil)
|
93
|
-
post 'department/update', JSON.generate({ id: departmentid, name: name, parentid: parentid, order: order }.
|
95
|
+
post 'department/update', JSON.generate({ id: departmentid, name: name, parentid: parentid, order: order }.compact)
|
94
96
|
end
|
95
97
|
|
96
98
|
def department(departmentid = 1)
|
@@ -155,7 +157,13 @@ module Wechat
|
|
155
157
|
end
|
156
158
|
|
157
159
|
def material(media_id)
|
158
|
-
|
160
|
+
ActiveSupport::Deprecation.warn('material is deprecated. use get_material instead.')
|
161
|
+
|
162
|
+
post 'material/get_material', JSON.generate(media_id: media_id), params: { agentid: agentid }, as: :file
|
163
|
+
end
|
164
|
+
|
165
|
+
def get_material(media_id)
|
166
|
+
post 'material/get_material', JSON.generate(media_id: media_id), params: { agentid: agentid }, as: :file
|
159
167
|
end
|
160
168
|
|
161
169
|
def material_add(type, file)
|
@@ -170,6 +178,14 @@ module Wechat
|
|
170
178
|
post 'message/send', Message.to(userid).text(message).agent_id(agentid).to_json, content_type: :json
|
171
179
|
end
|
172
180
|
|
181
|
+
def news_message_send(userid, title, description, link_url, pic_url)
|
182
|
+
post 'message/send', Message.to(userid).news([{ title: title,
|
183
|
+
description: description,
|
184
|
+
url: link_url,
|
185
|
+
pic_url: pic_url }])
|
186
|
+
.agent_id(agentid).to_json, content_type: :json
|
187
|
+
end
|
188
|
+
|
173
189
|
def custom_message_send(message)
|
174
190
|
post 'message/send', message.is_a?(Wechat::Message) ? message.agent_id(agentid).to_json : JSON.generate(message.merge(agent_id: agentid)), content_type: :json
|
175
191
|
end
|
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
@@ -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
|
data/lib/wechat/responder.rb
CHANGED
@@ -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
|
@@ -145,9 +146,10 @@ module Wechat
|
|
145
146
|
next
|
146
147
|
end
|
147
148
|
|
148
|
-
|
149
|
+
case condition
|
150
|
+
when Regexp
|
149
151
|
memo[:scoped] ||= [responder] + $LAST_MATCH_INFO.captures if value =~ condition
|
150
|
-
|
152
|
+
when value
|
151
153
|
memo[:scoped] ||= [responder, value]
|
152
154
|
end
|
153
155
|
end
|
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wechat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Skinnyworm
|
8
8
|
- Eric Guo
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain:
|
12
12
|
- |
|
13
13
|
-----BEGIN CERTIFICATE-----
|
14
14
|
MIIEQDCCAqigAwIBAgIBATANBgkqhkiG9w0BAQsFADAlMSMwIQYDVQQDDBplcmlj
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
15
|
+
Lmd1b2N6L0RDPWdtYWlsL0RDPWNvbTAeFw0yMDA5MDIwNDUzMjFaFw0yMTA5MDIw
|
16
|
+
NDUzMjFaMCUxIzAhBgNVBAMMGmVyaWMuZ3VvY3ovREM9Z21haWwvREM9Y29tMIIB
|
17
|
+
ojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwSfWr5RlUBlv9OuNgmxjPwhU
|
18
|
+
7eoT/m7K5h0PzUaue+dtno4WqjodoCPHF6r9hh8Ys0h1VAPu3sobH2gNaL18M0CY
|
19
|
+
bmq+ik6LgH5tX2E6c2BmhMuURt2y1YvIwvx0dDOlEXll9J8ZVqGyo3Rm9AIblA3/
|
20
|
+
w/V5VJGCj3XY6iipNkHHDlSWSYeD2mNr0wJW8EAUFFcyRddpotxR9Es8JwUpXdj8
|
21
|
+
Bc5a/OWxKvzqLVlu76zYRYuZ41+3gWNxYF9OPnp55sNtsboGh5LJSdXZOs5+gMw9
|
22
|
+
gEW/KsP4GSMlqBT7SQEO5EH3qjp3aatHaMT8Fq9h3AnNESQMubMWtlPqEYyrYkli
|
23
|
+
wr8A8SGiX3rCkNG0cc4zVsagtXm4csbSeaIjLV57LA2sKngI4/kw55UYlloAtGPh
|
24
|
+
qNEqsPLbN/RkyS1zQjf14mQBpBt3SdxnT7YDSPIYiAPTtLuThcy3Flgh6cDX1RH7
|
25
|
+
FQPZJzQ7pSb/3Edj+VBaYhpo+y4ySLxx9DOLfm6lAgMBAAGjezB5MAkGA1UdEwQC
|
26
|
+
MAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRWBfZurpq8AmvpfBq7eSA0ivhotDAf
|
27
27
|
BgNVHREEGDAWgRRlcmljLmd1b2N6QGdtYWlsLmNvbTAfBgNVHRIEGDAWgRRlcmlj
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
Lmd1b2N6QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAJ1tLpEqCXma9fFeU
|
29
|
+
l6N4tEDrwYVxdbkXgOScUZBsagNlEM9vvskygivKu8AV8ffdtsg9OAuhdfAjPjX+
|
30
|
+
GvGnmuoweHFTsIrOhNryqFDgvkufBczmFLOskjRuzt4NoBNgge8+xoNo+N9o/0jz
|
31
|
+
GZi69Dth2i92rffuEzyFbfA9xzkjL+uSqJRJVDP5UbIWGnQ99M4GfplJZWRkmoX9
|
32
|
+
5Ek/ZVhzEz6kdZuZErloYKqjWWvFHUFAYmJd3fqKpb468yTIaL4bl4aUl2+xLdyK
|
33
|
+
fPI/ZWGy2uNjffzbrhJ+Ti6qAdubkJoMIqrfbrFV1ew2Bxkp/93etXVNjAgHNmu1
|
34
|
+
o3VAf3sbhnj33jAri7JYx/1MhAcJXlvpKxX9QnYouxU/RgzBF7oqcT0dJ2jWUnAI
|
35
|
+
spvOK5/LPXWX6ZGc2SR8SH/s7ftYH2EkeM1VUbtemow08NdgCwJ4IG+fRQ9dcrJ+
|
36
|
+
L9TbpLHvVrCe1w8duMqNeUmqj+M1iC/5Zst2vIe14QcOTuAh
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date:
|
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
|
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
|
135
|
+
version: '1.0'
|
122
136
|
- !ruby/object:Gem::Dependency
|
123
137
|
name: rails
|
124
138
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,14 +153,14 @@ dependencies:
|
|
139
153
|
requirements:
|
140
154
|
- - "~>"
|
141
155
|
- !ruby/object:Gem::Version
|
142
|
-
version: '
|
156
|
+
version: '4.0'
|
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: '
|
163
|
+
version: '4.0'
|
150
164
|
- !ruby/object:Gem::Dependency
|
151
165
|
name: sqlite3
|
152
166
|
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
|
@@ -213,23 +229,23 @@ homepage: https://github.com/Eric-Guo/wechat
|
|
213
229
|
licenses:
|
214
230
|
- MIT
|
215
231
|
metadata: {}
|
216
|
-
post_install_message:
|
232
|
+
post_install_message:
|
217
233
|
rdoc_options: []
|
218
234
|
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
|
-
version: '2.
|
240
|
+
version: '2.4'
|
225
241
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
242
|
requirements:
|
227
243
|
- - ">="
|
228
244
|
- !ruby/object:Gem::Version
|
229
245
|
version: '0'
|
230
246
|
requirements: []
|
231
|
-
rubygems_version: 3.
|
232
|
-
signing_key:
|
247
|
+
rubygems_version: 3.2.3
|
248
|
+
signing_key:
|
233
249
|
specification_version: 4
|
234
250
|
summary: DSL for wechat message handling and API
|
235
251
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|