wechat-api 0.2.1 → 0.4.3

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
2
  SHA256:
3
- metadata.gz: 197097c39777d37a55379fcd924dbfd58af2fb184502a775508b7249e2587b0a
4
- data.tar.gz: '081365b0f92bd3fe4d949b80720763466916184bb4d6937692bf3e8373da5aa6'
3
+ metadata.gz: 7acc9381cefbe26a5dd3073b59b37a3ea04ea0ef78b67051cc43c58d9649542f
4
+ data.tar.gz: 924d53913a5d0cbfc4f2d0e0cdaab722e25c9f2f8261cf07fa054ba28afba97f
5
5
  SHA512:
6
- metadata.gz: da4a09f2c50ade7695c3e9b0ba106744f48c2330aed02bfde03187327e25a31093a8fc660daeb424b230372a7e4deb46f9f1f8b2d2d3eea4a25a462939d56ca4
7
- data.tar.gz: 590da45cc6017a13c342fbf1252b69258327adeae15acfe25139fe2ffb93c1c84df175e3d708597fdbda86ef8d9b818431adabfee346328e10cc4169d7be81c7
6
+ metadata.gz: bddcb1e25208e6be2900b576b064d5aa2661a6d354c79f8943c0f1e14b85a5f4577cf4aaa4d91d14381b539cfa785c0358206c559b9a9a0aa92ee59dd81955cd
7
+ data.tar.gz: 1f3710634744e5ef735f1ed73ce5f23d02a75bfa02943dee964fe412fc70d23e52e6f21c82b550d6d065aeb8db7f2849319ad1e445877d7a43b82322c15c2b7e
data/Gemfile CHANGED
@@ -1,9 +1,3 @@
1
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
@@ -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
 
@@ -10,6 +11,7 @@ module Wechat
10
11
  #
11
12
  class ResponseError < StandardError; end
12
13
  class AccessTokenExpiredError < ResponseError; end
14
+ class SubscribeError < ResponseError; end
13
15
  #
14
16
  class Client
15
17
  include Message
@@ -18,12 +20,13 @@ module Wechat
18
20
 
19
21
  API_BASE = 'https://api.weixin.qq.com/cgi-bin/'
20
22
 
21
- attr_reader :app_id, :secret
22
- attr_accessor :logger
23
+ attr_reader :app_id, :secret, :ticket
24
+ attr_accessor :logger, :site
23
25
 
24
26
  def initialize(app_id, secret)
25
27
  @app_id, @secret = app_id, secret
26
28
  @logger = Logger.new(STDOUT)
29
+ @ticket = JsTicket.new self
27
30
  @token_file = File.join('/tmp', "wechat-api-#{app_id}")
28
31
  end
29
32
 
@@ -37,10 +40,11 @@ module Wechat
37
40
  end
38
41
 
39
42
  def refresh
40
- url = format('%stoken', API_BASE)
43
+ url = format('%stoken', base_url)
41
44
  resp = connection.get(url, token_params)
42
45
  response = MultiJson.load(resp.body)
43
46
  return handle_error(response) if response['errcode']
47
+
44
48
  @access_token = response['access_token']
45
49
  File.open(@token_file, 'w') { |f| f.write(resp.body) } if @access_token
46
50
  @access_token
@@ -72,9 +76,11 @@ module Wechat
72
76
  end
73
77
 
74
78
  def with_access_token(uri, params, tried = 2)
75
- url = format('%s%s', API_BASE, uri)
79
+ url = format('%s%s', base_url, uri)
76
80
  begin
77
81
  resp = yield(url, params.merge(access_token: access_token))
82
+ raise ResponseError, resp unless resp.success?
83
+
78
84
  response = MultiJson.load(resp.body)
79
85
  handle_error(response)
80
86
  rescue AccessTokenExpiredError => e
@@ -86,6 +92,10 @@ module Wechat
86
92
 
87
93
  private
88
94
 
95
+ def base_url
96
+ site || API_BASE
97
+ end
98
+
89
99
  def debug_request
90
100
  response = yield
91
101
  logger.debug { response }
@@ -97,9 +107,11 @@ module Wechat
97
107
  when 0, nil
98
108
  response
99
109
  when 40_001, 42_001, 40_014
100
- fail AccessTokenExpiredError, response
110
+ raise AccessTokenExpiredError, response
111
+ when 43_004
112
+ raise SubscribeError, response
101
113
  else
102
- fail ResponseError, response
114
+ raise ResponseError, response
103
115
  end
104
116
  end
105
117
 
@@ -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.1'.freeze
5
+ VERSION = '0.4.3'.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,163 +1,162 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wechat-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.4.3
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: 2019-12-16 00:00:00.000000000 Z
11
+ date: 2021-01-22 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: []
157
157
  extensions: []
158
158
  extra_rdoc_files: []
159
159
  files:
160
- - ".github/workflows/rake_spec.yml"
161
160
  - ".gitignore"
162
161
  - ".rspec"
163
162
  - Gemfile
@@ -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
@@ -201,10 +199,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
199
  version: '0'
202
200
  requirements: []
203
201
  rubygems_version: 3.0.6
204
- signing_key:
202
+ signing_key:
205
203
  specification_version: 4
206
204
  summary: Wechat API wrapper
207
205
  test_files:
208
206
  - spec/spec_helper.rb
209
207
  - spec/wechat/api/client_spec.rb
210
- - spec/wechat/pay/client_spec.rb
208
+ - spec/wechat/api/js_ticket_spec.rb
209
+ - spec/wechat/api/util_spec.rb
@@ -1,20 +0,0 @@
1
- name: Ruby
2
-
3
- on: [push]
4
-
5
- jobs:
6
- build:
7
-
8
- runs-on: ubuntu-latest
9
-
10
- steps:
11
- - uses: actions/checkout@v1
12
- - name: Set up Ruby 2.6
13
- uses: actions/setup-ruby@v1
14
- with:
15
- ruby-version: 2.6.x
16
- - name: Build and test with Rake
17
- run: |
18
- gem install bundler
19
- bundle install --jobs 4 --retry 3
20
- bundle exec rake
@@ -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