activemerchant 1.130.0 → 1.137.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +268 -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 +13 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +64 -7
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +240 -41
  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 +44 -36
  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/borgun.rb +6 -4
  21. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
  22. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  23. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  25. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  26. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  29. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  30. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  31. data/lib/active_merchant/billing/gateways/checkout_v2.rb +252 -41
  32. data/lib/active_merchant/billing/gateways/commerce_hub.rb +69 -8
  33. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  34. data/lib/active_merchant/billing/gateways/cyber_source.rb +192 -41
  35. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  36. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  37. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  38. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  39. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  40. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  41. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  42. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  43. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  44. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  45. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  46. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  48. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  49. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  51. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  52. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  55. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  56. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  57. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  58. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  59. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  60. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  61. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  62. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  63. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  64. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  65. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  66. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  67. data/lib/active_merchant/billing/gateways/ipg.rb +10 -6
  68. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  69. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  70. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  71. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  72. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  74. data/lib/active_merchant/billing/gateways/kushki.rb +73 -13
  75. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  76. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  77. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  78. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  79. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  80. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  82. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  83. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  84. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  85. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  86. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  87. data/lib/active_merchant/billing/gateways/mit.rb +25 -20
  88. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  89. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  90. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  91. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  92. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  93. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  94. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  95. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  97. data/lib/active_merchant/billing/gateways/nmi.rb +23 -6
  98. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  99. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  100. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  101. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  102. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  103. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  104. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  105. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  106. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  107. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  109. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  110. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  111. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  112. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  113. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  114. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  115. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  116. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  117. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  118. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  119. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  120. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  121. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  122. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  123. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  124. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  125. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  129. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  131. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  132. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  133. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  134. data/lib/active_merchant/billing/gateways/redsys.rb +3 -11
  135. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  136. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  137. data/lib/active_merchant/billing/gateways/safe_charge.rb +38 -17
  138. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  139. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  140. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  142. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  143. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  144. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  145. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  146. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  147. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  148. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  149. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  150. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  151. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  152. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  153. data/lib/active_merchant/billing/gateways/stripe.rb +63 -19
  154. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +280 -88
  155. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  156. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  157. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  158. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  159. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  160. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  161. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  162. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  163. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  164. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  165. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  166. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  168. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  169. data/lib/active_merchant/billing/gateways/vpos.rb +4 -4
  170. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  171. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  172. data/lib/active_merchant/billing/gateways/worldpay.rb +147 -93
  173. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  174. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  175. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  176. data/lib/active_merchant/billing/response.rb +2 -2
  177. data/lib/active_merchant/connection.rb +3 -17
  178. data/lib/active_merchant/country.rb +1 -0
  179. data/lib/active_merchant/errors.rb +10 -0
  180. data/lib/active_merchant/version.rb +1 -1
  181. data/lib/support/gateway_support.rb +2 -2
  182. data/lib/support/ssl_verify.rb +4 -4
  183. data/lib/support/ssl_version.rb +6 -6
  184. metadata +30 -9
@@ -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
@@ -362,7 +363,7 @@ module ActiveMerchant
362
363
  xml.accountType(options[:account_type])
363
364
  xml.routingNumber(options[:routing_number])
364
365
  xml.accountNumber(options[:account_number])
365
- xml.nameOnAccount("#{options[:first_name]} #{options[:last_name]}")
366
+ xml.nameOnAccount(truncate("#{options[:first_name]} #{options[:last_name]}", 22))
366
367
  end
367
368
  else
368
369
  xml.creditCard do
@@ -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
@@ -208,9 +208,9 @@ module ActiveMerchant #:nodoc:
208
208
  # The amount to be billed to the customer
209
209
  # for each payment in the subscription
210
210
  xml.tag!('amount', amount(options[:amount])) if options[:amount]
211
- if trial = options[:trial]
211
+ if trial = options[:trial] && (trial[:amount])
212
212
  # The amount to be charged for each payment during a trial period (conditional)
213
- xml.tag!('trialAmount', amount(trial[:amount])) if trial[:amount]
213
+ xml.tag!('trialAmount', amount(trial[:amount]))
214
214
  end
215
215
  # Contains either the customer’s credit card
216
216
  # or bank account payment information
@@ -260,9 +260,9 @@ module ActiveMerchant #:nodoc:
260
260
  # Contains information about the interval of time between payments
261
261
  add_interval(xml, options)
262
262
  add_duration(xml, options)
263
- if trial = options[:trial]
263
+ if trial = options[:trial] && (trial[:occurrences])
264
264
  # Number of billing occurrences or payments in the trial period (optional)
265
- xml.tag!('trialOccurrences', trial[:occurrences]) if trial[:occurrences]
265
+ xml.tag!('trialOccurrences', trial[:occurrences])
266
266
  end
267
267
  end
268
268
  end
@@ -393,9 +393,13 @@ module ActiveMerchant #:nodoc:
393
393
  test_mode = test? || message =~ /Test Mode/
394
394
  success = response[:result_code] == 'Ok'
395
395
 
396
- Response.new(success, message, response,
396
+ Response.new(
397
+ success,
398
+ message,
399
+ response,
397
400
  test: test_mode,
398
- authorization: response[:subscription_id])
401
+ authorization: response[:subscription_id]
402
+ )
399
403
  end
400
404
 
401
405
  def recurring_parse(action, xml)
@@ -695,9 +695,7 @@ module ActiveMerchant #:nodoc:
695
695
  add_order(xml, transaction[:order]) if transaction[:order].present?
696
696
 
697
697
  end
698
- if %i[auth_capture auth_only capture_only].include?(transaction[:type])
699
- xml.tag!('recurringBilling', transaction[:recurring_billing]) if transaction.has_key?(:recurring_billing)
700
- end
698
+ xml.tag!('recurringBilling', transaction[:recurring_billing]) if %i[auth_capture auth_only capture_only].include?(transaction[:type]) && transaction.has_key?(:recurring_billing)
701
699
  tag_unless_blank(xml, 'cardCode', transaction[:card_code]) unless %i[void refund prior_auth_capture].include?(transaction[:type])
702
700
  end
703
701
  end
@@ -71,9 +71,13 @@ module ActiveMerchant #:nodoc:
71
71
  message = "#{response[:reason]} - #{response[:return]}"
72
72
  authorization = response[:unique_id]
73
73
 
74
- Response.new(success, message, response,
74
+ Response.new(
75
+ success,
76
+ message,
77
+ response,
75
78
  authorization: authorization,
76
- test: (response[:mode] != 'LIVE'))
79
+ test: (response[:mode] != 'LIVE')
80
+ )
77
81
  end
78
82
 
79
83
  def parse(body)
@@ -89,11 +89,13 @@ module ActiveMerchant #:nodoc:
89
89
  response = json_error(raw_response)
90
90
  end
91
91
 
92
- Response.new(success?(response),
92
+ Response.new(
93
+ success?(response),
93
94
  response['message'],
94
95
  response,
95
96
  test: test?,
96
- authorization: response['code_auth'])
97
+ authorization: response['code_auth']
98
+ )
97
99
  end
98
100
 
99
101
  def success?(response)
@@ -228,7 +228,7 @@ module ActiveMerchant #:nodoc:
228
228
 
229
229
  if billing_address = options[:billing_address] || options[:address]
230
230
  post[:ordName] = billing_address[:name]
231
- post[:ordPhoneNumber] = billing_address[:phone]
231
+ post[:ordPhoneNumber] = billing_address[:phone] || billing_address[:phone_number]
232
232
  post[:ordAddress1] = billing_address[:address1]
233
233
  post[:ordAddress2] = billing_address[:address2]
234
234
  post[:ordCity] = billing_address[:city]
@@ -413,11 +413,15 @@ module ActiveMerchant #:nodoc:
413
413
  def post(data, use_profile_api = nil)
414
414
  response = parse(ssl_post((use_profile_api ? SECURE_PROFILE_URL : self.live_url), data))
415
415
  response[:customer_vault_id] = response[:customerCode] if response[:customerCode]
416
- build_response(success?(response), message_from(response), response,
416
+ build_response(
417
+ success?(response),
418
+ message_from(response),
419
+ response,
417
420
  test: test? || response[:authCode] == 'TEST',
418
421
  authorization: authorization_from(response),
419
422
  cvv_result: CVD_CODES[response[:cvdId]],
420
- avs_result: { code: AVS_CODES.include?(response[:avsId]) ? AVS_CODES[response[:avsId]] : response[:avsId] })
423
+ avs_result: { code: AVS_CODES.include?(response[:avsId]) ? AVS_CODES[response[:avsId]] : response[:avsId] }
424
+ )
421
425
  end
422
426
 
423
427
  def recurring_post(data)
@@ -344,14 +344,18 @@ module ActiveMerchant #:nodoc:
344
344
  success = parsed[:status] != 'error'
345
345
  message = parsed[:status]
346
346
 
347
- Response.new(success, message, parsed,
347
+ Response.new(
348
+ success,
349
+ message,
350
+ parsed,
348
351
  test: test?,
349
- authorization: parsed[:rebill_id])
352
+ authorization: parsed[:rebill_id]
353
+ )
350
354
  end
351
355
 
352
356
  def parse(body)
353
357
  # The bp20api has max one value per form field.
354
- response_fields = Hash[CGI::parse(body).map { |k, v| [k.upcase, v.first] }]
358
+ response_fields = CGI::parse(body).map { |k, v| [k.upcase, v.first] }.to_h
355
359
 
356
360
  return parse_recurring(response_fields) if response_fields.include? 'REBILL_ID'
357
361
 
@@ -364,11 +368,15 @@ module ActiveMerchant #:nodoc:
364
368
  # normalize message
365
369
  message = message_from(parsed)
366
370
  success = parsed[:response_code] == '1'
367
- Response.new(success, message, parsed,
371
+ Response.new(
372
+ success,
373
+ message,
374
+ parsed,
368
375
  test: test?,
369
376
  authorization: (parsed[:rebid] && parsed[:rebid] != '' ? parsed[:rebid] : parsed[:transaction_id]),
370
377
  avs_result: { code: parsed[:avs_result_code] },
371
- cvv_result: parsed[:card_code])
378
+ cvv_result: parsed[:card_code]
379
+ )
372
380
  end
373
381
 
374
382
  def message_from(parsed)
@@ -446,10 +446,10 @@ module ActiveMerchant
446
446
  end
447
447
 
448
448
  def parse_element(parsed, node)
449
- if !node.elements.empty?
450
- node.elements.each { |e| parse_element(parsed, e) }
451
- else
449
+ if node.elements.empty?
452
450
  parsed[node.name.downcase] = node.text
451
+ else
452
+ node.elements.each { |e| parse_element(parsed, e) }
453
453
  end
454
454
  end
455
455
 
@@ -459,8 +459,8 @@ module ActiveMerchant
459
459
  e.response
460
460
  end
461
461
 
462
- def commit(action, options, verb = :post, payment_method_details = PaymentMethodDetails.new())
463
- request = build_xml_request(action, payment_method_details) { |doc| yield(doc) }
462
+ def commit(action, options, verb = :post, payment_method_details = PaymentMethodDetails.new(), &block)
463
+ request = build_xml_request(action, payment_method_details, &block)
464
464
  response = api_request(action, request, verb, payment_method_details, options)
465
465
  parsed = parse(response)
466
466
 
@@ -172,7 +172,7 @@ module ActiveMerchant #:nodoc:
172
172
  success,
173
173
  message_from(success, pairs),
174
174
  pairs,
175
- authorization: authorization_from(pairs),
175
+ authorization: authorization_from(pairs, options),
176
176
  test: test?
177
177
  )
178
178
  end
@@ -185,12 +185,12 @@ module ActiveMerchant #:nodoc:
185
185
  if succeeded
186
186
  'Succeeded'
187
187
  else
188
- response[:message] || "Error with ActionCode=#{response[:actioncode]}"
188
+ response[:message] || response[:status_errormessage] || "Error with ActionCode=#{response[:actioncode]}"
189
189
  end
190
190
  end
191
191
 
192
- def authorization_from(response)
193
- [
192
+ def authorization_from(response, options)
193
+ authorization = [
194
194
  response[:dateandtime],
195
195
  response[:batch],
196
196
  response[:transaction],
@@ -200,6 +200,8 @@ module ActiveMerchant #:nodoc:
200
200
  response[:tramount],
201
201
  response[:trcurrency]
202
202
  ].join('|')
203
+
204
+ authorization == '|||||||' ? nil : authorization
203
205
  end
204
206
 
205
207
  def split_authorization(authorization)
@@ -18,10 +18,10 @@ module ActiveMerchant #:nodoc:
18
18
  "https://payments#{'.sandbox' if sandbox}.braintree-api.com/graphql"
19
19
  end
20
20
 
21
- def create_token_nonce_for_payment_method(payment_method)
21
+ def create_token_nonce_for_payment_method(payment_method, options = {})
22
22
  headers = {
23
23
  'Accept' => 'application/json',
24
- 'Authorization' => "Bearer #{client_token}",
24
+ 'Authorization' => "Bearer #{client_token(options)['authorizationFingerprint']}",
25
25
  'Content-Type' => 'application/json',
26
26
  'Braintree-Version' => '2018-05-10'
27
27
  }
@@ -29,19 +29,19 @@ module ActiveMerchant #:nodoc:
29
29
  json_response = JSON.parse(resp)
30
30
 
31
31
  message = json_response['errors'].map { |err| err['message'] }.join("\n") if json_response['errors'].present?
32
- token = json_response.dig('data', 'tokenizeUsBankAccount', 'paymentMethod', 'id')
32
+ token = token_from(payment_method, json_response)
33
33
 
34
34
  return token, message
35
35
  end
36
36
 
37
- def client_token
38
- base64_token = @braintree_gateway.client_token.generate
39
- JSON.parse(Base64.decode64(base64_token))['authorizationFingerprint']
37
+ def client_token(options = {})
38
+ base64_token = @braintree_gateway.client_token.generate({ merchant_account_id: options[:merchant_account_id] || @options[:merchant_account_id] }.compact)
39
+ JSON.parse(Base64.decode64(base64_token))
40
40
  end
41
41
 
42
42
  private
43
43
 
44
- def graphql_query
44
+ def graphql_bank_query
45
45
  <<-GRAPHQL
46
46
  mutation TokenizeUsBankAccount($input: TokenizeUsBankAccountInput!) {
47
47
  tokenizeUsBankAccount(input: $input) {
@@ -58,6 +58,23 @@ module ActiveMerchant #:nodoc:
58
58
  GRAPHQL
59
59
  end
60
60
 
61
+ def graphql_credit_query
62
+ <<-GRAPHQL
63
+ mutation TokenizeCreditCard($input: TokenizeCreditCardInput!) {
64
+ tokenizeCreditCard(input: $input) {
65
+ paymentMethod {
66
+ id
67
+ details {
68
+ ... on CreditCardDetails {
69
+ last4
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ GRAPHQL
76
+ end
77
+
61
78
  def billing_address_from_options
62
79
  return nil if options[:billing_address].blank?
63
80
 
@@ -72,7 +89,42 @@ module ActiveMerchant #:nodoc:
72
89
  }.compact
73
90
  end
74
91
 
92
+ def build_nonce_credit_card_request(payment_method)
93
+ billing_address = billing_address_from_options
94
+ key_replacements = { city: :locality, state: :region, zipCode: :postalCode }
95
+ billing_address&.transform_keys! { |key| key_replacements[key] || key }
96
+ {
97
+ creditCard: {
98
+ number: payment_method.number,
99
+ expirationYear: payment_method.year.to_s,
100
+ expirationMonth: payment_method.month.to_s.rjust(2, '0'),
101
+ cvv: payment_method.verification_value,
102
+ cardholderName: payment_method.name,
103
+ billingAddress: billing_address
104
+ }
105
+ }
106
+ end
107
+
75
108
  def build_nonce_request(payment_method)
109
+ input = payment_method.is_a?(Check) ? build_nonce_bank_request(payment_method) : build_nonce_credit_card_request(payment_method)
110
+ graphql_query = payment_method.is_a?(Check) ? graphql_bank_query : graphql_credit_query
111
+
112
+ {
113
+ clientSdkMetadata: {
114
+ platform: 'web',
115
+ source: 'client',
116
+ integration: 'custom',
117
+ sessionId: SecureRandom.uuid,
118
+ version: '3.83.0'
119
+ },
120
+ query: graphql_query,
121
+ variables: {
122
+ input: input
123
+ }
124
+ }.to_json
125
+ end
126
+
127
+ def build_nonce_bank_request(payment_method)
76
128
  input = {
77
129
  usBankAccount: {
78
130
  achMandate: options[:ach_mandate],
@@ -94,19 +146,12 @@ module ActiveMerchant #:nodoc:
94
146
  }
95
147
  end
96
148
 
97
- {
98
- clientSdkMetadata: {
99
- platform: 'web',
100
- source: 'client',
101
- integration: 'custom',
102
- sessionId: SecureRandom.uuid,
103
- version: '3.83.0'
104
- },
105
- query: graphql_query,
106
- variables: {
107
- input: input
108
- }
109
- }.to_json
149
+ input
150
+ end
151
+
152
+ def token_from(payment_method, response)
153
+ tokenized_field = payment_method.is_a?(Check) ? 'tokenizeUsBankAccount' : 'tokenizeCreditCard'
154
+ response.dig('data', tokenized_field, 'paymentMethod', 'id')
110
155
  end
111
156
  end
112
157
  end