activemerchant 1.133.0 → 1.137.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +240 -0
  3. data/lib/active_merchant/billing/check.rb +2 -2
  4. data/lib/active_merchant/billing/compatibility.rb +4 -4
  5. data/lib/active_merchant/billing/credit_card.rb +11 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +59 -6
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +162 -43
  10. data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
  11. data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
  12. data/lib/active_merchant/billing/gateways/authorize_net.rb +43 -35
  13. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
  14. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
  15. data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
  16. data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
  17. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
  18. data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
  19. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  20. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
  21. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  22. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  24. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  25. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  26. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  29. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  30. data/lib/active_merchant/billing/gateways/checkout_v2.rb +238 -34
  31. data/lib/active_merchant/billing/gateways/commerce_hub.rb +63 -6
  32. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  33. data/lib/active_merchant/billing/gateways/cyber_source.rb +185 -47
  34. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  35. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  36. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  37. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  38. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  39. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  40. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  41. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  42. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  43. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  44. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  45. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  46. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  48. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  49. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  51. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  52. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  55. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  56. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  57. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  58. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  59. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  60. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  61. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  62. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  63. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  64. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  65. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  66. data/lib/active_merchant/billing/gateways/ipg.rb +9 -5
  67. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  68. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  69. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  70. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  71. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  72. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/kushki.rb +72 -12
  74. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  75. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  76. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  77. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  78. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  79. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  80. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  82. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  83. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  84. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  85. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  86. data/lib/active_merchant/billing/gateways/mit.rb +8 -3
  87. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  88. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  89. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  90. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  91. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  92. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  93. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  94. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  95. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/nmi.rb +18 -6
  97. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  98. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  99. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  100. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  101. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  102. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  103. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  104. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  105. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  106. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  107. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  109. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  110. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  111. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  112. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  113. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  114. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  115. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  116. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  117. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  118. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  119. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +2 -2
  120. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  121. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  122. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  123. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  124. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  125. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  129. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  131. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  132. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  133. data/lib/active_merchant/billing/gateways/redsys.rb +2 -10
  134. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  135. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  136. data/lib/active_merchant/billing/gateways/safe_charge.rb +36 -16
  137. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  138. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  139. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  140. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  142. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  143. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  144. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  145. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  146. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  147. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  148. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  149. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  150. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  151. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  152. data/lib/active_merchant/billing/gateways/stripe.rb +53 -21
  153. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +199 -50
  154. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  155. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  156. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  157. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  158. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  159. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  160. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  161. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  162. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  163. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  164. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  165. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  166. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  168. data/lib/active_merchant/billing/gateways/vpos.rb +3 -3
  169. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  170. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  171. data/lib/active_merchant/billing/gateways/worldpay.rb +140 -73
  172. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  173. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  174. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  175. data/lib/active_merchant/billing/response.rb +2 -2
  176. data/lib/active_merchant/connection.rb +3 -17
  177. data/lib/active_merchant/country.rb +1 -0
  178. data/lib/active_merchant/errors.rb +10 -0
  179. data/lib/active_merchant/version.rb +1 -1
  180. data/lib/support/gateway_support.rb +2 -2
  181. data/lib/support/ssl_verify.rb +4 -4
  182. data/lib/support/ssl_version.rb +6 -6
  183. metadata +30 -9
@@ -70,6 +70,7 @@ module ActiveMerchant #:nodoc:
70
70
  add_level_3_data(post, options)
71
71
  add_data_airline(post, options)
72
72
  add_data_lodging(post, options)
73
+ add_metadata(post, options)
73
74
  commit('authorise', post, options)
74
75
  end
75
76
 
@@ -93,12 +94,28 @@ module ActiveMerchant #:nodoc:
93
94
  end
94
95
 
95
96
  def credit(money, payment, options = {})
96
- action = 'refundWithData'
97
+ action = options[:payout] ? 'payout' : 'refundWithData'
97
98
  post = init_post(options)
98
99
  add_invoice(post, money, options)
99
100
  add_payment(post, payment, options, action)
100
101
  add_shopper_reference(post, options)
101
102
  add_network_transaction_reference(post, options)
103
+
104
+ if action == 'payout'
105
+ add_shopper_interaction(post, payment, options)
106
+ add_fraud_offset(post, options)
107
+ add_fund_source(post, options)
108
+ add_recurring_contract(post, options)
109
+ add_shopper_data(post, payment, options)
110
+
111
+ if (address = options[:billing_address] || options[:address]) && address[:country]
112
+ add_billing_address(post, options, address)
113
+ end
114
+
115
+ post[:dateOfBirth] = options[:date_of_birth] if options[:date_of_birth]
116
+ post[:nationality] = options[:nationality] if options[:nationality]
117
+ end
118
+
102
119
  commit(action, post, options)
103
120
  end
104
121
 
@@ -230,12 +247,30 @@ module ActiveMerchant #:nodoc:
230
247
 
231
248
  def add_extra_data(post, payment, options)
232
249
  post[:telephoneNumber] = (options[:billing_address][:phone_number] if options.dig(:billing_address, :phone_number)) || (options[:billing_address][:phone] if options.dig(:billing_address, :phone)) || ''
233
- post[:fraudOffset] = options[:fraud_offset] if options[:fraud_offset]
234
250
  post[:selectedBrand] = options[:selected_brand] if options[:selected_brand]
235
251
  post[:selectedBrand] ||= NETWORK_TOKENIZATION_CARD_SOURCE[payment.source.to_s] if payment.is_a?(NetworkTokenizationCreditCard)
236
252
  post[:deliveryDate] = options[:delivery_date] if options[:delivery_date]
237
253
  post[:merchantOrderReference] = options[:merchant_order_reference] if options[:merchant_order_reference]
238
254
  post[:captureDelayHours] = options[:capture_delay_hours] if options[:capture_delay_hours]
255
+ post[:deviceFingerprint] = options[:device_fingerprint] if options[:device_fingerprint]
256
+ post[:shopperIP] = options[:shopper_ip] || options[:ip] if options[:shopper_ip] || options[:ip]
257
+ post[:shopperStatement] = options[:shopper_statement] if options[:shopper_statement]
258
+ post[:store] = options[:store] if options[:store]
259
+ post[:mcc] = options[:mcc] if options[:mcc]
260
+
261
+ add_shopper_data(post, payment, options)
262
+ add_additional_data(post, payment, options)
263
+ add_risk_data(post, options)
264
+ add_shopper_reference(post, options)
265
+ add_merchant_data(post, options)
266
+ add_fraud_offset(post, options)
267
+ end
268
+
269
+ def add_fraud_offset(post, options)
270
+ post[:fraudOffset] = options[:fraud_offset] if options[:fraud_offset]
271
+ end
272
+
273
+ def add_additional_data(post, payment, options)
239
274
  post[:additionalData] ||= {}
240
275
  post[:additionalData][:overwriteBrand] = normalize(options[:overwrite_brand]) if options[:overwrite_brand]
241
276
  post[:additionalData][:customRoutingFlag] = options[:custom_routing_flag] if options[:custom_routing_flag]
@@ -244,11 +279,7 @@ module ActiveMerchant #:nodoc:
244
279
  post[:additionalData][:adjustAuthorisationData] = options[:adjust_authorisation_data] if options[:adjust_authorisation_data]
245
280
  post[:additionalData][:industryUsage] = options[:industry_usage] if options[:industry_usage]
246
281
  post[:additionalData][:RequestedTestAcquirerResponseCode] = options[:requested_test_acquirer_response_code] if options[:requested_test_acquirer_response_code] && test?
247
- post[:deviceFingerprint] = options[:device_fingerprint] if options[:device_fingerprint]
248
- add_shopper_data(post, options)
249
- add_risk_data(post, options)
250
- add_shopper_reference(post, options)
251
- add_merchant_data(post, options)
282
+ post[:additionalData][:updateShopperStatement] = options[:update_shopper_statement] if options[:update_shopper_statement]
252
283
  end
253
284
 
254
285
  def extract_and_transform(mapper, from)
@@ -371,15 +402,6 @@ module ActiveMerchant #:nodoc:
371
402
  post[:additionalData].compact!
372
403
  end
373
404
 
374
- def add_shopper_data(post, options)
375
- post[:shopperEmail] = options[:email] if options[:email]
376
- post[:shopperEmail] = options[:shopper_email] if options[:shopper_email]
377
- post[:shopperIP] = options[:ip] if options[:ip]
378
- post[:shopperIP] = options[:shopper_ip] if options[:shopper_ip]
379
- post[:shopperStatement] = options[:shopper_statement] if options[:shopper_statement]
380
- post[:additionalData][:updateShopperStatement] = options[:update_shopper_statement] if options[:update_shopper_statement]
381
- end
382
-
383
405
  def add_shopper_statement(post, options)
384
406
  return unless options[:shopper_statement]
385
407
 
@@ -403,7 +425,7 @@ module ActiveMerchant #:nodoc:
403
425
 
404
426
  def add_risk_data(post, options)
405
427
  if (risk_data = options[:risk_data])
406
- risk_data = Hash[risk_data.map { |k, v| ["riskdata.#{k}", v] }]
428
+ risk_data = risk_data.map { |k, v| ["riskdata.#{k}", v] }.to_h
407
429
  post[:additionalData].merge!(risk_data)
408
430
  end
409
431
  end
@@ -473,30 +495,39 @@ module ActiveMerchant #:nodoc:
473
495
  def add_address(post, options)
474
496
  if address = options[:shipping_address]
475
497
  post[:deliveryAddress] = {}
476
- post[:deliveryAddress][:street] = address[:address1] || 'NA'
477
- post[:deliveryAddress][:houseNumberOrName] = address[:address2] || 'NA'
498
+ post[:deliveryAddress][:street] = options[:address_override] == true ? address[:address2] : address[:address1] || 'NA'
499
+ post[:deliveryAddress][:houseNumberOrName] = options[:address_override] == true ? address[:address1] : address[:address2] || 'NA'
478
500
  post[:deliveryAddress][:postalCode] = address[:zip] if address[:zip]
479
501
  post[:deliveryAddress][:city] = address[:city] || 'NA'
480
502
  post[:deliveryAddress][:stateOrProvince] = get_state(address)
481
- post[:deliveryAddress][:country] = address[:country] if address[:country]
503
+ post[:deliveryAddress][:country] = get_country(address)
482
504
  end
483
505
  return unless post[:bankAccount]&.kind_of?(Hash) || post[:card]&.kind_of?(Hash)
484
506
 
485
507
  if (address = options[:billing_address] || options[:address]) && address[:country]
486
- post[:billingAddress] = {}
487
- post[:billingAddress][:street] = address[:address1] || 'NA'
488
- post[:billingAddress][:houseNumberOrName] = address[:address2] || 'NA'
489
- post[:billingAddress][:postalCode] = address[:zip] if address[:zip]
490
- post[:billingAddress][:city] = address[:city] || 'NA'
491
- post[:billingAddress][:stateOrProvince] = get_state(address)
492
- post[:billingAddress][:country] = address[:country] if address[:country]
508
+ add_billing_address(post, options, address)
493
509
  end
494
510
  end
495
511
 
512
+ def add_billing_address(post, options, address)
513
+ post[:billingAddress] = {}
514
+ post[:billingAddress][:street] = options[:address_override] == true ? address[:address2] : address[:address1] || 'NA'
515
+ post[:billingAddress][:houseNumberOrName] = options[:address_override] == true ? address[:address1] : address[:address2] || 'NA'
516
+ post[:billingAddress][:postalCode] = address[:zip] if address[:zip]
517
+ post[:billingAddress][:city] = address[:city] || 'NA'
518
+ post[:billingAddress][:stateOrProvince] = get_state(address)
519
+ post[:billingAddress][:country] = get_country(address)
520
+ post[:telephoneNumber] = address[:phone_number] || address[:phone] || ''
521
+ end
522
+
496
523
  def get_state(address)
497
524
  address[:state] && !address[:state].blank? ? address[:state] : 'NA'
498
525
  end
499
526
 
527
+ def get_country(address)
528
+ address[:country].present? ? address[:country] : 'ZZ'
529
+ end
530
+
500
531
  def add_invoice(post, money, options)
501
532
  currency = options[:currency] || currency(money)
502
533
  amount = {
@@ -557,6 +588,17 @@ module ActiveMerchant #:nodoc:
557
588
  post[:card] = card
558
589
  end
559
590
 
591
+ def add_shopper_data(post, payment, options)
592
+ if payment && !payment.is_a?(String)
593
+ post[:shopperName] = {}
594
+ post[:shopperName][:firstName] = payment.first_name
595
+ post[:shopperName][:lastName] = payment.last_name
596
+ end
597
+
598
+ post[:shopperEmail] = options[:email] if options[:email]
599
+ post[:shopperEmail] = options[:shopper_email] if options[:shopper_email]
600
+ end
601
+
560
602
  def capture_options(options)
561
603
  return options.merge(idempotency_key: "#{options[:idempotency_key]}-cap") if options[:idempotency_key]
562
604
 
@@ -588,11 +630,12 @@ module ActiveMerchant #:nodoc:
588
630
  def add_recurring_contract(post, options = {})
589
631
  return unless options[:recurring_contract_type]
590
632
 
591
- recurring = {
592
- contract: options[:recurring_contract_type]
593
- }
594
-
595
- post[:recurring] = recurring
633
+ post[:recurring] = {}
634
+ post[:recurring][:contract] = options[:recurring_contract_type]
635
+ post[:recurring][:recurringDetailName] = options[:recurring_detail_name] if options[:recurring_detail_name]
636
+ post[:recurring][:recurringExpiry] = options[:recurring_expiry] if options[:recurring_expiry]
637
+ post[:recurring][:recurringFrequency] = options[:recurring_frequency] if options[:recurring_frequency]
638
+ post[:recurring][:tokenService] = options[:token_service] if options[:token_service]
596
639
  end
597
640
 
598
641
  def add_application_info(post, options)
@@ -688,10 +731,58 @@ module ActiveMerchant #:nodoc:
688
731
  }
689
732
  end
690
733
 
734
+ def add_fund_source(post, options)
735
+ return unless fund_source = options[:fund_source]
736
+
737
+ post[:fundSource] = {}
738
+ post[:fundSource][:additionalData] = fund_source[:additional_data] if fund_source[:additional_data]
739
+
740
+ if fund_source[:first_name] && fund_source[:last_name]
741
+ post[:fundSource][:shopperName] = {}
742
+ post[:fundSource][:shopperName][:firstName] = fund_source[:first_name]
743
+ post[:fundSource][:shopperName][:lastName] = fund_source[:last_name]
744
+ end
745
+
746
+ if (address = fund_source[:billing_address])
747
+ add_billing_address(post[:fundSource], options, address)
748
+ end
749
+ end
750
+
751
+ def add_metadata(post, options = {})
752
+ return unless options[:metadata]
753
+
754
+ post[:metadata] ||= {}
755
+ post[:metadata].merge!(options[:metadata]) if options[:metadata]
756
+ end
757
+
758
+ def add_header_fields(response)
759
+ return unless @response_headers.present?
760
+
761
+ headers = {}
762
+ headers['response_headers'] = {}
763
+ headers['response_headers']['transient_error'] = @response_headers['transient-error'] if @response_headers['transient-error']
764
+
765
+ response.merge!(headers)
766
+ end
767
+
691
768
  def parse(body)
692
769
  return {} if body.blank?
693
770
 
694
- JSON.parse(body)
771
+ response = JSON.parse(body)
772
+ add_header_fields(response)
773
+ response
774
+ end
775
+
776
+ # Override the regular handle response so we can access the headers
777
+ # set header fields and values so we can add them to the response body
778
+ def handle_response(response)
779
+ @response_headers = response.each_header.to_h if response.respond_to?(:header)
780
+ case response.code.to_i
781
+ when 200...300
782
+ response.body
783
+ else
784
+ raise ResponseError.new(response)
785
+ end
695
786
  end
696
787
 
697
788
  def commit(action, parameters, options)
@@ -706,7 +797,7 @@ module ActiveMerchant #:nodoc:
706
797
  success = success_from(action, response, options)
707
798
  Response.new(
708
799
  success,
709
- message_from(action, response),
800
+ message_from(action, response, options),
710
801
  response,
711
802
  authorization: authorization_from(action, parameters, response),
712
803
  test: test?,
@@ -726,8 +817,14 @@ module ActiveMerchant #:nodoc:
726
817
  end
727
818
 
728
819
  def endpoint(action)
729
- recurring = %w(disable storeToken).include?(action)
730
- recurring ? "Recurring/#{RECURRING_API_VERSION}/#{action}" : "Payment/#{PAYMENT_API_VERSION}/#{action}"
820
+ case action
821
+ when 'disable', 'storeToken'
822
+ "Recurring/#{RECURRING_API_VERSION}/#{action}"
823
+ when 'payout'
824
+ "Payout/#{PAYMENT_API_VERSION}/#{action}"
825
+ else
826
+ "Payment/#{PAYMENT_API_VERSION}/#{action}"
827
+ end
731
828
  end
732
829
 
733
830
  def url(action)
@@ -754,7 +851,7 @@ module ActiveMerchant #:nodoc:
754
851
  end
755
852
 
756
853
  def success_from(action, response, options)
757
- if %w[RedirectShopper ChallengeShopper].include?(response.dig('resultCode')) && !options[:execute_threed] && !options[:threed_dynamic]
854
+ if %w[RedirectShopper ChallengeShopper].include?(response.dig('resultCode')) && !options[:execute_threed] && (!options[:threed_dynamic] || options[:ignore_threed_dynamic])
758
855
  response['refusalReason'] = 'Received unexpected 3DS authentication response, but a 3DS initiation flag was not included in the request.'
759
856
  return false
760
857
  end
@@ -771,18 +868,29 @@ module ActiveMerchant #:nodoc:
771
868
  response['response'] == '[detail-successfully-disabled]'
772
869
  when 'refundWithData'
773
870
  response['resultCode'] == 'Received'
871
+ when 'payout'
872
+ return false unless response['resultCode'] && response['authCode']
873
+
874
+ %[AuthenticationFinished Authorised Received].include?(response['resultCode'])
774
875
  else
775
876
  false
776
877
  end
777
878
  end
778
879
 
779
- def message_from(action, response)
780
- return authorize_message_from(response) if %w(authorise authorise3d authorise3ds2).include?(action.to_s)
781
-
782
- response['response'] || response['message'] || response['result'] || response['resultCode']
880
+ def message_from(action, response, options = {})
881
+ case action.to_s
882
+ when 'authorise', 'authorise3d', 'authorise3ds2'
883
+ authorize_message_from(response, options)
884
+ when 'payout'
885
+ response['refusalReason'] || response['resultCode'] || response['message']
886
+ else
887
+ response['response'] || response['message'] || response['result'] || response['resultCode']
888
+ end
783
889
  end
784
890
 
785
- def authorize_message_from(response)
891
+ def authorize_message_from(response, options = {})
892
+ return raw_authorize_error_message(response) if options[:raw_error_message]
893
+
786
894
  if response['refusalReason'] && response['additionalData'] && (response['additionalData']['merchantAdviceCode'] || response['additionalData']['refusalReasonRaw'])
787
895
  "#{response['refusalReason']} | #{response['additionalData']['merchantAdviceCode'] || response['additionalData']['refusalReasonRaw']}"
788
896
  else
@@ -790,6 +898,14 @@ module ActiveMerchant #:nodoc:
790
898
  end
791
899
  end
792
900
 
901
+ def raw_authorize_error_message(response)
902
+ if response['refusalReason'] && response['additionalData'] && response['additionalData']['refusalReasonRaw']
903
+ "#{response['refusalReason']} | #{response['additionalData']['refusalReasonRaw']}"
904
+ else
905
+ response['refusalReason'] || response['resultCode'] || response['message'] || response['result']
906
+ end
907
+ end
908
+
793
909
  def authorization_from(action, parameters, response)
794
910
  return nil if response['pspReference'].nil?
795
911
 
@@ -811,7 +927,10 @@ module ActiveMerchant #:nodoc:
811
927
  end
812
928
 
813
929
  def error_code_from(response)
814
- STANDARD_ERROR_CODE_MAPPING[response['errorCode']] || response['errorCode']
930
+ response.dig('additionalData', 'refusalReasonRaw').try(:match, /^([a-zA-Z0-9 ]{1,5})(?=:)/).try(:[], 1).try(:strip) ||
931
+ STANDARD_ERROR_CODE_MAPPING[response['errorCode']] ||
932
+ response['errorCode'] ||
933
+ response['refusalReason']
815
934
  end
816
935
 
817
936
  def network_transaction_id_from(response)
@@ -32,7 +32,7 @@ module ActiveMerchant #:nodoc:
32
32
  @client_id = options[:client_id]
33
33
  @client_api_key = options[:client_api_key]
34
34
  super
35
- @access_token = setup_access_token
35
+ @access_token = options[:access_token] || setup_access_token
36
36
  end
37
37
 
38
38
  def purchase(money, card, options = {})
@@ -133,13 +133,27 @@ module ActiveMerchant #:nodoc:
133
133
  'x-client-id' => @client_id,
134
134
  'x-api-key' => @client_api_key
135
135
  }
136
- response = ssl_post(build_request_url(:login), nil, token_headers)
137
- JSON.parse(response)['token']
136
+
137
+ begin
138
+ raw_response = ssl_post(build_request_url(:login), nil, token_headers)
139
+ rescue ResponseError => e
140
+ raise OAuthResponseError.new(e)
141
+ else
142
+ response = JSON.parse(raw_response)
143
+ if (token = response['token'])
144
+ token
145
+ else
146
+ oauth_response = Response.new(false, response['message'])
147
+ raise OAuthResponseError.new(oauth_response)
148
+ end
149
+ end
138
150
  end
139
151
 
140
152
  def build_request_url(action, id = nil)
141
153
  base_url = (test? ? test_url : live_url)
142
- base_url + ENDPOINTS[action].to_s % { id: id }
154
+ endpoint = ENDPOINTS[action].to_s
155
+ endpoint = id.present? ? endpoint % { id: id } : endpoint
156
+ base_url + endpoint
143
157
  end
144
158
 
145
159
  def add_referrer_data(post)
@@ -278,11 +292,11 @@ module ActiveMerchant #:nodoc:
278
292
  pm_options = post.dig('payment_method_options', 'card')
279
293
 
280
294
  external_three_ds = {
281
- 'version': format_three_ds_version(three_d_secure),
282
- 'eci': three_d_secure[:eci]
295
+ version: format_three_ds_version(three_d_secure),
296
+ eci: three_d_secure[:eci]
283
297
  }.merge(three_ds_version_specific_fields(three_d_secure))
284
298
 
285
- pm_options ? pm_options.merge!('external_three_ds': external_three_ds) : post['payment_method_options'] = { 'card': { 'external_three_ds': external_three_ds } }
299
+ pm_options ? pm_options.merge!(external_three_ds: external_three_ds) : post['payment_method_options'] = { card: { external_three_ds: external_three_ds } }
286
300
  end
287
301
 
288
302
  def format_three_ds_version(three_d_secure)
@@ -295,14 +309,14 @@ module ActiveMerchant #:nodoc:
295
309
  def three_ds_version_specific_fields(three_d_secure)
296
310
  if three_d_secure[:version].to_f >= 2
297
311
  {
298
- 'authentication_value': three_d_secure[:cavv],
299
- 'ds_transaction_id': three_d_secure[:ds_transaction_id],
300
- 'three_ds_server_transaction_id': three_d_secure[:three_ds_server_trans_id]
312
+ authentication_value: three_d_secure[:cavv],
313
+ ds_transaction_id: three_d_secure[:ds_transaction_id],
314
+ three_ds_server_transaction_id: three_d_secure[:three_ds_server_trans_id]
301
315
  }
302
316
  else
303
317
  {
304
- 'cavv': three_d_secure[:cavv],
305
- 'xid': three_d_secure[:xid]
318
+ cavv: three_d_secure[:cavv],
319
+ xid: three_d_secure[:xid]
306
320
  }
307
321
  end
308
322
  end
@@ -110,8 +110,18 @@ module ActiveMerchant #:nodoc:
110
110
  'Content-Type' => 'application/x-www-form-urlencoded'
111
111
  }
112
112
 
113
- parsed = parse(ssl_post(url('captura-oauth-provider/oauth/token'), post_data(params), headers))
114
- Response.new(true, parsed[:access_token], parsed)
113
+ begin
114
+ raw_response = ssl_post(url('captura-oauth-provider/oauth/token'), post_data(params), headers)
115
+ rescue ResponseError => e
116
+ raise OAuthResponseError.new(e)
117
+ else
118
+ response = parse(raw_response)
119
+ if (access_token = response[:access_token])
120
+ Response.new(true, access_token, response)
121
+ else
122
+ raise OAuthResponseError.new(response)
123
+ end
124
+ end
115
125
  end
116
126
 
117
127
  def remote_encryption_key(access_token)
@@ -144,9 +154,11 @@ module ActiveMerchant #:nodoc:
144
154
  access_token: access_token,
145
155
  multiresp: multiresp.responses.present? ? multiresp : nil
146
156
  }
147
- rescue ResponseError => error
157
+ rescue ActiveMerchant::OAuthResponseError => e
158
+ raise e
159
+ rescue ResponseError => e
148
160
  # retry to generate a new access_token when the provided one is expired
149
- raise error unless try_again && %w(401 404).include?(error.response.code) && @options[:access_token].present?
161
+ raise e unless retry?(try_again, e, :access_token)
150
162
 
151
163
  @options.delete(:access_token)
152
164
  @options.delete(:encryption_key)
@@ -206,9 +218,11 @@ module ActiveMerchant #:nodoc:
206
218
  multiresp.process { resp }
207
219
 
208
220
  multiresp
221
+ rescue ActiveMerchant::OAuthResponseError => e
222
+ raise OAuthResponseError.new(e)
209
223
  rescue ActiveMerchant::ResponseError => e
210
224
  # Retry on a possible expired encryption key
211
- if try_again && %w(401 404).include?(e.response.code) && @options[:encryption_key].present?
225
+ if retry?(try_again, e, :encryption_key)
212
226
  @options.delete(:encryption_key)
213
227
  commit(action, body, options, false)
214
228
  else
@@ -217,6 +231,10 @@ module ActiveMerchant #:nodoc:
217
231
  end
218
232
  end
219
233
 
234
+ def retry?(try_again, error, key)
235
+ try_again && %w(401 404).include?(error.response.code) && @options[key].present?
236
+ end
237
+
220
238
  def success_from(action, response)
221
239
  case action
222
240
  when 'capture/transaction/refund'
@@ -85,11 +85,10 @@ module ActiveMerchant
85
85
  AVS_REASON_CODES = %w(27 45)
86
86
 
87
87
  TRACKS = {
88
- 1 => /^%(?<format_code>.)(?<pan>[\d]{1,19}+)\^(?<name>.{2,26})\^(?<expiration>[\d]{0,4}|\^)(?<service_code>[\d]{0,3}|\^)(?<discretionary_data>.*)\?\Z/,
89
- 2 => /\A;(?<pan>[\d]{1,19}+)=(?<expiration>[\d]{0,4}|=)(?<service_code>[\d]{0,3}|=)(?<discretionary_data>.*)\?\Z/
88
+ 1 => /^%(?<format_code>.)(?<pan>\d{1,19}+)\^(?<name>.{2,26})\^(?<expiration>\d{0,4}|\^)(?<service_code>\d{0,3}|\^)(?<discretionary_data>.*)\?\Z/,
89
+ 2 => /\A;(?<pan>\d{1,19}+)=(?<expiration>\d{0,4}|=)(?<service_code>\d{0,3}|=)(?<discretionary_data>.*)\?\Z/
90
90
  }.freeze
91
91
 
92
- APPLE_PAY_DATA_DESCRIPTOR = 'COMMON.APPLE.INAPP.PAYMENT'
93
92
  PAYMENT_METHOD_NOT_SUPPORTED_ERROR = '155'
94
93
  INELIGIBLE_FOR_ISSUING_CREDIT_ERROR = '54'
95
94
 
@@ -165,7 +164,7 @@ module ActiveMerchant
165
164
  xml.transactionType('refundTransaction')
166
165
  xml.amount(amount(amount))
167
166
 
168
- add_payment_source(xml, payment, options, :credit)
167
+ add_payment_method(xml, payment, options, :credit)
169
168
  xml.refTransId(transaction_id_from(options[:transaction_id])) if options[:transaction_id]
170
169
  add_invoice(xml, 'refundTransaction', options)
171
170
  add_customer_data(xml, payment, options)
@@ -262,7 +261,7 @@ module ActiveMerchant
262
261
  xml.transactionRequest do
263
262
  xml.transactionType(transaction_type)
264
263
  xml.amount(amount(amount))
265
- add_payment_source(xml, payment, options)
264
+ add_payment_method(xml, payment, options)
266
265
  add_invoice(xml, transaction_type, options)
267
266
  add_tax_fields(xml, options)
268
267
  add_duty_fields(xml, options)
@@ -273,6 +272,7 @@ module ActiveMerchant
273
272
  add_market_type_device_type(xml, payment, options)
274
273
  add_settings(xml, payment, options)
275
274
  add_user_fields(xml, amount, options)
275
+ add_surcharge_fields(xml, options)
276
276
  add_ship_from_address(xml, options)
277
277
  add_processing_options(xml, options)
278
278
  add_subsequent_auth_information(xml, options)
@@ -287,8 +287,9 @@ module ActiveMerchant
287
287
  add_tax_fields(xml, options)
288
288
  add_shipping_fields(xml, options)
289
289
  add_duty_fields(xml, options)
290
- add_payment_source(xml, payment, options)
290
+ add_payment_method(xml, payment, options)
291
291
  add_invoice(xml, transaction_type, options)
292
+ add_surcharge_fields(xml, options)
292
293
  add_tax_exempt_status(xml, options)
293
294
  end
294
295
  end
@@ -407,20 +408,27 @@ module ActiveMerchant
407
408
  end
408
409
  end
409
410
 
410
- def add_payment_source(xml, source, options, action = nil)
411
- return unless source
411
+ def add_payment_method(xml, payment_method, options, action = nil)
412
+ return unless payment_method
412
413
 
413
- if source.is_a?(String)
414
- add_token_payment_method(xml, source, options)
415
- elsif card_brand(source) == 'check'
416
- add_check(xml, source)
417
- elsif card_brand(source) == 'apple_pay'
418
- add_apple_pay_payment_token(xml, source)
414
+ case payment_method
415
+ when String
416
+ add_token_payment_method(xml, payment_method, options)
417
+ when Check
418
+ add_check(xml, payment_method)
419
419
  else
420
- add_credit_card(xml, source, action)
420
+ if network_token?(payment_method, options, action)
421
+ add_network_token(xml, payment_method)
422
+ else
423
+ add_credit_card(xml, payment_method, action)
424
+ end
421
425
  end
422
426
  end
423
427
 
428
+ def network_token?(payment_method, options, action)
429
+ payment_method.instance_of?(NetworkTokenizationCreditCard) && action != :credit
430
+ end
431
+
424
432
  def camel_case_lower(key)
425
433
  String(key).split('_').inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
426
434
  end
@@ -499,7 +507,6 @@ module ActiveMerchant
499
507
  xml.cardNumber(truncate(credit_card.number, 16))
500
508
  xml.expirationDate(format(credit_card.month, :two_digits) + '/' + format(credit_card.year, :four_digits))
501
509
  xml.cardCode(credit_card.verification_value) if credit_card.valid_card_verification_value?(credit_card.verification_value, credit_card.brand)
502
- xml.cryptogram(credit_card.payment_cryptogram) if credit_card.is_a?(NetworkTokenizationCreditCard) && action != :credit
503
510
  end
504
511
  end
505
512
  end
@@ -526,17 +533,20 @@ module ActiveMerchant
526
533
  xml.customerPaymentProfileId(customer_payment_profile_id)
527
534
  end
528
535
 
529
- def add_apple_pay_payment_token(xml, apple_pay_payment_token)
536
+ def add_network_token(xml, payment_method)
530
537
  xml.payment do
531
- xml.opaqueData do
532
- xml.dataDescriptor(APPLE_PAY_DATA_DESCRIPTOR)
533
- xml.dataValue(Base64.strict_encode64(apple_pay_payment_token.payment_data.to_json))
538
+ xml.creditCard do
539
+ xml.cardNumber(truncate(payment_method.number, 16))
540
+ xml.expirationDate(format(payment_method.month, :two_digits) + '/' + format(payment_method.year, :four_digits))
541
+ xml.isPaymentToken(true)
542
+ xml.cryptogram(payment_method.payment_cryptogram)
534
543
  end
535
544
  end
536
545
  end
537
546
 
538
547
  def add_market_type_device_type(xml, payment, options)
539
- return if payment.is_a?(String) || card_brand(payment) == 'check' || card_brand(payment) == 'apple_pay'
548
+ return unless payment.is_a?(CreditCard)
549
+ return if payment.is_a?(NetworkTokenizationCreditCard)
540
550
 
541
551
  if valid_track_data
542
552
  xml.retail do
@@ -701,6 +711,16 @@ module ActiveMerchant
701
711
  end
702
712
  end
703
713
 
714
+ def add_surcharge_fields(xml, options)
715
+ surcharge = options[:surcharge] if options[:surcharge]
716
+ if surcharge.is_a?(Hash)
717
+ xml.surcharge do
718
+ xml.amount(amount(surcharge[:amount].to_i)) if surcharge[:amount]
719
+ xml.description(surcharge[:description]) if surcharge[:description]
720
+ end
721
+ end
722
+ end
723
+
704
724
  def add_shipping_fields(xml, options)
705
725
  shipping = options[:shipping]
706
726
  if shipping.is_a?(Hash)
@@ -754,13 +774,7 @@ module ActiveMerchant
754
774
  xml.customerProfileId options[:customer_profile_id]
755
775
  xml.paymentProfile do
756
776
  add_billing_address(xml, credit_card, options)
757
- xml.payment do
758
- xml.creditCard do
759
- xml.cardNumber(truncate(credit_card.number, 16))
760
- xml.expirationDate(format(credit_card.year, :four_digits) + '-' + format(credit_card.month, :two_digits))
761
- xml.cardCode(credit_card.verification_value) if credit_card.verification_value
762
- end
763
- end
777
+ add_credit_card(xml, credit_card, :cim_store_update)
764
778
  end
765
779
  end
766
780
  end
@@ -776,13 +790,7 @@ module ActiveMerchant
776
790
  xml.customerType('individual')
777
791
  add_billing_address(xml, credit_card, options)
778
792
  add_shipping_address(xml, options, 'shipToList')
779
- xml.payment do
780
- xml.creditCard do
781
- xml.cardNumber(truncate(credit_card.number, 16))
782
- xml.expirationDate(format(credit_card.year, :four_digits) + '-' + format(credit_card.month, :two_digits))
783
- xml.cardCode(credit_card.verification_value) if credit_card.verification_value
784
- end
785
- end
793
+ add_credit_card(xml, credit_card, :cim_store)
786
794
  end
787
795
  end
788
796
  end