wechat-api 0.2.0 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6d5004c2f463eb0b4f3bdbdc7011e9bc1424c8de
4
- data.tar.gz: 7e1e9ff5632c305ee2e3589085c7a0912b44dbff
2
+ SHA256:
3
+ metadata.gz: 761fc67b404a0484aa97ed60b2c77f915c9c39ec3f9d57c37fed05049ac4dbad
4
+ data.tar.gz: addbff9065f1cd426bf13bc7a1cb56a6b4b598be49342ae204847af2f7873359
5
5
  SHA512:
6
- metadata.gz: ecf554acceb4735dd74191f9b461b84c8314a7b3401d43e6e481af9dd3e4707099551725421f354013e2afd0ac1c0a16d9e192a4180b956063779329aead4529
7
- data.tar.gz: 5cd2529274cac2084aa95c2de52f01d36411d103d3cf38c80b3572929105d562b3617ef9bd825e6300da6168f6ef6424968d7cfded809ac15e082bde14b6f4a8
6
+ metadata.gz: e88647dfffae7e124d68126675ff03c86f3a8b6dfaa7fc3d17834d99f4a027898ebf3fe45ed6f18ec237a5b54203cc02a0fcd38008abb481b8c1bc2eb98fd738
7
+ data.tar.gz: 65815dfb44f9b412242f651e0a567cd4e7cb8d66a9550c594fc843b03cc005d41feafd19248f4789c70ccbe942e744b9941137c253ddbb5899ef9d60b541ce42
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  Gemfile.lock
2
2
  pkg
3
+ .DS_Store
data/Gemfile CHANGED
@@ -1,9 +1,3 @@
1
- source 'https://ruby.taobao.org'
1
+ source 'https://rubygems.org'
2
2
  # Specify your gem's dependencies in ucpaas.gemspec
3
3
  gemspec
4
-
5
- group :development do
6
- gem 'guard'
7
- gem 'guard-rspec'
8
- gem 'rspec-its'
9
- end
data/README.md CHANGED
@@ -4,8 +4,7 @@ https://github.com/lazing/wechat-api
4
4
 
5
5
  用于微信 api 调用(非服务端推送信息)的处理。
6
6
 
7
- [![Circle CI](https://circleci.com/gh/lazing/wechat-api.svg?style=svg)](https://circleci.com/gh/lazing/wechat-api)
8
- [![Gem Version](https://badge.fury.io/rb/wechat-api.svg)](http://badge.fury.io/rb/ucpaas)
7
+ [![Gem Version](https://badge.fury.io/rb/wechat-api.svg)](http://badge.fury.io/rb/wechat-api)
9
8
 
10
9
  常见的应用场景如:
11
10
  * 获取关注用户
@@ -1,3 +1,2 @@
1
1
  require 'wechat/api'
2
- require 'wechat/pay'
3
2
  require 'wechat/qy'
@@ -4,5 +4,18 @@ require 'wechat/api/client'
4
4
  module Wechat
5
5
  #
6
6
  module Api
7
+ class Error < StandardError; end
8
+
9
+ def self.client(appid = 'origin_id')
10
+ var = "@_client_#{appid}"
11
+ if instance_variable_defined?(var)
12
+ instance_variable_get(var)
13
+ elsif block_given?
14
+ c = yield(Client)
15
+ instance_variable_set var, c
16
+ else
17
+ raise Error, :not_initialized
18
+ end
19
+ end
7
20
  end
8
21
  end
@@ -2,6 +2,7 @@ require 'multi_json'
2
2
  require 'wechat/api/message'
3
3
  require 'wechat/api/user'
4
4
  require 'wechat/api/util'
5
+ require 'wechat/api/js_ticket'
5
6
  require 'faraday'
6
7
  require 'logger'
7
8
 
@@ -18,12 +19,13 @@ module Wechat
18
19
 
19
20
  API_BASE = 'https://api.weixin.qq.com/cgi-bin/'
20
21
 
21
- attr_reader :app_id, :secret
22
- attr_accessor :logger
22
+ attr_reader :app_id, :secret, :ticket
23
+ attr_accessor :logger, :site
23
24
 
24
25
  def initialize(app_id, secret)
25
26
  @app_id, @secret = app_id, secret
26
27
  @logger = Logger.new(STDOUT)
28
+ @ticket = JsTicket.new self
27
29
  @token_file = File.join('/tmp', "wechat-api-#{app_id}")
28
30
  end
29
31
 
@@ -37,10 +39,11 @@ module Wechat
37
39
  end
38
40
 
39
41
  def refresh
40
- url = format('%stoken', API_BASE)
42
+ url = format('%stoken', base_url)
41
43
  resp = connection.get(url, token_params)
42
44
  response = MultiJson.load(resp.body)
43
45
  return handle_error(response) if response['errcode']
46
+
44
47
  @access_token = response['access_token']
45
48
  File.open(@token_file, 'w') { |f| f.write(resp.body) } if @access_token
46
49
  @access_token
@@ -72,9 +75,11 @@ module Wechat
72
75
  end
73
76
 
74
77
  def with_access_token(uri, params, tried = 2)
75
- url = format('%s%s', API_BASE, uri)
78
+ url = format('%s%s', base_url, uri)
76
79
  begin
77
80
  resp = yield(url, params.merge(access_token: access_token))
81
+ raise ResponseError, resp unless resp.success?
82
+
78
83
  response = MultiJson.load(resp.body)
79
84
  handle_error(response)
80
85
  rescue AccessTokenExpiredError => e
@@ -86,6 +91,10 @@ module Wechat
86
91
 
87
92
  private
88
93
 
94
+ def base_url
95
+ site || API_BASE
96
+ end
97
+
89
98
  def debug_request
90
99
  response = yield
91
100
  logger.debug { response }
@@ -97,9 +106,9 @@ module Wechat
97
106
  when 0, nil
98
107
  response
99
108
  when 40_001, 42_001, 40_014
100
- fail AccessTokenExpiredError, response
109
+ raise AccessTokenExpiredError, response
101
110
  else
102
- fail ResponseError, response
111
+ raise ResponseError, response
103
112
  end
104
113
  end
105
114
 
@@ -0,0 +1,22 @@
1
+ module Wechat
2
+ module Api
3
+
4
+ class JsTicket
5
+ attr_reader :client, :ticket, :expires_at
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def refresh
11
+ js = client.js_ticket
12
+ @ticket = js['ticket']
13
+ @expires_at = DateTime.now + Rational(js['expires_in'].to_i, 3600 * 24)
14
+ self
15
+ end
16
+
17
+ def expired?
18
+ expires_at.nil? || DateTime.now > expires_at
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,6 @@
1
+ require 'securerandom'
2
+ require 'digest/sha1'
3
+
1
4
  module Wechat
2
5
  module Api
3
6
  #
@@ -29,8 +32,24 @@ module Wechat
29
32
  end
30
33
 
31
34
  def js_ticket
32
- res = get 'ticket/getticket', type: :jsapi
33
- res['ticket']
35
+ get 'ticket/getticket', type: :jsapi
36
+ end
37
+
38
+ def sign(params)
39
+ str = params.to_a.sort.map { |p| p.join('=') }.join('&')
40
+ logger.debug { "to_sign: #{str}" }
41
+ Digest::SHA1.hexdigest str
42
+ end
43
+
44
+ def js_config(url: nil)
45
+ r = ticket.tap { |j| j.refresh if j.expired? }.ticket
46
+ nonce = SecureRandom.hex
47
+ timestamp = Time.now.to_i
48
+ signature = sign(noncestr: nonce, timestamp: timestamp, jsapi_ticket: r, url: url)
49
+ {
50
+ appId: app_id, timestamp: timestamp, nonceStr: nonce,
51
+ signature: signature
52
+ }.tap { |hash| logger.debug { "js_config: #{hash}, url: #{url}" } }
34
53
  end
35
54
  end
36
55
  end
@@ -2,6 +2,6 @@
2
2
  module Wechat
3
3
  #
4
4
  module Api
5
- VERSION = '0.2.0'
5
+ VERSION = '0.4.2'.freeze
6
6
  end
7
7
  end
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ RSpec.describe Wechat::Api::JsTicket do
4
+
5
+ let(:client) { double(:client) }
6
+ subject do
7
+ Wechat::Api::JsTicket.new client
8
+ end
9
+
10
+ it :refresh do
11
+ allow(client).to receive(:js_ticket).and_return('expires_in'=> 7200, 'ticket'=> 'bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA')
12
+ subject.refresh
13
+ expect(subject.ticket).not_to be_nil
14
+ should_not be_expired
15
+ expect(subject.expires_at).to be_a(Date)
16
+ end
17
+
18
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ RSpec.describe Wechat::Api::Util do
4
+ subject { Wechat::Api::Client.new('APPID', 'APPSECRET') }
5
+
6
+ before do
7
+ subject.logger.level = Logger::DEBUG
8
+ end
9
+
10
+ it :js_config do
11
+ allow(SecureRandom).to receive(:hex).and_return('Wm3WZYTPz0wzccnW')
12
+ allow_any_instance_of(Time).to receive(:to_i).and_return(1414587457)
13
+ allow(subject).to receive(:js_ticket).and_return('expires_in' => 7200, 'ticket' => 'sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg')
14
+ js = subject.js_config(url: 'http://mp.weixin.qq.com?params=value')
15
+ expect(js).not_to be_nil
16
+ expect(js).to include(signature: '0f9de62fce790f9a083d5c99e95740ceb90c27ed')
17
+ expect(js).to have_key :appId
18
+ end
19
+ end
@@ -13,18 +13,19 @@ Gem::Specification.new do |spec|
13
13
  spec.license = "MIT"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
16
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
17
  spec.require_paths = ["lib"]
19
18
 
20
- spec.add_runtime_dependency "faraday", ">= 0.9"
21
- spec.add_runtime_dependency "rest-client", ">= 1.7.0"
22
- spec.add_runtime_dependency "multi_json", ">= 1.2"
23
- spec.add_runtime_dependency 'gyoku', '>= 1.0.0'
24
- spec.add_runtime_dependency 'nori'
25
- spec.add_development_dependency "bundler"
26
- spec.add_development_dependency "rake"
27
- spec.add_development_dependency "pry"
28
- spec.add_development_dependency "rspec", "~> 3.0"
29
- spec.add_development_dependency "webmock", "~> 1.18"
19
+ spec.add_runtime_dependency 'faraday', '~> 1.0'
20
+ spec.add_runtime_dependency 'multi_json', '~> 1.0'
21
+ spec.add_runtime_dependency 'oj', '~>3.0'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.0'
24
+ spec.add_development_dependency 'guard', '~> 2.0'
25
+ spec.add_development_dependency 'guard-rspec', '~> 4.0'
26
+ spec.add_development_dependency 'rake', '~> 13.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ spec.add_development_dependency 'rspec-its', '~> 1.0'
29
+ spec.add_development_dependency 'webmock', '~> 3.0'
30
+
30
31
  end
metadata CHANGED
@@ -1,156 +1,156 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Wong
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-13 00:00:00.000000000 Z
11
+ date: 2021-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.9'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.9'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rest-client
28
+ name: multi_json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.7.0
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.7.0
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: multi_json
42
+ name: oj
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.2'
47
+ version: '3.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.2'
54
+ version: '3.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: gyoku
56
+ name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 1.0.0
62
- type: :runtime
61
+ version: '1.0'
62
+ type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 1.0.0
68
+ version: '1.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: nori
70
+ name: guard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
75
+ version: '2.0'
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '2.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: bundler
84
+ name: guard-rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '4.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '4.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '13.0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '13.0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: pry
112
+ name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '3.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '3.0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: rspec
126
+ name: rspec-its
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '3.0'
131
+ version: '1.0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '3.0'
138
+ version: '1.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: webmock
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '1.18'
145
+ version: '3.0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '1.18'
153
- description:
152
+ version: '3.0'
153
+ description:
154
154
  email:
155
155
  - lazing@gmail.com
156
156
  executables: []
@@ -159,7 +159,6 @@ extra_rdoc_files: []
159
159
  files:
160
160
  - ".gitignore"
161
161
  - ".rspec"
162
- - ".travis.yml"
163
162
  - Gemfile
164
163
  - Guardfile
165
164
  - README.md
@@ -167,25 +166,24 @@ files:
167
166
  - lib/wechat-api.rb
168
167
  - lib/wechat/api.rb
169
168
  - lib/wechat/api/client.rb
169
+ - lib/wechat/api/js_ticket.rb
170
170
  - lib/wechat/api/message.rb
171
171
  - lib/wechat/api/user.rb
172
172
  - lib/wechat/api/util.rb
173
173
  - lib/wechat/api/version.rb
174
- - lib/wechat/pay.rb
175
- - lib/wechat/pay/client.rb
176
- - lib/wechat/pay/redpack.rb
177
174
  - lib/wechat/qy.rb
178
175
  - lib/wechat/qy/client.rb
179
176
  - lib/wechat/qy/message.rb
180
177
  - spec/spec_helper.rb
181
178
  - spec/wechat/api/client_spec.rb
182
- - spec/wechat/pay/client_spec.rb
179
+ - spec/wechat/api/js_ticket_spec.rb
180
+ - spec/wechat/api/util_spec.rb
183
181
  - wechat-api.gemspec
184
182
  homepage: https://github.com/lazing/wechat-api
185
183
  licenses:
186
184
  - MIT
187
185
  metadata: {}
188
- post_install_message:
186
+ post_install_message:
189
187
  rdoc_options: []
190
188
  require_paths:
191
189
  - lib
@@ -200,13 +198,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
198
  - !ruby/object:Gem::Version
201
199
  version: '0'
202
200
  requirements: []
203
- rubyforge_project:
204
- rubygems_version: 2.2.2
205
- signing_key:
201
+ rubygems_version: 3.0.6
202
+ signing_key:
206
203
  specification_version: 4
207
204
  summary: Wechat API wrapper
208
205
  test_files:
209
206
  - spec/spec_helper.rb
210
207
  - spec/wechat/api/client_spec.rb
211
- - spec/wechat/pay/client_spec.rb
212
- has_rdoc:
208
+ - spec/wechat/api/js_ticket_spec.rb
209
+ - spec/wechat/api/util_spec.rb
@@ -1,5 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - ruby-head
4
- - 2.1.0
5
- - 1.9.3
@@ -1,7 +0,0 @@
1
- require 'wechat/pay/client'
2
-
3
- module Wechat
4
- #
5
- module Pay
6
- end
7
- end
@@ -1,116 +0,0 @@
1
- require 'rest-client'
2
- require 'logger'
3
- require 'multi_json'
4
- require 'openssl'
5
- require 'nori'
6
- require 'gyoku'
7
-
8
- require 'wechat/pay/redpack'
9
-
10
- module Wechat
11
- module Pay
12
- class PayError < StandardError; end
13
- class NoAuthError < PayError; end
14
- class NotEnoughError < PayError; end
15
- class TimeLimitedError < PayError; end
16
- class MoneyLimitedError < PayError; end
17
-
18
- #
19
- class Client
20
- include Redpack
21
- BASE_URL = 'https://api.mch.weixin.qq.com'
22
- REQUIRED_OPTS = %w(key password cert sign_key).map(&:to_sym).freeze
23
- ERRORS = {
24
- 'NO_AUTH' => NoAuthError,
25
- 'NOTENOUGH' => NotEnoughError,
26
- 'TIME_LIMITED' => TimeLimitedError,
27
- 'MONEY_LIMITED' => MoneyLimitedError
28
- }
29
-
30
- attr_accessor :logger
31
-
32
- def initialize(mch_id, wxappid, opts = {})
33
- @mch_id = mch_id
34
- @wxappid = wxappid
35
- @opts = Hash[opts.map { |k, v| [k.to_sym, v] }]
36
- unless (REQUIRED_OPTS - @opts.keys).empty?
37
- fail format('%s required', REQUIRED_OPTS.join(','))
38
- end
39
- @logger = Logger.new(STDOUT)
40
- rsa_setup
41
- @parser = Nori.new
42
- end
43
-
44
- def post(path, params)
45
- merged_params = merge(params)
46
- logger.debug { merged_params }
47
- resp = resource(path).post(xml(sign(merged_params)))
48
- handle(resp)
49
- rescue RestClient::ExceptionWithResponse => err
50
- raise PayError, err.response
51
- end
52
-
53
- private
54
-
55
- def handle(resp)
56
- response = parser.parse(resp)
57
- check(response)
58
- response
59
- end
60
-
61
- def check(r)
62
- return if r['xml']['result_code'] == 'SUCCESS'
63
- handle_error(r['xml']['err_code'], r)
64
- end
65
-
66
- def handle_error(error_code, response)
67
- fail ERRORS[error_code] || PayError, response.inspect
68
- end
69
-
70
- def rsa_setup
71
- @rsa_key = OpenSSL::PKey::RSA.new @opts[:key], @opts[:password]
72
- @rsa_cert = OpenSSL::X509::Certificate.new @opts[:cert]
73
- rescue StandardError => e
74
- logger.error { e.inspect }
75
- end
76
-
77
- def resource(path)
78
- RestClient.log = logger
79
- RestClient::Resource.new\
80
- [BASE_URL, path].join,
81
- ssl_client_key: @rsa_key,
82
- ssl_client_cert: @rsa_cert,
83
- verify_ssl: OpenSSL::SSL::VERIFY_NONE
84
- end
85
-
86
- def xml(hash)
87
- Gyoku.xml({ xml: hash }, key_converter: :none)
88
- end
89
-
90
- def sign(params)
91
- ordered = trim_and_sort(params)
92
- keystr = format('key=%s', @opts[:sign_key])
93
- origin =
94
- ordered.map { |k, v| [k, v].join('=') }.push(keystr).join('&')
95
- sign = Digest::MD5.hexdigest(origin).upcase
96
- logger.debug { format('origin: %s, sign: %s', origin, sign) }
97
- params.merge(sign: sign)
98
- end
99
-
100
- def trim_and_sort(params)
101
- params.delete_if { |_k, v| v.blank? }
102
- Hash[params.sort]
103
- end
104
-
105
- def merge(params)
106
- params.reverse_merge\
107
- mch_id: @mch_id,
108
- nonce_str: nonce_str
109
- end
110
-
111
- def nonce_str
112
- SecureRandom.hex
113
- end
114
- end
115
- end
116
- end
@@ -1,39 +0,0 @@
1
- require 'securerandom'
2
-
3
- module Wechat
4
- module Pay
5
- #
6
- module Redpack
7
- def redpack(transaction_id, openid, params = {})
8
- post\
9
- '/mmpaymkttransfers/sendredpack',
10
- params.merge(
11
- mch_billno: tran_id(transaction_id),
12
- wxappid: @wxappid, re_openid: openid
13
- )
14
- end
15
-
16
- def group_redpack(transaction_id, openid, params = {})
17
- post\
18
- '/mmpaymkttransfers/sendgroupredpack',
19
- params.merge(
20
- mch_billno: tran_id(transaction_id),
21
- wxappid: @wxappid, re_openid: openid
22
- )
23
- end
24
-
25
- def redpack_info(transaction_id)
26
- post\
27
- '/mmpaymkttransfers/gethbinfo',
28
- mch_billno: tran_id(transaction_id),
29
- bill_type: 'MCHT', appid: @wxappid
30
- end
31
-
32
- private
33
-
34
- def tran_id(origin)
35
- format('%s%s', @mch_id, origin)
36
- end
37
- end
38
- end
39
- end
@@ -1,24 +0,0 @@
1
- require File.expand_path('../../../spec_helper', __FILE__)
2
-
3
- RSpec.describe Wechat::Pay::Client do
4
- subject do
5
- described_class.new\
6
- 'mch_id', 'wxappid',
7
- key: 'key', password: 'password', cert: 'cert',
8
- sign_key: 'sign_key'
9
- end
10
-
11
- it :trim_and_sort do
12
- expect(
13
- subject.send(:trim_and_sort, b: 2, c: 3, a: 1).values
14
- ).to start_with(1)
15
- end
16
-
17
- it :sign do
18
- expect(subject.send(:sign, b: 2, a: 1)).to have_key(:sign)
19
- end
20
-
21
- it :xml do
22
- expect(subject.send(:xml, b_1: 2, a: 1)).to match(/xml/)
23
- end
24
- end