activemerchant 1.119.0 → 1.124.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +216 -1
  3. data/README.md +4 -2
  4. data/lib/active_merchant/billing/check.rb +19 -12
  5. data/lib/active_merchant/billing/credit_card.rb +3 -0
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +32 -14
  8. data/lib/active_merchant/billing/gateways/adyen.rb +94 -25
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -11
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -0
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
  12. data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
  13. data/lib/active_merchant/billing/gateways/braintree_blue.rb +52 -8
  14. data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
  15. data/lib/active_merchant/billing/gateways/cashnet.rb +7 -2
  16. data/lib/active_merchant/billing/gateways/checkout_v2.rb +31 -0
  17. data/lib/active_merchant/billing/gateways/credorax.rb +15 -9
  18. data/lib/active_merchant/billing/gateways/cyber_source.rb +53 -6
  19. data/lib/active_merchant/billing/gateways/d_local.rb +9 -2
  20. data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
  21. data/lib/active_merchant/billing/gateways/elavon.rb +70 -28
  22. data/lib/active_merchant/billing/gateways/element.rb +2 -0
  23. data/lib/active_merchant/billing/gateways/forte.rb +12 -0
  24. data/lib/active_merchant/billing/gateways/global_collect.rb +24 -10
  25. data/lib/active_merchant/billing/gateways/hps.rb +55 -1
  26. data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
  27. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  28. data/lib/active_merchant/billing/gateways/mercado_pago.rb +5 -4
  29. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
  30. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  31. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  32. data/lib/active_merchant/billing/gateways/monei.rb +228 -144
  33. data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
  34. data/lib/active_merchant/billing/gateways/netbanx.rb +26 -2
  35. data/lib/active_merchant/billing/gateways/nmi.rb +27 -9
  36. data/lib/active_merchant/billing/gateways/orbital.rb +99 -59
  37. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  38. data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
  39. data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
  40. data/lib/active_merchant/billing/gateways/payeezy.rb +34 -6
  41. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  42. data/lib/active_merchant/billing/gateways/payflow.rb +21 -4
  43. data/lib/active_merchant/billing/gateways/payment_express.rb +5 -5
  44. data/lib/active_merchant/billing/gateways/paymentez.rb +5 -0
  45. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -0
  46. data/lib/active_merchant/billing/gateways/paysafe.rb +376 -0
  47. data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
  48. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  49. data/lib/active_merchant/billing/gateways/qvalent.rb +23 -9
  50. data/lib/active_merchant/billing/gateways/realex.rb +18 -0
  51. data/lib/active_merchant/billing/gateways/redsys.rb +42 -24
  52. data/lib/active_merchant/billing/gateways/safe_charge.rb +25 -13
  53. data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
  54. data/lib/active_merchant/billing/gateways/stripe.rb +18 -8
  55. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +126 -48
  56. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
  57. data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
  58. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
  59. data/lib/active_merchant/billing/gateways/vpos.rb +220 -0
  60. data/lib/active_merchant/billing/gateways/worldpay.rb +78 -18
  61. data/lib/active_merchant/billing/response.rb +4 -0
  62. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  63. data/lib/active_merchant/billing.rb +1 -0
  64. data/lib/active_merchant/version.rb +1 -1
  65. data/lib/certs/cacert.pem +1582 -2431
  66. metadata +11 -3
@@ -71,7 +71,7 @@ module ActiveMerchant #:nodoc:
71
71
  def capture(money, authorization, options = {})
72
72
  authorization = order_id_from_authorization(authorization.to_s)
73
73
  MultiResponse.run do |r|
74
- r.process { inquire_request(authorization, options, 'AUTHORISED') } unless options[:authorization_validated]
74
+ r.process { inquire_request(authorization, options, 'AUTHORISED', 'CAPTURED') } unless options[:authorization_validated]
75
75
  if r.params
76
76
  authorization_currency = r.params['amount_currency_code']
77
77
  options = options.merge(currency: authorization_currency) if authorization_currency.present?
@@ -90,8 +90,10 @@ module ActiveMerchant #:nodoc:
90
90
 
91
91
  def refund(money, authorization, options = {})
92
92
  authorization = order_id_from_authorization(authorization.to_s)
93
+ success_criteria = %w(CAPTURED SETTLED SETTLED_BY_MERCHANT SENT_FOR_REFUND)
94
+ success_criteria.push('AUTHORIZED') if options[:cancel_or_refund]
93
95
  response = MultiResponse.run do |r|
94
- r.process { inquire_request(authorization, options, 'CAPTURED', 'SETTLED', 'SETTLED_BY_MERCHANT') } unless options[:authorization_validated]
96
+ r.process { inquire_request(authorization, options, *success_criteria) } unless options[:authorization_validated]
95
97
  r.process { refund_request(money, authorization, options) }
96
98
  end
97
99
 
@@ -113,8 +115,9 @@ module ActiveMerchant #:nodoc:
113
115
  end
114
116
 
115
117
  def verify(payment_method, options = {})
118
+ amount = (eligible_for_0_auth?(payment_method, options) ? 0 : 100)
116
119
  MultiResponse.run(:use_first_response) do |r|
117
- r.process { authorize(100, payment_method, options) }
120
+ r.process { authorize(amount, payment_method, options) }
118
121
  r.process(:ignore_result) { void(r.authorization, options.merge(authorization_validated: true)) }
119
122
  end
120
123
  end
@@ -128,6 +131,10 @@ module ActiveMerchant #:nodoc:
128
131
  true
129
132
  end
130
133
 
134
+ def supports_network_tokenization?
135
+ true
136
+ end
137
+
131
138
  def scrub(transcript)
132
139
  transcript.
133
140
  gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
@@ -138,11 +145,11 @@ module ActiveMerchant #:nodoc:
138
145
  private
139
146
 
140
147
  def authorize_request(money, payment_method, options)
141
- commit('authorize', build_authorization_request(money, payment_method, options), 'AUTHORISED', options)
148
+ commit('authorize', build_authorization_request(money, payment_method, options), 'AUTHORISED', 'CAPTURED', options)
142
149
  end
143
150
 
144
151
  def capture_request(money, authorization, options)
145
- commit('capture', build_capture_request(money, authorization, options), :ok, options)
152
+ commit('capture', build_capture_request(money, authorization, options), 'CAPTURED', :ok, options)
146
153
  end
147
154
 
148
155
  def cancel_request(authorization, options)
@@ -154,7 +161,7 @@ module ActiveMerchant #:nodoc:
154
161
  end
155
162
 
156
163
  def refund_request(money, authorization, options)
157
- commit('refund', build_refund_request(money, authorization, options), :ok, options)
164
+ commit('refund', build_refund_request(money, authorization, options), :ok, 'SENT_FOR_REFUND', options)
158
165
  end
159
166
 
160
167
  def credit_request(money, payment_method, options)
@@ -206,7 +213,9 @@ module ActiveMerchant #:nodoc:
206
213
  end
207
214
  add_payment_method(xml, money, payment_method, options)
208
215
  add_shopper(xml, options)
216
+ add_statement_narrative(xml, options)
209
217
  add_risk_data(xml, options[:risk_data]) if options[:risk_data]
218
+ add_sub_merchant_data(xml, options[:sub_merchant_data]) if options[:sub_merchant_data]
210
219
  add_hcg_additional_data(xml, options) if options[:hcg_additional_data]
211
220
  add_instalments_data(xml, options) if options[:instalments]
212
221
  add_moto_flag(xml, options) if options.dig(:metadata, :manual_entry)
@@ -232,13 +241,22 @@ module ActiveMerchant #:nodoc:
232
241
  end
233
242
 
234
243
  def build_void_request(authorization, options)
235
- build_order_modify_request(authorization, &:cancel)
244
+ if options[:cancel_or_refund]
245
+ build_order_modify_request(authorization, &:cancelOrRefund)
246
+ else
247
+ build_order_modify_request(authorization, &:cancel)
248
+ end
236
249
  end
237
250
 
238
251
  def build_refund_request(money, authorization, options)
239
252
  build_order_modify_request(authorization) do |xml|
240
- xml.refund do
241
- add_amount(xml, money, options.merge(debit_credit_indicator: 'credit'))
253
+ if options[:cancel_or_refund]
254
+ # Worldpay docs claim amount must be passed. This causes an error.
255
+ xml.cancelOrRefund # { add_amount(xml, money, options.merge(debit_credit_indicator: 'credit')) }
256
+ else
257
+ xml.refund do
258
+ add_amount(xml, money, options.merge(debit_credit_indicator: 'credit'))
259
+ end
242
260
  end
243
261
  end
244
262
  end
@@ -297,6 +315,20 @@ module ActiveMerchant #:nodoc:
297
315
  end
298
316
  end
299
317
 
318
+ def add_sub_merchant_data(xml, options)
319
+ xml.subMerchantData do
320
+ xml.pfId options[:pf_id] if options[:pf_id]
321
+ xml.subName options[:sub_name] if options[:sub_name]
322
+ xml.subId options[:sub_id] if options[:sub_id]
323
+ xml.subStreet options[:sub_street] if options[:sub_street]
324
+ xml.subCity options[:sub_city] if options[:sub_city]
325
+ xml.subState options[:sub_state] if options[:sub_state]
326
+ xml.subCountryCode options[:sub_country_code] if options[:sub_country_code]
327
+ xml.subPostalCode options[:sub_postal_code] if options[:sub_postal_code]
328
+ xml.subTaxId options[:sub_tax_id] if options[:sub_tax_id]
329
+ end
330
+ end
331
+
300
332
  def add_shopper_account_risk_data(xml, shopper_account_risk_data)
301
333
  return unless shopper_account_risk_data
302
334
 
@@ -381,6 +413,8 @@ module ActiveMerchant #:nodoc:
381
413
  add_amount(xml, amount, options)
382
414
  end
383
415
  end
416
+ elsif options[:payment_type] == :network_token
417
+ add_network_tokenization_card(xml, payment_method)
384
418
  else
385
419
  xml.paymentDetails credit_fund_transfer_attribute(options) do
386
420
  if options[:payment_type] == :token
@@ -399,7 +433,6 @@ module ActiveMerchant #:nodoc:
399
433
  xml.session 'shopperIPAddress' => options[:ip] if options[:ip]
400
434
  xml.session 'id' => options[:session_id] if options[:session_id]
401
435
  end
402
-
403
436
  if three_d_secure = options[:three_d_secure]
404
437
  add_three_d_secure(three_d_secure, xml)
405
438
  end
@@ -407,10 +440,26 @@ module ActiveMerchant #:nodoc:
407
440
  end
408
441
  end
409
442
 
443
+ def add_network_tokenization_card(xml, payment_method)
444
+ xml.paymentDetails do
445
+ xml.tag! 'EMVCO_TOKEN-SSL', 'type' => 'NETWORKTOKEN' do
446
+ xml.tokenNumber payment_method.number
447
+ xml.expiryDate do
448
+ xml.date(
449
+ 'month' => format(payment_method.month, :two_digits),
450
+ 'year' => format(payment_method.year, :four_digits_year)
451
+ )
452
+ end
453
+ xml.cryptogram payment_method.payment_cryptogram
454
+ xml.eciIndicator format(payment_method.eci, :two_digits)
455
+ end
456
+ end
457
+ end
458
+
410
459
  def add_three_d_secure(three_d_secure, xml)
411
460
  xml.info3DSecure do
412
461
  xml.threeDSVersion three_d_secure[:version]
413
- if /^2/.match?(three_d_secure[:version])
462
+ if three_d_secure[:version] && three_d_secure[:ds_transaction_id]
414
463
  xml.dsTransactionId three_d_secure[:ds_transaction_id]
415
464
  else
416
465
  xml.xid three_d_secure[:xid]
@@ -425,11 +474,11 @@ module ActiveMerchant #:nodoc:
425
474
  xml.expiryDate do
426
475
  xml.date(
427
476
  'month' => format(payment_method.month, :two_digits),
428
- 'year' => format(payment_method.year, :four_digits)
477
+ 'year' => format(payment_method.year, :four_digits_year)
429
478
  )
430
479
  end
431
480
 
432
- card_holder_name = options[:execute_threed] && !options[:three_ds_version]&.start_with?('2') ? '3D' : payment_method.name
481
+ card_holder_name = test? && options[:execute_threed] && !options[:three_ds_version]&.start_with?('2') ? '3D' : payment_method.name
433
482
  xml.cardHolderName card_holder_name
434
483
  xml.cvc payment_method.verification_value
435
484
 
@@ -485,6 +534,10 @@ module ActiveMerchant #:nodoc:
485
534
  end
486
535
  end
487
536
 
537
+ def add_statement_narrative(xml, options)
538
+ xml.statementNarrative truncate(options[:statement_narrative], 50) if options[:statement_narrative]
539
+ end
540
+
488
541
  def add_authenticated_shopper_id(xml, options)
489
542
  xml.authenticatedShopperID options[:customer] if options[:customer]
490
543
  end
@@ -538,11 +591,10 @@ module ActiveMerchant #:nodoc:
538
591
 
539
592
  def default_address
540
593
  {
541
- address1: 'N/A',
542
594
  zip: '0000',
595
+ country: 'US',
543
596
  city: 'N/A',
544
- state: 'N/A',
545
- country: 'US'
597
+ address1: 'N/A'
546
598
  }
547
599
  end
548
600
 
@@ -654,7 +706,9 @@ module ActiveMerchant #:nodoc:
654
706
  # - An array of strings if one of many responses could be considered a
655
707
  # success.
656
708
  def success_criteria_success?(raw, success_criteria)
657
- success_criteria.include?(raw[:last_event]) || raw[:ok].present?
709
+ return if raw[:error]
710
+
711
+ raw[:ok].present? || (success_criteria.include?(raw[:last_event]) if raw[:last_event])
658
712
  end
659
713
 
660
714
  def action_success?(action, raw)
@@ -717,7 +771,9 @@ module ActiveMerchant #:nodoc:
717
771
 
718
772
  def payment_details_from(payment_method)
719
773
  payment_details = {}
720
- if payment_method.respond_to?(:number)
774
+ if payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :network_token
775
+ payment_details[:payment_type] = :network_token
776
+ elsif payment_method.respond_to?(:number)
721
777
  payment_details[:payment_type] = :credit
722
778
  else
723
779
  token_details = token_details_from_authorization(payment_method)
@@ -753,6 +809,10 @@ module ActiveMerchant #:nodoc:
753
809
  def card_code_for(payment_method)
754
810
  CARD_CODES[card_brand(payment_method)] || CARD_CODES['unknown']
755
811
  end
812
+
813
+ def eligible_for_0_auth?(payment_method, options = {})
814
+ payment_method.is_a?(CreditCard) && %w(visa master).include?(payment_method.brand) && options[:zero_dollar_auth]
815
+ end
756
816
  end
757
817
  end
758
818
  end
@@ -10,6 +10,10 @@ module ActiveMerchant #:nodoc:
10
10
  @success
11
11
  end
12
12
 
13
+ def failure?
14
+ !success?
15
+ end
16
+
13
17
  def test?
14
18
  @test
15
19
  end
@@ -0,0 +1,27 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ module ThreeDSecureEciMapper
4
+ NON_THREE_D_SECURE_TRANSACTION = :non_three_d_secure_transaction
5
+ ATTEMPTED_AUTHENTICATION_TRANSACTION = :attempted_authentication_transaction
6
+ FULLY_AUTHENTICATED_TRANSACTION = :fully_authenticated_transaction
7
+
8
+ ECI_00_01_02_MAP = { '00' => NON_THREE_D_SECURE_TRANSACTION, '01' => ATTEMPTED_AUTHENTICATION_TRANSACTION, '02' => FULLY_AUTHENTICATED_TRANSACTION }.freeze
9
+ ECI_05_06_07_MAP = { '05' => FULLY_AUTHENTICATED_TRANSACTION, '06' => ATTEMPTED_AUTHENTICATION_TRANSACTION, '07' => NON_THREE_D_SECURE_TRANSACTION }.freeze
10
+ BRAND_TO_ECI_MAP = {
11
+ american_express: ECI_05_06_07_MAP,
12
+ dankort: ECI_05_06_07_MAP,
13
+ diners_club: ECI_05_06_07_MAP,
14
+ discover: ECI_05_06_07_MAP,
15
+ elo: ECI_05_06_07_MAP,
16
+ jcb: ECI_05_06_07_MAP,
17
+ maestro: ECI_00_01_02_MAP,
18
+ master: ECI_00_01_02_MAP,
19
+ visa: ECI_05_06_07_MAP
20
+ }.freeze
21
+
22
+ def self.map(brand, eci)
23
+ BRAND_TO_ECI_MAP.dig(brand, eci)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -13,3 +13,4 @@ require 'active_merchant/billing/apple_pay_payment_token'
13
13
  require 'active_merchant/billing/response'
14
14
  require 'active_merchant/billing/gateways'
15
15
  require 'active_merchant/billing/gateway'
16
+ require 'active_merchant/billing/three_d_secure_eci_mapper'
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.119.0'
2
+ VERSION = '1.124.0'
3
3
  end