wx_pay 0.17.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
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: