wx_pay 0.17.0 → 0.21.0

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: 161782a3a1d52339e8ff2e0f3bfc408071fca7452e0390832e78af0294154f19
4
- data.tar.gz: b8251fb2072d5dda662e27e7f2e27d88a785f5cb0737dca9c1f955817ad1f07c
3
+ metadata.gz: e472765b251f44ad368e4738c8593e8b47e349892cec1d39017ec466243edfbf
4
+ data.tar.gz: bb4338988b511b4573b2a40acdb0e1d95131cee04fa8e776d455a9602b87b5e5
5
5
  SHA512:
6
- metadata.gz: f14c5ff39a759e960b3578f68a94a6120cef8b69fc9ed5349b40182f493b733999064fdb0105e1f525283146fbf3ea96e90381b38d1f2fbf5eca018dd3a88d26
7
- data.tar.gz: aad7882af734bafc4e3bca5a91f49dd1442726a42ca31e041cdc6b005b9d4d7bde6e9feba91b13b37ce0532692b17a8419feb64e03bff3239ead289694a7d97d
6
+ metadata.gz: a313ebc9905ea19414c3e3d58e0b512941052707ea3fc2a4f5d3b194e20d72ffd40035e1fbf951dc3b4ad789a901b9c4a73b763c6c21fe221eee484815f044df
7
+ data.tar.gz: faa85e84cd7c78ce8be986039d7bd56ea0061d2a7e284130cf37ceef3cd03918eee06872dee2e42640ea9ca29f1049d107e86f02495e8a3572fd25484e04e086
@@ -11,7 +11,7 @@ module WxPay
11
11
 
12
12
  class<< self
13
13
  attr_accessor :appid, :mch_id, :key, :appsecret, :extra_rest_client_options, :debug_mode
14
- attr_accessor :sandbox_mode, :sandbox_key, :sandbox_mch_id
14
+ attr_accessor :sandbox_mode, :manual_get_sandbox_key
15
15
  attr_reader :apiclient_cert, :apiclient_key
16
16
 
17
17
  def set_apiclient_by_pkcs12(str, pass)
@@ -37,5 +37,9 @@ module WxPay
37
37
  def sandbox_mode?
38
38
  @sandbox_mode
39
39
  end
40
+
41
+ def manual_get_sandbox_key?
42
+ @manual_get_sandbox_key
43
+ end
40
44
  end
41
45
  end
@@ -17,19 +17,27 @@ module WxPay
17
17
 
18
18
  def self.authenticate(authorization_code, options = {})
19
19
  options = WxPay.extra_rest_client_options.merge(options)
20
- url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=#{WxPay.appid}&secret=#{WxPay.appsecret}&code=#{authorization_code}&grant_type=authorization_code"
20
+ payload = {
21
+ appid: options.delete(:appid) || WxPay.appid,
22
+ secret: options.delete(:appsecret) || WxPay.appsecret,
23
+ code: authorization_code,
24
+ grant_type: 'authorization_code'
25
+ }
26
+ url = "https://api.weixin.qq.com/sns/oauth2/access_token"
21
27
 
22
28
  ::JSON.parse(RestClient::Request.execute(
23
29
  {
24
30
  method: :get,
31
+ headers: {params: payload},
25
32
  url: url
26
33
  }.merge(options)
27
34
  ), quirks_mode: true)
28
35
  end
29
36
 
30
- def self.get_sandbox_signkey
37
+ def self.get_sandbox_signkey(mch_id = WxPay.mch_id, options = {})
31
38
  params = {
32
- mch_id: WxPay.mch_id,
39
+ mch_id: mch_id,
40
+ key: options.delete(:key) || WxPay.key,
33
41
  nonce_str: SecureRandom.uuid.tr('-', '')
34
42
  }
35
43
  r = WxPay::Result.new(Hash.from_xml(invoke_remote("/pay/getsignkey", xmlify_payload(params))))
@@ -39,11 +47,18 @@ module WxPay
39
47
 
40
48
  def self.authenticate_from_weapp(js_code, options = {})
41
49
  options = WxPay.extra_rest_client_options.merge(options)
42
- url = "https://api.weixin.qq.com/sns/jscode2session?appid=#{WxPay.appid}&secret=#{WxPay.appsecret}&js_code=#{js_code}&grant_type=authorization_code"
50
+ payload = {
51
+ appid: options.delete(:appid) || WxPay.appid,
52
+ secret: options.delete(:appsecret) || WxPay.appsecret,
53
+ js_code: js_code,
54
+ grant_type: 'authorization_code'
55
+ }
56
+ url = "https://api.weixin.qq.com/sns/jscode2session"
43
57
 
44
58
  ::JSON.parse(RestClient::Request.execute(
45
59
  {
46
60
  method: :get,
61
+ headers: {params: payload},
47
62
  url: url
48
63
  }.merge(options)
49
64
  ), quirks_mode: true)
@@ -152,6 +167,7 @@ module WxPay
152
167
  params = {
153
168
  appid: options.delete(:appid) || WxPay.appid,
154
169
  mch_id: options.delete(:mch_id) || WxPay.mch_id,
170
+ key: options.delete(:key) || WxPay.key,
155
171
  nonce_str: SecureRandom.uuid.tr('-', '')
156
172
  }.merge(params)
157
173
 
@@ -286,6 +302,7 @@ module WxPay
286
302
  params = {
287
303
  appid: options.delete(:appid) || WxPay.appid,
288
304
  mch_id: options.delete(:mch_id) || WxPay.mch_id,
305
+ key: options.delete(:key) || WxPay.key,
289
306
  nonce_str: SecureRandom.uuid.tr('-', '')
290
307
  }.merge(params)
291
308
 
@@ -309,6 +326,7 @@ module WxPay
309
326
  params = {
310
327
  appid: options.delete(:appid) || WxPay.appid,
311
328
  mch_id: options.delete(:mch_id) || WxPay.mch_id,
329
+ key: options.delete(:key) || WxPay.key,
312
330
  nonce_str: SecureRandom.uuid.tr('-', '')
313
331
  }.merge(params)
314
332
 
@@ -332,6 +350,7 @@ module WxPay
332
350
  params = {
333
351
  appid: options.delete(:appid) || WxPay.appid,
334
352
  mch_id: options.delete(:mch_id) || WxPay.mch_id,
353
+ key: options.delete(:key) || WxPay.key,
335
354
  nonce_str: SecureRandom.uuid.tr('-', '')
336
355
  }.merge(params)
337
356
 
@@ -349,6 +368,7 @@ module WxPay
349
368
  params = {
350
369
  appid: options.delete(:appid) || WxPay.appid,
351
370
  mch_id: options.delete(:mch_id) || WxPay.mch_id,
371
+ key: options.delete(:key) || WxPay.key,
352
372
  nonce_str: SecureRandom.uuid.tr('-', ''),
353
373
  }.merge(params)
354
374
 
@@ -361,10 +381,35 @@ module WxPay
361
381
  r
362
382
  end
363
383
 
384
+ DOWNLOAD_FUND_FLOW_REQUIRED_FIELDS = [:bill_date, :account_type]
385
+ def self.download_fund_flow(params, options = {})
386
+ params = {
387
+ appid: options.delete(:appid) || WxPay.appid,
388
+ mch_id: options.delete(:mch_id) || WxPay.mch_id,
389
+ nonce_str: SecureRandom.uuid.tr('-', ''),
390
+ key: options.delete(:key) || WxPay.key
391
+ }.merge(params)
392
+
393
+ check_required_options(params, DOWNLOAD_FUND_FLOW_REQUIRED_FIELDS)
394
+
395
+ options = {
396
+ ssl_client_cert: options.delete(:apiclient_cert) || WxPay.apiclient_cert,
397
+ ssl_client_key: options.delete(:apiclient_key) || WxPay.apiclient_key,
398
+ verify_ssl: OpenSSL::SSL::VERIFY_NONE
399
+ }.merge(options)
400
+
401
+ r = invoke_remote("/pay/downloadfundflow", make_payload(params, WxPay::Sign::SIGN_TYPE_HMAC_SHA256), options)
402
+
403
+ yield r if block_given?
404
+
405
+ r
406
+ end
407
+
364
408
  def self.sendgroupredpack(params, options={})
365
409
  params = {
366
410
  wxappid: options.delete(:appid) || WxPay.appid,
367
411
  mch_id: options.delete(:mch_id) || WxPay.mch_id,
412
+ key: options.delete(:key) || WxPay.key,
368
413
  nonce_str: SecureRandom.uuid.tr('-', '')
369
414
  }.merge(params)
370
415
 
@@ -387,6 +432,7 @@ module WxPay
387
432
  params = {
388
433
  wxappid: options.delete(:appid) || WxPay.appid,
389
434
  mch_id: options.delete(:mch_id) || WxPay.mch_id,
435
+ key: options.delete(:key) || WxPay.key,
390
436
  nonce_str: SecureRandom.uuid.tr('-', '')
391
437
  }.merge(params)
392
438
 
@@ -405,6 +451,97 @@ module WxPay
405
451
  r
406
452
  end
407
453
 
454
+ # 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包。
455
+ GETHBINFO_FIELDS = [:mch_billno, :bill_type]
456
+ def self.gethbinfo(params, options = {})
457
+ params = {
458
+ appid: options.delete(:appid) || WxPay.appid,
459
+ mch_id: options.delete(:mch_id) || WxPay.mch_id,
460
+ nonce_str: SecureRandom.uuid.tr('-', ''),
461
+ key: options.delete(:key) || WxPay.key
462
+ }.merge(params)
463
+
464
+ check_required_options(params, GETHBINFO_FIELDS)
465
+
466
+ options = {
467
+ ssl_client_cert: options.delete(:apiclient_cert) || WxPay.apiclient_cert,
468
+ ssl_client_key: options.delete(:apiclient_key) || WxPay.apiclient_key,
469
+ verify_ssl: OpenSSL::SSL::VERIFY_NONE
470
+ }.merge(options)
471
+
472
+ r = WxPay::Result.new(Hash.from_xml(invoke_remote("/mmpaymkttransfers/gethbinfo", make_payload(params), options)))
473
+
474
+ yield r if block_given?
475
+
476
+ r
477
+ end
478
+
479
+ PROFITSHARINGADDRECEIVER = [:nonce_str, :receiver]
480
+
481
+ # 添加分账接收方
482
+ def self.profitsharingaddreceiver(params, options = {})
483
+ params = {
484
+ appid: options.delete(:appid) || WxPay.appid,
485
+ mch_id: options.delete(:mch_id) || WxPay.mch_id,
486
+ nonce_str: SecureRandom.uuid.tr('-', ''),
487
+ key: options.delete(:key) || WxPay.key
488
+ }.merge(params)
489
+
490
+ check_required_options(params, PROFITSHARINGADDRECEIVER)
491
+
492
+ r = WxPay::Result.new(Hash.from_xml(invoke_remote("/pay/profitsharingaddreceiver", make_payload(params, WxPay::Sign::SIGN_TYPE_HMAC_SHA256), options)))
493
+
494
+ yield r if block_given?
495
+
496
+ r
497
+ end
498
+
499
+ PROFITSHARINGREMOVERECEIVER = [:nonce_str, :receiver]
500
+ # 删除分账接收方
501
+ def self.profitsharingremovereceiver(params, options = {})
502
+ params = {
503
+ appid: options.delete(:appid) || WxPay.appid,
504
+ mch_id: options.delete(:mch_id) || WxPay.mch_id,
505
+ nonce_str: SecureRandom.uuid.tr('-', ''),
506
+ key: options.delete(:key) || WxPay.key
507
+ }.merge(params)
508
+
509
+ check_required_options(params, PROFITSHARINGADDRECEIVER)
510
+
511
+ r = WxPay::Result.new(Hash.from_xml(invoke_remote("/pay/profitsharingremovereceiver", make_payload(params, WxPay::Sign::SIGN_TYPE_HMAC_SHA256), options)))
512
+
513
+ yield r if block_given?
514
+
515
+ r
516
+ end
517
+
518
+ # 单次分账
519
+
520
+ PROFITSHARING = [:nonce_str, :receivers, :transaction_id, :out_order_no]
521
+
522
+ def self.profitsharing(params, options = {})
523
+ params = {
524
+ appid: options.delete(:appid) || WxPay.appid,
525
+ mch_id: options.delete(:mch_id) || WxPay.mch_id,
526
+ nonce_str: SecureRandom.uuid.tr('-', ''),
527
+ key: options.delete(:key) || WxPay.key
528
+ }.merge(params)
529
+
530
+ check_required_options(params, PROFITSHARING)
531
+
532
+ options = {
533
+ ssl_client_cert: options.delete(:apiclient_cert) || WxPay.apiclient_cert,
534
+ ssl_client_key: options.delete(:apiclient_key) || WxPay.apiclient_key,
535
+ verify_ssl: OpenSSL::SSL::VERIFY_NONE
536
+ }.merge(options)
537
+
538
+ r = WxPay::Result.new(Hash.from_xml(invoke_remote("/secapi/pay/profitsharing", make_payload(params, WxPay::Sign::SIGN_TYPE_HMAC_SHA256), options)))
539
+
540
+ yield r if block_given?
541
+
542
+ r
543
+ end
544
+
408
545
  class << self
409
546
  private
410
547
 
@@ -420,26 +557,26 @@ module WxPay
420
557
  end
421
558
  end
422
559
 
423
- def xmlify_payload(params)
424
- sign = WxPay::Sign.generate(params)
425
- params.delete(:key) if params[:key]
426
- "<xml>#{params.map { |k, v| "<#{k}>#{v}</#{k}>" }.join}<sign>#{sign}</sign></xml>"
560
+ def xmlify_payload(params, sign_type = WxPay::Sign::SIGN_TYPE_MD5)
561
+ sign = WxPay::Sign.generate(params, sign_type)
562
+ "<xml>#{params.except(:key).sort.map { |k, v| "<#{k}>#{v}</#{k}>" }.join}<sign>#{sign}</sign></xml>"
427
563
  end
428
564
 
429
- def make_payload(params)
430
- if WxPay.sandbox_mode?
565
+ def make_payload(params, sign_type = WxPay::Sign::SIGN_TYPE_MD5)
566
+ # TODO: Move this out
567
+ if WxPay.sandbox_mode? && !WxPay.manual_get_sandbox_key?
431
568
  r = get_sandbox_signkey
432
569
  if r['return_code'] == WxPay::Result::SUCCESS_FLAG
433
- params = params.merge({
434
- :mch_id => r['mch_id'] || WxPay.mch_id,
435
- :key => r['sandbox_signkey']
436
- })
437
- WxPay.sandbox_key = r['sandbox_signkey']
570
+ params = params.merge(
571
+ mch_id: r['mch_id'] || WxPay.mch_id,
572
+ key: r['sandbox_signkey']
573
+ )
438
574
  else
439
575
  warn("WxPay Warn: fetch sandbox sign key failed #{r['return_msg']}")
440
576
  end
441
577
  end
442
- xmlify_payload(params)
578
+
579
+ xmlify_payload(params, sign_type)
443
580
  end
444
581
 
445
582
  def invoke_remote(url, payload, options = {})
@@ -2,26 +2,42 @@ require 'digest/md5'
2
2
 
3
3
  module WxPay
4
4
  module Sign
5
- def self.generate(params)
5
+
6
+ SIGN_TYPE_MD5 = 'MD5'
7
+ SIGN_TYPE_HMAC_SHA256 = 'HMAC-SHA256'
8
+
9
+ def self.generate(params, sign_type = SIGN_TYPE_MD5)
6
10
  key = params.delete(:key)
7
11
 
12
+ new_key = params["key"] #after
13
+ key = params.delete("key") if params["key"] #after
14
+
8
15
  query = params.sort.map do |k, v|
9
16
  "#{k}=#{v}" if v.to_s != ''
10
17
  end.compact.join('&')
11
18
 
12
- Digest::MD5.hexdigest("#{query}&key=#{key || WxPay.key}").upcase
19
+ string_sign_temp = "#{query}&key=#{key || new_key || WxPay.key}" #after
20
+
21
+ if sign_type == SIGN_TYPE_MD5
22
+ Digest::MD5.hexdigest(string_sign_temp).upcase
23
+ elsif sign_type == SIGN_TYPE_HMAC_SHA256
24
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, string_sign_temp).upcase
25
+ else
26
+ warn("WxPay Warn: unknown sign_type : #{sign_type}")
27
+ end
13
28
  end
14
29
 
15
30
  def self.verify?(params, options = {})
31
+ return true if WxPay.sandbox_mode?
32
+
16
33
  params = params.dup
17
- params = params.merge(options)
18
- if WxPay.sandbox_mode?
19
- params = params.merge(:key => WxPay.sandbox_key)
20
- end
34
+ params["appid"] = options[:appid] if options[:appid]
35
+ params["mch_id"] = options[:mch_id] if options[:mch_id]
36
+ params["key"] = options[:key] if options[:key]
21
37
 
22
38
  sign = params.delete('sign') || params.delete(:sign)
23
39
 
24
- generate(params) == sign
40
+ generate(params, options[:sign_type] || SIGN_TYPE_MD5) == sign
25
41
  end
26
42
  end
27
43
  end
@@ -1,3 +1,3 @@
1
1
  module WxPay
2
- VERSION = '0.17.0'.freeze
2
+ VERSION = '0.21.0'.freeze
3
3
  end
@@ -48,7 +48,7 @@ class ServiceTest < MiniTest::Test
48
48
  mch_id: 'mch_id',
49
49
  key: 'key'
50
50
  }
51
- xml_str = '<xml><body>测试商品</body><out_trade_no>test003</out_trade_no><total_fee>1</total_fee><spbill_create_ip>127.0.0.1</spbill_create_ip><notify_url>http://making.dev/notify</notify_url><trade_type>JSAPI</trade_type><openid>OPENID</openid><app_id>app_id</app_id><mch_id>mch_id</mch_id><sign>172A2D487A37D13FDE32B874BA823DD6</sign></xml>'
51
+ xml_str = '<xml><app_id>app_id</app_id><body>测试商品</body><mch_id>mch_id</mch_id><notify_url>http://making.dev/notify</notify_url><openid>OPENID</openid><out_trade_no>test003</out_trade_no><spbill_create_ip>127.0.0.1</spbill_create_ip><total_fee>1</total_fee><trade_type>JSAPI</trade_type><sign>172A2D487A37D13FDE32B874BA823DD6</sign></xml>'
52
52
  assert_equal xml_str, WxPay::Service.send(:make_payload, params)
53
53
  end
54
54
  end
@@ -14,19 +14,29 @@ class WxPay::SignTest < MiniTest::Test
14
14
  total_fee: 1
15
15
  }
16
16
 
17
- @sign = '729A68AC3DE268DBD9ADE442382E7B24'
17
+ @sign_md5 = '729A68AC3DE268DBD9ADE442382E7B24'
18
+ @sign_hmac_sha256 = 'A58C01F990B45A4D0E496F835B2739E391C6C734927B1DA740DC873E607FB42A'
18
19
  end
19
20
 
20
21
  def test_generate_sign
21
- assert_equal @sign, WxPay::Sign.generate(@params)
22
+ assert_equal @sign_md5, WxPay::Sign.generate(@params)
23
+ end
24
+
25
+ def test_generate_sign_md5
26
+ assert_equal @sign_md5, WxPay::Sign.generate(@params, WxPay::Sign::SIGN_TYPE_MD5)
27
+ end
28
+
29
+ def test_generate_sign_hmac_sha256
30
+ @params.merge!(key: "key")
31
+ assert_equal @sign_hmac_sha256, WxPay::Sign.generate(@params, WxPay::Sign::SIGN_TYPE_HMAC_SHA256)
22
32
  end
23
33
 
24
34
  def test_verify_sign
25
- assert WxPay::Sign.verify?(@params.merge(:sign => @sign))
35
+ assert WxPay::Sign.verify?(@params.merge(:sign => @sign_md5))
26
36
  end
27
37
 
28
38
  def test_verify_sign_when_fails
29
- assert !WxPay::Sign.verify?(@params.merge(:danger => 'danger', :sign => @sign))
39
+ assert !WxPay::Sign.verify?(@params.merge(:danger => 'danger', :sign => @sign_md5))
30
40
  end
31
41
 
32
42
  def test_accept_pars_key_to_generate_sign
@@ -34,4 +44,10 @@ class WxPay::SignTest < MiniTest::Test
34
44
 
35
45
  assert_equal "1454C32E885B8D9E4A05E976D1C45B88", WxPay::Sign.generate(@params)
36
46
  end
47
+
48
+ def test_verify_sign_when_use_hmac_sha256
49
+ opts = { key: "key", sign_type: WxPay::Sign::SIGN_TYPE_HMAC_SHA256 }
50
+
51
+ assert WxPay::Sign.verify?(@params.merge(:sign => @sign_hmac_sha256), opts)
52
+ end
37
53
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wx_pay
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jasl
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-09 00:00:00.000000000 Z
11
+ date: 2020-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -38,34 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.2'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rake
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
- - - "~>"
45
+ - - ">="
60
46
  - !ruby/object:Gem::Version
61
- version: '11.2'
47
+ version: 12.3.3
62
48
  type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - "~>"
52
+ - - ">="
67
53
  - !ruby/object:Gem::Version
68
- version: '11.2'
54
+ version: 12.3.3
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: webmock
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -116,7 +102,7 @@ homepage: https://github.com/jasl/wx_pay
116
102
  licenses:
117
103
  - MIT
118
104
  metadata: {}
119
- post_install_message:
105
+ post_install_message:
120
106
  rdoc_options: []
121
107
  require_paths:
122
108
  - lib
@@ -131,9 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
117
  - !ruby/object:Gem::Version
132
118
  version: '0'
133
119
  requirements: []
134
- rubyforge_project:
135
- rubygems_version: 2.7.4
136
- signing_key:
120
+ rubygems_version: 3.1.4
121
+ signing_key:
137
122
  specification_version: 4
138
123
  summary: An unofficial simple wechat pay gem
139
124
  test_files: