activemerchant 1.133.0 → 1.138.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 (285) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +450 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/lib/active_merchant/billing/apple_pay_payment_token.rb +2 -2
  5. data/lib/active_merchant/billing/base.rb +2 -2
  6. data/lib/active_merchant/billing/check.rb +16 -4
  7. data/lib/active_merchant/billing/compatibility.rb +4 -4
  8. data/lib/active_merchant/billing/credit_card.rb +35 -16
  9. data/lib/active_merchant/billing/credit_card_formatting.rb +13 -2
  10. data/lib/active_merchant/billing/credit_card_methods.rb +74 -19
  11. data/lib/active_merchant/billing/gateway.rb +22 -2
  12. data/lib/active_merchant/billing/gateways/adyen.rb +282 -87
  13. data/lib/active_merchant/billing/gateways/airwallex.rb +46 -25
  14. data/lib/active_merchant/billing/gateways/alelo.rb +29 -11
  15. data/lib/active_merchant/billing/gateways/allied_wallet.rb +2 -2
  16. data/lib/active_merchant/billing/gateways/authorize_net.rb +49 -41
  17. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +14 -10
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -5
  19. data/lib/active_merchant/billing/gateways/axcessms.rb +9 -5
  20. data/lib/active_merchant/billing/gateways/balanced.rb +2 -2
  21. data/lib/active_merchant/billing/gateways/bambora_apac.rb +2 -2
  22. data/lib/active_merchant/billing/gateways/bank_frick.rb +2 -2
  23. data/lib/active_merchant/billing/gateways/banwire.rb +6 -4
  24. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +8 -8
  25. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +2 -2
  26. data/lib/active_merchant/billing/gateways/be2bill.rb +2 -2
  27. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +12 -8
  28. data/lib/active_merchant/billing/gateways/beanstream.rb +2 -2
  29. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +2 -2
  30. data/lib/active_merchant/billing/gateways/blue_pay.rb +15 -7
  31. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  32. data/lib/active_merchant/billing/gateways/bogus.rb +2 -2
  33. data/lib/active_merchant/billing/gateways/borgun.rb +2 -2
  34. data/lib/active_merchant/billing/gateways/bpoint.rb +2 -2
  35. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +3 -1
  36. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +68 -23
  37. data/lib/active_merchant/billing/gateways/braintree.rb +2 -2
  38. data/lib/active_merchant/billing/gateways/braintree_blue.rb +266 -89
  39. data/lib/active_merchant/billing/gateways/braintree_orange.rb +3 -3
  40. data/lib/active_merchant/billing/gateways/bridge_pay.rb +2 -2
  41. data/lib/active_merchant/billing/gateways/cams.rb +2 -2
  42. data/lib/active_merchant/billing/gateways/card_connect.rb +7 -4
  43. data/lib/active_merchant/billing/gateways/card_save.rb +2 -2
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +12 -13
  45. data/lib/active_merchant/billing/gateways/cardknox.rb +2 -2
  46. data/lib/active_merchant/billing/gateways/cardprocess.rb +2 -2
  47. data/lib/active_merchant/billing/gateways/cashnet.rb +4 -4
  48. data/lib/active_merchant/billing/gateways/cc5.rb +2 -2
  49. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  50. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +331 -0
  51. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  52. data/lib/active_merchant/billing/gateways/cecabank.rb +9 -242
  53. data/lib/active_merchant/billing/gateways/cenpos.rb +9 -3
  54. data/lib/active_merchant/billing/gateways/checkout.rb +5 -5
  55. data/lib/active_merchant/billing/gateways/checkout_v2.rb +362 -50
  56. data/lib/active_merchant/billing/gateways/clearhaus.rb +2 -2
  57. data/lib/active_merchant/billing/gateways/commerce_hub.rb +117 -35
  58. data/lib/active_merchant/billing/gateways/commercegate.rb +4 -4
  59. data/lib/active_merchant/billing/gateways/conekta.rb +2 -2
  60. data/lib/active_merchant/billing/gateways/creditcall.rb +2 -2
  61. data/lib/active_merchant/billing/gateways/credorax.rb +109 -20
  62. data/lib/active_merchant/billing/gateways/ct_payment.rb +6 -6
  63. data/lib/active_merchant/billing/gateways/culqi.rb +2 -2
  64. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +2 -2
  65. data/lib/active_merchant/billing/gateways/cyber_source.rb +379 -100
  66. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +147 -76
  67. data/lib/active_merchant/billing/gateways/d_local.rb +45 -22
  68. data/lib/active_merchant/billing/gateways/data_cash.rb +22 -18
  69. data/lib/active_merchant/billing/gateways/datatrans.rb +284 -0
  70. data/lib/active_merchant/billing/gateways/decidir.rb +82 -46
  71. data/lib/active_merchant/billing/gateways/decidir_plus.rb +31 -35
  72. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  73. data/lib/active_merchant/billing/gateways/dibs.rb +3 -3
  74. data/lib/active_merchant/billing/gateways/digitzs.rb +2 -2
  75. data/lib/active_merchant/billing/gateways/ebanx.rb +116 -68
  76. data/lib/active_merchant/billing/gateways/efsnet.rb +13 -8
  77. data/lib/active_merchant/billing/gateways/elavon.rb +80 -47
  78. data/lib/active_merchant/billing/gateways/element.rb +39 -10
  79. data/lib/active_merchant/billing/gateways/epay.rb +8 -4
  80. data/lib/active_merchant/billing/gateways/evo_ca.rb +8 -4
  81. data/lib/active_merchant/billing/gateways/eway.rb +6 -4
  82. data/lib/active_merchant/billing/gateways/eway_managed.rb +8 -4
  83. data/lib/active_merchant/billing/gateways/eway_rapid.rb +3 -3
  84. data/lib/active_merchant/billing/gateways/exact.rb +8 -4
  85. data/lib/active_merchant/billing/gateways/fat_zebra.rb +37 -7
  86. data/lib/active_merchant/billing/gateways/federated_canada.rb +8 -4
  87. data/lib/active_merchant/billing/gateways/finansbank.rb +2 -2
  88. data/lib/active_merchant/billing/gateways/first_giving.rb +2 -2
  89. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  90. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  91. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  92. data/lib/active_merchant/billing/gateways/first_pay.rb +8 -174
  93. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +8 -4
  94. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +9 -5
  95. data/lib/active_merchant/billing/gateways/flex_charge.rb +359 -0
  96. data/lib/active_merchant/billing/gateways/flo2cash.rb +4 -2
  97. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +2 -2
  98. data/lib/active_merchant/billing/gateways/forte.rb +6 -4
  99. data/lib/active_merchant/billing/gateways/fortis.rb +347 -0
  100. data/lib/active_merchant/billing/gateways/garanti.rb +6 -4
  101. data/lib/active_merchant/billing/gateways/global_collect.rb +69 -50
  102. data/lib/active_merchant/billing/gateways/global_transport.rb +2 -2
  103. data/lib/active_merchant/billing/gateways/hdfc.rb +2 -2
  104. data/lib/active_merchant/billing/gateways/hi_pay.rb +287 -0
  105. data/lib/active_merchant/billing/gateways/hps.rb +40 -47
  106. data/lib/active_merchant/billing/gateways/iats_payments.rb +9 -4
  107. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +2 -2
  108. data/lib/active_merchant/billing/gateways/inspire.rb +8 -6
  109. data/lib/active_merchant/billing/gateways/instapay.rb +9 -6
  110. data/lib/active_merchant/billing/gateways/ipg.rb +14 -10
  111. data/lib/active_merchant/billing/gateways/ipp.rb +2 -2
  112. data/lib/active_merchant/billing/gateways/iridium.rb +18 -8
  113. data/lib/active_merchant/billing/gateways/itransact.rb +8 -4
  114. data/lib/active_merchant/billing/gateways/iveri.rb +12 -9
  115. data/lib/active_merchant/billing/gateways/ixopay.rb +4 -4
  116. data/lib/active_merchant/billing/gateways/jetpay.rb +6 -4
  117. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +9 -6
  118. data/lib/active_merchant/billing/gateways/komoju.rb +2 -2
  119. data/lib/active_merchant/billing/gateways/kushki.rb +79 -16
  120. data/lib/active_merchant/billing/gateways/latitude19.rb +2 -2
  121. data/lib/active_merchant/billing/gateways/linkpoint.rb +8 -4
  122. data/lib/active_merchant/billing/gateways/litle.rb +37 -54
  123. data/lib/active_merchant/billing/gateways/loan_payment_pro.rb +267 -0
  124. data/lib/active_merchant/billing/gateways/loan_payment_pro_ach.rb +93 -0
  125. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  126. data/lib/active_merchant/billing/gateways/maxipago.rb +4 -4
  127. data/lib/active_merchant/billing/gateways/mercado_pago.rb +32 -11
  128. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +10 -7
  129. data/lib/active_merchant/billing/gateways/merchant_one.rb +2 -2
  130. data/lib/active_merchant/billing/gateways/merchant_partners.rb +2 -2
  131. data/lib/active_merchant/billing/gateways/merchant_ware.rb +13 -6
  132. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +13 -6
  133. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +21 -5
  134. data/lib/active_merchant/billing/gateways/mercury.rb +11 -5
  135. data/lib/active_merchant/billing/gateways/metrics_global.rb +10 -8
  136. data/lib/active_merchant/billing/gateways/micropayment.rb +2 -2
  137. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +7 -6
  138. data/lib/active_merchant/billing/gateways/migs.rb +8 -4
  139. data/lib/active_merchant/billing/gateways/mit.rb +10 -5
  140. data/lib/active_merchant/billing/gateways/modern_payments.rb +2 -2
  141. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +21 -13
  142. data/lib/active_merchant/billing/gateways/moka.rb +2 -2
  143. data/lib/active_merchant/billing/gateways/monei.rb +3 -3
  144. data/lib/active_merchant/billing/gateways/moneris.rb +11 -5
  145. data/lib/active_merchant/billing/gateways/money_movers.rb +8 -4
  146. data/lib/active_merchant/billing/gateways/multi_pay.rb +267 -0
  147. data/lib/active_merchant/billing/gateways/mundipagg.rb +5 -3
  148. data/lib/active_merchant/billing/gateways/nab_transact.rb +18 -10
  149. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +2 -2
  150. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  151. data/lib/active_merchant/billing/gateways/netaxept.rb +4 -4
  152. data/lib/active_merchant/billing/gateways/netbanx.rb +4 -6
  153. data/lib/active_merchant/billing/gateways/netbilling.rb +8 -4
  154. data/lib/active_merchant/billing/gateways/netpay.rb +2 -2
  155. data/lib/active_merchant/billing/gateways/network_merchants.rb +9 -5
  156. data/lib/active_merchant/billing/gateways/nmi.rb +29 -8
  157. data/lib/active_merchant/billing/gateways/nuvei.rb +573 -0
  158. data/lib/active_merchant/billing/gateways/ogone.rb +8 -4
  159. data/lib/active_merchant/billing/gateways/omise.rb +2 -2
  160. data/lib/active_merchant/billing/gateways/openpay.rb +6 -4
  161. data/lib/active_merchant/billing/gateways/opp.rb +3 -4
  162. data/lib/active_merchant/billing/gateways/optimal_payment.rb +12 -6
  163. data/lib/active_merchant/billing/gateways/orbital/orbital_codes.rb +273 -0
  164. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +3 -5
  165. data/lib/active_merchant/billing/gateways/orbital.rb +114 -94
  166. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +9 -6
  167. data/lib/active_merchant/billing/gateways/pagarme.rb +2 -2
  168. data/lib/active_merchant/billing/gateways/pago_facil.rb +2 -2
  169. data/lib/active_merchant/billing/gateways/pay_arc.rb +9 -7
  170. data/lib/active_merchant/billing/gateways/pay_conex.rb +6 -4
  171. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +8 -4
  172. data/lib/active_merchant/billing/gateways/pay_hub.rb +7 -5
  173. data/lib/active_merchant/billing/gateways/pay_junction.rb +8 -4
  174. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +2 -2
  175. data/lib/active_merchant/billing/gateways/pay_secure.rb +8 -4
  176. data/lib/active_merchant/billing/gateways/pay_trace.rb +36 -22
  177. data/lib/active_merchant/billing/gateways/paybox_direct.rb +14 -14
  178. data/lib/active_merchant/billing/gateways/payeezy.rb +26 -13
  179. data/lib/active_merchant/billing/gateways/payex.rb +8 -6
  180. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +3 -3
  181. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +2 -2
  182. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +2 -2
  183. data/lib/active_merchant/billing/gateways/payflow.rb +12 -11
  184. data/lib/active_merchant/billing/gateways/payflow_express.rb +2 -2
  185. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +2 -2
  186. data/lib/active_merchant/billing/gateways/payflow_uk.rb +2 -2
  187. data/lib/active_merchant/billing/gateways/payment_express.rb +10 -6
  188. data/lib/active_merchant/billing/gateways/paymentez.rb +30 -16
  189. data/lib/active_merchant/billing/gateways/paymill.rb +6 -4
  190. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +17 -12
  191. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +2 -2
  192. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +2 -2
  193. data/lib/active_merchant/billing/gateways/paypal.rb +4 -2
  194. data/lib/active_merchant/billing/gateways/paypal_ca.rb +2 -2
  195. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +2 -2
  196. data/lib/active_merchant/billing/gateways/paypal_express.rb +4 -2
  197. data/lib/active_merchant/billing/gateways/paysafe.rb +48 -24
  198. data/lib/active_merchant/billing/gateways/payscout.rb +9 -6
  199. data/lib/active_merchant/billing/gateways/paystation.rb +9 -5
  200. data/lib/active_merchant/billing/gateways/payu_in.rb +2 -2
  201. data/lib/active_merchant/billing/gateways/payu_latam.rb +7 -5
  202. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  203. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +6 -6
  204. data/lib/active_merchant/billing/gateways/pin.rb +126 -41
  205. data/lib/active_merchant/billing/gateways/plexo.rb +71 -20
  206. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  207. data/lib/active_merchant/billing/gateways/priority.rb +29 -24
  208. data/lib/active_merchant/billing/gateways/pro_pay.rb +2 -2
  209. data/lib/active_merchant/billing/gateways/psigate.rb +8 -4
  210. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  211. data/lib/active_merchant/billing/gateways/qbms.rb +9 -5
  212. data/lib/active_merchant/billing/gateways/quantum.rb +9 -5
  213. data/lib/active_merchant/billing/gateways/quickbooks.rb +27 -17
  214. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  215. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +8 -4
  216. data/lib/active_merchant/billing/gateways/quickpay.rb +2 -2
  217. data/lib/active_merchant/billing/gateways/qvalent.rb +2 -2
  218. data/lib/active_merchant/billing/gateways/rapyd.rb +172 -53
  219. data/lib/active_merchant/billing/gateways/reach.rb +16 -9
  220. data/lib/active_merchant/billing/gateways/redsys.rb +7 -15
  221. data/lib/active_merchant/billing/gateways/redsys_rest.rb +545 -0
  222. data/lib/active_merchant/billing/gateways/s5.rb +5 -5
  223. data/lib/active_merchant/billing/gateways/safe_charge.rb +47 -24
  224. data/lib/active_merchant/billing/gateways/sage.rb +14 -6
  225. data/lib/active_merchant/billing/gateways/sage_pay.rb +81 -7
  226. data/lib/active_merchant/billing/gateways/sallie_mae.rb +8 -4
  227. data/lib/active_merchant/billing/gateways/secure_net.rb +9 -5
  228. data/lib/active_merchant/billing/gateways/secure_pay.rb +10 -8
  229. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +25 -15
  230. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +8 -4
  231. data/lib/active_merchant/billing/gateways/securion_pay.rb +26 -12
  232. data/lib/active_merchant/billing/gateways/shift4.rb +34 -26
  233. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  234. data/lib/active_merchant/billing/gateways/simetrik.rb +26 -17
  235. data/lib/active_merchant/billing/gateways/skip_jack.rb +8 -4
  236. data/lib/active_merchant/billing/gateways/smart_ps.rb +10 -7
  237. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +6 -4
  238. data/lib/active_merchant/billing/gateways/spreedly_core.rb +4 -6
  239. data/lib/active_merchant/billing/gateways/stripe.rb +88 -84
  240. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +388 -77
  241. data/lib/active_merchant/billing/gateways/sum_up.rb +224 -0
  242. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +6 -4
  243. data/lib/active_merchant/billing/gateways/telr.rb +6 -7
  244. data/lib/active_merchant/billing/gateways/trans_first.rb +6 -4
  245. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +10 -18
  246. data/lib/active_merchant/billing/gateways/transact_pro.rb +3 -3
  247. data/lib/active_merchant/billing/gateways/transax.rb +2 -2
  248. data/lib/active_merchant/billing/gateways/transnational.rb +2 -2
  249. data/lib/active_merchant/billing/gateways/trexle.rb +2 -2
  250. data/lib/active_merchant/billing/gateways/trust_commerce.rb +9 -5
  251. data/lib/active_merchant/billing/gateways/usa_epay.rb +2 -2
  252. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +32 -31
  253. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -4
  254. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  255. data/lib/active_merchant/billing/gateways/vantiv_express.rb +668 -0
  256. data/lib/active_merchant/billing/gateways/verifi.rb +12 -8
  257. data/lib/active_merchant/billing/gateways/versa_pay.rb +307 -0
  258. data/lib/active_merchant/billing/gateways/viaklix.rb +8 -4
  259. data/lib/active_merchant/billing/gateways/visanet_peru.rb +5 -5
  260. data/lib/active_merchant/billing/gateways/vpos.rb +25 -13
  261. data/lib/active_merchant/billing/gateways/webpay.rb +3 -3
  262. data/lib/active_merchant/billing/gateways/wepay.rb +6 -4
  263. data/lib/active_merchant/billing/gateways/wirecard.rb +10 -6
  264. data/lib/active_merchant/billing/gateways/wompi.rb +14 -7
  265. data/lib/active_merchant/billing/gateways/world_net.rb +2 -2
  266. data/lib/active_merchant/billing/gateways/worldpay.rb +297 -113
  267. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +16 -13
  268. data/lib/active_merchant/billing/gateways/worldpay_us.rb +2 -2
  269. data/lib/active_merchant/billing/gateways/xpay.rb +244 -0
  270. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +15 -3
  271. data/lib/active_merchant/billing/payment_token.rb +2 -2
  272. data/lib/active_merchant/billing/response.rb +7 -6
  273. data/lib/active_merchant/billing.rb +1 -0
  274. data/lib/active_merchant/connection.rb +8 -20
  275. data/lib/active_merchant/country.rb +3 -1
  276. data/lib/active_merchant/errors.rb +12 -2
  277. data/lib/active_merchant/net_http_ssl_connection.rb +35 -0
  278. data/lib/active_merchant/posts_data.rb +19 -4
  279. data/lib/active_merchant/version.rb +1 -1
  280. data/lib/active_merchant/versionable.rb +29 -0
  281. data/lib/certs/cacert.pem +1326 -1491
  282. data/lib/support/gateway_support.rb +3 -3
  283. data/lib/support/ssl_verify.rb +6 -6
  284. data/lib/support/ssl_version.rb +8 -8
  285. metadata +35 -9
@@ -1,5 +1,7 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant # :nodoc:
4
+ module Billing # :nodoc:
3
5
  # Initial setup instructions can be found in
4
6
  # http://apps.cybersource.com/library/documentation/dev_guides/SOAP_Toolkits/SOAP_toolkits.pdf
5
7
  #
@@ -33,9 +35,29 @@ module ActiveMerchant #:nodoc:
33
35
  discover: 'pb',
34
36
  diners_club: 'pb'
35
37
  }.freeze
38
+ THREEDS_EXEMPTIONS = {
39
+ authentication_outage: 'authenticationOutageExemptionIndicator',
40
+ corporate_card: 'secureCorporatePaymentIndicator',
41
+ delegated_authentication: 'delegatedAuthenticationExemptionIndicator',
42
+ low_risk: 'riskAnalysisExemptionIndicator',
43
+ low_value: 'lowValueExemptionIndicator',
44
+ trusted_merchant: 'trustedMerchantExemptionIndicator'
45
+ }
36
46
  DEFAULT_COLLECTION_INDICATOR = 2
37
47
 
38
- self.supported_cardtypes = %i[visa master american_express discover diners_club jcb dankort maestro elo]
48
+ NS_DS = 'http://www.w3.org/2000/09/xmldsig#'
49
+ NS_WSSE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
50
+ C14N_ALGORITHM = 'http://www.w3.org/2001/10/xml-exc-c14n#'
51
+ RSA_SHA256_ALGORITHM = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
52
+ SHA256_ALGORITHM = 'http://www.w3.org/2001/04/xmlenc#sha256'
53
+ BINARY_SECURITY_TOKEN_PROFILE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3'
54
+ BINARY_SECURITY_TOKEN_TYPE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary'
55
+ BINARY_SECURITY_TOKEN_WSU = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
56
+ BINARY_SECURITY_TOKEN_ID = 'X509Token'
57
+ USERNAME_TOKEN_PROFILE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'
58
+ ENVELOPE = 'http://schemas.xmlsoap.org/soap/envelope/'
59
+
60
+ self.supported_cardtypes = %i[visa master american_express discover diners_club jcb dankort maestro elo patagonia_365 tarjeta_sol]
39
61
  self.supported_countries = %w(US AE BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB PK)
40
62
 
41
63
  self.default_currency = 'USD'
@@ -53,7 +75,8 @@ module ActiveMerchant #:nodoc:
53
75
  jcb: '007',
54
76
  dankort: '034',
55
77
  maestro: '042',
56
- elo: '054'
78
+ elo: '054',
79
+ carnet: '002'
57
80
  }
58
81
 
59
82
  @@decision_codes = {
@@ -132,11 +155,16 @@ module ActiveMerchant #:nodoc:
132
155
  r703: 'Export hostname_country/ip_country match'
133
156
  }
134
157
 
135
- @@payment_solution = {
158
+ @@wallet_payment_solution = {
136
159
  apple_pay: '001',
137
160
  google_pay: '012'
138
161
  }
139
162
 
163
+ NT_PAYMENT_SOLUTION = {
164
+ 'master' => '014',
165
+ 'visa' => '015'
166
+ }
167
+
140
168
  # These are the options that can be used when creating a new CyberSource
141
169
  # Gateway object.
142
170
  #
@@ -157,13 +185,24 @@ module ActiveMerchant #:nodoc:
157
185
  # :ignore_cvv => true don't want to use CVV so continue processing even
158
186
  # if CVV would have failed
159
187
  def initialize(options = {})
160
- requires!(options, :login, :password)
188
+ if options[:public_key]
189
+ requires!(options, :login, :public_key, :private_key)
190
+ else
191
+ requires!(options, :login, :password)
192
+ end
193
+
161
194
  super
162
195
  end
163
196
 
164
- def authorize(money, creditcard_or_reference, options = {})
165
- setup_address_hash(options)
166
- commit(build_auth_request(money, creditcard_or_reference, options), :authorize, money, options)
197
+ def authorize(money, payment_method, options = {})
198
+ if valid_payment_method?(payment_method, options)
199
+ setup_address_hash(options)
200
+ commit(build_auth_request(money, payment_method, options), :authorize, money, options)
201
+ else
202
+ # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource
203
+ payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '')
204
+ Response.new(false, "#{card_brand(payment_method).capitalize} is not supported by #{payment_type} at CyberSource, check https://developer.cybersource.com/docs/cybs/en-us/payments/developer/all/rest/payments/CreatingOnlineAuth/CreatingAuthReqPNT.html")
205
+ end
167
206
  end
168
207
 
169
208
  def capture(money, authorization, options = {})
@@ -171,9 +210,15 @@ module ActiveMerchant #:nodoc:
171
210
  commit(build_capture_request(money, authorization, options), :capture, money, options)
172
211
  end
173
212
 
174
- def purchase(money, payment_method_or_reference, options = {})
175
- setup_address_hash(options)
176
- commit(build_purchase_request(money, payment_method_or_reference, options), :purchase, money, options)
213
+ def purchase(money, payment_method, options = {})
214
+ if valid_payment_method?(payment_method, options)
215
+ setup_address_hash(options)
216
+ commit(build_purchase_request(money, payment_method, options), :purchase, money, options)
217
+ else
218
+ # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource
219
+ payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '')
220
+ Response.new(false, "#{card_brand(payment_method).capitalize} is not supported by #{payment_type} at CyberSource, check https://developer.cybersource.com/docs/cybs/en-us/payments/developer/all/rest/payments/CreatingOnlineAuth/CreatingAuthReqPNT.html")
221
+ end
177
222
  end
178
223
 
179
224
  def void(identification, options = {})
@@ -206,8 +251,14 @@ module ActiveMerchant #:nodoc:
206
251
  # To charge the card while creating a profile, pass
207
252
  # options[:setup_fee] => money
208
253
  def store(payment_method, options = {})
209
- setup_address_hash(options)
210
- commit(build_create_subscription_request(payment_method, options), :store, nil, options)
254
+ if valid_payment_method?(payment_method, options)
255
+ setup_address_hash(options)
256
+ commit(build_create_subscription_request(payment_method, options), :store, nil, options)
257
+ else
258
+ # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource
259
+ payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '')
260
+ Response.new(false, "#{card_brand(payment_method).capitalize} is not supported by #{payment_type} at CyberSource, check https://developer.cybersource.com/docs/cybs/en-us/payments/developer/all/rest/payments/CreatingOnlineAuth/CreatingAuthReqPNT.html")
261
+ end
211
262
  end
212
263
 
213
264
  # Updates a customer subscription/profile
@@ -268,10 +319,15 @@ module ActiveMerchant #:nodoc:
268
319
  def scrub(transcript)
269
320
  transcript.
270
321
  gsub(%r((<wsse:Password [^>]*>)[^<]*(</wsse:Password>))i, '\1[FILTERED]\2').
322
+ gsub(%r((<wsse:BinarySecurityToken [^>]*>)[^<]*(</wsse:BinarySecurityToken>))i, '\1[FILTERED]\2').
323
+ gsub(%r((<ds:DigestValue>)[^<]*(</ds:DigestValue>))i, '\1[FILTERED]\2').
324
+ gsub(%r((<ds:SignatureValue [^>]*>)[^<]*(</ds:SignatureValue>))i, '\1[FILTERED]\2').
271
325
  gsub(%r((<accountNumber>)[^<]*(</accountNumber>))i, '\1[FILTERED]\2').
272
326
  gsub(%r((<cvNumber>)[^<]*(</cvNumber>))i, '\1[FILTERED]\2').
273
327
  gsub(%r((<cavv>)[^<]*(</cavv>))i, '\1[FILTERED]\2').
274
328
  gsub(%r((<xid>)[^<]*(</xid>))i, '\1[FILTERED]\2').
329
+ gsub(%r((<networkTokenCryptogram>)[^<]*(</networkTokenCryptogram>))i, '\1[FILTERED]\2').
330
+ gsub(%r((<requestorID>)[^<]*(</requestorID>))i, '\1[FILTERED]\2').
275
331
  gsub(%r((<authenticationData>)[^<]*(</authenticationData>))i, '\1[FILTERED]\2')
276
332
  end
277
333
 
@@ -286,6 +342,14 @@ module ActiveMerchant #:nodoc:
286
342
 
287
343
  private
288
344
 
345
+ def valid_payment_method?(payment_method, options)
346
+ return true unless payment_method.is_a?(NetworkTokenizationCreditCard)
347
+
348
+ brands = %w(visa master american_express)
349
+ brands << 'discover' if options[:enable_cybs_discover_apple_pay]
350
+ brands.include?(card_brand(payment_method))
351
+ end
352
+
289
353
  # Create all required address hash key value pairs
290
354
  # If a value of nil is received, that value will be passed on to the gateway and will not be replaced with a default value
291
355
  # Billing address fields received without an override value or with an empty string value will be replaced with the default_address values
@@ -317,17 +381,20 @@ module ActiveMerchant #:nodoc:
317
381
  xml = Builder::XmlMarkup.new indent: 2
318
382
  add_customer_id(xml, options)
319
383
  add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
320
- add_other_tax(xml, options)
321
384
  add_threeds_2_ucaf_data(xml, creditcard_or_reference, options)
385
+ add_mastercard_network_tokenization_ucaf_data(xml, creditcard_or_reference, options)
322
386
  add_decision_manager_fields(xml, options)
387
+ add_other_tax(xml, options)
323
388
  add_mdd_fields(xml, options)
324
389
  add_auth_service(xml, creditcard_or_reference, options)
390
+ add_capture_service_fields_with_run_false(xml, options)
325
391
  add_threeds_services(xml, options)
326
392
  add_business_rules_data(xml, creditcard_or_reference, options)
327
393
  add_airline_data(xml, options)
394
+ add_merchant_category_code(xml, options)
328
395
  add_sales_slip_number(xml, options)
329
- add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
330
- add_payment_solution(xml, creditcard_or_reference.source) if network_tokenization?(creditcard_or_reference)
396
+ add_payment_network_token(xml, creditcard_or_reference, options)
397
+ add_payment_solution(xml, creditcard_or_reference)
331
398
  add_tax_management_indicator(xml, options)
332
399
  add_stored_credential_subsequent_auth(xml, options)
333
400
  add_issuer_additional_data(xml, options)
@@ -360,7 +427,7 @@ module ActiveMerchant #:nodoc:
360
427
 
361
428
  def build_capture_request(money, authorization, options)
362
429
  order_id, request_id, request_token = authorization.split(';')
363
- options[:order_id] = order_id
430
+ options[:order_id] = options[:merchant_reference_code] || order_id
364
431
 
365
432
  xml = Builder::XmlMarkup.new indent: 2
366
433
  add_purchase_data(xml, money, true, options)
@@ -368,6 +435,7 @@ module ActiveMerchant #:nodoc:
368
435
  add_mdd_fields(xml, options)
369
436
  add_capture_service(xml, request_id, request_token, options)
370
437
  add_business_rules_data(xml, authorization, options)
438
+ add_merchant_category_code(xml, options)
371
439
  add_tax_management_indicator(xml, options)
372
440
  add_issuer_additional_data(xml, options)
373
441
  add_merchant_description(xml, options)
@@ -380,13 +448,15 @@ module ActiveMerchant #:nodoc:
380
448
  xml = Builder::XmlMarkup.new indent: 2
381
449
  add_customer_id(xml, options)
382
450
  add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
383
- add_other_tax(xml, options)
384
451
  add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
452
+ add_mastercard_network_tokenization_ucaf_data(xml, payment_method_or_reference, options)
385
453
  add_decision_manager_fields(xml, options)
454
+ add_other_tax(xml, options)
386
455
  add_mdd_fields(xml, options)
387
456
  if (!payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check') || reference_is_a_check?(payment_method_or_reference)
388
457
  add_check_service(xml)
389
458
  add_airline_data(xml, options)
459
+ add_merchant_category_code(xml, options)
390
460
  add_sales_slip_number(xml, options)
391
461
  add_tax_management_indicator(xml, options)
392
462
  add_issuer_additional_data(xml, options)
@@ -397,9 +467,10 @@ module ActiveMerchant #:nodoc:
397
467
  add_threeds_services(xml, options)
398
468
  add_business_rules_data(xml, payment_method_or_reference, options)
399
469
  add_airline_data(xml, options)
470
+ add_merchant_category_code(xml, options)
400
471
  add_sales_slip_number(xml, options)
401
- add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
402
- add_payment_solution(xml, payment_method_or_reference.source) if network_tokenization?(payment_method_or_reference)
472
+ add_payment_network_token(xml, payment_method_or_reference, options)
473
+ add_payment_solution(xml, payment_method_or_reference)
403
474
  add_tax_management_indicator(xml, options)
404
475
  add_stored_credential_subsequent_auth(xml, options)
405
476
  add_issuer_additional_data(xml, options)
@@ -418,9 +489,12 @@ module ActiveMerchant #:nodoc:
418
489
  end
419
490
 
420
491
  def build_void_request(identification, options)
421
- order_id, request_id, request_token, action, money, currency = identification.split(';')
492
+ order_id, request_id, request_token, action, money, currency = identification&.split(';')
422
493
  options[:order_id] = order_id
423
494
 
495
+ money ||= options[:amount]
496
+ currency ||= options[:currency]
497
+
424
498
  xml = Builder::XmlMarkup.new indent: 2
425
499
  case action
426
500
  when 'capture', 'purchase'
@@ -431,6 +505,7 @@ module ActiveMerchant #:nodoc:
431
505
  add_mdd_fields(xml, options)
432
506
  add_auth_reversal_service(xml, request_id, request_token)
433
507
  end
508
+ add_merchant_category_code(xml, options)
434
509
  add_issuer_additional_data(xml, options)
435
510
  add_partner_solution_id(xml)
436
511
 
@@ -443,9 +518,10 @@ module ActiveMerchant #:nodoc:
443
518
 
444
519
  xml = Builder::XmlMarkup.new indent: 2
445
520
  add_purchase_data(xml, money, true, options)
446
- add_credit_service(xml, request_id: request_id,
447
- request_token: request_token,
521
+ add_credit_service(xml, request_id:,
522
+ request_token:,
448
523
  use_check_service: reference_is_a_check?(identification))
524
+ add_merchant_category_code(xml, options)
449
525
  add_partner_solution_id(xml)
450
526
 
451
527
  xml.target!
@@ -487,7 +563,7 @@ module ActiveMerchant #:nodoc:
487
563
  add_check_service(xml)
488
564
  else
489
565
  add_purchase_service(xml, payment_method, options)
490
- add_payment_network_token(xml) if network_tokenization?(payment_method)
566
+ add_payment_network_token(xml, payment_method, options)
491
567
  end
492
568
  end
493
569
  add_subscription_create_service(xml, options)
@@ -556,7 +632,7 @@ module ActiveMerchant #:nodoc:
556
632
  end
557
633
 
558
634
  def add_merchant_data(xml, options)
559
- xml.tag! 'merchantID', @options[:login]
635
+ xml.tag! 'merchantID', options[:merchant_id] || @options[:login]
560
636
  xml.tag! 'merchantReferenceCode', options[:order_id] || generate_unique_id
561
637
  xml.tag! 'clientLibrary', 'Ruby Active Merchant'
562
638
  xml.tag! 'clientLibraryVersion', VERSION
@@ -566,12 +642,24 @@ module ActiveMerchant #:nodoc:
566
642
  end
567
643
 
568
644
  def add_merchant_descriptor(xml, options)
569
- return unless options[:merchant_descriptor] || options[:user_po] || options[:taxable] || options[:reference_data_code] || options[:invoice_number]
645
+ return unless options[:merchant_descriptor] ||
646
+ options[:user_po] ||
647
+ options[:taxable] ||
648
+ options[:reference_data_code] ||
649
+ options[:invoice_number] ||
650
+ options[:merchant_descriptor_city] ||
651
+ options[:submerchant_id] ||
652
+ options[:merchant_descriptor_state] ||
653
+ options[:merchant_descriptor_country]
570
654
 
571
655
  xml.tag! 'invoiceHeader' do
572
656
  xml.tag! 'merchantDescriptor', options[:merchant_descriptor] if options[:merchant_descriptor]
657
+ xml.tag! 'merchantDescriptorCity', options[:merchant_descriptor_city] if options[:merchant_descriptor_city]
658
+ xml.tag! 'merchantDescriptorState', options[:merchant_descriptor_state] if options[:merchant_descriptor_state]
659
+ xml.tag! 'merchantDescriptorCountry', options[:merchant_descriptor_country] if options[:merchant_descriptor_country]
573
660
  xml.tag! 'userPO', options[:user_po] if options[:user_po]
574
661
  xml.tag! 'taxable', options[:taxable] if options[:taxable]
662
+ xml.tag! 'submerchantID', options[:submerchant_id] if options[:submerchant_id]
575
663
  xml.tag! 'referenceDataCode', options[:reference_data_code] if options[:reference_data_code]
576
664
  xml.tag! 'invoiceNumber', options[:invoice_number] if options[:invoice_number]
577
665
  end
@@ -645,9 +733,23 @@ module ActiveMerchant #:nodoc:
645
733
  xml.tag! 'driversLicenseNumber', options[:drivers_license_number] unless options[:drivers_license_number].blank?
646
734
  xml.tag! 'driversLicenseState', options[:drivers_license_state] unless options[:drivers_license_state].blank?
647
735
  xml.tag! 'merchantTaxID', bill_to_merchant_tax_id unless bill_to_merchant_tax_id.blank?
736
+ add_browser_info(xml, options, shipTo)
648
737
  end
649
738
  end
650
739
 
740
+ def add_browser_info(xml, options, shipTo)
741
+ return if shipTo
742
+ return unless browser_info = options.dig(:three_ds_2, :browser_info)
743
+
744
+ xml.tag! 'httpBrowserColorDepth', browser_info[:depth]&.to_s
745
+ xml.tag! 'httpBrowserJavaEnabled', browser_info[:java]
746
+ xml.tag! 'httpBrowserJavaScriptEnabled', browser_info[:javascript]
747
+ xml.tag! 'httpBrowserLanguage', browser_info[:language]&.to_s
748
+ xml.tag! 'httpBrowserScreenHeight', browser_info[:height]&.to_s
749
+ xml.tag! 'httpBrowserScreenWidth', browser_info[:width]&.to_s
750
+ xml.tag! 'httpBrowserTimeDifference', browser_info[:timezone]&.to_s
751
+ end
752
+
651
753
  def address_names(address_name, payment_method)
652
754
  names = split_names(address_name)
653
755
  return names if names.any?(&:present?)
@@ -677,8 +779,10 @@ module ActiveMerchant #:nodoc:
677
779
  end
678
780
  end
679
781
 
680
- def add_payment_solution(xml, source)
681
- return unless (payment_solution = @@payment_solution[source])
782
+ def add_payment_solution(xml, payment_method)
783
+ return unless network_tokenization?(payment_method)
784
+
785
+ payment_solution = payment_method.network_token? ? NT_PAYMENT_SOLUTION[payment_method.brand] : @@wallet_payment_solution[payment_method.source]
682
786
 
683
787
  xml.tag! 'paymentSolution', payment_solution
684
788
  end
@@ -692,7 +796,7 @@ module ActiveMerchant #:nodoc:
692
796
  end
693
797
 
694
798
  def add_other_tax(xml, options)
695
- return unless options[:local_tax_amount] || options[:national_tax_amount] || options[:national_tax_indicator]
799
+ return unless %i[vat_tax_rate local_tax_amount national_tax_amount national_tax_indicator].any? { |gsf| options.include?(gsf) }
696
800
 
697
801
  xml.tag! 'otherTax' do
698
802
  xml.tag! 'vatTaxRate', options[:vat_tax_rate] if options[:vat_tax_rate]
@@ -730,22 +834,39 @@ module ActiveMerchant #:nodoc:
730
834
  end
731
835
 
732
836
  def add_auth_service(xml, payment_method, options)
733
- if network_tokenization?(payment_method)
734
- add_auth_network_tokenization(xml, payment_method, options)
735
- else
736
- xml.tag! 'ccAuthService', { 'run' => 'true' } do
737
- if options[:three_d_secure]
738
- add_normalized_threeds_2_data(xml, payment_method, options)
739
- else
740
- indicator = options[:commerce_indicator] || stored_credential_commerce_indicator(options)
741
- xml.tag!('commerceIndicator', indicator) if indicator
742
- end
743
- xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
744
- xml.tag!('mobileRemotePaymentType', options[:mobile_remote_payment_type]) if options[:mobile_remote_payment_type]
837
+ xml.tag! 'ccAuthService', { 'run' => 'true' } do
838
+ if network_tokenization?(payment_method)
839
+ add_auth_network_tokenization(xml, payment_method, options)
840
+ elsif options[:three_d_secure]
841
+ add_normalized_threeds_2_data(xml, payment_method, options)
842
+ add_threeds_exemption_data(xml, options)
843
+ elsif (indicator = options[:commerce_indicator] || stored_credential_commerce_indicator(options))
844
+ xml.tag!('commerceIndicator', indicator)
845
+ end
846
+
847
+ unless options[:three_d_secure]
848
+ add_reconciliation_and_aggregator_id(xml, options)
849
+ add_optional_fields(xml, options)
745
850
  end
746
851
  end
747
852
  end
748
853
 
854
+ def add_reconciliation_and_aggregator_id(xml, options)
855
+ xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
856
+ xml.tag!('aggregatorID', options[:aggregator_id]) if options[:aggregator_id]
857
+ end
858
+
859
+ def add_optional_fields(xml, options)
860
+ xml.tag!('firstRecurringPayment', options[:first_recurring_payment]) if options[:first_recurring_payment]
861
+ xml.tag!('mobileRemotePaymentType', options[:mobile_remote_payment_type]) if options[:mobile_remote_payment_type]
862
+ end
863
+
864
+ def add_threeds_exemption_data(xml, options)
865
+ return unless (exemption = THREEDS_EXEMPTIONS[options[:three_ds_exemption_type]&.to_sym])
866
+
867
+ xml.tag!(exemption, '1')
868
+ end
869
+
749
870
  def add_incremental_auth_service(xml, authorization, options)
750
871
  xml.tag! 'ccIncrementalAuthService', { 'run' => 'true' } do
751
872
  xml.tag! 'authRequestID', authorization
@@ -775,8 +896,10 @@ module ActiveMerchant #:nodoc:
775
896
  xml.tag!('xid', cavv) if cavv.present?
776
897
  end
777
898
 
899
+ add_reconciliation_and_aggregator_id(xml, options)
778
900
  xml.tag!('veresEnrolled', threeds_2_options[:enrolled]) if threeds_2_options[:enrolled]
779
901
  xml.tag!('paresStatus', threeds_2_options[:authentication_response_status]) if threeds_2_options[:authentication_response_status]
902
+ add_optional_fields(xml, options)
780
903
  end
781
904
 
782
905
  def infer_commerce_indicator?(options, cc_brand)
@@ -793,13 +916,15 @@ module ActiveMerchant #:nodoc:
793
916
  end
794
917
 
795
918
  def stored_credential_commerce_indicator(options)
796
- return unless options[:stored_credential]
797
-
798
- return if options[:stored_credential][:initial_transaction]
919
+ return unless (reason_type = options.dig(:stored_credential, :reason_type))
799
920
 
800
- case options[:stored_credential][:reason_type]
801
- when 'installment' then 'install'
802
- when 'recurring' then 'recurring'
921
+ case reason_type
922
+ when 'installment'
923
+ 'install'
924
+ when 'recurring'
925
+ 'recurring'
926
+ else
927
+ 'internet'
803
928
  end
804
929
  end
805
930
 
@@ -807,53 +932,95 @@ module ActiveMerchant #:nodoc:
807
932
  payment_method.is_a?(NetworkTokenizationCreditCard)
808
933
  end
809
934
 
935
+ def subsequent_wallet_auth(payment_method, options)
936
+ return unless options[:stored_credential] || options[:stored_credential_overrides]
937
+ return unless @@wallet_payment_solution[payment_method.source]
938
+
939
+ options.dig(:stored_credential_overrides, :subsequent_auth) || options.dig(:stored_credential, :initiator) == 'merchant'
940
+ end
941
+
810
942
  def add_auth_network_tokenization(xml, payment_method, options)
811
- return unless network_tokenization?(payment_method)
943
+ brand = card_brand(payment_method)
944
+ return if payment_method.mobile_wallet? && brand == 'discover' && !options[:enable_cybs_discover_apple_pay]
945
+
946
+ if payment_method.network_token?
947
+ xml.tag!('networkTokenCryptogram', payment_method.payment_cryptogram)
948
+ xml.tag!('commerceIndicator', stored_credential_commerce_indicator(options) || 'internet')
949
+ elsif send_only_commerce_indicator(payment_method, options)
950
+ commerce_indicator = if brand == 'discover'
951
+ 'dipb'
952
+ elsif subsequent_wallet_auth(payment_method, options)
953
+ 'internet'
954
+ else
955
+ ECI_BRAND_MAPPING[brand.to_sym]
956
+ end
957
+
958
+ xml.commerceIndicator(commerce_indicator)
959
+ else
960
+ default_wallet_values(xml, payment_method)
961
+ end
962
+ end
963
+
964
+ def send_only_commerce_indicator(payment_method, options)
965
+ brand = card_brand(payment_method)
966
+
967
+ return false if brand == 'american_express'
968
+
969
+ brand == 'master' || subsequent_wallet_auth(payment_method, options)
970
+ end
812
971
 
972
+ def default_wallet_values(xml, payment_method)
813
973
  brand = card_brand(payment_method).to_sym
974
+ commerce_indicator = brand == :discover ? 'dipb' : ECI_BRAND_MAPPING[brand]
975
+ cryptogram = brand == :american_express ? Base64.decode64(payment_method.payment_cryptogram) : payment_method.payment_cryptogram
976
+ cavv = xid = cryptogram
814
977
 
815
- case brand
816
- when :visa
817
- xml.tag! 'ccAuthService', { 'run' => 'true' } do
818
- xml.tag!('cavv', payment_method.payment_cryptogram)
819
- xml.tag!('commerceIndicator', ECI_BRAND_MAPPING[brand])
820
- xml.tag!('xid', payment_method.payment_cryptogram)
821
- xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
822
- end
823
- when :master
824
- xml.tag! 'ucaf' do
825
- xml.tag!('authenticationData', payment_method.payment_cryptogram)
826
- xml.tag!('collectionIndicator', DEFAULT_COLLECTION_INDICATOR)
827
- end
828
- xml.tag! 'ccAuthService', { 'run' => 'true' } do
829
- xml.tag!('commerceIndicator', ECI_BRAND_MAPPING[brand])
830
- xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
831
- end
832
- when :american_express
833
- cryptogram = Base64.decode64(payment_method.payment_cryptogram)
834
- xml.tag! 'ccAuthService', { 'run' => 'true' } do
835
- xml.tag!('cavv', Base64.encode64(cryptogram[0...20]))
836
- xml.tag!('commerceIndicator', ECI_BRAND_MAPPING[brand])
837
- xml.tag!('xid', Base64.encode64(cryptogram[20...40])) if cryptogram.bytes.count > 20
838
- xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
839
- end
840
- else
841
- raise ArgumentError.new("Payment method #{brand} is not supported, check https://developer.cybersource.com/docs/cybs/en-us/payments/developer/all/rest/payments/CreatingOnlineAuth/CreatingAuthReqPNT.html")
978
+ if brand == :american_express
979
+ cavv = Base64.encode64(cavv[0...20])
980
+ xid = xid.bytes.count > 20 ? Base64.encode64(xid[20...40]) : nil
981
+ end
982
+
983
+ xml.tag! 'cavv', cavv
984
+ xml.tag! 'commerceIndicator', commerce_indicator
985
+ xml.tag! 'xid', xid if xid
986
+ end
987
+
988
+ def add_mastercard_network_tokenization_ucaf_data(xml, payment_method, options)
989
+ return unless network_tokenization?(payment_method) && card_brand(payment_method).to_sym == :master
990
+ return if payment_method.source == :network_token
991
+
992
+ commerce_indicator = 'internet' if subsequent_wallet_auth(payment_method, options)
993
+
994
+ xml.tag! 'ucaf' do
995
+ xml.tag!('authenticationData', payment_method.payment_cryptogram) unless commerce_indicator
996
+ xml.tag!('collectionIndicator', DEFAULT_COLLECTION_INDICATOR)
842
997
  end
843
998
  end
844
999
 
845
- def add_payment_network_token(xml)
1000
+ def add_payment_network_token(xml, payment_method, options)
1001
+ return unless network_tokenization?(payment_method)
1002
+
1003
+ transaction_type = payment_method.network_token? ? '3' : '1'
846
1004
  xml.tag! 'paymentNetworkToken' do
847
- xml.tag!('transactionType', '1')
1005
+ xml.tag!('requestorID', options[:trid]) if transaction_type == '3' && options[:trid]
1006
+ xml.tag!('transactionType', transaction_type)
848
1007
  end
849
1008
  end
850
1009
 
851
1010
  def add_capture_service(xml, request_id, request_token, options)
852
1011
  xml.tag! 'ccCaptureService', { 'run' => 'true' } do
853
1012
  xml.tag! 'authRequestID', request_id
1013
+ xml.tag! 'reconciliationID', options[:reconciliation_id] if options[:reconciliation_id]
854
1014
  xml.tag! 'authRequestToken', request_token
855
1015
  xml.tag! 'gratuityAmount', options[:gratuity_amount] if options[:gratuity_amount]
856
- xml.tag! 'reconciliationID', options[:reconciliation_id] if options[:reconciliation_id]
1016
+ end
1017
+ end
1018
+
1019
+ def add_capture_service_fields_with_run_false(xml, options)
1020
+ return unless options[:gratuity_amount]
1021
+
1022
+ xml.tag! 'ccCaptureService', { 'run' => 'false' } do
1023
+ xml.tag! 'gratuityAmount', options[:gratuity_amount]
857
1024
  end
858
1025
  end
859
1026
 
@@ -861,6 +1028,7 @@ module ActiveMerchant #:nodoc:
861
1028
  add_auth_service(xml, payment_method, options)
862
1029
  xml.tag! 'ccCaptureService', { 'run' => 'true' } do
863
1030
  xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
1031
+ xml.tag!('gratuityAmount', options[:gratuity_amount]) if options[:gratuity_amount]
864
1032
  end
865
1033
  end
866
1034
 
@@ -873,7 +1041,7 @@ module ActiveMerchant #:nodoc:
873
1041
 
874
1042
  def add_auth_reversal_service(xml, request_id, request_token)
875
1043
  xml.tag! 'ccAuthReversalService', { 'run' => 'true' } do
876
- xml.tag! 'authRequestID', request_id
1044
+ xml.tag! 'authRequestID', request_id unless request_id.nil?
877
1045
  xml.tag! 'authRequestToken', request_token
878
1046
  end
879
1047
  end
@@ -909,6 +1077,11 @@ module ActiveMerchant #:nodoc:
909
1077
  xml.tag! 'paySubscriptionRetrieveService', { 'run' => 'true' }
910
1078
  end
911
1079
 
1080
+ def add_merchant_category_code(xml, options)
1081
+ xml.tag! 'merchantTransactionIdentifier', options[:merchant_transaction_id] if options[:merchant_transaction_id]
1082
+ xml.tag! 'merchantCategoryCode', options[:merchant_category_code] if options[:merchant_category_code]
1083
+ end
1084
+
912
1085
  def add_subscription(xml, options, reference = nil)
913
1086
  options[:subscription] ||= {}
914
1087
 
@@ -977,10 +1150,18 @@ module ActiveMerchant #:nodoc:
977
1150
  end
978
1151
 
979
1152
  def add_threeds_services(xml, options)
980
- xml.tag! 'payerAuthEnrollService', { 'run' => 'true' } if options[:payer_auth_enroll_service]
1153
+ if options[:payer_auth_enroll_service]
1154
+ xml.tag! 'payerAuthEnrollService', { 'run' => 'true' } do
1155
+ browser_info = options.dig(:three_ds_2, :browser_info)
1156
+ xml.tag! 'httpUserAgent', browser_info[:user_agent] if browser_info&.dig(:user_agent)
1157
+ xml.tag! 'returnURL', options[:return_url] if options[:return_url]
1158
+ xml.tag! 'httpUserAccept', browser_info[:accept_header] if browser_info&.dig(:accept_header)
1159
+ end
1160
+ end
1161
+
981
1162
  if options[:payer_auth_validate_service]
982
1163
  xml.tag! 'payerAuthValidateService', { 'run' => 'true' } do
983
- xml.tag! 'signedPARes', options[:pares]
1164
+ xml.tag! 'authenticationTransactionID', options[:authentication_transaction_id]
984
1165
  end
985
1166
  end
986
1167
  end
@@ -1003,9 +1184,9 @@ module ActiveMerchant #:nodoc:
1003
1184
  def add_stored_credential_options(xml, options = {})
1004
1185
  return unless options[:stored_credential] || options[:stored_credential_overrides]
1005
1186
 
1006
- stored_credential_subsequent_auth_first = 'true' if options.dig(:stored_credential, :initial_transaction)
1187
+ stored_credential_subsequent_auth_first = 'true' if cardholder_or_initiated_transaction?(options)
1007
1188
  stored_credential_transaction_id = options.dig(:stored_credential, :network_transaction_id) if options.dig(:stored_credential, :initiator) == 'merchant'
1008
- stored_credential_subsequent_auth_stored_cred = 'true' if options.dig(:stored_credential, :initiator) == 'cardholder' && !options.dig(:stored_credential, :initial_transaction) || options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
1189
+ stored_credential_subsequent_auth_stored_cred = 'true' if subsequent_cardholder_initiated_transaction?(options) || unscheduled_merchant_initiated_transaction?(options) || threeds_stored_credential_exemption?(options)
1009
1190
 
1010
1191
  override_subsequent_auth_first = options.dig(:stored_credential_overrides, :subsequent_auth_first)
1011
1192
  override_subsequent_auth_transaction_id = options.dig(:stored_credential_overrides, :subsequent_auth_transaction_id)
@@ -1016,34 +1197,127 @@ module ActiveMerchant #:nodoc:
1016
1197
  xml.subsequentAuthStoredCredential override_subsequent_auth_stored_cred.nil? ? stored_credential_subsequent_auth_stored_cred : override_subsequent_auth_stored_cred
1017
1198
  end
1018
1199
 
1200
+ def cardholder_or_initiated_transaction?(options)
1201
+ options.dig(:stored_credential, :initiator) == 'cardholder' || options.dig(:stored_credential, :initial_transaction)
1202
+ end
1203
+
1204
+ def subsequent_cardholder_initiated_transaction?(options)
1205
+ options.dig(:stored_credential, :initiator) == 'cardholder' && !options.dig(:stored_credential, :initial_transaction)
1206
+ end
1207
+
1208
+ def unscheduled_merchant_initiated_transaction?(options)
1209
+ options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
1210
+ end
1211
+
1212
+ def threeds_stored_credential_exemption?(options)
1213
+ options[:three_ds_exemption_type] == 'stored_credential'
1214
+ end
1215
+
1019
1216
  def add_partner_solution_id(xml)
1020
1217
  return unless application_id
1021
1218
 
1022
1219
  xml.tag!('partnerSolutionID', application_id)
1023
1220
  end
1024
1221
 
1025
- # Where we actually build the full SOAP request using builder
1026
- def build_request(body, options)
1027
- xsd_version = test? ? TEST_XSD_VERSION : PRODUCTION_XSD_VERSION
1222
+ def sign_info(body)
1223
+ canonicalized = canonicalization(body)
1224
+ digest_value = OpenSSL::Digest::SHA256.digest(canonicalized)
1028
1225
 
1029
1226
  xml = Builder::XmlMarkup.new indent: 2
1030
- xml.instruct!
1031
- xml.tag! 's:Envelope', { 'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/' } do
1032
- xml.tag! 's:Header' do
1033
- xml.tag! 'wsse:Security', { 's:mustUnderstand' => '1', 'xmlns:wsse' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' } do
1227
+
1228
+ xml.tag! 'ds:SignedInfo', { 'xmlns:ds' => NS_DS } do
1229
+ xml.tag! 'ds:CanonicalizationMethod', { 'Algorithm' => C14N_ALGORITHM }
1230
+ xml.tag! 'ds:SignatureMethod', { 'Algorithm' => RSA_SHA256_ALGORITHM }
1231
+ xml.tag! 'ds:Reference', { 'URI' => '#Body' } do
1232
+ xml.tag! 'ds:Transforms' do
1233
+ xml.tag! 'ds:Transform', { 'Algorithm' => C14N_ALGORITHM }
1234
+ end
1235
+ xml.tag! 'ds:DigestMethod', { 'Algorithm' => SHA256_ALGORITHM }
1236
+ xml.tag! 'ds:DigestValue', Base64.encode64(digest_value).strip
1237
+ end
1238
+ end
1239
+
1240
+ canonicalization(xml.target!)
1241
+ end
1242
+
1243
+ def signature_element(xml, body)
1244
+ signed_info = sign_info(body)
1245
+ rsa_private_key = OpenSSL::PKey::RSA.new(@options[:private_key])
1246
+ signature = rsa_private_key.sign(OpenSSL::Digest.new('SHA256'), signed_info)
1247
+
1248
+ xml.tag! 'ds:Signature', { 'xmlns:ds' => NS_DS } do
1249
+ xml << signed_info
1250
+ xml.tag! 'ds:SignatureValue', { 'xmlns:ds' => NS_DS } do
1251
+ xml.text! Base64.encode64(signature).strip
1252
+ end
1253
+ xml.tag! 'ds:KeyInfo', { 'xmlns:ds' => NS_DS } do
1254
+ xml.tag! 'wsse:SecurityTokenReference', { 'xmlns:wsse' => NS_WSSE } do
1255
+ xml.tag! 'wsse:Reference', { 'URI' => '#X509Token', 'xmlns:wsse' => NS_WSSE }
1256
+ end
1257
+ end
1258
+ end
1259
+ end
1260
+
1261
+ def security_token_reference(xml)
1262
+ xml.tag! 'wsse:BinarySecurityToken', { 'ValueType' => BINARY_SECURITY_TOKEN_PROFILE, 'EncodingType' => BINARY_SECURITY_TOKEN_TYPE, 'xmlns:wsu' => BINARY_SECURITY_TOKEN_WSU, 'wsu:Id' => BINARY_SECURITY_TOKEN_ID } do
1263
+ xml.text! @options[:public_key]
1264
+ end
1265
+ end
1266
+
1267
+ def set_headers(xml, body)
1268
+ xml.tag! 's:Header' do
1269
+ xml.tag! 'wsse:Security', { 'xmlns:wsse' => NS_WSSE } do
1270
+ if @options[:public_key]
1271
+ security_token_reference(xml)
1272
+ signature_element(xml, body)
1273
+ else
1034
1274
  xml.tag! 'wsse:UsernameToken' do
1035
1275
  xml.tag! 'wsse:Username', @options[:login]
1036
- xml.tag! 'wsse:Password', @options[:password], 'Type' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'
1276
+ xml.tag! 'wsse:Password', @options[:password], 'Type' => USERNAME_TOKEN_PROFILE
1037
1277
  end
1038
1278
  end
1039
1279
  end
1040
- xml.tag! 's:Body', { 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema' } do
1041
- xml.tag! 'requestMessage', { 'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{xsd_version}" } do
1042
- add_merchant_data(xml, options)
1043
- xml << body
1044
- end
1280
+ end
1281
+ end
1282
+
1283
+ def build_body(request, options, xsd_version)
1284
+ xml = Builder::XmlMarkup.new indent: 2
1285
+
1286
+ arguments =
1287
+ if @options[:public_key]
1288
+ { 'xmlns:s' => ENVELOPE, 'xmlns:wsu' => BINARY_SECURITY_TOKEN_WSU, 'wsu:Id' => 'Body' }
1289
+ else
1290
+ { 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema' }
1045
1291
  end
1292
+
1293
+ xml.tag! 's:Body', arguments do
1294
+ xml.tag! 'requestMessage', { 'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{xsd_version}" } do
1295
+ add_merchant_data(xml, options)
1296
+ xml << request
1297
+ end
1298
+ end
1299
+
1300
+ xml.target!
1301
+ end
1302
+
1303
+ def canonicalization(xml)
1304
+ doc = Nokogiri::XML(xml)
1305
+ doc.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
1306
+ end
1307
+
1308
+ # Where we actually build the full SOAP request using builder
1309
+ def build_request(request, options)
1310
+ xsd_version = test? ? TEST_XSD_VERSION : PRODUCTION_XSD_VERSION
1311
+
1312
+ body = build_body(request, options, xsd_version)
1313
+ xml = Builder::XmlMarkup.new indent: 2
1314
+
1315
+ xml.instruct!
1316
+ xml.tag! 's:Envelope', { 'xmlns:s' => ENVELOPE, 'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{xsd_version}" } do
1317
+ set_headers(xml, body)
1318
+ xml << body
1046
1319
  end
1320
+
1047
1321
  xml.target!
1048
1322
  end
1049
1323
 
@@ -1068,12 +1342,16 @@ module ActiveMerchant #:nodoc:
1068
1342
 
1069
1343
  message = auto_void?(authorization_from(response, action, amount, options), response, message, options)
1070
1344
 
1071
- Response.new(success, message, response,
1345
+ Response.new(
1346
+ success,
1347
+ message,
1348
+ response,
1072
1349
  test: test?,
1073
- authorization: authorization,
1350
+ authorization:,
1074
1351
  fraud_review: in_fraud_review?(response),
1075
1352
  avs_result: { code: response[:avsCode] },
1076
- cvv_result: response[:cvCode])
1353
+ cvv_result: response[:cvCode]
1354
+ )
1077
1355
  end
1078
1356
 
1079
1357
  def auto_void?(authorization, response, message, options = {})
@@ -1115,6 +1393,7 @@ module ActiveMerchant #:nodoc:
1115
1393
  parent += '_' + node.parent.attributes['id'] if node.parent.attributes['id']
1116
1394
  parent += '_'
1117
1395
  end
1396
+ reply[:reconciliationID2] = node.text if node.name == 'reconciliationID' && reply[:reconciliationID]
1118
1397
  reply["#{parent}#{node.name}".to_sym] ||= node.text
1119
1398
  end
1120
1399
  return reply