activemerchant 1.100.0 → 1.133.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (267) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +1057 -0
  3. data/README.md +11 -9
  4. data/lib/active_merchant/billing/avs_result.rb +9 -9
  5. data/lib/active_merchant/billing/base.rb +0 -13
  6. data/lib/active_merchant/billing/check.rb +49 -17
  7. data/lib/active_merchant/billing/compatibility.rb +5 -4
  8. data/lib/active_merchant/billing/credit_card.rb +55 -8
  9. data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
  10. data/lib/active_merchant/billing/credit_card_methods.rb +209 -36
  11. data/lib/active_merchant/billing/cvv_result.rb +0 -1
  12. data/lib/active_merchant/billing/gateway.rb +38 -36
  13. data/lib/active_merchant/billing/gateways/adyen.rb +399 -78
  14. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  15. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  16. data/lib/active_merchant/billing/gateways/allied_wallet.rb +14 -14
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +200 -130
  18. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +27 -20
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +48 -51
  20. data/lib/active_merchant/billing/gateways/axcessms.rb +13 -15
  21. data/lib/active_merchant/billing/gateways/balanced.rb +43 -36
  22. data/lib/active_merchant/billing/gateways/bambora_apac.rb +16 -20
  23. data/lib/active_merchant/billing/gateways/bank_frick.rb +13 -13
  24. data/lib/active_merchant/billing/gateways/banwire.rb +5 -5
  25. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +43 -30
  26. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/be2bill.rb +5 -5
  28. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +37 -36
  29. data/lib/active_merchant/billing/gateways/beanstream.rb +21 -3
  30. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +1 -1
  31. data/lib/active_merchant/billing/gateways/blue_pay.rb +53 -28
  32. data/lib/active_merchant/billing/gateways/blue_snap.rb +176 -54
  33. data/lib/active_merchant/billing/gateways/bogus.rb +24 -20
  34. data/lib/active_merchant/billing/gateways/borgun.rb +92 -38
  35. data/lib/active_merchant/billing/gateways/bpoint.rb +15 -15
  36. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +8 -2
  37. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +1 -1
  39. data/lib/active_merchant/billing/gateways/braintree_blue.rb +387 -175
  40. data/lib/active_merchant/billing/gateways/bridge_pay.rb +13 -13
  41. data/lib/active_merchant/billing/gateways/cams.rb +10 -10
  42. data/lib/active_merchant/billing/gateways/card_connect.rb +33 -14
  43. data/lib/active_merchant/billing/gateways/card_save.rb +3 -4
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +67 -40
  45. data/lib/active_merchant/billing/gateways/cardknox.rb +13 -13
  46. data/lib/active_merchant/billing/gateways/cardprocess.rb +4 -2
  47. data/lib/active_merchant/billing/gateways/cashnet.rb +28 -12
  48. data/lib/active_merchant/billing/gateways/cc5.rb +9 -9
  49. data/lib/active_merchant/billing/gateways/cecabank.rb +38 -38
  50. data/lib/active_merchant/billing/gateways/cenpos.rb +29 -28
  51. data/lib/active_merchant/billing/gateways/checkout.rb +7 -9
  52. data/lib/active_merchant/billing/gateways/checkout_v2.rb +316 -68
  53. data/lib/active_merchant/billing/gateways/citrus_pay.rb +1 -2
  54. data/lib/active_merchant/billing/gateways/clearhaus.rb +32 -33
  55. data/lib/active_merchant/billing/gateways/commerce_hub.rb +370 -0
  56. data/lib/active_merchant/billing/gateways/commercegate.rb +4 -4
  57. data/lib/active_merchant/billing/gateways/conekta.rb +8 -6
  58. data/lib/active_merchant/billing/gateways/creditcall.rb +18 -17
  59. data/lib/active_merchant/billing/gateways/credorax.rb +152 -63
  60. data/lib/active_merchant/billing/gateways/ct_payment.rb +15 -14
  61. data/lib/active_merchant/billing/gateways/culqi.rb +30 -28
  62. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  63. data/lib/active_merchant/billing/gateways/cyber_source.rb +496 -187
  64. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +454 -0
  65. data/lib/active_merchant/billing/gateways/d_local.rb +148 -31
  66. data/lib/active_merchant/billing/gateways/data_cash.rb +34 -37
  67. data/lib/active_merchant/billing/gateways/decidir.rb +134 -21
  68. data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
  69. data/lib/active_merchant/billing/gateways/dibs.rb +10 -10
  70. data/lib/active_merchant/billing/gateways/digitzs.rb +11 -8
  71. data/lib/active_merchant/billing/gateways/ebanx.rb +90 -40
  72. data/lib/active_merchant/billing/gateways/efsnet.rb +36 -36
  73. data/lib/active_merchant/billing/gateways/elavon.rb +349 -194
  74. data/lib/active_merchant/billing/gateways/element.rb +71 -21
  75. data/lib/active_merchant/billing/gateways/epay.rb +43 -43
  76. data/lib/active_merchant/billing/gateways/evo_ca.rb +12 -13
  77. data/lib/active_merchant/billing/gateways/eway.rb +9 -9
  78. data/lib/active_merchant/billing/gateways/eway_managed.rb +55 -56
  79. data/lib/active_merchant/billing/gateways/eway_rapid.rb +37 -22
  80. data/lib/active_merchant/billing/gateways/exact.rb +19 -20
  81. data/lib/active_merchant/billing/gateways/ezic.rb +9 -9
  82. data/lib/active_merchant/billing/gateways/fat_zebra.rb +24 -19
  83. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -7
  84. data/lib/active_merchant/billing/gateways/finansbank.rb +3 -3
  85. data/lib/active_merchant/billing/gateways/first_giving.rb +5 -4
  86. data/lib/active_merchant/billing/gateways/first_pay.rb +7 -7
  87. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +39 -38
  88. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +51 -31
  89. data/lib/active_merchant/billing/gateways/flo2cash.rb +24 -24
  90. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +1 -1
  91. data/lib/active_merchant/billing/gateways/forte.rb +38 -22
  92. data/lib/active_merchant/billing/gateways/garanti.rb +12 -15
  93. data/lib/active_merchant/billing/gateways/global_collect.rb +333 -89
  94. data/lib/active_merchant/billing/gateways/global_transport.rb +8 -9
  95. data/lib/active_merchant/billing/gateways/hdfc.rb +22 -23
  96. data/lib/active_merchant/billing/gateways/hps.rb +171 -50
  97. data/lib/active_merchant/billing/gateways/iats_payments.rb +47 -25
  98. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +1 -1
  99. data/lib/active_merchant/billing/gateways/inspire.rb +22 -27
  100. data/lib/active_merchant/billing/gateways/instapay.rb +5 -8
  101. data/lib/active_merchant/billing/gateways/ipg.rb +420 -0
  102. data/lib/active_merchant/billing/gateways/ipp.rb +9 -9
  103. data/lib/active_merchant/billing/gateways/iridium.rb +30 -31
  104. data/lib/active_merchant/billing/gateways/itransact.rb +11 -10
  105. data/lib/active_merchant/billing/gateways/iveri.rb +62 -23
  106. data/lib/active_merchant/billing/gateways/ixopay.rb +320 -0
  107. data/lib/active_merchant/billing/gateways/jetpay.rb +10 -17
  108. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +13 -18
  109. data/lib/active_merchant/billing/gateways/komoju.rb +1 -1
  110. data/lib/active_merchant/billing/gateways/kushki.rb +100 -22
  111. data/lib/active_merchant/billing/gateways/latitude19.rb +20 -19
  112. data/lib/active_merchant/billing/gateways/linkpoint.rb +71 -72
  113. data/lib/active_merchant/billing/gateways/litle.rb +181 -45
  114. data/lib/active_merchant/billing/gateways/mastercard.rb +16 -22
  115. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  116. data/lib/active_merchant/billing/gateways/mercado_pago.rb +89 -18
  117. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +58 -24
  118. data/lib/active_merchant/billing/gateways/merchant_one.rb +7 -10
  119. data/lib/active_merchant/billing/gateways/merchant_partners.rb +19 -19
  120. data/lib/active_merchant/billing/gateways/merchant_ware.rb +18 -22
  121. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +15 -17
  122. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +46 -8
  123. data/lib/active_merchant/billing/gateways/mercury.rb +19 -23
  124. data/lib/active_merchant/billing/gateways/metrics_global.rb +24 -33
  125. data/lib/active_merchant/billing/gateways/micropayment.rb +11 -12
  126. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +7 -7
  127. data/lib/active_merchant/billing/gateways/migs.rb +18 -21
  128. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  129. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +10 -12
  130. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  131. data/lib/active_merchant/billing/gateways/monei.rb +236 -150
  132. data/lib/active_merchant/billing/gateways/moneris.rb +122 -53
  133. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -7
  134. data/lib/active_merchant/billing/gateways/mundipagg.rb +69 -23
  135. data/lib/active_merchant/billing/gateways/nab_transact.rb +18 -20
  136. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +10 -12
  137. data/lib/active_merchant/billing/gateways/net_registry.rb +8 -9
  138. data/lib/active_merchant/billing/gateways/netaxept.rb +12 -12
  139. data/lib/active_merchant/billing/gateways/netbanx.rb +128 -46
  140. data/lib/active_merchant/billing/gateways/netbilling.rb +18 -21
  141. data/lib/active_merchant/billing/gateways/netpay.rb +5 -4
  142. data/lib/active_merchant/billing/gateways/network_merchants.rb +7 -10
  143. data/lib/active_merchant/billing/gateways/nmi.rb +69 -27
  144. data/lib/active_merchant/billing/gateways/ogone.rb +62 -31
  145. data/lib/active_merchant/billing/gateways/omise.rb +15 -16
  146. data/lib/active_merchant/billing/gateways/openpay.rb +33 -15
  147. data/lib/active_merchant/billing/gateways/opp.rb +39 -33
  148. data/lib/active_merchant/billing/gateways/optimal_payment.rb +43 -42
  149. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +3 -5
  150. data/lib/active_merchant/billing/gateways/orbital.rb +623 -362
  151. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +20 -20
  152. data/lib/active_merchant/billing/gateways/pagarme.rb +16 -23
  153. data/lib/active_merchant/billing/gateways/pago_facil.rb +4 -6
  154. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  155. data/lib/active_merchant/billing/gateways/pay_conex.rb +17 -17
  156. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +30 -33
  157. data/lib/active_merchant/billing/gateways/pay_hub.rb +10 -10
  158. data/lib/active_merchant/billing/gateways/pay_junction.rb +31 -31
  159. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +36 -18
  160. data/lib/active_merchant/billing/gateways/pay_secure.rb +10 -11
  161. data/lib/active_merchant/billing/gateways/pay_trace.rb +450 -0
  162. data/lib/active_merchant/billing/gateways/paybox_direct.rb +64 -40
  163. data/lib/active_merchant/billing/gateways/payeezy.rb +130 -27
  164. data/lib/active_merchant/billing/gateways/payex.rb +24 -25
  165. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +17 -17
  166. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +1 -1
  167. data/lib/active_merchant/billing/gateways/payflow.rb +103 -25
  168. data/lib/active_merchant/billing/gateways/payflow_express.rb +4 -4
  169. data/lib/active_merchant/billing/gateways/payflow_uk.rb +1 -1
  170. data/lib/active_merchant/billing/gateways/payment_express.rb +22 -18
  171. data/lib/active_merchant/billing/gateways/paymentez.rb +89 -24
  172. data/lib/active_merchant/billing/gateways/paymill.rb +14 -16
  173. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +2 -1
  174. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  175. data/lib/active_merchant/billing/gateways/paypal.rb +13 -5
  176. data/lib/active_merchant/billing/gateways/paypal_ca.rb +1 -1
  177. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +1 -1
  178. data/lib/active_merchant/billing/gateways/paypal_express.rb +4 -1
  179. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +1 -1
  180. data/lib/active_merchant/billing/gateways/paysafe.rb +420 -0
  181. data/lib/active_merchant/billing/gateways/payscout.rb +8 -9
  182. data/lib/active_merchant/billing/gateways/paystation.rb +6 -9
  183. data/lib/active_merchant/billing/gateways/payu_in.rb +20 -19
  184. data/lib/active_merchant/billing/gateways/payu_latam.rb +70 -37
  185. data/lib/active_merchant/billing/gateways/payway.rb +22 -22
  186. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  187. data/lib/active_merchant/billing/gateways/pin.rb +60 -21
  188. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  189. data/lib/active_merchant/billing/gateways/plugnpay.rb +20 -21
  190. data/lib/active_merchant/billing/gateways/priority.rb +392 -0
  191. data/lib/active_merchant/billing/gateways/pro_pay.rb +13 -14
  192. data/lib/active_merchant/billing/gateways/psigate.rb +29 -29
  193. data/lib/active_merchant/billing/gateways/psl_card.rb +7 -8
  194. data/lib/active_merchant/billing/gateways/qbms.rb +25 -26
  195. data/lib/active_merchant/billing/gateways/quantum.rb +9 -11
  196. data/lib/active_merchant/billing/gateways/quickbooks.rb +126 -39
  197. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +98 -98
  198. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +19 -23
  199. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +3 -3
  200. data/lib/active_merchant/billing/gateways/quickpay.rb +0 -1
  201. data/lib/active_merchant/billing/gateways/qvalent.rb +36 -20
  202. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  203. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  204. data/lib/active_merchant/billing/gateways/realex.rb +42 -16
  205. data/lib/active_merchant/billing/gateways/redsys.rb +191 -86
  206. data/lib/active_merchant/billing/gateways/s5.rb +10 -9
  207. data/lib/active_merchant/billing/gateways/safe_charge.rb +70 -33
  208. data/lib/active_merchant/billing/gateways/sage.rb +19 -21
  209. data/lib/active_merchant/billing/gateways/sage_pay.rb +57 -57
  210. data/lib/active_merchant/billing/gateways/sallie_mae.rb +3 -4
  211. data/lib/active_merchant/billing/gateways/secure_net.rb +19 -26
  212. data/lib/active_merchant/billing/gateways/secure_pay.rb +24 -33
  213. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +18 -20
  214. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +4 -5
  215. data/lib/active_merchant/billing/gateways/securion_pay.rb +48 -7
  216. data/lib/active_merchant/billing/gateways/shift4.rb +345 -0
  217. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  218. data/lib/active_merchant/billing/gateways/skip_jack.rb +19 -19
  219. data/lib/active_merchant/billing/gateways/smart_ps.rb +26 -32
  220. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +24 -25
  221. data/lib/active_merchant/billing/gateways/spreedly_core.rb +27 -21
  222. data/lib/active_merchant/billing/gateways/stripe.rb +126 -53
  223. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +441 -113
  224. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +7 -8
  225. data/lib/active_merchant/billing/gateways/telr.rb +17 -18
  226. data/lib/active_merchant/billing/gateways/tns.rb +3 -7
  227. data/lib/active_merchant/billing/gateways/trans_first.rb +10 -9
  228. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +28 -24
  229. data/lib/active_merchant/billing/gateways/transact_pro.rb +13 -15
  230. data/lib/active_merchant/billing/gateways/transax.rb +1 -2
  231. data/lib/active_merchant/billing/gateways/trexle.rb +5 -2
  232. data/lib/active_merchant/billing/gateways/trust_commerce.rb +57 -47
  233. data/lib/active_merchant/billing/gateways/usa_epay.rb +1 -2
  234. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +176 -184
  235. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +60 -48
  236. data/lib/active_merchant/billing/gateways/vanco.rb +17 -8
  237. data/lib/active_merchant/billing/gateways/verifi.rb +13 -14
  238. data/lib/active_merchant/billing/gateways/viaklix.rb +9 -14
  239. data/lib/active_merchant/billing/gateways/visanet_peru.rb +26 -21
  240. data/lib/active_merchant/billing/gateways/vpos.rb +223 -0
  241. data/lib/active_merchant/billing/gateways/webpay.rb +4 -4
  242. data/lib/active_merchant/billing/gateways/wepay.rb +14 -16
  243. data/lib/active_merchant/billing/gateways/wirecard.rb +14 -16
  244. data/lib/active_merchant/billing/gateways/wompi.rb +197 -0
  245. data/lib/active_merchant/billing/gateways/world_net.rb +36 -35
  246. data/lib/active_merchant/billing/gateways/worldpay.rb +556 -190
  247. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +47 -54
  248. data/lib/active_merchant/billing/gateways/worldpay_us.rb +16 -16
  249. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +2 -2
  250. data/lib/active_merchant/billing/response.rb +25 -6
  251. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  252. data/lib/active_merchant/billing.rb +1 -0
  253. data/lib/active_merchant/connection.rb +14 -15
  254. data/lib/active_merchant/country.rb +3 -1
  255. data/lib/active_merchant/errors.rb +4 -1
  256. data/lib/active_merchant/net_http_ssl_connection.rb +1 -0
  257. data/lib/active_merchant/network_connection_retries.rb +15 -17
  258. data/lib/active_merchant/post_data.rb +3 -2
  259. data/lib/active_merchant/posts_data.rb +2 -2
  260. data/lib/active_merchant/version.rb +1 -1
  261. data/lib/active_merchant.rb +2 -2
  262. data/lib/certs/cacert.pem +1587 -2361
  263. data/lib/support/gateway_support.rb +1 -1
  264. data/lib/support/ssl_verify.rb +3 -7
  265. data/lib/support/ssl_version.rb +2 -3
  266. metadata +86 -34
  267. data/lib/active_merchant/billing/gateways/moneris_us.rb +0 -352
@@ -15,9 +15,6 @@ module ActiveMerchant #:nodoc:
15
15
  # CyberSource what kind of item you are selling. It is used when
16
16
  # calculating tax/VAT.
17
17
  # * All transactions use dollar values.
18
- # * To process pinless debit cards through the pinless debit card
19
- # network, your Cybersource merchant account must accept pinless
20
- # debit card payments.
21
18
  # * The order of the XML elements does matter, make sure to follow the order in
22
19
  # the documentation exactly.
23
20
  class CyberSourceGateway < Gateway
@@ -25,11 +22,21 @@ module ActiveMerchant #:nodoc:
25
22
  self.live_url = 'https://ics2wsa.ic3.com/commerce/1.x/transactionProcessor'
26
23
 
27
24
  # Schema files can be found here: https://ics2ws.ic3.com/commerce/1.x/transactionProcessor/
28
- TEST_XSD_VERSION = '1.159'
29
- PRODUCTION_XSD_VERSION = '1.159'
30
-
31
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro, :elo]
32
- self.supported_countries = %w(US BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB PK)
25
+ TEST_XSD_VERSION = '1.201'
26
+ PRODUCTION_XSD_VERSION = '1.201'
27
+ ECI_BRAND_MAPPING = {
28
+ visa: 'vbv',
29
+ master: 'spa',
30
+ maestro: 'spa',
31
+ american_express: 'aesk',
32
+ jcb: 'js',
33
+ discover: 'pb',
34
+ diners_club: 'pb'
35
+ }.freeze
36
+ DEFAULT_COLLECTION_INDICATOR = 2
37
+
38
+ self.supported_cardtypes = %i[visa master american_express discover diners_club jcb dankort maestro elo]
39
+ self.supported_countries = %w(US AE BR CA CN DK FI FR DE IN JP MX NO SE GB SG LB PK)
33
40
 
34
41
  self.default_currency = 'USD'
35
42
  self.currencies_without_fractions = %w(JPY)
@@ -38,56 +45,96 @@ module ActiveMerchant #:nodoc:
38
45
  self.display_name = 'CyberSource'
39
46
 
40
47
  @@credit_card_codes = {
41
- :visa => '001',
42
- :master => '002',
43
- :american_express => '003',
44
- :discover => '004',
45
- :diners_club => '005',
46
- :jcb => '007',
47
- :dankort => '034',
48
- :maestro => '042',
49
- :elo => '054'
48
+ visa: '001',
49
+ master: '002',
50
+ american_express: '003',
51
+ discover: '004',
52
+ diners_club: '005',
53
+ jcb: '007',
54
+ dankort: '034',
55
+ maestro: '042',
56
+ elo: '054'
57
+ }
58
+
59
+ @@decision_codes = {
60
+ accept: 'ACCEPT',
61
+ review: 'REVIEW'
50
62
  }
51
63
 
52
64
  @@response_codes = {
53
- :r100 => 'Successful transaction',
54
- :r101 => 'Request is missing one or more required fields',
55
- :r102 => 'One or more fields contains invalid data',
56
- :r150 => 'General failure',
57
- :r151 => 'The request was received but a server time-out occurred',
58
- :r152 => 'The request was received, but a service timed out',
59
- :r200 => 'The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the AVS check',
60
- :r201 => 'The issuing bank has questions about the request',
61
- :r202 => 'Expired card',
62
- :r203 => 'General decline of the card',
63
- :r204 => 'Insufficient funds in the account',
64
- :r205 => 'Stolen or lost card',
65
- :r207 => 'Issuing bank unavailable',
66
- :r208 => 'Inactive card or card not authorized for card-not-present transactions',
67
- :r209 => 'American Express Card Identifiction Digits (CID) did not match',
68
- :r210 => 'The card has reached the credit limit',
69
- :r211 => 'Invalid card verification number',
70
- :r221 => "The customer matched an entry on the processor's negative file",
71
- :r230 => 'The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check',
72
- :r231 => 'Invalid account number',
73
- :r232 => 'The card type is not accepted by the payment processor',
74
- :r233 => 'General decline by the processor',
75
- :r234 => 'A problem exists with your CyberSource merchant configuration',
76
- :r235 => 'The requested amount exceeds the originally authorized amount',
77
- :r236 => 'Processor failure',
78
- :r237 => 'The authorization has already been reversed',
79
- :r238 => 'The authorization has already been captured',
80
- :r239 => 'The requested transaction amount must match the previous transaction amount',
81
- :r240 => 'The card type sent is invalid or does not correlate with the credit card number',
82
- :r241 => 'The request ID is invalid',
83
- :r242 => 'You requested a capture, but there is no corresponding, unused authorization record.',
84
- :r243 => 'The transaction has already been settled or reversed',
85
- :r244 => 'The bank account number failed the validation check',
86
- :r246 => 'The capture or credit is not voidable because the capture or credit information has already been submitted to your processor',
87
- :r247 => 'You requested a credit for a capture that was previously voided',
88
- :r250 => 'The request was received, but a time-out occurred with the payment processor',
89
- :r254 => 'Your CyberSource account is prohibited from processing stand-alone refunds',
90
- :r255 => 'Your CyberSource account is not configured to process the service in the country you specified'
65
+ r100: 'Successful transaction',
66
+ r101: 'Request is missing one or more required fields',
67
+ r102: 'One or more fields contains invalid data',
68
+ r104: 'The merchantReferenceCode sent with this authorization request matches the merchantReferenceCode of another authorization request that you sent in the last 15 minutes.', r110: 'Partial amount was approved',
69
+ r150: 'General failure',
70
+ r151: 'The request was received but a server time-out occurred',
71
+ r152: 'The request was received, but a service timed out',
72
+ r200: 'The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the AVS check',
73
+ r201: 'The issuing bank has questions about the request',
74
+ r202: 'Expired card',
75
+ r203: 'General decline of the card',
76
+ r204: 'Insufficient funds in the account',
77
+ r205: 'Stolen or lost card',
78
+ r207: 'Issuing bank unavailable',
79
+ r208: 'Inactive card or card not authorized for card-not-present transactions',
80
+ r209: 'American Express Card Identifiction Digits (CID) did not match',
81
+ r210: 'The card has reached the credit limit',
82
+ r211: 'Invalid card verification number',
83
+ r220: 'Generic Decline.',
84
+ r221: "The customer matched an entry on the processor's negative file",
85
+ r222: 'customer\'s account is frozen',
86
+ r230: 'The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check',
87
+ r231: 'Invalid account number',
88
+ r232: 'The card type is not accepted by the payment processor',
89
+ r233: 'General decline by the processor',
90
+ r234: 'A problem exists with your CyberSource merchant configuration',
91
+ r235: 'The requested amount exceeds the originally authorized amount',
92
+ r236: 'Processor failure',
93
+ r237: 'The authorization has already been reversed',
94
+ r238: 'The authorization has already been captured',
95
+ r239: 'The requested transaction amount must match the previous transaction amount',
96
+ r240: 'The card type sent is invalid or does not correlate with the credit card number',
97
+ r241: 'The request ID is invalid',
98
+ r242: 'You requested a capture, but there is no corresponding, unused authorization record.',
99
+ r243: 'The transaction has already been settled or reversed',
100
+ r244: 'The bank account number failed the validation check',
101
+ r246: 'The capture or credit is not voidable because the capture or credit information has already been submitted to your processor',
102
+ r247: 'You requested a credit for a capture that was previously voided',
103
+ r248: 'The boleto request was declined by your processor.',
104
+ r250: 'The request was received, but a time-out occurred with the payment processor',
105
+ r251: 'The Pinless Debit card\'s use frequency or maximum amount per use has been exceeded.',
106
+ r254: 'Your CyberSource account is prohibited from processing stand-alone refunds',
107
+ r255: 'Your CyberSource account is not configured to process the service in the country you specified',
108
+ r400: 'Soft Decline - Fraud score exceeds threshold.',
109
+ r450: 'Apartment number missing or not found.',
110
+ r451: 'Insufficient address information.',
111
+ r452: 'House/Box number not found on street.',
112
+ r453: 'Multiple address matches were found.',
113
+ r454: 'P.O. Box identifier not found or out of range.',
114
+ r455: 'Route service identifier not found or out of range.',
115
+ r456: 'Street name not found in Postal code.',
116
+ r457: 'Postal code not found in database.',
117
+ r458: 'Unable to verify or correct address.',
118
+ r459: 'Multiple addres matches were found (international)',
119
+ r460: 'Address match not found (no reason given)',
120
+ r461: 'Unsupported character set',
121
+ r475: 'The cardholder is enrolled in Payer Authentication. Please authenticate the cardholder before continuing with the transaction.',
122
+ r476: 'Encountered a Payer Authentication problem. Payer could not be authenticated.',
123
+ r478: 'Strong customer authentication (SCA) is required for this transaction.',
124
+ r480: 'The order is marked for review by Decision Manager',
125
+ r481: 'The order has been rejected by Decision Manager',
126
+ r490: 'Your aggregator or acquirer is not accepting transactions from you at this time.',
127
+ r491: 'Your aggregator or acquirer is not accepting this transaction.',
128
+ r520: 'Soft Decline - The authorization request was approved by the issuing bank but declined by CyberSource based on your Smart Authorization settings.',
129
+ r700: 'The customer matched the Denied Parties List',
130
+ r701: 'Export bill_country/ship_country match',
131
+ r702: 'Export email_country match',
132
+ r703: 'Export hostname_country/ip_country match'
133
+ }
134
+
135
+ @@payment_solution = {
136
+ apple_pay: '001',
137
+ google_pay: '012'
91
138
  }
92
139
 
93
140
  # These are the options that can be used when creating a new CyberSource
@@ -124,7 +171,6 @@ module ActiveMerchant #:nodoc:
124
171
  commit(build_capture_request(money, authorization, options), :capture, money, options)
125
172
  end
126
173
 
127
- # options[:pinless_debit_card] => true # attempts to process as pinless debit card
128
174
  def purchase(money, payment_method_or_reference, options = {})
129
175
  setup_address_hash(options)
130
176
  commit(build_purchase_request(money, payment_method_or_reference, options), :purchase, money, options)
@@ -138,10 +184,15 @@ module ActiveMerchant #:nodoc:
138
184
  commit(build_refund_request(money, identification, options), :refund, money, options)
139
185
  end
140
186
 
187
+ def adjust(money, authorization, options = {})
188
+ commit(build_adjust_request(money, authorization, options), :adjust, money, options)
189
+ end
190
+
141
191
  def verify(payment, options = {})
192
+ amount = eligible_for_zero_auth?(payment, options) ? 0 : 100
142
193
  MultiResponse.run(:use_first_response) do |r|
143
- r.process { authorize(100, payment, options) }
144
- r.process(:ignore_result) { void(r.authorization, options) }
194
+ r.process { authorize(amount, payment, options) }
195
+ r.process(:ignore_result) { void(r.authorization, options) } unless amount == 0
145
196
  end
146
197
  end
147
198
 
@@ -205,17 +256,11 @@ module ActiveMerchant #:nodoc:
205
256
  # This functionality is only supported by this particular gateway may
206
257
  # be changed at any time
207
258
  def calculate_tax(creditcard, options)
208
- requires!(options, :line_items)
259
+ requires!(options, :line_items)
209
260
  setup_address_hash(options)
210
261
  commit(build_tax_calculation_request(creditcard, options), :calculate_tax, nil, options)
211
262
  end
212
263
 
213
- # Determines if a card can be used for Pinless Debit Card transactions
214
- def validate_pinless_debit_card(creditcard, options = {})
215
- requires!(options, :order_id)
216
- commit(build_validate_pinless_debit_request(creditcard, options), :validate_pinless_debit_card, nil, options)
217
- end
218
-
219
264
  def supports_scrubbing?
220
265
  true
221
266
  end
@@ -241,44 +286,75 @@ module ActiveMerchant #:nodoc:
241
286
 
242
287
  private
243
288
 
244
- # Create all address hash key value pairs so that we still function if we
245
- # were only provided with one or two of them or even none
289
+ # Create all required address hash key value pairs
290
+ # 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
+ # Billing address fields received without an override value or with an empty string value will be replaced with the default_address values
246
292
  def setup_address_hash(options)
247
293
  default_address = {
248
- :address1 => 'Unspecified',
249
- :city => 'Unspecified',
250
- :state => 'NC',
251
- :zip => '00000',
252
- :country => 'US'
294
+ address1: 'Unspecified',
295
+ city: 'Unspecified',
296
+ state: 'NC',
297
+ zip: '00000',
298
+ country: 'US'
253
299
  }
254
- options[:billing_address] = options[:billing_address] || options[:address] || default_address
300
+
301
+ submitted_address = options[:billing_address] || options[:address] || default_address
302
+ options[:billing_address] = default_address.merge(submitted_address.symbolize_keys) { |_k, default, submitted| check_billing_field_value(default, submitted) }
255
303
  options[:shipping_address] = options[:shipping_address] || {}
256
304
  end
257
305
 
306
+ def check_billing_field_value(default, submitted)
307
+ if submitted.nil?
308
+ nil
309
+ elsif submitted.blank?
310
+ default
311
+ else
312
+ submitted
313
+ end
314
+ end
315
+
258
316
  def build_auth_request(money, creditcard_or_reference, options)
259
- xml = Builder::XmlMarkup.new :indent => 2
317
+ xml = Builder::XmlMarkup.new indent: 2
318
+ add_customer_id(xml, options)
260
319
  add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
320
+ add_other_tax(xml, options)
261
321
  add_threeds_2_ucaf_data(xml, creditcard_or_reference, options)
262
322
  add_decision_manager_fields(xml, options)
263
323
  add_mdd_fields(xml, options)
264
324
  add_auth_service(xml, creditcard_or_reference, options)
265
325
  add_threeds_services(xml, options)
266
- add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
267
326
  add_business_rules_data(xml, creditcard_or_reference, options)
268
- add_stored_credential_options(xml, options)
327
+ add_airline_data(xml, options)
328
+ 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)
331
+ add_tax_management_indicator(xml, options)
332
+ add_stored_credential_subsequent_auth(xml, options)
269
333
  add_issuer_additional_data(xml, options)
334
+ add_partner_solution_id(xml)
335
+ add_stored_credential_options(xml, options)
336
+ add_merchant_description(xml, options)
337
+ xml.target!
338
+ end
339
+
340
+ def build_adjust_request(money, authorization, options)
341
+ _, request_id = authorization.split(';')
270
342
 
343
+ xml = Builder::XmlMarkup.new indent: 2
344
+ add_purchase_data(xml, money, true, options)
345
+ add_incremental_auth_service(xml, request_id, options)
271
346
  xml.target!
272
347
  end
273
348
 
274
349
  def build_tax_calculation_request(creditcard, options)
275
- xml = Builder::XmlMarkup.new :indent => 2
350
+ xml = Builder::XmlMarkup.new indent: 2
276
351
  add_address(xml, creditcard, options[:billing_address], options, false)
277
352
  add_address(xml, creditcard, options[:shipping_address], options, true)
278
353
  add_line_item_data(xml, options)
279
354
  add_purchase_data(xml, 0, false, options)
280
355
  add_tax_service(xml)
281
356
  add_business_rules_data(xml, creditcard, options)
357
+ add_tax_management_indicator(xml, options)
282
358
  xml.target!
283
359
  end
284
360
 
@@ -286,43 +362,78 @@ module ActiveMerchant #:nodoc:
286
362
  order_id, request_id, request_token = authorization.split(';')
287
363
  options[:order_id] = order_id
288
364
 
289
- xml = Builder::XmlMarkup.new :indent => 2
365
+ xml = Builder::XmlMarkup.new indent: 2
290
366
  add_purchase_data(xml, money, true, options)
291
- add_capture_service(xml, request_id, request_token)
367
+ add_other_tax(xml, options)
368
+ add_mdd_fields(xml, options)
369
+ add_capture_service(xml, request_id, request_token, options)
292
370
  add_business_rules_data(xml, authorization, options)
371
+ add_tax_management_indicator(xml, options)
372
+ add_issuer_additional_data(xml, options)
373
+ add_merchant_description(xml, options)
374
+ add_partner_solution_id(xml)
375
+
293
376
  xml.target!
294
377
  end
295
378
 
296
379
  def build_purchase_request(money, payment_method_or_reference, options)
297
- xml = Builder::XmlMarkup.new :indent => 2
380
+ xml = Builder::XmlMarkup.new indent: 2
381
+ add_customer_id(xml, options)
298
382
  add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
383
+ add_other_tax(xml, options)
299
384
  add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
300
385
  add_decision_manager_fields(xml, options)
301
386
  add_mdd_fields(xml, options)
302
- if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
387
+ if (!payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check') || reference_is_a_check?(payment_method_or_reference)
303
388
  add_check_service(xml)
389
+ add_airline_data(xml, options)
390
+ add_sales_slip_number(xml, options)
391
+ add_tax_management_indicator(xml, options)
392
+ add_issuer_additional_data(xml, options)
393
+ add_partner_solution_id(xml)
394
+ options[:payment_method] = :check
304
395
  else
305
396
  add_purchase_service(xml, payment_method_or_reference, options)
306
397
  add_threeds_services(xml, options)
398
+ add_business_rules_data(xml, payment_method_or_reference, options)
399
+ add_airline_data(xml, options)
400
+ add_sales_slip_number(xml, options)
307
401
  add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
308
- add_business_rules_data(xml, payment_method_or_reference, options) unless options[:pinless_debit_card]
402
+ add_payment_solution(xml, payment_method_or_reference.source) if network_tokenization?(payment_method_or_reference)
403
+ add_tax_management_indicator(xml, options)
404
+ add_stored_credential_subsequent_auth(xml, options)
405
+ add_issuer_additional_data(xml, options)
406
+ add_partner_solution_id(xml)
407
+ add_stored_credential_options(xml, options)
408
+ options[:payment_method] = :credit_card
309
409
  end
310
- add_issuer_additional_data(xml, options)
410
+
411
+ add_merchant_description(xml, options)
311
412
 
312
413
  xml.target!
313
414
  end
314
415
 
416
+ def reference_is_a_check?(payment_method_or_reference)
417
+ payment_method_or_reference.is_a?(String) && payment_method_or_reference.split(';')[7] == 'check'
418
+ end
419
+
315
420
  def build_void_request(identification, options)
316
- order_id, request_id, request_token, action, money, currency = identification.split(';')
421
+ order_id, request_id, request_token, action, money, currency = identification.split(';')
317
422
  options[:order_id] = order_id
318
423
 
319
- xml = Builder::XmlMarkup.new :indent => 2
320
- if action == 'capture'
424
+ xml = Builder::XmlMarkup.new indent: 2
425
+ case action
426
+ when 'capture', 'purchase'
427
+ add_mdd_fields(xml, options)
321
428
  add_void_service(xml, request_id, request_token)
322
429
  else
323
- add_purchase_data(xml, money, true, options.merge(:currency => currency || default_currency))
430
+ add_purchase_data(xml, money, true, options.merge(currency: currency || default_currency))
431
+ add_mdd_fields(xml, options)
324
432
  add_auth_reversal_service(xml, request_id, request_token)
325
433
  end
434
+ add_issuer_additional_data(xml, options)
435
+ add_partner_solution_id(xml)
436
+
326
437
  xml.target!
327
438
  end
328
439
 
@@ -330,37 +441,45 @@ module ActiveMerchant #:nodoc:
330
441
  order_id, request_id, request_token = identification.split(';')
331
442
  options[:order_id] = order_id
332
443
 
333
- xml = Builder::XmlMarkup.new :indent => 2
444
+ xml = Builder::XmlMarkup.new indent: 2
334
445
  add_purchase_data(xml, money, true, options)
335
- add_credit_service(xml, request_id, request_token)
446
+ add_credit_service(xml, request_id: request_id,
447
+ request_token: request_token,
448
+ use_check_service: reference_is_a_check?(identification))
449
+ add_partner_solution_id(xml)
336
450
 
337
451
  xml.target!
338
452
  end
339
453
 
340
454
  def build_credit_request(money, creditcard_or_reference, options)
341
- xml = Builder::XmlMarkup.new :indent => 2
455
+ xml = Builder::XmlMarkup.new indent: 2
342
456
 
343
457
  add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
344
- add_credit_service(xml)
458
+ add_mdd_fields(xml, options)
459
+ add_credit_service(xml, use_check_service: creditcard_or_reference.is_a?(Check))
460
+ add_issuer_additional_data(xml, options)
461
+ add_merchant_description(xml, options)
345
462
 
346
463
  xml.target!
347
464
  end
348
465
 
349
466
  def build_create_subscription_request(payment_method, options)
350
- default_subscription_params = {:frequency => 'on-demand', :amount => 0, :automatic_renew => false}
467
+ default_subscription_params = { frequency: 'on-demand', amount: 0, automatic_renew: false }
351
468
  options[:subscription] = default_subscription_params.update(
352
469
  options[:subscription] || {}
353
470
  )
354
471
 
355
- xml = Builder::XmlMarkup.new :indent => 2
472
+ xml = Builder::XmlMarkup.new indent: 2
356
473
  add_address(xml, payment_method, options[:billing_address], options)
357
474
  add_purchase_data(xml, options[:setup_fee] || 0, true, options)
358
475
  if card_brand(payment_method) == 'check'
359
- add_check(xml, payment_method)
476
+ add_check(xml, payment_method, options)
360
477
  add_check_payment_method(xml)
478
+ options[:payment_method] = :check
361
479
  else
362
480
  add_creditcard(xml, payment_method)
363
481
  add_creditcard_payment_method(xml)
482
+ options[:payment_method] = :credit_card
364
483
  end
365
484
  add_subscription(xml, options)
366
485
  if options[:setup_fee]
@@ -373,11 +492,12 @@ module ActiveMerchant #:nodoc:
373
492
  end
374
493
  add_subscription_create_service(xml, options)
375
494
  add_business_rules_data(xml, payment_method, options)
495
+ add_tax_management_indicator(xml, options)
376
496
  xml.target!
377
497
  end
378
498
 
379
499
  def build_update_subscription_request(reference, creditcard, options)
380
- xml = Builder::XmlMarkup.new :indent => 2
500
+ xml = Builder::XmlMarkup.new indent: 2
381
501
  add_address(xml, creditcard, options[:billing_address], options) unless options[:billing_address].blank?
382
502
  add_purchase_data(xml, options[:setup_fee], true, options) unless options[:setup_fee].blank?
383
503
  add_creditcard(xml, creditcard) if creditcard
@@ -385,38 +505,30 @@ module ActiveMerchant #:nodoc:
385
505
  add_subscription(xml, options, reference)
386
506
  add_subscription_update_service(xml, options)
387
507
  add_business_rules_data(xml, creditcard, options)
508
+ add_tax_management_indicator(xml, options)
388
509
  xml.target!
389
510
  end
390
511
 
391
512
  def build_delete_subscription_request(reference, options)
392
- xml = Builder::XmlMarkup.new :indent => 2
513
+ xml = Builder::XmlMarkup.new indent: 2
393
514
  add_subscription(xml, options, reference)
394
515
  add_subscription_delete_service(xml, options)
395
516
  xml.target!
396
517
  end
397
518
 
398
519
  def build_retrieve_subscription_request(reference, options)
399
- xml = Builder::XmlMarkup.new :indent => 2
520
+ xml = Builder::XmlMarkup.new indent: 2
400
521
  add_subscription(xml, options, reference)
401
522
  add_subscription_retrieve_service(xml, options)
402
523
  xml.target!
403
524
  end
404
525
 
405
- def build_validate_pinless_debit_request(creditcard, options)
406
- xml = Builder::XmlMarkup.new :indent => 2
407
- add_creditcard(xml, creditcard)
408
- add_validate_pinless_debit_service(xml)
409
- xml.target!
410
- end
411
-
412
526
  def add_business_rules_data(xml, payment_method, options)
413
527
  prioritized_options = [options, @options]
414
528
 
415
- unless network_tokenization?(payment_method)
416
- xml.tag! 'businessRules' do
417
- xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs)
418
- xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv)
419
- end
529
+ xml.tag! 'businessRules' do
530
+ xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs).to_s == 'true'
531
+ xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true'
420
532
  end
421
533
  end
422
534
 
@@ -428,13 +540,17 @@ module ActiveMerchant #:nodoc:
428
540
  end
429
541
 
430
542
  def add_line_item_data(xml, options)
543
+ return unless options[:line_items]
544
+
431
545
  options[:line_items].each_with_index do |value, index|
432
- xml.tag! 'item', {'id' => index} do
546
+ xml.tag! 'item', { 'id' => index } do
433
547
  xml.tag! 'unitPrice', localized_amount(value[:declared_value].to_i, options[:currency] || default_currency)
434
548
  xml.tag! 'quantity', value[:quantity]
435
549
  xml.tag! 'productCode', value[:code] || 'shipping_only'
436
550
  xml.tag! 'productName', value[:description]
437
551
  xml.tag! 'productSKU', value[:sku]
552
+ xml.tag! 'taxAmount', value[:tax_amount] if value[:tax_amount]
553
+ xml.tag! 'nationalTax', value[:national_tax] if value[:national_tax]
438
554
  end
439
555
  end
440
556
  end
@@ -443,23 +559,80 @@ module ActiveMerchant #:nodoc:
443
559
  xml.tag! 'merchantID', @options[:login]
444
560
  xml.tag! 'merchantReferenceCode', options[:order_id] || generate_unique_id
445
561
  xml.tag! 'clientLibrary', 'Ruby Active Merchant'
446
- xml.tag! 'clientLibraryVersion', VERSION
562
+ xml.tag! 'clientLibraryVersion', VERSION
447
563
  xml.tag! 'clientEnvironment', RUBY_PLATFORM
564
+
565
+ add_merchant_descriptor(xml, options)
566
+ end
567
+
568
+ def add_merchant_descriptor(xml, options)
569
+ return unless options[:merchant_descriptor] || options[:user_po] || options[:taxable] || options[:reference_data_code] || options[:invoice_number]
570
+
571
+ xml.tag! 'invoiceHeader' do
572
+ xml.tag! 'merchantDescriptor', options[:merchant_descriptor] if options[:merchant_descriptor]
573
+ xml.tag! 'userPO', options[:user_po] if options[:user_po]
574
+ xml.tag! 'taxable', options[:taxable] if options[:taxable]
575
+ xml.tag! 'referenceDataCode', options[:reference_data_code] if options[:reference_data_code]
576
+ xml.tag! 'invoiceNumber', options[:invoice_number] if options[:invoice_number]
577
+ end
578
+ end
579
+
580
+ def add_customer_id(xml, options)
581
+ return unless options[:customer_id]
582
+
583
+ xml.tag! 'customerID', options[:customer_id]
584
+ end
585
+
586
+ def add_merchant_description(xml, options)
587
+ return unless options[:merchant_descriptor_name] || options[:merchant_descriptor_address1] || options[:merchant_descriptor_locality]
588
+
589
+ xml.tag! 'merchantInformation' do
590
+ xml.tag! 'merchantDescriptor' do
591
+ xml.tag! 'name', options[:merchant_descriptor_name] if options[:merchant_descriptor_name]
592
+ xml.tag! 'address1', options[:merchant_descriptor_address1] if options[:merchant_descriptor_address1]
593
+ xml.tag! 'locality', options[:merchant_descriptor_locality] if options[:merchant_descriptor_locality]
594
+ end
595
+ end
596
+ end
597
+
598
+ def add_sales_slip_number(xml, options)
599
+ xml.tag! 'salesSlipNumber', options[:sales_slip_number] if options[:sales_slip_number]
600
+ end
601
+
602
+ def add_airline_data(xml, options)
603
+ return unless options[:airline_agent_code]
604
+
605
+ xml.tag! 'airlineData' do
606
+ xml.tag! 'agentCode', options[:airline_agent_code]
607
+ end
608
+ end
609
+
610
+ def add_tax_management_indicator(xml, options)
611
+ return unless options[:tax_management_indicator]
612
+
613
+ xml.tag! 'taxManagementIndicator', options[:tax_management_indicator] if options[:tax_management_indicator]
448
614
  end
449
615
 
450
- def add_purchase_data(xml, money = 0, include_grand_total = false, options={})
616
+ def add_purchase_data(xml, money = 0, include_grand_total = false, options = {})
451
617
  xml.tag! 'purchaseTotals' do
452
618
  xml.tag! 'currency', options[:currency] || currency(money)
453
- xml.tag!('grandTotalAmount', localized_amount(money.to_i, options[:currency] || default_currency)) if include_grand_total
619
+ xml.tag!('discountManagementIndicator', options[:discount_management_indicator]) if options[:discount_management_indicator]
620
+ xml.tag!('taxAmount', options[:purchase_tax_amount]) if options[:purchase_tax_amount]
621
+ xml.tag!('grandTotalAmount', localized_amount(money.to_i, options[:currency] || default_currency)) if include_grand_total
622
+ xml.tag!('originalAmount', options[:original_amount]) if options[:original_amount]
623
+ xml.tag!('invoiceAmount', options[:invoice_amount]) if options[:invoice_amount]
454
624
  end
455
625
  end
456
626
 
457
627
  def add_address(xml, payment_method, address, options, shipTo = false)
628
+ first_name, last_name = address_names(address[:name], payment_method)
629
+ bill_to_merchant_tax_id = options[:merchant_tax_id] unless shipTo
630
+
458
631
  xml.tag! shipTo ? 'shipTo' : 'billTo' do
459
- xml.tag! 'firstName', payment_method.first_name if payment_method
460
- xml.tag! 'lastName', payment_method.last_name if payment_method
632
+ xml.tag! 'firstName', first_name if first_name
633
+ xml.tag! 'lastName', last_name if last_name
461
634
  xml.tag! 'street1', address[:address1]
462
- xml.tag! 'street2', address[:address2] unless address[:address2].blank?
635
+ xml.tag! 'street2', address[:address2] unless address[:address2].blank?
463
636
  xml.tag! 'city', address[:city]
464
637
  xml.tag! 'state', address[:state]
465
638
  xml.tag! 'postalCode', address[:zip]
@@ -467,19 +640,30 @@ module ActiveMerchant #:nodoc:
467
640
  xml.tag! 'company', address[:company] unless address[:company].blank?
468
641
  xml.tag! 'companyTaxID', address[:companyTaxID] unless address[:company_tax_id].blank?
469
642
  xml.tag! 'phoneNumber', address[:phone] unless address[:phone].blank?
470
- xml.tag! 'email', options[:email] || 'null@cybersource.com'
643
+ xml.tag! 'email', options[:email].presence || 'null@cybersource.com'
471
644
  xml.tag! 'ipAddress', options[:ip] unless options[:ip].blank? || shipTo
472
645
  xml.tag! 'driversLicenseNumber', options[:drivers_license_number] unless options[:drivers_license_number].blank?
473
646
  xml.tag! 'driversLicenseState', options[:drivers_license_state] unless options[:drivers_license_state].blank?
647
+ xml.tag! 'merchantTaxID', bill_to_merchant_tax_id unless bill_to_merchant_tax_id.blank?
474
648
  end
475
649
  end
476
650
 
651
+ def address_names(address_name, payment_method)
652
+ names = split_names(address_name)
653
+ return names if names.any?(&:present?)
654
+
655
+ [
656
+ payment_method&.first_name,
657
+ payment_method&.last_name
658
+ ]
659
+ end
660
+
477
661
  def add_creditcard(xml, creditcard)
478
662
  xml.tag! 'card' do
479
663
  xml.tag! 'accountNumber', creditcard.number
480
664
  xml.tag! 'expirationMonth', format(creditcard.month, :two_digits)
481
665
  xml.tag! 'expirationYear', format(creditcard.year, :four_digits)
482
- xml.tag!('cvNumber', creditcard.verification_value) unless @options[:ignore_cvv] || creditcard.verification_value.blank?
666
+ xml.tag!('cvNumber', creditcard.verification_value) unless @options[:ignore_cvv].to_s == 'true' || creditcard.verification_value.blank?
483
667
  xml.tag! 'cardType', @@credit_card_codes[card_brand(creditcard).to_sym]
484
668
  end
485
669
  end
@@ -493,6 +677,12 @@ module ActiveMerchant #:nodoc:
493
677
  end
494
678
  end
495
679
 
680
+ def add_payment_solution(xml, source)
681
+ return unless (payment_solution = @@payment_solution[source])
682
+
683
+ xml.tag! 'paymentSolution', payment_solution
684
+ end
685
+
496
686
  def add_issuer_additional_data(xml, options)
497
687
  return unless options[:issuer_additional_data]
498
688
 
@@ -501,27 +691,39 @@ module ActiveMerchant #:nodoc:
501
691
  end
502
692
  end
503
693
 
694
+ def add_other_tax(xml, options)
695
+ return unless options[:local_tax_amount] || options[:national_tax_amount] || options[:national_tax_indicator]
696
+
697
+ xml.tag! 'otherTax' do
698
+ xml.tag! 'vatTaxRate', options[:vat_tax_rate] if options[:vat_tax_rate]
699
+ xml.tag! 'localTaxAmount', options[:local_tax_amount] if options[:local_tax_amount]
700
+ xml.tag! 'nationalTaxAmount', options[:national_tax_amount] if options[:national_tax_amount]
701
+ xml.tag! 'nationalTaxIndicator', options[:national_tax_indicator] if options[:national_tax_indicator]
702
+ end
703
+ end
704
+
504
705
  def add_mdd_fields(xml, options)
505
- return unless options.keys.any? { |key| key.to_s.start_with?('mdd_field') }
706
+ return unless options.keys.any? { |key| key.to_s.start_with?('mdd_field') && options[key] }
506
707
 
507
708
  xml.tag! 'merchantDefinedData' do
508
709
  (1..100).each do |each|
509
710
  key = "mdd_field_#{each}".to_sym
510
- xml.tag!("field#{each}", options[key]) if options[key]
711
+ xml.tag!('mddField', options[key], 'id' => each) if options[key]
511
712
  end
512
713
  end
513
714
  end
514
715
 
515
- def add_check(xml, check)
716
+ def add_check(xml, check, options)
516
717
  xml.tag! 'check' do
517
718
  xml.tag! 'accountNumber', check.account_number
518
- xml.tag! 'accountType', check.account_type[0]
519
- xml.tag! 'bankTransitNumber', check.routing_number
719
+ xml.tag! 'accountType', check.account_type == 'checking' ? 'C' : 'S'
720
+ xml.tag! 'bankTransitNumber', format_routing_number(check.routing_number, options)
721
+ xml.tag! 'secCode', options[:sec_code] if options[:sec_code]
520
722
  end
521
723
  end
522
724
 
523
725
  def add_tax_service(xml)
524
- xml.tag! 'taxService', {'run' => 'true'} do
726
+ xml.tag! 'taxService', { 'run' => 'true' } do
525
727
  xml.tag!('nexus', @options[:nexus]) unless @options[:nexus].blank?
526
728
  xml.tag!('sellerRegistration', @options[:vat_reg_number]) unless @options[:vat_reg_number].blank?
527
729
  end
@@ -531,43 +733,70 @@ module ActiveMerchant #:nodoc:
531
733
  if network_tokenization?(payment_method)
532
734
  add_auth_network_tokenization(xml, payment_method, options)
533
735
  else
534
- xml.tag! 'ccAuthService', {'run' => 'true'} do
736
+ xml.tag! 'ccAuthService', { 'run' => 'true' } do
535
737
  if options[:three_d_secure]
536
738
  add_normalized_threeds_2_data(xml, payment_method, options)
537
739
  else
538
740
  indicator = options[:commerce_indicator] || stored_credential_commerce_indicator(options)
539
741
  xml.tag!('commerceIndicator', indicator) if indicator
540
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]
541
745
  end
542
746
  end
543
747
  end
544
748
 
749
+ def add_incremental_auth_service(xml, authorization, options)
750
+ xml.tag! 'ccIncrementalAuthService', { 'run' => 'true' } do
751
+ xml.tag! 'authRequestID', authorization
752
+ end
753
+ xml.tag! 'subsequentAuthReason', options[:auth_reason]
754
+ end
755
+
545
756
  def add_normalized_threeds_2_data(xml, payment_method, options)
546
757
  threeds_2_options = options[:three_d_secure]
758
+ cc_brand = card_brand(payment_method).to_sym
759
+
760
+ return if threeds_2_options[:cavv].blank? && infer_commerce_indicator?(options, cc_brand)
547
761
 
548
- xml.tag!('cavv', threeds_2_options[:cavv]) if threeds_2_options[:cavv] && card_brand(payment_method).to_sym != :master
762
+ xid = threeds_2_options[:xid]
763
+
764
+ xml.tag!('cavv', threeds_2_options[:cavv]) if threeds_2_options[:cavv] && cc_brand != :master
549
765
  xml.tag!('cavvAlgorithm', threeds_2_options[:cavv_algorithm]) if threeds_2_options[:cavv_algorithm]
550
766
  xml.tag!('paSpecificationVersion', threeds_2_options[:version]) if threeds_2_options[:version]
551
767
  xml.tag!('directoryServerTransactionID', threeds_2_options[:ds_transaction_id]) if threeds_2_options[:ds_transaction_id]
552
- xml.tag!('commerceIndicator', options[:commerce_indicator]) if options[:commerce_indicator]
768
+ xml.tag!('commerceIndicator', options[:commerce_indicator] || ECI_BRAND_MAPPING[cc_brand])
553
769
  xml.tag!('eciRaw', threeds_2_options[:eci]) if threeds_2_options[:eci]
554
- xml.tag!('xid', threeds_2_options[:xid]) if threeds_2_options[:xid]
770
+
771
+ if xid.present?
772
+ xml.tag!('xid', xid)
773
+ elsif threeds_2_options[:version]&.start_with?('2') && cc_brand != :master
774
+ cavv = threeds_2_options[:cavv]
775
+ xml.tag!('xid', cavv) if cavv.present?
776
+ end
777
+
555
778
  xml.tag!('veresEnrolled', threeds_2_options[:enrolled]) if threeds_2_options[:enrolled]
556
779
  xml.tag!('paresStatus', threeds_2_options[:authentication_response_status]) if threeds_2_options[:authentication_response_status]
557
780
  end
558
781
 
782
+ def infer_commerce_indicator?(options, cc_brand)
783
+ options[:commerce_indicator].blank? && ECI_BRAND_MAPPING[cc_brand].present?
784
+ end
785
+
559
786
  def add_threeds_2_ucaf_data(xml, payment_method, options)
560
787
  return unless options[:three_d_secure] && card_brand(payment_method).to_sym == :master
561
788
 
562
789
  xml.tag! 'ucaf' do
563
790
  xml.tag!('authenticationData', options[:three_d_secure][:cavv])
564
- xml.tag!('collectionIndicator', options[:collection_indicator]) if options[:collection_indicator]
791
+ xml.tag!('collectionIndicator', options[:collection_indicator] || DEFAULT_COLLECTION_INDICATOR)
565
792
  end
566
793
  end
567
794
 
568
795
  def stored_credential_commerce_indicator(options)
569
796
  return unless options[:stored_credential]
797
+
570
798
  return if options[:stored_credential][:initial_transaction]
799
+
571
800
  case options[:stored_credential][:reason_type]
572
801
  when 'installment' then 'install'
573
802
  when 'recurring' then 'recurring'
@@ -581,28 +810,35 @@ module ActiveMerchant #:nodoc:
581
810
  def add_auth_network_tokenization(xml, payment_method, options)
582
811
  return unless network_tokenization?(payment_method)
583
812
 
584
- case card_brand(payment_method).to_sym
813
+ brand = card_brand(payment_method).to_sym
814
+
815
+ case brand
585
816
  when :visa
586
- xml.tag! 'ccAuthService', {'run' => 'true'} do
817
+ xml.tag! 'ccAuthService', { 'run' => 'true' } do
587
818
  xml.tag!('cavv', payment_method.payment_cryptogram)
588
- xml.tag!('commerceIndicator', 'vbv')
819
+ xml.tag!('commerceIndicator', ECI_BRAND_MAPPING[brand])
589
820
  xml.tag!('xid', payment_method.payment_cryptogram)
821
+ xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
590
822
  end
591
823
  when :master
592
824
  xml.tag! 'ucaf' do
593
825
  xml.tag!('authenticationData', payment_method.payment_cryptogram)
594
- xml.tag!('collectionIndicator', '2')
826
+ xml.tag!('collectionIndicator', DEFAULT_COLLECTION_INDICATOR)
595
827
  end
596
- xml.tag! 'ccAuthService', {'run' => 'true'} do
597
- xml.tag!('commerceIndicator', 'spa')
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]
598
831
  end
599
832
  when :american_express
600
833
  cryptogram = Base64.decode64(payment_method.payment_cryptogram)
601
- xml.tag! 'ccAuthService', {'run' => 'true'} do
834
+ xml.tag! 'ccAuthService', { 'run' => 'true' } do
602
835
  xml.tag!('cavv', Base64.encode64(cryptogram[0...20]))
603
- xml.tag!('commerceIndicator', 'aesk')
604
- xml.tag!('xid', Base64.encode64(cryptogram[20...40]))
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]
605
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")
606
842
  end
607
843
  end
608
844
 
@@ -612,61 +848,65 @@ module ActiveMerchant #:nodoc:
612
848
  end
613
849
  end
614
850
 
615
- def add_capture_service(xml, request_id, request_token)
616
- xml.tag! 'ccCaptureService', {'run' => 'true'} do
851
+ def add_capture_service(xml, request_id, request_token, options)
852
+ xml.tag! 'ccCaptureService', { 'run' => 'true' } do
617
853
  xml.tag! 'authRequestID', request_id
618
854
  xml.tag! 'authRequestToken', request_token
855
+ xml.tag! 'gratuityAmount', options[:gratuity_amount] if options[:gratuity_amount]
856
+ xml.tag! 'reconciliationID', options[:reconciliation_id] if options[:reconciliation_id]
619
857
  end
620
858
  end
621
859
 
622
860
  def add_purchase_service(xml, payment_method, options)
623
- if options[:pinless_debit_card]
624
- xml.tag! 'pinlessDebitService', {'run' => 'true'}
625
- else
626
- add_auth_service(xml, payment_method, options)
627
- xml.tag! 'ccCaptureService', {'run' => 'true'}
861
+ add_auth_service(xml, payment_method, options)
862
+ xml.tag! 'ccCaptureService', { 'run' => 'true' } do
863
+ xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
628
864
  end
629
865
  end
630
866
 
631
867
  def add_void_service(xml, request_id, request_token)
632
- xml.tag! 'voidService', {'run' => 'true'} do
868
+ xml.tag! 'voidService', { 'run' => 'true' } do
633
869
  xml.tag! 'voidRequestID', request_id
634
870
  xml.tag! 'voidRequestToken', request_token
635
871
  end
636
872
  end
637
873
 
638
874
  def add_auth_reversal_service(xml, request_id, request_token)
639
- xml.tag! 'ccAuthReversalService', {'run' => 'true'} do
875
+ xml.tag! 'ccAuthReversalService', { 'run' => 'true' } do
640
876
  xml.tag! 'authRequestID', request_id
641
877
  xml.tag! 'authRequestToken', request_token
642
878
  end
643
879
  end
644
880
 
645
- def add_credit_service(xml, request_id = nil, request_token = nil)
646
- xml.tag! 'ccCreditService', {'run' => 'true'} do
647
- xml.tag! 'captureRequestID', request_id if request_id
648
- xml.tag! 'captureRequestToken', request_token if request_token
881
+ def add_credit_service(xml, options = {})
882
+ service = options[:use_check_service] ? 'ecCreditService' : 'ccCreditService'
883
+ request_tag = options[:use_check_service] ? 'debitRequestID' : 'captureRequestID'
884
+ options.delete :request_token if options[:use_check_service]
885
+
886
+ xml.tag! service, { 'run' => 'true' } do
887
+ xml.tag! request_tag, options[:request_id] if options[:request_id]
888
+ xml.tag! 'captureRequestToken', options[:request_token] if options[:request_token]
649
889
  end
650
890
  end
651
891
 
652
892
  def add_check_service(xml)
653
- xml.tag! 'ecDebitService', {'run' => 'true'}
893
+ xml.tag! 'ecDebitService', { 'run' => 'true' }
654
894
  end
655
895
 
656
896
  def add_subscription_create_service(xml, options)
657
- xml.tag! 'paySubscriptionCreateService', {'run' => 'true'}
897
+ xml.tag! 'paySubscriptionCreateService', { 'run' => 'true' }
658
898
  end
659
899
 
660
900
  def add_subscription_update_service(xml, options)
661
- xml.tag! 'paySubscriptionUpdateService', {'run' => 'true'}
901
+ xml.tag! 'paySubscriptionUpdateService', { 'run' => 'true' }
662
902
  end
663
903
 
664
904
  def add_subscription_delete_service(xml, options)
665
- xml.tag! 'paySubscriptionDeleteService', {'run' => 'true'}
905
+ xml.tag! 'paySubscriptionDeleteService', { 'run' => 'true' }
666
906
  end
667
907
 
668
908
  def add_subscription_retrieve_service(xml, options)
669
- xml.tag! 'paySubscriptionRetrieveService', {'run' => 'true'}
909
+ xml.tag! 'paySubscriptionRetrieveService', { 'run' => 'true' }
670
910
  end
671
911
 
672
912
  def add_subscription(xml, options, reference = nil)
@@ -678,7 +918,7 @@ module ActiveMerchant #:nodoc:
678
918
  xml.tag! 'subscriptionID', subscription_id
679
919
  end
680
920
 
681
- xml.tag! 'status', options[:subscription][:status] if options[:subscription][:status]
921
+ xml.tag! 'status', options[:subscription][:status] if options[:subscription][:status]
682
922
  xml.tag! 'amount', localized_amount(options[:subscription][:amount].to_i, options[:currency] || default_currency) if options[:subscription][:amount]
683
923
  xml.tag! 'numberOfPayments', options[:subscription][:occurrences] if options[:subscription][:occurrences]
684
924
  xml.tag! 'automaticRenew', options[:subscription][:automatic_renew] if options[:subscription][:automatic_renew]
@@ -706,27 +946,40 @@ module ActiveMerchant #:nodoc:
706
946
  def add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
707
947
  if payment_method_or_reference.is_a?(String)
708
948
  add_purchase_data(xml, money, true, options)
949
+ add_installments(xml, options)
709
950
  add_subscription(xml, options, payment_method_or_reference)
710
951
  elsif card_brand(payment_method_or_reference) == 'check'
711
952
  add_address(xml, payment_method_or_reference, options[:billing_address], options)
712
953
  add_purchase_data(xml, money, true, options)
713
- add_check(xml, payment_method_or_reference)
954
+ add_installments(xml, options)
955
+ add_check(xml, payment_method_or_reference, options)
714
956
  else
715
957
  add_address(xml, payment_method_or_reference, options[:billing_address], options)
716
958
  add_address(xml, payment_method_or_reference, options[:shipping_address], options, true)
959
+ add_line_item_data(xml, options)
717
960
  add_purchase_data(xml, money, true, options)
961
+ add_installments(xml, options)
718
962
  add_creditcard(xml, payment_method_or_reference)
719
963
  end
720
964
  end
721
965
 
722
- def add_validate_pinless_debit_service(xml)
723
- xml.tag! 'pinlessDebitValidateService', {'run' => 'true'}
966
+ def add_installments(xml, options)
967
+ return unless %i[installment_total_count installment_total_amount installment_plan_type first_installment_date installment_annual_interest_rate installment_grace_period_duration].any? { |gsf| options.include?(gsf) }
968
+
969
+ xml.tag! 'installment' do
970
+ xml.tag!('totalCount', options[:installment_total_count]) if options[:installment_total_count]
971
+ xml.tag!('totalAmount', options[:installment_total_amount]) if options[:installment_total_amount]
972
+ xml.tag!('planType', options[:installment_plan_type]) if options[:installment_plan_type]
973
+ xml.tag!('firstInstallmentDate', options[:first_installment_date]) if options[:first_installment_date]
974
+ xml.tag!('annualInterestRate', options[:installment_annual_interest_rate]) if options[:installment_annual_interest_rate]
975
+ xml.tag!('gracePeriodDuration', options[:installment_grace_period_duration]) if options[:installment_grace_period_duration]
976
+ end
724
977
  end
725
978
 
726
979
  def add_threeds_services(xml, options)
727
- xml.tag! 'payerAuthEnrollService', {'run' => 'true'} if options[:payer_auth_enroll_service]
980
+ xml.tag! 'payerAuthEnrollService', { 'run' => 'true' } if options[:payer_auth_enroll_service]
728
981
  if options[:payer_auth_validate_service]
729
- xml.tag! 'payerAuthValidateService', {'run' => 'true'} do
982
+ xml.tag! 'payerAuthValidateService', { 'run' => 'true' } do
730
983
  xml.tag! 'signedPARes', options[:pares]
731
984
  end
732
985
  end
@@ -737,35 +990,55 @@ module ActiveMerchant #:nodoc:
737
990
  country_code&.code(:alpha2)
738
991
  end
739
992
 
740
- def add_stored_credential_options(xml, options={})
741
- return unless options[:stored_credential]
742
- if options[:stored_credential][:initial_transaction]
743
- xml.tag! 'subsequentAuthFirst', 'true'
744
- elsif options[:stored_credential][:reason_type] == 'unscheduled'
745
- xml.tag! 'subsequentAuth', 'true'
746
- xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
747
- else
748
- xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id]
749
- end
993
+ def add_stored_credential_subsequent_auth(xml, options = {})
994
+ return unless options[:stored_credential] || options[:stored_credential_overrides]
995
+
996
+ stored_credential_subsequent_auth = 'true' if options.dig(:stored_credential, :initiator) == 'merchant'
997
+
998
+ override_subsequent_auth = options.dig(:stored_credential_overrides, :subsequent_auth)
999
+
1000
+ xml.subsequentAuth override_subsequent_auth.nil? ? stored_credential_subsequent_auth : override_subsequent_auth
1001
+ end
1002
+
1003
+ def add_stored_credential_options(xml, options = {})
1004
+ return unless options[:stored_credential] || options[:stored_credential_overrides]
1005
+
1006
+ stored_credential_subsequent_auth_first = 'true' if options.dig(:stored_credential, :initial_transaction)
1007
+ 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'
1009
+
1010
+ override_subsequent_auth_first = options.dig(:stored_credential_overrides, :subsequent_auth_first)
1011
+ override_subsequent_auth_transaction_id = options.dig(:stored_credential_overrides, :subsequent_auth_transaction_id)
1012
+ override_subsequent_auth_stored_cred = options.dig(:stored_credential_overrides, :subsequent_auth_stored_credential)
1013
+
1014
+ xml.subsequentAuthFirst override_subsequent_auth_first.nil? ? stored_credential_subsequent_auth_first : override_subsequent_auth_first
1015
+ xml.subsequentAuthTransactionID override_subsequent_auth_transaction_id.nil? ? stored_credential_transaction_id : override_subsequent_auth_transaction_id
1016
+ xml.subsequentAuthStoredCredential override_subsequent_auth_stored_cred.nil? ? stored_credential_subsequent_auth_stored_cred : override_subsequent_auth_stored_cred
1017
+ end
1018
+
1019
+ def add_partner_solution_id(xml)
1020
+ return unless application_id
1021
+
1022
+ xml.tag!('partnerSolutionID', application_id)
750
1023
  end
751
1024
 
752
1025
  # Where we actually build the full SOAP request using builder
753
1026
  def build_request(body, options)
754
1027
  xsd_version = test? ? TEST_XSD_VERSION : PRODUCTION_XSD_VERSION
755
1028
 
756
- xml = Builder::XmlMarkup.new :indent => 2
1029
+ xml = Builder::XmlMarkup.new indent: 2
757
1030
  xml.instruct!
758
- xml.tag! 's:Envelope', {'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/'} do
1031
+ xml.tag! 's:Envelope', { 'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/' } do
759
1032
  xml.tag! 's:Header' do
760
- 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
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
761
1034
  xml.tag! 'wsse:UsernameToken' do
762
1035
  xml.tag! 'wsse:Username', @options[:login]
763
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'
764
1037
  end
765
1038
  end
766
1039
  end
767
- xml.tag! 's:Body', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
768
- xml.tag! 'requestMessage', {'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{xsd_version}"} do
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
769
1042
  add_merchant_data(xml, options)
770
1043
  xml << body
771
1044
  end
@@ -789,17 +1062,26 @@ module ActiveMerchant #:nodoc:
789
1062
  response = { message: e.to_s }
790
1063
  end
791
1064
 
792
- success = response[:decision] == 'ACCEPT'
793
- message = response[:message]
1065
+ success = success?(response)
1066
+ message = message_from(response)
1067
+ authorization = success || in_fraud_review?(response) ? authorization_from(response, action, amount, options) : nil
794
1068
 
795
- authorization = success ? authorization_from(response, action, amount, options) : nil
1069
+ message = auto_void?(authorization_from(response, action, amount, options), response, message, options)
796
1070
 
797
1071
  Response.new(success, message, response,
798
- :test => test?,
799
- :authorization => authorization,
800
- :avs_result => { :code => response[:avsCode] },
801
- :cvv_result => response[:cvCode]
802
- )
1072
+ test: test?,
1073
+ authorization: authorization,
1074
+ fraud_review: in_fraud_review?(response),
1075
+ avs_result: { code: response[:avsCode] },
1076
+ cvv_result: response[:cvCode])
1077
+ end
1078
+
1079
+ def auto_void?(authorization, response, message, options = {})
1080
+ return message unless response[:reasonCode] == '230' && options[:auto_void_230]
1081
+
1082
+ response = void(authorization, options)
1083
+ response&.success? ? message += ' - transaction has been auto-voided.' : message += ' - transaction could not be auto-voided.'
1084
+ message
803
1085
  end
804
1086
 
805
1087
  # Parse the SOAP response
@@ -828,7 +1110,7 @@ module ActiveMerchant #:nodoc:
828
1110
  if node.has_elements?
829
1111
  node.elements.each { |e| parse_element(reply, e) }
830
1112
  else
831
- if node.parent.name =~ /item/
1113
+ if /item/.match?(node.parent.name)
832
1114
  parent = node.parent.name
833
1115
  parent += '_' + node.parent.attributes['id'] if node.parent.attributes['id']
834
1116
  parent += '_'
@@ -840,12 +1122,39 @@ module ActiveMerchant #:nodoc:
840
1122
 
841
1123
  def reason_message(reason_code)
842
1124
  return if reason_code.blank?
1125
+
843
1126
  @@response_codes[:"r#{reason_code}"]
844
1127
  end
845
1128
 
846
1129
  def authorization_from(response, action, amount, options)
847
1130
  [options[:order_id], response[:requestID], response[:requestToken], action, amount,
848
- options[:currency], response[:subscriptionID]].join(';')
1131
+ options[:currency], response[:subscriptionID], options[:payment_method]].join(';')
1132
+ end
1133
+
1134
+ def in_fraud_review?(response)
1135
+ response[:decision] == @@decision_codes[:review]
1136
+ end
1137
+
1138
+ def success?(response)
1139
+ response[:decision] == @@decision_codes[:accept]
1140
+ end
1141
+
1142
+ def message_from(response)
1143
+ if response[:reasonCode] == '101' && response[:missingField]
1144
+ "#{response[:message]}: #{response[:missingField]}"
1145
+ elsif response[:reasonCode] == '102' && response[:invalidField]
1146
+ "#{response[:message]}: #{response[:invalidField]}"
1147
+ else
1148
+ response[:message]
1149
+ end
1150
+ end
1151
+
1152
+ def eligible_for_zero_auth?(payment_method, options = {})
1153
+ payment_method.is_a?(CreditCard) && options[:zero_amount_auth]
1154
+ end
1155
+
1156
+ def format_routing_number(routing_number, options)
1157
+ options[:currency] == 'CAD' && routing_number.length > 8 ? routing_number[-8..-1] : routing_number
849
1158
  end
850
1159
  end
851
1160
  end