activemerchant 1.133.0 → 1.137.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.
- checksums.yaml +4 -4
- data/CHANGELOG +240 -0
- data/lib/active_merchant/billing/check.rb +2 -2
- data/lib/active_merchant/billing/compatibility.rb +4 -4
- data/lib/active_merchant/billing/credit_card.rb +11 -8
- data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +59 -6
- data/lib/active_merchant/billing/gateway.rb +9 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +162 -43
- data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
- data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
- data/lib/active_merchant/billing/gateways/authorize_net.rb +43 -35
- data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
- data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
- data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
- data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
- data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
- data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
- data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
- data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
- data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +238 -34
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +63 -6
- data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
- data/lib/active_merchant/billing/gateways/cyber_source.rb +185 -47
- data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
- data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
- data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
- data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
- data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
- data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
- data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
- data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
- data/lib/active_merchant/billing/gateways/element.rb +36 -7
- data/lib/active_merchant/billing/gateways/epay.rb +6 -2
- data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
- data/lib/active_merchant/billing/gateways/eway.rb +4 -2
- data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
- data/lib/active_merchant/billing/gateways/exact.rb +6 -2
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
- data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
- data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
- data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
- data/lib/active_merchant/billing/gateways/hps.rb +1 -1
- data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
- data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
- data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
- data/lib/active_merchant/billing/gateways/ipg.rb +9 -5
- data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
- data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
- data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
- data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
- data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
- data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
- data/lib/active_merchant/billing/gateways/kushki.rb +72 -12
- data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
- data/lib/active_merchant/billing/gateways/litle.rb +33 -50
- data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
- data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
- data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
- data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
- data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
- data/lib/active_merchant/billing/gateways/migs.rb +6 -2
- data/lib/active_merchant/billing/gateways/mit.rb +8 -3
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
- data/lib/active_merchant/billing/gateways/monei.rb +1 -1
- data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
- data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
- data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
- data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
- data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
- data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
- data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
- data/lib/active_merchant/billing/gateways/nmi.rb +18 -6
- data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
- data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
- data/lib/active_merchant/billing/gateways/opp.rb +1 -2
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
- data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
- data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
- data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
- data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
- data/lib/active_merchant/billing/gateways/payex.rb +4 -2
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
- data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
- data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
- data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
- data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
- data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
- data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
- data/lib/active_merchant/billing/gateways/payway.rb +6 -2
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +2 -2
- data/lib/active_merchant/billing/gateways/pin.rb +22 -4
- data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
- data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
- data/lib/active_merchant/billing/gateways/priority.rb +6 -5
- data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
- data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
- data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
- data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
- data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
- data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
- data/lib/active_merchant/billing/gateways/reach.rb +11 -4
- data/lib/active_merchant/billing/gateways/redsys.rb +2 -10
- data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
- data/lib/active_merchant/billing/gateways/s5.rb +3 -3
- data/lib/active_merchant/billing/gateways/safe_charge.rb +36 -16
- data/lib/active_merchant/billing/gateways/sage.rb +12 -4
- data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
- data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
- data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
- data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
- data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
- data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
- data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
- data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
- data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +53 -21
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +199 -50
- data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
- data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
- data/lib/active_merchant/billing/gateways/telr.rb +3 -4
- data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
- data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
- data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
- data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
- data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
- data/lib/active_merchant/billing/gateways/vpos.rb +3 -3
- data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
- data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +140 -73
- data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
- data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
- data/lib/active_merchant/billing/response.rb +2 -2
- data/lib/active_merchant/connection.rb +3 -17
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/errors.rb +10 -0
- data/lib/active_merchant/version.rb +1 -1
- data/lib/support/gateway_support.rb +2 -2
- data/lib/support/ssl_verify.rb +4 -4
- data/lib/support/ssl_version.rb +6 -6
- metadata +30 -9
| @@ -55,6 +55,7 @@ module ActiveMerchant #:nodoc: | |
| 55 55 | 
             
                    add_invoice(post, money, options)
         | 
| 56 56 | 
             
                    add_transaction_details(post, options, 'capture')
         | 
| 57 57 | 
             
                    add_reference_transaction_details(post, authorization, options, :capture)
         | 
| 58 | 
            +
                    add_dynamic_descriptors(post, options)
         | 
| 58 59 |  | 
| 59 60 | 
             
                    commit('sale', post, options)
         | 
| 60 61 | 
             
                  end
         | 
| @@ -68,6 +69,15 @@ module ActiveMerchant #:nodoc: | |
| 68 69 | 
             
                    commit('refund', post, options)
         | 
| 69 70 | 
             
                  end
         | 
| 70 71 |  | 
| 72 | 
            +
                  def credit(money, payment_method, options = {})
         | 
| 73 | 
            +
                    post = {}
         | 
| 74 | 
            +
                    add_invoice(post, money, options)
         | 
| 75 | 
            +
                    add_transaction_interaction(post, options)
         | 
| 76 | 
            +
                    add_payment(post, payment_method, options)
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    commit('refund', post, options)
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 71 81 | 
             
                  def void(authorization, options = {})
         | 
| 72 82 | 
             
                    post = {}
         | 
| 73 83 | 
             
                    add_transaction_details(post, options)
         | 
| @@ -102,6 +112,7 @@ module ActiveMerchant #:nodoc: | |
| 102 112 | 
             
                    transcript.
         | 
| 103 113 | 
             
                      gsub(%r((Authorization: )[a-zA-Z0-9+./=]+), '\1[FILTERED]').
         | 
| 104 114 | 
             
                      gsub(%r((Api-Key: )\w+), '\1[FILTERED]').
         | 
| 115 | 
            +
                      gsub(%r(("apiKey\\?":\\?")\w+), '\1[FILTERED]').
         | 
| 105 116 | 
             
                      gsub(%r(("cardData\\?":\\?")\d+), '\1[FILTERED]').
         | 
| 106 117 | 
             
                      gsub(%r(("securityCode\\?":\\?")\d+), '\1[FILTERED]').
         | 
| 107 118 | 
             
                      gsub(%r(("cavv\\?":\\?")\w+), '\1[FILTERED]')
         | 
| @@ -109,6 +120,23 @@ module ActiveMerchant #:nodoc: | |
| 109 120 |  | 
| 110 121 | 
             
                  private
         | 
| 111 122 |  | 
| 123 | 
            +
                  def add_three_d_secure(post, payment, options)
         | 
| 124 | 
            +
                    return unless three_d_secure = options[:three_d_secure]
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    post[:additionalData3DS] = {
         | 
| 127 | 
            +
                      dsTransactionId: three_d_secure[:ds_transaction_id],
         | 
| 128 | 
            +
                      authenticationStatus: three_d_secure[:authentication_response_status],
         | 
| 129 | 
            +
                      serviceProviderTransactionId: three_d_secure[:three_ds_server_trans_id],
         | 
| 130 | 
            +
                      acsTransactionId: three_d_secure[:acs_transaction_id],
         | 
| 131 | 
            +
                      mpiData: {
         | 
| 132 | 
            +
                        cavv: three_d_secure[:cavv],
         | 
| 133 | 
            +
                        eci: three_d_secure[:eci],
         | 
| 134 | 
            +
                        xid: three_d_secure[:xid]
         | 
| 135 | 
            +
                      }.compact,
         | 
| 136 | 
            +
                      versionData: { recommendedVersion: three_d_secure[:version] }
         | 
| 137 | 
            +
                    }.compact
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
             | 
| 112 140 | 
             
                  def add_transaction_interaction(post, options)
         | 
| 113 141 | 
             
                    post[:transactionInteraction] = {}
         | 
| 114 142 | 
             
                    post[:transactionInteraction][:origin] = options[:origin] || 'ECOM'
         | 
| @@ -144,10 +172,7 @@ module ActiveMerchant #:nodoc: | |
| 144 172 | 
             
                    return unless billing = options[:billing_address]
         | 
| 145 173 |  | 
| 146 174 | 
             
                    billing_address = {}
         | 
| 147 | 
            -
                     | 
| 148 | 
            -
                      billing_address[:firstName] = payment.first_name if payment.first_name
         | 
| 149 | 
            -
                      billing_address[:lastName] = payment.last_name if payment.last_name
         | 
| 150 | 
            -
                    end
         | 
| 175 | 
            +
                    name_from_address(billing_address, billing) || name_from_payment(billing_address, payment)
         | 
| 151 176 | 
             
                    address = {}
         | 
| 152 177 | 
             
                    address[:street] = billing[:address1] if billing[:address1]
         | 
| 153 178 | 
             
                    address[:houseNumberOrName] = billing[:address2] if billing[:address2]
         | 
| @@ -165,6 +190,22 @@ module ActiveMerchant #:nodoc: | |
| 165 190 | 
             
                    post[:billingAddress] = billing_address
         | 
| 166 191 | 
             
                  end
         | 
| 167 192 |  | 
| 193 | 
            +
                  def name_from_payment(billing_address, payment)
         | 
| 194 | 
            +
                    return unless payment.respond_to?(:first_name) && payment.respond_to?(:last_name)
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                    billing_address[:firstName] = payment.first_name if payment.first_name
         | 
| 197 | 
            +
                    billing_address[:lastName] = payment.last_name if payment.last_name
         | 
| 198 | 
            +
                  end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                  def name_from_address(billing_address, billing)
         | 
| 201 | 
            +
                    return unless address = billing
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                    first_name, last_name = split_names(address[:name]) if address[:name]
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                    billing_address[:firstName] = first_name if first_name
         | 
| 206 | 
            +
                    billing_address[:lastName] = last_name if last_name
         | 
| 207 | 
            +
                  end
         | 
| 208 | 
            +
             | 
| 168 209 | 
             
                  def add_shipping_address(post, options)
         | 
| 169 210 | 
             
                    return unless shipping = options[:shipping_address]
         | 
| 170 211 |  | 
| @@ -187,12 +228,28 @@ module ActiveMerchant #:nodoc: | |
| 187 228 | 
             
                  end
         | 
| 188 229 |  | 
| 189 230 | 
             
                  def build_purchase_and_auth_request(post, money, payment, options)
         | 
| 231 | 
            +
                    add_three_d_secure(post, payment, options)
         | 
| 190 232 | 
             
                    add_invoice(post, money, options)
         | 
| 191 233 | 
             
                    add_payment(post, payment, options)
         | 
| 192 234 | 
             
                    add_stored_credentials(post, options)
         | 
| 193 235 | 
             
                    add_transaction_interaction(post, options)
         | 
| 194 236 | 
             
                    add_billing_address(post, payment, options)
         | 
| 195 237 | 
             
                    add_shipping_address(post, options)
         | 
| 238 | 
            +
                    add_dynamic_descriptors(post, options)
         | 
| 239 | 
            +
                  end
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                  def add_dynamic_descriptors(post, options)
         | 
| 242 | 
            +
                    dynamic_descriptors_fields = %i[mcc merchant_name customer_service_number service_entitlement dynamic_descriptors_address]
         | 
| 243 | 
            +
                    return unless dynamic_descriptors_fields.any? { |key| options.include?(key) }
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                    dynamic_descriptors = {}
         | 
| 246 | 
            +
                    dynamic_descriptors[:mcc] = options[:mcc] if options[:mcc]
         | 
| 247 | 
            +
                    dynamic_descriptors[:merchantName] = options[:merchant_name] if options[:merchant_name]
         | 
| 248 | 
            +
                    dynamic_descriptors[:customerServiceNumber] = options[:customer_service_number] if options[:customer_service_number]
         | 
| 249 | 
            +
                    dynamic_descriptors[:serviceEntitlement] = options[:service_entitlement] if options[:service_entitlement]
         | 
| 250 | 
            +
                    dynamic_descriptors[:address] = options[:dynamic_descriptors_address] if options[:dynamic_descriptors_address]
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                    post[:dynamicDescriptors] = dynamic_descriptors
         | 
| 196 253 | 
             
                  end
         | 
| 197 254 |  | 
| 198 255 | 
             
                  def add_reference_transaction_details(post, authorization, options, action = nil)
         | 
| @@ -282,7 +339,7 @@ module ActiveMerchant #:nodoc: | |
| 282 339 | 
             
                    raw_signature = @options[:api_key] + client_request_id.to_s + time + request
         | 
| 283 340 | 
             
                    hmac = OpenSSL::HMAC.digest('sha256', @options[:api_secret], raw_signature)
         | 
| 284 341 | 
             
                    signature = Base64.strict_encode64(hmac.to_s).to_s
         | 
| 285 | 
            -
             | 
| 342 | 
            +
                    custom_headers = options.fetch(:headers_identifiers, {})
         | 
| 286 343 | 
             
                    {
         | 
| 287 344 | 
             
                      'Client-Request-Id' => client_request_id,
         | 
| 288 345 | 
             
                      'Api-Key' => @options[:api_key],
         | 
| @@ -292,7 +349,7 @@ module ActiveMerchant #:nodoc: | |
| 292 349 | 
             
                      'Content-Type' => 'application/json',
         | 
| 293 350 | 
             
                      'Accept' => 'application/json',
         | 
| 294 351 | 
             
                      'Authorization' => signature
         | 
| 295 | 
            -
                    }
         | 
| 352 | 
            +
                    }.merge!(custom_headers)
         | 
| 296 353 | 
             
                  end
         | 
| 297 354 |  | 
| 298 355 | 
             
                  def add_merchant_details(post)
         | 
| @@ -254,9 +254,7 @@ module ActiveMerchant #:nodoc: | |
| 254 254 | 
             
                        normalized_value = normalize(value)
         | 
| 255 255 | 
             
                        next if normalized_value.nil?
         | 
| 256 256 |  | 
| 257 | 
            -
                        if key == :'3ds_homephonecountry'
         | 
| 258 | 
            -
                          next unless options[:billing_address] && options[:billing_address][:phone]
         | 
| 259 | 
            -
                        end
         | 
| 257 | 
            +
                        next if key == :'3ds_homephonecountry' && !(options[:billing_address] && options[:billing_address][:phone])
         | 
| 260 258 |  | 
| 261 259 | 
             
                        post[key] = normalized_value unless post[key]
         | 
| 262 260 | 
             
                      end
         | 
| @@ -417,7 +415,7 @@ module ActiveMerchant #:nodoc: | |
| 417 415 | 
             
                      three_d_secure_options[:eci],
         | 
| 418 416 | 
             
                      three_d_secure_options[:cavv]
         | 
| 419 417 | 
             
                    )
         | 
| 420 | 
            -
                    post[:'3ds_version'] = three_d_secure_options[:version] | 
| 418 | 
            +
                    post[:'3ds_version'] = three_d_secure_options[:version] == '2' ? '2.0' : three_d_secure_options[:version]
         | 
| 421 419 | 
             
                    post[:'3ds_dstrxid'] = three_d_secure_options[:ds_transaction_id]
         | 
| 422 420 | 
             
                  end
         | 
| 423 421 |  | 
| @@ -507,7 +505,7 @@ module ActiveMerchant #:nodoc: | |
| 507 505 | 
             
                  end
         | 
| 508 506 |  | 
| 509 507 | 
             
                  def parse(body)
         | 
| 510 | 
            -
                     | 
| 508 | 
            +
                    CGI::parse(body).map { |k, v| [k.upcase, v.first] }.to_h
         | 
| 511 509 | 
             
                  end
         | 
| 512 510 |  | 
| 513 511 | 
             
                  def success_from(response)
         | 
| @@ -33,6 +33,15 @@ module ActiveMerchant #:nodoc: | |
| 33 33 | 
             
                    discover: 'pb',
         | 
| 34 34 | 
             
                    diners_club: 'pb'
         | 
| 35 35 | 
             
                  }.freeze
         | 
| 36 | 
            +
                  THREEDS_EXEMPTIONS = {
         | 
| 37 | 
            +
                    authentication_outage: 'authenticationOutageExemptionIndicator',
         | 
| 38 | 
            +
                    corporate_card: 'secureCorporatePaymentIndicator',
         | 
| 39 | 
            +
                    delegated_authentication: 'delegatedAuthenticationExemptionIndicator',
         | 
| 40 | 
            +
                    low_risk: 'riskAnalysisExemptionIndicator',
         | 
| 41 | 
            +
                    low_value: 'lowValueExemptionIndicator',
         | 
| 42 | 
            +
                    stored_credential: 'stored_credential',
         | 
| 43 | 
            +
                    trusted_merchant: 'trustedMerchantExemptionIndicator'
         | 
| 44 | 
            +
                  }
         | 
| 36 45 | 
             
                  DEFAULT_COLLECTION_INDICATOR = 2
         | 
| 37 46 |  | 
| 38 47 | 
             
                  self.supported_cardtypes = %i[visa master american_express discover diners_club jcb dankort maestro elo]
         | 
| @@ -53,7 +62,8 @@ module ActiveMerchant #:nodoc: | |
| 53 62 | 
             
                    jcb: '007',
         | 
| 54 63 | 
             
                    dankort: '034',
         | 
| 55 64 | 
             
                    maestro: '042',
         | 
| 56 | 
            -
                    elo: '054'
         | 
| 65 | 
            +
                    elo: '054',
         | 
| 66 | 
            +
                    carnet: '058'
         | 
| 57 67 | 
             
                  }
         | 
| 58 68 |  | 
| 59 69 | 
             
                  @@decision_codes = {
         | 
| @@ -132,11 +142,16 @@ module ActiveMerchant #:nodoc: | |
| 132 142 | 
             
                    r703: 'Export hostname_country/ip_country match'
         | 
| 133 143 | 
             
                  }
         | 
| 134 144 |  | 
| 135 | 
            -
                  @@ | 
| 145 | 
            +
                  @@wallet_payment_solution = {
         | 
| 136 146 | 
             
                    apple_pay: '001',
         | 
| 137 147 | 
             
                    google_pay: '012'
         | 
| 138 148 | 
             
                  }
         | 
| 139 149 |  | 
| 150 | 
            +
                  NT_PAYMENT_SOLUTION = {
         | 
| 151 | 
            +
                    'master' => '014',
         | 
| 152 | 
            +
                    'visa' => '015'
         | 
| 153 | 
            +
                  }
         | 
| 154 | 
            +
             | 
| 140 155 | 
             
                  # These are the options that can be used when creating a new CyberSource
         | 
| 141 156 | 
             
                  # Gateway object.
         | 
| 142 157 | 
             
                  #
         | 
| @@ -161,9 +176,15 @@ module ActiveMerchant #:nodoc: | |
| 161 176 | 
             
                    super
         | 
| 162 177 | 
             
                  end
         | 
| 163 178 |  | 
| 164 | 
            -
                  def authorize(money,  | 
| 165 | 
            -
                     | 
| 166 | 
            -
             | 
| 179 | 
            +
                  def authorize(money, payment_method, options = {})
         | 
| 180 | 
            +
                    if valid_payment_method?(payment_method)
         | 
| 181 | 
            +
                      setup_address_hash(options)
         | 
| 182 | 
            +
                      commit(build_auth_request(money, payment_method, options), :authorize, money, options)
         | 
| 183 | 
            +
                    else
         | 
| 184 | 
            +
                      # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource
         | 
| 185 | 
            +
                      payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '')
         | 
| 186 | 
            +
                      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")
         | 
| 187 | 
            +
                    end
         | 
| 167 188 | 
             
                  end
         | 
| 168 189 |  | 
| 169 190 | 
             
                  def capture(money, authorization, options = {})
         | 
| @@ -171,9 +192,15 @@ module ActiveMerchant #:nodoc: | |
| 171 192 | 
             
                    commit(build_capture_request(money, authorization, options), :capture, money, options)
         | 
| 172 193 | 
             
                  end
         | 
| 173 194 |  | 
| 174 | 
            -
                  def purchase(money,  | 
| 175 | 
            -
                     | 
| 176 | 
            -
             | 
| 195 | 
            +
                  def purchase(money, payment_method, options = {})
         | 
| 196 | 
            +
                    if valid_payment_method?(payment_method)
         | 
| 197 | 
            +
                      setup_address_hash(options)
         | 
| 198 | 
            +
                      commit(build_purchase_request(money, payment_method, options), :purchase, money, options)
         | 
| 199 | 
            +
                    else
         | 
| 200 | 
            +
                      # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource
         | 
| 201 | 
            +
                      payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '')
         | 
| 202 | 
            +
                      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")
         | 
| 203 | 
            +
                    end
         | 
| 177 204 | 
             
                  end
         | 
| 178 205 |  | 
| 179 206 | 
             
                  def void(identification, options = {})
         | 
| @@ -206,8 +233,14 @@ module ActiveMerchant #:nodoc: | |
| 206 233 | 
             
                  # To charge the card while creating a profile, pass
         | 
| 207 234 | 
             
                  # options[:setup_fee] => money
         | 
| 208 235 | 
             
                  def store(payment_method, options = {})
         | 
| 209 | 
            -
                     | 
| 210 | 
            -
             | 
| 236 | 
            +
                    if valid_payment_method?(payment_method)
         | 
| 237 | 
            +
                      setup_address_hash(options)
         | 
| 238 | 
            +
                      commit(build_create_subscription_request(payment_method, options), :store, nil, options)
         | 
| 239 | 
            +
                    else
         | 
| 240 | 
            +
                      # this is for NetworkToken, ApplePay or GooglePay brands that aren't supported at CyberSource
         | 
| 241 | 
            +
                      payment_type = payment_method.source.to_s.gsub('_', ' ').titleize.gsub(' ', '')
         | 
| 242 | 
            +
                      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")
         | 
| 243 | 
            +
                    end
         | 
| 211 244 | 
             
                  end
         | 
| 212 245 |  | 
| 213 246 | 
             
                  # Updates a customer subscription/profile
         | 
| @@ -272,6 +305,8 @@ module ActiveMerchant #:nodoc: | |
| 272 305 | 
             
                      gsub(%r((<cvNumber>)[^<]*(</cvNumber>))i, '\1[FILTERED]\2').
         | 
| 273 306 | 
             
                      gsub(%r((<cavv>)[^<]*(</cavv>))i, '\1[FILTERED]\2').
         | 
| 274 307 | 
             
                      gsub(%r((<xid>)[^<]*(</xid>))i, '\1[FILTERED]\2').
         | 
| 308 | 
            +
                      gsub(%r((<networkTokenCryptogram>)[^<]*(</networkTokenCryptogram>))i, '\1[FILTERED]\2').
         | 
| 309 | 
            +
                      gsub(%r((<requestorID>)[^<]*(</requestorID>))i, '\1[FILTERED]\2').
         | 
| 275 310 | 
             
                      gsub(%r((<authenticationData>)[^<]*(</authenticationData>))i, '\1[FILTERED]\2')
         | 
| 276 311 | 
             
                  end
         | 
| 277 312 |  | 
| @@ -286,6 +321,12 @@ module ActiveMerchant #:nodoc: | |
| 286 321 |  | 
| 287 322 | 
             
                  private
         | 
| 288 323 |  | 
| 324 | 
            +
                  def valid_payment_method?(payment_method)
         | 
| 325 | 
            +
                    return true unless payment_method.is_a?(NetworkTokenizationCreditCard)
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                    %w(visa master american_express).include?(card_brand(payment_method))
         | 
| 328 | 
            +
                  end
         | 
| 329 | 
            +
             | 
| 289 330 | 
             
                  # Create all required address hash key value pairs
         | 
| 290 331 | 
             
                  # 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 332 | 
             
                  # Billing address fields received without an override value or with an empty string value will be replaced with the default_address values
         | 
| @@ -317,17 +358,19 @@ module ActiveMerchant #:nodoc: | |
| 317 358 | 
             
                    xml = Builder::XmlMarkup.new indent: 2
         | 
| 318 359 | 
             
                    add_customer_id(xml, options)
         | 
| 319 360 | 
             
                    add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
         | 
| 320 | 
            -
                    add_other_tax(xml, options)
         | 
| 321 361 | 
             
                    add_threeds_2_ucaf_data(xml, creditcard_or_reference, options)
         | 
| 362 | 
            +
                    add_mastercard_network_tokenization_ucaf_data(xml, creditcard_or_reference, options)
         | 
| 322 363 | 
             
                    add_decision_manager_fields(xml, options)
         | 
| 364 | 
            +
                    add_other_tax(xml, options)
         | 
| 323 365 | 
             
                    add_mdd_fields(xml, options)
         | 
| 324 366 | 
             
                    add_auth_service(xml, creditcard_or_reference, options)
         | 
| 367 | 
            +
                    add_capture_service_fields_with_run_false(xml, options)
         | 
| 325 368 | 
             
                    add_threeds_services(xml, options)
         | 
| 326 369 | 
             
                    add_business_rules_data(xml, creditcard_or_reference, options)
         | 
| 327 370 | 
             
                    add_airline_data(xml, options)
         | 
| 328 371 | 
             
                    add_sales_slip_number(xml, options)
         | 
| 329 | 
            -
                    add_payment_network_token(xml | 
| 330 | 
            -
                    add_payment_solution(xml, creditcard_or_reference | 
| 372 | 
            +
                    add_payment_network_token(xml, creditcard_or_reference, options)
         | 
| 373 | 
            +
                    add_payment_solution(xml, creditcard_or_reference)
         | 
| 331 374 | 
             
                    add_tax_management_indicator(xml, options)
         | 
| 332 375 | 
             
                    add_stored_credential_subsequent_auth(xml, options)
         | 
| 333 376 | 
             
                    add_issuer_additional_data(xml, options)
         | 
| @@ -380,9 +423,10 @@ module ActiveMerchant #:nodoc: | |
| 380 423 | 
             
                    xml = Builder::XmlMarkup.new indent: 2
         | 
| 381 424 | 
             
                    add_customer_id(xml, options)
         | 
| 382 425 | 
             
                    add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
         | 
| 383 | 
            -
                    add_other_tax(xml, options)
         | 
| 384 426 | 
             
                    add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
         | 
| 427 | 
            +
                    add_mastercard_network_tokenization_ucaf_data(xml, payment_method_or_reference, options)
         | 
| 385 428 | 
             
                    add_decision_manager_fields(xml, options)
         | 
| 429 | 
            +
                    add_other_tax(xml, options)
         | 
| 386 430 | 
             
                    add_mdd_fields(xml, options)
         | 
| 387 431 | 
             
                    if (!payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check') || reference_is_a_check?(payment_method_or_reference)
         | 
| 388 432 | 
             
                      add_check_service(xml)
         | 
| @@ -398,8 +442,8 @@ module ActiveMerchant #:nodoc: | |
| 398 442 | 
             
                      add_business_rules_data(xml, payment_method_or_reference, options)
         | 
| 399 443 | 
             
                      add_airline_data(xml, options)
         | 
| 400 444 | 
             
                      add_sales_slip_number(xml, options)
         | 
| 401 | 
            -
                      add_payment_network_token(xml | 
| 402 | 
            -
                      add_payment_solution(xml, payment_method_or_reference | 
| 445 | 
            +
                      add_payment_network_token(xml, payment_method_or_reference, options)
         | 
| 446 | 
            +
                      add_payment_solution(xml, payment_method_or_reference)
         | 
| 403 447 | 
             
                      add_tax_management_indicator(xml, options)
         | 
| 404 448 | 
             
                      add_stored_credential_subsequent_auth(xml, options)
         | 
| 405 449 | 
             
                      add_issuer_additional_data(xml, options)
         | 
| @@ -487,7 +531,7 @@ module ActiveMerchant #:nodoc: | |
| 487 531 | 
             
                        add_check_service(xml)
         | 
| 488 532 | 
             
                      else
         | 
| 489 533 | 
             
                        add_purchase_service(xml, payment_method, options)
         | 
| 490 | 
            -
                        add_payment_network_token(xml | 
| 534 | 
            +
                        add_payment_network_token(xml, payment_method, options)
         | 
| 491 535 | 
             
                      end
         | 
| 492 536 | 
             
                    end
         | 
| 493 537 | 
             
                    add_subscription_create_service(xml, options)
         | 
| @@ -556,7 +600,7 @@ module ActiveMerchant #:nodoc: | |
| 556 600 | 
             
                  end
         | 
| 557 601 |  | 
| 558 602 | 
             
                  def add_merchant_data(xml, options)
         | 
| 559 | 
            -
                    xml.tag! 'merchantID', @options[:login]
         | 
| 603 | 
            +
                    xml.tag! 'merchantID', options[:merchant_id] || @options[:login]
         | 
| 560 604 | 
             
                    xml.tag! 'merchantReferenceCode', options[:order_id] || generate_unique_id
         | 
| 561 605 | 
             
                    xml.tag! 'clientLibrary', 'Ruby Active Merchant'
         | 
| 562 606 | 
             
                    xml.tag! 'clientLibraryVersion', VERSION
         | 
| @@ -566,12 +610,24 @@ module ActiveMerchant #:nodoc: | |
| 566 610 | 
             
                  end
         | 
| 567 611 |  | 
| 568 612 | 
             
                  def add_merchant_descriptor(xml, options)
         | 
| 569 | 
            -
                    return unless options[:merchant_descriptor] || | 
| 613 | 
            +
                    return unless options[:merchant_descriptor] ||
         | 
| 614 | 
            +
                                  options[:user_po] ||
         | 
| 615 | 
            +
                                  options[:taxable] ||
         | 
| 616 | 
            +
                                  options[:reference_data_code] ||
         | 
| 617 | 
            +
                                  options[:invoice_number] ||
         | 
| 618 | 
            +
                                  options[:merchant_descriptor_city] ||
         | 
| 619 | 
            +
                                  options[:submerchant_id] ||
         | 
| 620 | 
            +
                                  options[:merchant_descriptor_state] ||
         | 
| 621 | 
            +
                                  options[:merchant_descriptor_country]
         | 
| 570 622 |  | 
| 571 623 | 
             
                    xml.tag! 'invoiceHeader' do
         | 
| 572 624 | 
             
                      xml.tag! 'merchantDescriptor', options[:merchant_descriptor] if options[:merchant_descriptor]
         | 
| 625 | 
            +
                      xml.tag! 'merchantDescriptorCity', options[:merchant_descriptor_city] if options[:merchant_descriptor_city]
         | 
| 626 | 
            +
                      xml.tag! 'merchantDescriptorState', options[:merchant_descriptor_state] if options[:merchant_descriptor_state]
         | 
| 627 | 
            +
                      xml.tag! 'merchantDescriptorCountry', options[:merchant_descriptor_country] if options[:merchant_descriptor_country]
         | 
| 573 628 | 
             
                      xml.tag! 'userPO', options[:user_po] if options[:user_po]
         | 
| 574 629 | 
             
                      xml.tag! 'taxable', options[:taxable] if options[:taxable]
         | 
| 630 | 
            +
                      xml.tag! 'submerchantID', options[:submerchant_id] if options[:submerchant_id]
         | 
| 575 631 | 
             
                      xml.tag! 'referenceDataCode', options[:reference_data_code] if options[:reference_data_code]
         | 
| 576 632 | 
             
                      xml.tag! 'invoiceNumber', options[:invoice_number] if options[:invoice_number]
         | 
| 577 633 | 
             
                    end
         | 
| @@ -677,10 +733,16 @@ module ActiveMerchant #:nodoc: | |
| 677 733 | 
             
                    end
         | 
| 678 734 | 
             
                  end
         | 
| 679 735 |  | 
| 680 | 
            -
                  def add_payment_solution(xml,  | 
| 681 | 
            -
                    return unless ( | 
| 736 | 
            +
                  def add_payment_solution(xml, payment_method)
         | 
| 737 | 
            +
                    return unless network_tokenization?(payment_method)
         | 
| 682 738 |  | 
| 683 | 
            -
                     | 
| 739 | 
            +
                    case payment_method.source
         | 
| 740 | 
            +
                    when :network_token
         | 
| 741 | 
            +
                      payment_solution = NT_PAYMENT_SOLUTION[payment_method.brand]
         | 
| 742 | 
            +
                      xml.tag! 'paymentSolution', payment_solution if payment_solution
         | 
| 743 | 
            +
                    when :apple_pay, :google_pay
         | 
| 744 | 
            +
                      xml.tag! 'paymentSolution', @@wallet_payment_solution[payment_method.source]
         | 
| 745 | 
            +
                    end
         | 
| 684 746 | 
             
                  end
         | 
| 685 747 |  | 
| 686 748 | 
             
                  def add_issuer_additional_data(xml, options)
         | 
| @@ -692,7 +754,7 @@ module ActiveMerchant #:nodoc: | |
| 692 754 | 
             
                  end
         | 
| 693 755 |  | 
| 694 756 | 
             
                  def add_other_tax(xml, options)
         | 
| 695 | 
            -
                    return unless  | 
| 757 | 
            +
                    return unless %i[vat_tax_rate local_tax_amount national_tax_amount national_tax_indicator].any? { |gsf| options.include?(gsf) }
         | 
| 696 758 |  | 
| 697 759 | 
             
                    xml.tag! 'otherTax' do
         | 
| 698 760 | 
             
                      xml.tag! 'vatTaxRate', options[:vat_tax_rate] if options[:vat_tax_rate]
         | 
| @@ -731,21 +793,39 @@ module ActiveMerchant #:nodoc: | |
| 731 793 |  | 
| 732 794 | 
             
                  def add_auth_service(xml, payment_method, options)
         | 
| 733 795 | 
             
                    if network_tokenization?(payment_method)
         | 
| 734 | 
            -
                       | 
| 796 | 
            +
                      if payment_method.source == :network_token
         | 
| 797 | 
            +
                        add_auth_network_tokenization(xml, payment_method, options)
         | 
| 798 | 
            +
                      else
         | 
| 799 | 
            +
                        add_auth_wallet(xml, payment_method, options)
         | 
| 800 | 
            +
                      end
         | 
| 735 801 | 
             
                    else
         | 
| 736 802 | 
             
                      xml.tag! 'ccAuthService', { 'run' => 'true' } do
         | 
| 737 803 | 
             
                        if options[:three_d_secure]
         | 
| 738 804 | 
             
                          add_normalized_threeds_2_data(xml, payment_method, options)
         | 
| 805 | 
            +
                          add_threeds_exemption_data(xml, options) if options[:three_ds_exemption_type]
         | 
| 739 806 | 
             
                        else
         | 
| 740 807 | 
             
                          indicator = options[:commerce_indicator] || stored_credential_commerce_indicator(options)
         | 
| 741 808 | 
             
                          xml.tag!('commerceIndicator', indicator) if indicator
         | 
| 742 809 | 
             
                        end
         | 
| 810 | 
            +
                        xml.tag!('aggregatorID', options[:aggregator_id]) if options[:aggregator_id]
         | 
| 743 811 | 
             
                        xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
         | 
| 812 | 
            +
                        xml.tag!('firstRecurringPayment', options[:first_recurring_payment]) if options[:first_recurring_payment]
         | 
| 744 813 | 
             
                        xml.tag!('mobileRemotePaymentType', options[:mobile_remote_payment_type]) if options[:mobile_remote_payment_type]
         | 
| 745 814 | 
             
                      end
         | 
| 746 815 | 
             
                    end
         | 
| 747 816 | 
             
                  end
         | 
| 748 817 |  | 
| 818 | 
            +
                  def add_threeds_exemption_data(xml, options)
         | 
| 819 | 
            +
                    return unless options[:three_ds_exemption_type]
         | 
| 820 | 
            +
             | 
| 821 | 
            +
                    exemption = options[:three_ds_exemption_type].to_sym
         | 
| 822 | 
            +
             | 
| 823 | 
            +
                    case exemption
         | 
| 824 | 
            +
                    when :authentication_outage, :corporate_card, :delegated_authentication, :low_risk, :low_value, :trusted_merchant
         | 
| 825 | 
            +
                      xml.tag!(THREEDS_EXEMPTIONS[exemption], '1')
         | 
| 826 | 
            +
                    end
         | 
| 827 | 
            +
                  end
         | 
| 828 | 
            +
             | 
| 749 829 | 
             
                  def add_incremental_auth_service(xml, authorization, options)
         | 
| 750 830 | 
             
                    xml.tag! 'ccIncrementalAuthService', { 'run' => 'true' } do
         | 
| 751 831 | 
             
                      xml.tag! 'authRequestID', authorization
         | 
| @@ -793,13 +873,15 @@ module ActiveMerchant #:nodoc: | |
| 793 873 | 
             
                  end
         | 
| 794 874 |  | 
| 795 875 | 
             
                  def stored_credential_commerce_indicator(options)
         | 
| 796 | 
            -
                    return unless options | 
| 876 | 
            +
                    return unless (reason_type = options.dig(:stored_credential, :reason_type))
         | 
| 797 877 |  | 
| 798 | 
            -
                     | 
| 799 | 
            -
             | 
| 800 | 
            -
             | 
| 801 | 
            -
                    when ' | 
| 802 | 
            -
             | 
| 878 | 
            +
                    case reason_type
         | 
| 879 | 
            +
                    when 'installment'
         | 
| 880 | 
            +
                      'install'
         | 
| 881 | 
            +
                    when 'recurring'
         | 
| 882 | 
            +
                      'recurring'
         | 
| 883 | 
            +
                    else
         | 
| 884 | 
            +
                      'internet'
         | 
| 803 885 | 
             
                    end
         | 
| 804 886 | 
             
                  end
         | 
| 805 887 |  | 
| @@ -807,26 +889,38 @@ module ActiveMerchant #:nodoc: | |
| 807 889 | 
             
                    payment_method.is_a?(NetworkTokenizationCreditCard)
         | 
| 808 890 | 
             
                  end
         | 
| 809 891 |  | 
| 892 | 
            +
                  def subsequent_nt_apple_pay_auth(source, options)
         | 
| 893 | 
            +
                    return unless options[:stored_credential] || options[:stored_credential_overrides]
         | 
| 894 | 
            +
                    return unless @@wallet_payment_solution[source]
         | 
| 895 | 
            +
             | 
| 896 | 
            +
                    options.dig(:stored_credential_overrides, :subsequent_auth) || options.dig(:stored_credential, :initiator) == 'merchant'
         | 
| 897 | 
            +
                  end
         | 
| 898 | 
            +
             | 
| 810 899 | 
             
                  def add_auth_network_tokenization(xml, payment_method, options)
         | 
| 811 | 
            -
                     | 
| 900 | 
            +
                    commerce_indicator = stored_credential_commerce_indicator(options) || 'internet'
         | 
| 901 | 
            +
                    xml.tag! 'ccAuthService', { 'run' => 'true' } do
         | 
| 902 | 
            +
                      xml.tag!('networkTokenCryptogram', payment_method.payment_cryptogram)
         | 
| 903 | 
            +
                      xml.tag!('commerceIndicator', commerce_indicator)
         | 
| 904 | 
            +
                      xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
         | 
| 905 | 
            +
                    end
         | 
| 906 | 
            +
                  end
         | 
| 907 | 
            +
             | 
| 908 | 
            +
                  def add_auth_wallet(xml, payment_method, options)
         | 
| 909 | 
            +
                    commerce_indicator = 'internet' if subsequent_nt_apple_pay_auth(payment_method.source, options)
         | 
| 812 910 |  | 
| 813 911 | 
             
                    brand = card_brand(payment_method).to_sym
         | 
| 814 912 |  | 
| 815 913 | 
             
                    case brand
         | 
| 816 914 | 
             
                    when :visa
         | 
| 817 915 | 
             
                      xml.tag! 'ccAuthService', { 'run' => 'true' } do
         | 
| 818 | 
            -
                        xml.tag!('cavv', payment_method.payment_cryptogram)
         | 
| 819 | 
            -
                        xml. | 
| 820 | 
            -
                        xml.tag!('xid', payment_method.payment_cryptogram)
         | 
| 916 | 
            +
                        xml.tag!('cavv', payment_method.payment_cryptogram) unless commerce_indicator
         | 
| 917 | 
            +
                        xml.commerceIndicator commerce_indicator.nil? ? ECI_BRAND_MAPPING[brand] : commerce_indicator
         | 
| 918 | 
            +
                        xml.tag!('xid', payment_method.payment_cryptogram) unless commerce_indicator
         | 
| 821 919 | 
             
                        xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
         | 
| 822 920 | 
             
                      end
         | 
| 823 921 | 
             
                    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 922 | 
             
                      xml.tag! 'ccAuthService', { 'run' => 'true' } do
         | 
| 829 | 
            -
                        xml. | 
| 923 | 
            +
                        xml.commerceIndicator commerce_indicator.nil? ? ECI_BRAND_MAPPING[brand] : commerce_indicator
         | 
| 830 924 | 
             
                        xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
         | 
| 831 925 | 
             
                      end
         | 
| 832 926 | 
             
                    when :american_express
         | 
| @@ -837,14 +931,28 @@ module ActiveMerchant #:nodoc: | |
| 837 931 | 
             
                        xml.tag!('xid', Base64.encode64(cryptogram[20...40])) if cryptogram.bytes.count > 20
         | 
| 838 932 | 
             
                        xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
         | 
| 839 933 | 
             
                      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")
         | 
| 842 934 | 
             
                    end
         | 
| 843 935 | 
             
                  end
         | 
| 844 936 |  | 
| 845 | 
            -
                  def  | 
| 937 | 
            +
                  def add_mastercard_network_tokenization_ucaf_data(xml, payment_method, options)
         | 
| 938 | 
            +
                    return unless network_tokenization?(payment_method) && card_brand(payment_method).to_sym == :master
         | 
| 939 | 
            +
                    return if payment_method.source == :network_token
         | 
| 940 | 
            +
             | 
| 941 | 
            +
                    commerce_indicator = 'internet' if subsequent_nt_apple_pay_auth(payment_method.source, options)
         | 
| 942 | 
            +
             | 
| 943 | 
            +
                    xml.tag! 'ucaf' do
         | 
| 944 | 
            +
                      xml.tag!('authenticationData', payment_method.payment_cryptogram) unless commerce_indicator
         | 
| 945 | 
            +
                      xml.tag!('collectionIndicator', DEFAULT_COLLECTION_INDICATOR)
         | 
| 946 | 
            +
                    end
         | 
| 947 | 
            +
                  end
         | 
| 948 | 
            +
             | 
| 949 | 
            +
                  def add_payment_network_token(xml, payment_method, options)
         | 
| 950 | 
            +
                    return unless network_tokenization?(payment_method)
         | 
| 951 | 
            +
             | 
| 952 | 
            +
                    transaction_type = payment_method.source == :network_token ? '3' : '1'
         | 
| 846 953 | 
             
                    xml.tag! 'paymentNetworkToken' do
         | 
| 847 | 
            -
                      xml.tag!(' | 
| 954 | 
            +
                      xml.tag!('requestorID', options[:trid]) if transaction_type == '3' && options[:trid]
         | 
| 955 | 
            +
                      xml.tag!('transactionType', transaction_type)
         | 
| 848 956 | 
             
                    end
         | 
| 849 957 | 
             
                  end
         | 
| 850 958 |  | 
| @@ -857,10 +965,19 @@ module ActiveMerchant #:nodoc: | |
| 857 965 | 
             
                    end
         | 
| 858 966 | 
             
                  end
         | 
| 859 967 |  | 
| 968 | 
            +
                  def add_capture_service_fields_with_run_false(xml, options)
         | 
| 969 | 
            +
                    return unless options[:gratuity_amount]
         | 
| 970 | 
            +
             | 
| 971 | 
            +
                    xml.tag! 'ccCaptureService', { 'run' => 'false' } do
         | 
| 972 | 
            +
                      xml.tag! 'gratuityAmount', options[:gratuity_amount]
         | 
| 973 | 
            +
                    end
         | 
| 974 | 
            +
                  end
         | 
| 975 | 
            +
             | 
| 860 976 | 
             
                  def add_purchase_service(xml, payment_method, options)
         | 
| 861 977 | 
             
                    add_auth_service(xml, payment_method, options)
         | 
| 862 978 | 
             
                    xml.tag! 'ccCaptureService', { 'run' => 'true' } do
         | 
| 863 979 | 
             
                      xml.tag!('reconciliationID', options[:reconciliation_id]) if options[:reconciliation_id]
         | 
| 980 | 
            +
                      xml.tag!('gratuityAmount', options[:gratuity_amount]) if options[:gratuity_amount]
         | 
| 864 981 | 
             
                    end
         | 
| 865 982 | 
             
                  end
         | 
| 866 983 |  | 
| @@ -1003,9 +1120,9 @@ module ActiveMerchant #:nodoc: | |
| 1003 1120 | 
             
                  def add_stored_credential_options(xml, options = {})
         | 
| 1004 1121 | 
             
                    return unless options[:stored_credential] || options[:stored_credential_overrides]
         | 
| 1005 1122 |  | 
| 1006 | 
            -
                    stored_credential_subsequent_auth_first = 'true' if options | 
| 1123 | 
            +
                    stored_credential_subsequent_auth_first = 'true' if cardholder_or_initiated_transaction?(options)
         | 
| 1007 1124 | 
             
                    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 | 
| 1125 | 
            +
                    stored_credential_subsequent_auth_stored_cred = 'true' if subsequent_cardholder_initiated_transaction?(options) || unscheduled_merchant_initiated_transaction?(options) || threeds_stored_credential_exemption?(options)
         | 
| 1009 1126 |  | 
| 1010 1127 | 
             
                    override_subsequent_auth_first = options.dig(:stored_credential_overrides, :subsequent_auth_first)
         | 
| 1011 1128 | 
             
                    override_subsequent_auth_transaction_id = options.dig(:stored_credential_overrides, :subsequent_auth_transaction_id)
         | 
| @@ -1016,6 +1133,22 @@ module ActiveMerchant #:nodoc: | |
| 1016 1133 | 
             
                    xml.subsequentAuthStoredCredential override_subsequent_auth_stored_cred.nil? ? stored_credential_subsequent_auth_stored_cred : override_subsequent_auth_stored_cred
         | 
| 1017 1134 | 
             
                  end
         | 
| 1018 1135 |  | 
| 1136 | 
            +
                  def cardholder_or_initiated_transaction?(options)
         | 
| 1137 | 
            +
                    options.dig(:stored_credential, :initiator) == 'cardholder' || options.dig(:stored_credential, :initial_transaction)
         | 
| 1138 | 
            +
                  end
         | 
| 1139 | 
            +
             | 
| 1140 | 
            +
                  def subsequent_cardholder_initiated_transaction?(options)
         | 
| 1141 | 
            +
                    options.dig(:stored_credential, :initiator) == 'cardholder' && !options.dig(:stored_credential, :initial_transaction)
         | 
| 1142 | 
            +
                  end
         | 
| 1143 | 
            +
             | 
| 1144 | 
            +
                  def unscheduled_merchant_initiated_transaction?(options)
         | 
| 1145 | 
            +
                    options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
         | 
| 1146 | 
            +
                  end
         | 
| 1147 | 
            +
             | 
| 1148 | 
            +
                  def threeds_stored_credential_exemption?(options)
         | 
| 1149 | 
            +
                    options[:three_ds_exemption_type] == THREEDS_EXEMPTIONS[:stored_credential]
         | 
| 1150 | 
            +
                  end
         | 
| 1151 | 
            +
             | 
| 1019 1152 | 
             
                  def add_partner_solution_id(xml)
         | 
| 1020 1153 | 
             
                    return unless application_id
         | 
| 1021 1154 |  | 
| @@ -1068,12 +1201,16 @@ module ActiveMerchant #:nodoc: | |
| 1068 1201 |  | 
| 1069 1202 | 
             
                    message = auto_void?(authorization_from(response, action, amount, options), response, message, options)
         | 
| 1070 1203 |  | 
| 1071 | 
            -
                    Response.new( | 
| 1204 | 
            +
                    Response.new(
         | 
| 1205 | 
            +
                      success,
         | 
| 1206 | 
            +
                      message,
         | 
| 1207 | 
            +
                      response,
         | 
| 1072 1208 | 
             
                      test: test?,
         | 
| 1073 1209 | 
             
                      authorization: authorization,
         | 
| 1074 1210 | 
             
                      fraud_review: in_fraud_review?(response),
         | 
| 1075 1211 | 
             
                      avs_result: { code: response[:avsCode] },
         | 
| 1076 | 
            -
                      cvv_result: response[:cvCode] | 
| 1212 | 
            +
                      cvv_result: response[:cvCode]
         | 
| 1213 | 
            +
                    )
         | 
| 1077 1214 | 
             
                  end
         | 
| 1078 1215 |  | 
| 1079 1216 | 
             
                  def auto_void?(authorization, response, message, options = {})
         | 
| @@ -1115,6 +1252,7 @@ module ActiveMerchant #:nodoc: | |
| 1115 1252 | 
             
                        parent += '_' + node.parent.attributes['id'] if node.parent.attributes['id']
         | 
| 1116 1253 | 
             
                        parent += '_'
         | 
| 1117 1254 | 
             
                      end
         | 
| 1255 | 
            +
                      reply[:reconciliationID2] = node.text if node.name == 'reconciliationID' && reply[:reconciliationID]
         | 
| 1118 1256 | 
             
                      reply["#{parent}#{node.name}".to_sym] ||= node.text
         | 
| 1119 1257 | 
             
                    end
         | 
| 1120 1258 | 
             
                    return reply
         |