activemerchant 1.129.0 → 1.133.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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +51 -1
  3. data/lib/active_merchant/billing/credit_card.rb +2 -0
  4. data/lib/active_merchant/billing/credit_card_methods.rb +7 -3
  5. data/lib/active_merchant/billing/gateways/adyen.rb +82 -2
  6. data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
  7. data/lib/active_merchant/billing/gateways/borgun.rb +11 -8
  8. data/lib/active_merchant/billing/gateways/braintree_blue.rb +8 -7
  9. data/lib/active_merchant/billing/gateways/checkout_v2.rb +15 -8
  10. data/lib/active_merchant/billing/gateways/commerce_hub.rb +13 -4
  11. data/lib/active_merchant/billing/gateways/cyber_source.rb +32 -7
  12. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +6 -8
  13. data/lib/active_merchant/billing/gateways/d_local.rb +1 -0
  14. data/lib/active_merchant/billing/gateways/global_collect.rb +41 -19
  15. data/lib/active_merchant/billing/gateways/ipg.rb +1 -1
  16. data/lib/active_merchant/billing/gateways/kushki.rb +1 -1
  17. data/lib/active_merchant/billing/gateways/mit.rb +18 -18
  18. data/lib/active_merchant/billing/gateways/nmi.rb +5 -0
  19. data/lib/active_merchant/billing/gateways/paypal_express.rb +2 -0
  20. data/lib/active_merchant/billing/gateways/payu_latam.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +1 -1
  22. data/lib/active_merchant/billing/gateways/redsys.rb +2 -1
  23. data/lib/active_merchant/billing/gateways/safe_charge.rb +2 -1
  24. data/lib/active_merchant/billing/gateways/shift4.rb +5 -2
  25. data/lib/active_merchant/billing/gateways/stripe.rb +21 -5
  26. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +111 -68
  27. data/lib/active_merchant/billing/gateways/vpos.rb +1 -1
  28. data/lib/active_merchant/billing/gateways/worldpay.rb +12 -24
  29. data/lib/active_merchant/version.rb +1 -1
  30. metadata +3 -3
@@ -34,9 +34,9 @@ module ActiveMerchant #:nodoc:
34
34
  add_connected_account(post, options)
35
35
  add_radar_data(post, options)
36
36
  add_shipping_address(post, options)
37
+ add_stored_credentials(post, options)
37
38
  setup_future_usage(post, options)
38
39
  add_exemption(post, options)
39
- add_stored_credentials(post, options)
40
40
  add_ntid(post, options)
41
41
  add_claim_without_transaction_id(post, options)
42
42
  add_error_on_requires_action(post, options)
@@ -76,22 +76,27 @@ module ActiveMerchant #:nodoc:
76
76
 
77
77
  def create_payment_method(payment_method, options = {})
78
78
  post_data = add_payment_method_data(payment_method, options)
79
-
80
79
  options = format_idempotency_key(options, 'pm')
81
80
  commit(:post, 'payment_methods', post_data, options)
82
81
  end
83
82
 
84
83
  def add_payment_method_data(payment_method, options = {})
85
- post_data = {}
86
- post_data[:type] = 'card'
87
- post_data[:card] = {}
88
- post_data[:card][:number] = payment_method.number
89
- post_data[:card][:exp_month] = payment_method.month
90
- post_data[:card][:exp_year] = payment_method.year
91
- post_data[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
92
- add_billing_address(post_data, options)
93
- add_name_only(post_data, payment_method) if post_data[:billing_details].nil?
94
- post_data
84
+ post = {
85
+ type: 'card',
86
+ card: {
87
+ number: payment_method.number,
88
+ exp_month: payment_method.month,
89
+ exp_year: payment_method.year
90
+ }
91
+ }
92
+
93
+ post[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
94
+ if billing = options[:billing_address] || options[:address]
95
+ post[:billing_details] = add_address(billing, options)
96
+ end
97
+
98
+ add_name_only(post, payment_method) if post[:billing_details].nil?
99
+ post
95
100
  end
96
101
 
97
102
  def add_payment_method_card_data_token(post_data, payment_method)
@@ -212,16 +217,7 @@ module ActiveMerchant #:nodoc:
212
217
  result = add_payment_method_token(params, payment_method, options)
213
218
  return result if result.is_a?(ActiveMerchant::Billing::Response)
214
219
 
215
- if options[:customer]
216
- customer_id = options[:customer]
217
- else
218
- post[:description] = options[:description] if options[:description]
219
- post[:email] = options[:email] if options[:email]
220
- options = format_idempotency_key(options, 'customer')
221
- post[:expand] = [:sources]
222
- customer = commit(:post, 'customers', post, options)
223
- customer_id = customer.params['id']
224
- end
220
+ customer_id = options[:customer] || customer(post, payment_method, options).params['id']
225
221
  options = format_idempotency_key(options, 'attach')
226
222
  attach_parameters = { customer: customer_id }
227
223
  attach_parameters[:validate] = options[:validate] unless options[:validate].nil?
@@ -231,6 +227,23 @@ module ActiveMerchant #:nodoc:
231
227
  end
232
228
  end
233
229
 
230
+ def customer(post, payment, options)
231
+ post[:description] = options[:description] if options[:description]
232
+ post[:expand] = [:sources]
233
+ post[:email] = options[:email]
234
+
235
+ if billing = options[:billing_address] || options[:address]
236
+ post.merge!(add_address(billing, options))
237
+ end
238
+
239
+ if shipping = options[:shipping_address]
240
+ post[:shipping] = add_address(shipping, options).except(:email)
241
+ end
242
+
243
+ options = format_idempotency_key(options, 'customer')
244
+ commit(:post, 'customers', post, options)
245
+ end
246
+
234
247
  def unstore(identification, options = {}, deprecated_options = {})
235
248
  if identification.include?('pm_')
236
249
  _, payment_method = identification.split('|')
@@ -399,17 +412,19 @@ module ActiveMerchant #:nodoc:
399
412
  post[:payment_method_options][:card][:moto] = true if options[:moto]
400
413
  end
401
414
 
402
- # Stripe Payment Intents does not pass any parameters for cardholder/merchant initiated
403
- # it also does not support installments for any country other than Mexico (reason for this is unknown)
404
- # The only thing that Stripe PI requires for stored credentials to work currently is the network_transaction_id
405
- # network_transaction_id is created when the card is authenticated using the field `setup_for_future_usage` with the value `off_session` see def setup_future_usage below
415
+ # Stripe Payment Intents now supports specifying on a transaction level basis stored credential information.
416
+ # The feature is currently gated but is listed as `stored_credential_transaction_type` inside the
417
+ # `post[:payment_method_options][:card]` hash. Since this is a beta field adding an extra check to use
418
+ # the existing logic by default. To be able to utilize this field, you must reach out to Stripe.
406
419
 
407
420
  def add_stored_credentials(post, options = {})
408
421
  return unless options[:stored_credential] && !options[:stored_credential].values.all?(&:nil?)
409
422
 
410
- stored_credential = options[:stored_credential]
411
423
  post[:payment_method_options] ||= {}
412
424
  post[:payment_method_options][:card] ||= {}
425
+ add_stored_credential_transaction_type(post, options) if options[:stored_credential_transaction_type]
426
+
427
+ stored_credential = options[:stored_credential]
413
428
  post[:payment_method_options][:card][:mit_exemption] = {}
414
429
 
415
430
  # Stripe PI accepts network_transaction_id and ds_transaction_id via mit field under card.
@@ -419,6 +434,50 @@ module ActiveMerchant #:nodoc:
419
434
  post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
420
435
  end
421
436
 
437
+ def add_stored_credential_transaction_type(post, options = {})
438
+ stored_credential = options[:stored_credential]
439
+ # Do not add anything unless these are present.
440
+ return unless stored_credential[:reason_type] && stored_credential[:initiator]
441
+
442
+ # Not compatible with off_session parameter.
443
+ options.delete(:off_session)
444
+ if stored_credential[:initial_transaction]
445
+ # Initial transactions must by CIT
446
+ return unless stored_credential[:initiator] == 'cardholder'
447
+
448
+ initial_transaction_stored_credential(post, stored_credential[:reason_type])
449
+ else
450
+ # Subsequent transaction
451
+ subsequent_transaction_stored_credential(post, stored_credential[:initiator], stored_credential[:reason_type])
452
+ end
453
+ end
454
+
455
+ def initial_transaction_stored_credential(post, reason_type)
456
+ if reason_type == 'unscheduled'
457
+ # Charge on-session and store card for future one-off payment use
458
+ post[:payment_method_options][:card][:stored_credential_transaction_type] = 'setup_off_session_unscheduled'
459
+ elsif reason_type == 'recurring'
460
+ # Charge on-session and store card for future recurring payment use
461
+ post[:payment_method_options][:card][:stored_credential_transaction_type] = 'setup_off_session_recurring'
462
+ else
463
+ # Charge on-session and store card for future on-session payment use.
464
+ post[:payment_method_options][:card][:stored_credential_transaction_type] = 'setup_on_session'
465
+ end
466
+ end
467
+
468
+ def subsequent_transaction_stored_credential(post, initiator, reason_type)
469
+ if initiator == 'cardholder'
470
+ # Charge on-session customer using previously stored card.
471
+ post[:payment_method_options][:card][:stored_credential_transaction_type] = 'stored_on_session'
472
+ elsif reason_type == 'recurring'
473
+ # Charge off-session customer using previously stored card for recurring transaction
474
+ post[:payment_method_options][:card][:stored_credential_transaction_type] = 'stored_off_session_recurring'
475
+ else
476
+ # Charge off-session customer using previously stored card for one-off transaction
477
+ post[:payment_method_options][:card][:stored_credential_transaction_type] = 'stored_off_session_unscheduled'
478
+ end
479
+ end
480
+
422
481
  def add_ntid(post, options = {})
423
482
  return unless options[:network_transaction_id]
424
483
 
@@ -478,30 +537,35 @@ module ActiveMerchant #:nodoc:
478
537
  def add_billing_address_for_card_tokenization(post, options = {})
479
538
  return unless (billing = options[:billing_address] || options[:address])
480
539
 
481
- post[:card][:address_city] = billing[:city] if billing[:city]
482
- post[:card][:address_country] = billing[:country] if billing[:country]
483
- post[:card][:address_line1] = billing[:address1] if billing[:address1]
484
- post[:card][:address_line2] = billing[:address2] if billing[:address2]
485
- post[:card][:address_zip] = billing[:zip] if billing[:zip]
486
- post[:card][:address_state] = billing[:state] if billing[:state]
540
+ billing = add_address(billing, options)
541
+ billing[:address].transform_keys! { |k| k == :postal_code ? :address_zip : k.to_s.prepend('address_').to_sym }
542
+
543
+ post[:card][:name] = billing[:name]
544
+ post[:card].merge!(billing[:address])
487
545
  end
488
546
 
489
- def add_billing_address(post, options = {})
490
- return unless billing = options[:billing_address] || options[:address]
547
+ def add_shipping_address(post, options = {})
548
+ return unless shipping = options[:shipping_address]
491
549
 
492
- email = billing[:email] || options[:email]
550
+ post[:shipping] = add_address(shipping, options).except(:email)
551
+ post[:shipping][:carrier] = (shipping[:carrier] || options[:shipping_carrier]) if shipping[:carrier] || options[:shipping_carrier]
552
+ post[:shipping][:tracking_number] = (shipping[:tracking_number] || options[:shipping_tracking_number]) if shipping[:tracking_number] || options[:shipping_tracking_number]
553
+ end
493
554
 
494
- post[:billing_details] = {}
495
- post[:billing_details][:address] = {}
496
- post[:billing_details][:address][:city] = billing[:city] if billing[:city]
497
- post[:billing_details][:address][:country] = billing[:country] if billing[:country]
498
- post[:billing_details][:address][:line1] = billing[:address1] if billing[:address1]
499
- post[:billing_details][:address][:line2] = billing[:address2] if billing[:address2]
500
- post[:billing_details][:address][:postal_code] = billing[:zip] if billing[:zip]
501
- post[:billing_details][:address][:state] = billing[:state] if billing[:state]
502
- post[:billing_details][:email] = email if email
503
- post[:billing_details][:name] = billing[:name] if billing[:name]
504
- post[:billing_details][:phone] = billing[:phone] if billing[:phone]
555
+ def add_address(address, options)
556
+ {
557
+ address: {
558
+ city: address[:city],
559
+ country: address[:country],
560
+ line1: address[:address1],
561
+ line2: address[:address2],
562
+ postal_code: address[:zip],
563
+ state: address[:state]
564
+ }.compact,
565
+ email: address[:email] || options[:email],
566
+ phone: address[:phone] || address[:phone_number],
567
+ name: address[:name]
568
+ }.compact
505
569
  end
506
570
 
507
571
  def add_name_only(post, payment_method)
@@ -511,27 +575,6 @@ module ActiveMerchant #:nodoc:
511
575
  post[:billing_details][:name] = name
512
576
  end
513
577
 
514
- def add_shipping_address(post, options = {})
515
- return unless shipping = options[:shipping_address]
516
-
517
- post[:shipping] = {}
518
-
519
- # fields required by Stripe PI
520
- post[:shipping][:address] = {}
521
- post[:shipping][:address][:line1] = shipping[:address1]
522
- post[:shipping][:name] = shipping[:name]
523
-
524
- # fields considered optional by Stripe PI
525
- post[:shipping][:address][:city] = shipping[:city] if shipping[:city]
526
- post[:shipping][:address][:country] = shipping[:country] if shipping[:country]
527
- post[:shipping][:address][:line2] = shipping[:address2] if shipping[:address2]
528
- post[:shipping][:address][:postal_code] = shipping[:zip] if shipping[:zip]
529
- post[:shipping][:address][:state] = shipping[:state] if shipping[:state]
530
- post[:shipping][:phone] = shipping[:phone_number] if shipping[:phone_number]
531
- post[:shipping][:carrier] = (shipping[:carrier] || options[:shipping_carrier]) if shipping[:carrier] || options[:shipping_carrier]
532
- post[:shipping][:tracking_number] = (shipping[:tracking_number] || options[:shipping_tracking_number]) if shipping[:tracking_number] || options[:shipping_tracking_number]
533
- end
534
-
535
578
  def format_idempotency_key(options, suffix)
536
579
  return options unless options[:idempotency_key]
537
580
 
@@ -9,7 +9,7 @@ module ActiveMerchant #:nodoc:
9
9
 
10
10
  self.supported_countries = ['PY']
11
11
  self.default_currency = 'PYG'
12
- self.supported_cardtypes = %i[visa master]
12
+ self.supported_cardtypes = %i[visa master panal]
13
13
 
14
14
  self.homepage_url = 'https://comercios.bancard.com.py'
15
15
  self.display_name = 'vPOS'
@@ -28,21 +28,6 @@ module ActiveMerchant #:nodoc:
28
28
  network_token: 'NETWORKTOKEN'
29
29
  }
30
30
 
31
- CARD_CODES = {
32
- 'visa' => 'VISA-SSL',
33
- 'master' => 'ECMC-SSL',
34
- 'discover' => 'DISCOVER-SSL',
35
- 'american_express' => 'AMEX-SSL',
36
- 'jcb' => 'JCB-SSL',
37
- 'maestro' => 'MAESTRO-SSL',
38
- 'diners_club' => 'DINERS-SSL',
39
- 'elo' => 'ELO-SSL',
40
- 'naranja' => 'NARANJA-SSL',
41
- 'cabal' => 'CABAL-SSL',
42
- 'unionpay' => 'CHINAUNIONPAY-SSL',
43
- 'unknown' => 'CARD-SSL'
44
- }
45
-
46
31
  AVS_CODE_MAP = {
47
32
  'A' => 'M', # Match
48
33
  'B' => 'P', # Postcode matches, address not verified
@@ -646,7 +631,7 @@ module ActiveMerchant #:nodoc:
646
631
  end
647
632
 
648
633
  def add_card_details(xml, payment_method, options)
649
- xml.tag! card_code_for(payment_method) do
634
+ xml.tag! 'CARD-SSL' do
650
635
  add_card(xml, payment_method, options)
651
636
  end
652
637
  end
@@ -683,7 +668,8 @@ module ActiveMerchant #:nodoc:
683
668
  'year' => format(payment_method.year, :four_digits_year)
684
669
  )
685
670
  end
686
- xml.cardHolderName card_holder_name(payment_method, options)
671
+ name = card_holder_name(payment_method, options)
672
+ xml.cardHolderName name if name.present?
687
673
  xml.cvc payment_method.verification_value
688
674
 
689
675
  add_address(xml, (options[:billing_address] || options[:address]), options)
@@ -995,13 +981,19 @@ module ActiveMerchant #:nodoc:
995
981
  case payment_method
996
982
  when String
997
983
  token_type_and_details(payment_method)
998
- when NetworkTokenizationCreditCard
999
- { payment_type: :network_token }
1000
984
  else
1001
- { payment_type: :credit }
985
+ type = network_token?(payment_method) ? :network_token : :credit
986
+
987
+ { payment_type: type }
1002
988
  end
1003
989
  end
1004
990
 
991
+ def network_token?(payment_method)
992
+ payment_method.respond_to?(:source) &&
993
+ payment_method.respond_to?(:payment_cryptogram) &&
994
+ payment_method.respond_to?(:eci)
995
+ end
996
+
1005
997
  def token_type_and_details(token)
1006
998
  token_details = token_details_from_authorization(token)
1007
999
  token_details[:payment_type] = token_details.has_key?(:token_id) ? :token : :pay_as_order
@@ -1027,10 +1019,6 @@ module ActiveMerchant #:nodoc:
1027
1019
  return 2
1028
1020
  end
1029
1021
 
1030
- def card_code_for(payment_method)
1031
- CARD_CODES[card_brand(payment_method)] || CARD_CODES['unknown']
1032
- end
1033
-
1034
1022
  def eligible_for_0_auth?(payment_method, options = {})
1035
1023
  payment_method.is_a?(CreditCard) && %w(visa master).include?(payment_method.brand) && options[:zero_dollar_auth]
1036
1024
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.129.0'
2
+ VERSION = '1.133.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemerchant
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.129.0
4
+ version: 1.133.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-03 00:00:00.000000000 Z
11
+ date: 2023-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -480,7 +480,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
480
480
  - !ruby/object:Gem::Version
481
481
  version: '0'
482
482
  requirements: []
483
- rubygems_version: 3.4.12
483
+ rubygems_version: 3.4.16
484
484
  signing_key:
485
485
  specification_version: 4
486
486
  summary: Framework and tools for dealing with credit card transactions.