wx_opendata 0.1.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 +7 -0
- data/Rakefile +6 -0
- data/lib/wx_opendata/service.rb +137 -0
- data/lib/wx_opendata/token.rb +59 -0
- data/lib/wx_opendata/version.rb +3 -0
- data/lib/wx_opendata.rb +14 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/wx_opendata_spec.rb +66 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1699ef3c57e9e4189e2c371b5c47905e9d331321
|
4
|
+
data.tar.gz: 42749163d3b371025c129d23fb7a93b6e787ab55
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 063d446971c3127d3ff93fff01dac39902c75700eac5d0b031a560009fc35681bff4f297d2e1c75d373906d3c85a4d11ba55c1e0d816b77e474feb2a381e3981
|
7
|
+
data.tar.gz: 402202ff4258eae20d649c66e47e779b036c79ac3c61a38fc1902cd073dd0fcfde5ef9f15b9a1d760c87a4f6e5a03375a043a01431ecbb8d19e384023bbe3214
|
data/Rakefile
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'mime/types'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module WxOpendata
|
6
|
+
BASE_URL = 'https://api.weixin.qq.com/'.freeze
|
7
|
+
class Service
|
8
|
+
attr_accessor :content_type
|
9
|
+
|
10
|
+
# 发送模板消息
|
11
|
+
def send_template_message(token, params)
|
12
|
+
raise InvalidParametersError unless params[:touser] && params[:template_id] && params[:form_id]
|
13
|
+
url = "cgi-bin/message/wxopen/template/send?access_token=#{token}"
|
14
|
+
touser = params[:touser]
|
15
|
+
template_id = params[:template_id]
|
16
|
+
form_id = params[:form_id]
|
17
|
+
page = params[:page] || 'pages/index/main'
|
18
|
+
data = params[:data] || { keyword1: { value: 'Test Message Template' } }
|
19
|
+
emphasis_keyword = params[:emphasis_keyword] || "keyword1.DATA"
|
20
|
+
p = { touser: touser, template_id: template_id, form_id: form_id, page: page, data: data, emphasis_keyword: emphasis_keyword }
|
21
|
+
jsondata = post(url, p)
|
22
|
+
begin
|
23
|
+
raise ErrCodeError, 'template_id不正确' if jsondata['errcode'] == 40037
|
24
|
+
raise ErrCodeError, 'form_id不正确,或者过期' if jsondata['errcode'] == 41028
|
25
|
+
raise ErrCodeError, 'form_id已被使用' if jsondata['errcode'] == 41029
|
26
|
+
raise ErrCodeError, 'page不正确' if jsondata['errcode'] == 41030
|
27
|
+
raise ErrCodeError, '接口调用超过限额(目前默认每个帐号日调用限额为100万)' if jsondata['errcode'] == 45009
|
28
|
+
jsondata['errcode'] == 0
|
29
|
+
rescue ErrCodeError => e
|
30
|
+
p "#{e.class}: #{e.message}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# 检查一段文本是否含有违法违规内容
|
35
|
+
def msg_sec_check(token, content)
|
36
|
+
url = "wxa/msg_sec_check?access_token=#{token}"
|
37
|
+
p = { content: content }
|
38
|
+
jsondata = post(url, p)
|
39
|
+
return true if jsondata['errcode'] == 0
|
40
|
+
return false if jsondata['errcode'] == 87014
|
41
|
+
end
|
42
|
+
|
43
|
+
# 校验一张图片是否含有违法违规内容
|
44
|
+
def img_sec_check
|
45
|
+
end
|
46
|
+
|
47
|
+
# 创建被分享动态消息的 activity_id
|
48
|
+
def create_activity_id(token)
|
49
|
+
url = "cgi-bin/message/wxopen/activityid/create?access_token=#{token}"
|
50
|
+
jsondata = get(url)
|
51
|
+
raise ServiceNotAvailableError if jsondata['errcode'] != 0
|
52
|
+
jsondata['activity_id']
|
53
|
+
end
|
54
|
+
|
55
|
+
# 获取小程序二维码,适用于需要的码数量较少的业务场景
|
56
|
+
def create_wx_aqrcode(token, params = {})
|
57
|
+
url = "cgi-bin/wxaapp/createwxaqrcode?access_token=#{token}"
|
58
|
+
path = params[:path] || 'pages/index/main'
|
59
|
+
width = params[:width] || 430
|
60
|
+
p = { path: path, width: width }
|
61
|
+
data = post(url, p)
|
62
|
+
raise InvalidCredentialError if data['errcode'] == 45029
|
63
|
+
tmpfile(data)
|
64
|
+
end
|
65
|
+
|
66
|
+
# 获取小程序码,适用于需要的码数量较少的业务场景
|
67
|
+
def get_wx_acode(token, params = {})
|
68
|
+
url = "wxa/getwxacode?access_token=#{token}"
|
69
|
+
path = params[:path] || 'pages/index/main'
|
70
|
+
width = params[:width] || 430
|
71
|
+
auto_color = params[:auto_color] || false
|
72
|
+
line_color = params[:line_color] || {"r": 0,"g": 0,"b": 0}
|
73
|
+
is_hyaline = params[:is_hyaline] || true
|
74
|
+
p = { path: path, width: width, auto_color: auto_color, line_color: line_color, is_hyaline: is_hyaline }
|
75
|
+
data = post(url, p)
|
76
|
+
raise InvalidCredentialError if data['errcode'] == 45029
|
77
|
+
tmpfile(data)
|
78
|
+
end
|
79
|
+
|
80
|
+
# 获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。
|
81
|
+
def get_wx_acode_unlimit(token, params = {})
|
82
|
+
url = "wxa/getwxacodeunlimit?access_token=#{token}"
|
83
|
+
scene = params[:scene] || 'api'
|
84
|
+
page = params[:page] || 'pages/index/main'
|
85
|
+
width = params[:width] || 430
|
86
|
+
auto_color = params[:auto_color] || false
|
87
|
+
line_color = params[:line_color] || {"r": 0,"g": 0,"b": 0}
|
88
|
+
is_hyaline = params[:is_hyaline] || true
|
89
|
+
p = { scene: scene, page: page, width: width, auto_color: auto_color, line_color: line_color, is_hyaline: is_hyaline }
|
90
|
+
data = post(url, p)
|
91
|
+
raise InvalidCredentialError if data['errcode'] == 45009 || data['errcode'] == 41030
|
92
|
+
tmpfile(data)
|
93
|
+
end
|
94
|
+
|
95
|
+
# 下发小程序和公众号统一的服务消息
|
96
|
+
def send_uniform_message
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
protected
|
101
|
+
def get(url)
|
102
|
+
url = BASE_URL + url
|
103
|
+
resp = RestClient.get url
|
104
|
+
format_result(resp)
|
105
|
+
end
|
106
|
+
|
107
|
+
def post(url, params)
|
108
|
+
url = BASE_URL + url
|
109
|
+
resp = RestClient.post url, params.to_json, {accept: :json}
|
110
|
+
format_result(resp)
|
111
|
+
end
|
112
|
+
|
113
|
+
def format_result(resp)
|
114
|
+
@content_type = resp.headers[:content_type]
|
115
|
+
if resp.headers[:content_type].include? "application/json".freeze
|
116
|
+
JSON.parse resp.body
|
117
|
+
else
|
118
|
+
resp.body
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def current_req_type
|
123
|
+
@content_type
|
124
|
+
end
|
125
|
+
|
126
|
+
def tmpfile(data)
|
127
|
+
tmpname = (Time.now.to_i + rand(1000...9999)).to_s
|
128
|
+
ext = '.' + MIME::Types[current_req_type].first.extensions.first
|
129
|
+
f = Tempfile.new([tmpname, ext], Dir.tmpdir)
|
130
|
+
# f.binmode
|
131
|
+
f.write(data)
|
132
|
+
f.flush
|
133
|
+
f.path
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module WxOpendata
|
2
|
+
|
3
|
+
WX_ACCESS_TOKEN = 'https://api.weixin.qq.com/cgi-bin/token'.freeze
|
4
|
+
|
5
|
+
class Token
|
6
|
+
attr_reader :appid, :secret, :token_file, :access_token, :token_expires_in, :store_token_at
|
7
|
+
|
8
|
+
def initialize(appid, appsecret, token_file)
|
9
|
+
@appid = appid
|
10
|
+
@appsecret = appsecret
|
11
|
+
@token_file = token_file
|
12
|
+
@random_generator = Random.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def token
|
16
|
+
read_token_from_cache
|
17
|
+
refresh_token if remain_seconds < @random_generator.rand(30..3 * 60)
|
18
|
+
access_token
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def refresh_token
|
24
|
+
url = "#{WX_ACCESS_TOKEN}?grant_type=client_credential&appid=#{@appid}&secret=#{@appsecret}"
|
25
|
+
resp = RestClient.get url
|
26
|
+
store_token_to_cache(resp.body)
|
27
|
+
read_token_from_cache
|
28
|
+
end
|
29
|
+
|
30
|
+
def read_token_from_cache
|
31
|
+
token = read_token
|
32
|
+
@token_expires_in = token.fetch('expires_in').to_i
|
33
|
+
@store_token_at = token.fetch('store_token_at').to_i
|
34
|
+
@access_token = token.fetch('access_token')
|
35
|
+
rescue JSON::ParserError, Errno::ENOENT, KeyError, TypeError => e
|
36
|
+
refresh_token
|
37
|
+
end
|
38
|
+
|
39
|
+
def store_token_to_cache(token)
|
40
|
+
token_hash = JSON.parse token
|
41
|
+
raise InvalidCredentialError unless token_hash['access_token']
|
42
|
+
token_hash['store_token_at'.freeze] = Time.now.to_i
|
43
|
+
write_token(token_hash.to_json)
|
44
|
+
end
|
45
|
+
|
46
|
+
def write_token(token)
|
47
|
+
File.write(token_file, token)
|
48
|
+
end
|
49
|
+
|
50
|
+
def read_token
|
51
|
+
JSON.parse File.read(token_file)
|
52
|
+
end
|
53
|
+
|
54
|
+
def remain_seconds
|
55
|
+
token_expires_in - (Time.now.to_i - store_token_at.to_i)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/lib/wx_opendata.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "wx_opendata/version"
|
2
|
+
require 'wx_opendata/service'
|
3
|
+
require 'wx_opendata/token'
|
4
|
+
|
5
|
+
module WxOpendata
|
6
|
+
class AccessTokenExpiredError < StandardError; end
|
7
|
+
class InvalidCredentialError < StandardError; end
|
8
|
+
class ServiceNotAvailableError < StandardError; end
|
9
|
+
class InvalidParametersError < StandardError; end
|
10
|
+
class ErrCodeError < StandardError; end
|
11
|
+
|
12
|
+
class<< self
|
13
|
+
end
|
14
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "wx_opendata"
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
# Enable flags like --only-failures and --next-failure
|
6
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
7
|
+
|
8
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
9
|
+
config.disable_monkey_patching!
|
10
|
+
|
11
|
+
config.expect_with :rspec do |c|
|
12
|
+
c.syntax = :expect
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
appid = ''
|
3
|
+
appsecret = ''
|
4
|
+
token_file = '/tmp/weapp_access_token'
|
5
|
+
tk = WxOpendata::Token.new(appid, appsecret, token_file)
|
6
|
+
service = WxOpendata::Service.new
|
7
|
+
|
8
|
+
RSpec.describe WxOpendata do
|
9
|
+
it "1. should return corrent length access_token" do
|
10
|
+
token = tk.token
|
11
|
+
expect(token.size).to be > 120
|
12
|
+
end
|
13
|
+
|
14
|
+
it "2. should return activity id" do
|
15
|
+
token = tk.token
|
16
|
+
activity_id = service.create_activity_id(token)
|
17
|
+
expect(activity_id.size).to be > 10
|
18
|
+
end
|
19
|
+
|
20
|
+
it '3.1 should return get_wx_acode_unlimit pic path' do
|
21
|
+
token = tk.token
|
22
|
+
pic = service.get_wx_acode_unlimit(token, { width: 100, scene: 'uid=12345678' })
|
23
|
+
expect(pic).to include('/var')
|
24
|
+
end
|
25
|
+
|
26
|
+
it '3.2 should return get_wx_acode pic path' do
|
27
|
+
token = tk.token
|
28
|
+
pic = service.get_wx_acode(token)
|
29
|
+
expect(pic).to include('/var')
|
30
|
+
end
|
31
|
+
|
32
|
+
it '3.3 should return create_wx_aqrcode pic path' do
|
33
|
+
token = tk.token
|
34
|
+
pic = service.create_wx_aqrcode(token)
|
35
|
+
expect(pic).to include('/var')
|
36
|
+
end
|
37
|
+
|
38
|
+
it '4. should return ok if content is: Mot最棒' do
|
39
|
+
token = tk.token
|
40
|
+
isOk = service.msg_sec_check(token, "Mot最棒")
|
41
|
+
expect(isOk).to eq(true)
|
42
|
+
end
|
43
|
+
it '5.1 should return risky content if content is: 特3456书yuuo莞6543李zxcz蒜7782法fgnv级' do
|
44
|
+
token = tk.token
|
45
|
+
isOk = service.msg_sec_check(token, "特3456书yuuo莞6543李zxcz蒜7782法fgnv级")
|
46
|
+
expect(isOk).to eq(false)
|
47
|
+
end
|
48
|
+
|
49
|
+
it '5.2 should return risky content if content is: 完2347全dfji试3726测asad感3847知qwez到' do
|
50
|
+
token = tk.token
|
51
|
+
isOk = service.msg_sec_check(token, "完2347全dfji试3726测asad感3847知qwez到")
|
52
|
+
expect(isOk).to eq(false)
|
53
|
+
end
|
54
|
+
|
55
|
+
# it '6. send message template to user and should return ok' do
|
56
|
+
# isOk = service.send_template_message(token, {
|
57
|
+
# touser: '',
|
58
|
+
# template_id: '',
|
59
|
+
# form_id: '',
|
60
|
+
# data: {
|
61
|
+
# },
|
62
|
+
# emphasis_keyword: ''
|
63
|
+
# })
|
64
|
+
# expect(isOk).to eq(true)
|
65
|
+
# end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wx_opendata
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mot_Wu
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: activesupport
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.15'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.15'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '10.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '10.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '3.0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '3.0'
|
89
|
+
description: This is a gem for weapp open data API.小程序开放数据API
|
90
|
+
email:
|
91
|
+
- motevans412@gmail.com
|
92
|
+
executables: []
|
93
|
+
extensions: []
|
94
|
+
extra_rdoc_files: []
|
95
|
+
files:
|
96
|
+
- Rakefile
|
97
|
+
- lib/wx_opendata.rb
|
98
|
+
- lib/wx_opendata/service.rb
|
99
|
+
- lib/wx_opendata/token.rb
|
100
|
+
- lib/wx_opendata/version.rb
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
- spec/wx_opendata_spec.rb
|
103
|
+
homepage: https://github.com/mozillo/wx_opendata
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata:
|
107
|
+
allowed_push_host: https://rubygems.org
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.6.12
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: This is a gem for weapp open data API.小程序开放数据API
|
128
|
+
test_files:
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
- spec/wx_opendata_spec.rb
|