From 9b4d250ca17f025a62e720f332f2d523a64de41b Mon Sep 17 00:00:00 2001 From: Alma Malambo Date: Mon, 15 Jul 2024 15:40:22 -0500 Subject: [PATCH] HPs: Update NetworkTokenizationCreditCard flow Update NetworkTokenizationCreditCArd flow to now be under WalletData. Remote 54 tests, 143 assertions, 2 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 96.2963% passed Unit 61 tests, 295 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed --- lib/active_merchant/billing/gateways/hps.rb | 71 +++++++++------------ test/remote/gateways/remote_hps_test.rb | 51 --------------- test/unit/gateways/hps_test.rb | 52 +++++++-------- 3 files changed, 55 insertions(+), 119 deletions(-) diff --git a/lib/active_merchant/billing/gateways/hps.rb b/lib/active_merchant/billing/gateways/hps.rb index a4a6370b992..560ac00c699 100644 --- a/lib/active_merchant/billing/gateways/hps.rb +++ b/lib/active_merchant/billing/gateways/hps.rb @@ -17,11 +17,6 @@ class HpsGateway < Gateway PAYMENT_DATA_SOURCE_MAPPING = { apple_pay: 'ApplePay', - master: 'MasterCard 3DSecure', - visa: 'Visa 3DSecure', - american_express: 'AMEX 3DSecure', - discover: 'Discover 3DSecure', - android_pay: 'GooglePayApp', google_pay: 'GooglePayApp' } @@ -30,15 +25,16 @@ def initialize(options = {}) super end - def authorize(money, card_or_token, options = {}) + def authorize(money, payment_method, options = {}) commit('CreditAuth') do |xml| add_amount(xml, money) add_allow_dup(xml) - add_card_or_token_customer_data(xml, card_or_token, options) + add_card_or_token_customer_data(xml, payment_method, options) add_details(xml, options) add_descriptor_name(xml, options) - add_card_or_token_payment(xml, card_or_token, options) - add_three_d_secure(xml, card_or_token, options) + add_card_or_token_payment(xml, payment_method, options) + add_wallet_data(xml, payment_method, options) + add_three_d_secure(xml, payment_method, options) add_stored_credentials(xml, options) end end @@ -110,7 +106,8 @@ def scrub(transcript) gsub(%r(()[^<]*(<\/hps:SecretAPIKey>))i, '\1[FILTERED]\2'). gsub(%r(()[^<]*(<\/hps:PaymentData>))i, '\1[FILTERED]\2'). gsub(%r(()[^<]*(<\/hps:RoutingNumber>))i, '\1[FILTERED]\2'). - gsub(%r(()[^<]*(<\/hps:AccountNumber>))i, '\1[FILTERED]\2') + gsub(%r(()[^<]*(<\/hps:AccountNumber>))i, '\1[FILTERED]\2'). + gsub(%r(()[^<]*(<\/hps:Cryptogram>))i, '\1[FILTERED]\2') end private @@ -125,28 +122,30 @@ def commit_check_sale(money, check, options) end end - def commit_credit_sale(money, card_or_token, options) + def commit_credit_sale(money, payment_method, options) commit('CreditSale') do |xml| add_amount(xml, money) add_allow_dup(xml) - add_card_or_token_customer_data(xml, card_or_token, options) + add_card_or_token_customer_data(xml, payment_method, options) add_details(xml, options) add_descriptor_name(xml, options) - add_card_or_token_payment(xml, card_or_token, options) - add_three_d_secure(xml, card_or_token, options) + add_card_or_token_payment(xml, payment_method, options) + add_wallet_data(xml, payment_method, options) + add_three_d_secure(xml, payment_method, options) add_stored_credentials(xml, options) end end - def commit_recurring_billing_sale(money, card_or_token, options) + def commit_recurring_billing_sale(money, payment_method, options) commit('RecurringBilling') do |xml| add_amount(xml, money) add_allow_dup(xml) - add_card_or_token_customer_data(xml, card_or_token, options) + add_card_or_token_customer_data(xml, payment_method, options) add_details(xml, options) add_descriptor_name(xml, options) - add_card_or_token_payment(xml, card_or_token, options) - add_three_d_secure(xml, card_or_token, options) + add_card_or_token_payment(xml, payment_method, options) + add_wallet_data(xml, payment_method, options) + add_three_d_secure(xml, payment_method, options) add_stored_credentials(xml, options) add_stored_credentials_for_recurring_billing(xml, options) end @@ -254,32 +253,24 @@ def add_descriptor_name(xml, options) xml.hps :TxnDescriptor, options[:descriptor_name] if options[:descriptor_name] end - def add_three_d_secure(xml, card_or_token, options) - if card_or_token.is_a?(NetworkTokenizationCreditCard) - build_three_d_secure(xml, { - source: card_or_token.source, - cavv: card_or_token.payment_cryptogram, - eci: card_or_token.eci, - xid: card_or_token.transaction_id - }) - elsif options[:three_d_secure] - options[:three_d_secure][:source] ||= card_brand(card_or_token) - build_three_d_secure(xml, options[:three_d_secure]) + def add_wallet_data(xml, payment_method, options) + return unless payment_method.is_a?(NetworkTokenizationCreditCard) + + xml.hps :WalletData do + xml.hps :PaymentSource, PAYMENT_DATA_SOURCE_MAPPING[payment_method.source] + xml.hps :Cryptogram, payment_method.payment_cryptogram + xml.hps :ECI, payment_method.eci&.to_s&.sub!(/^0/, '') if payment_method.eci end end - def build_three_d_secure(xml, three_d_secure) - # PaymentDataSource is required when supplying the SecureECommerce data group, - # and the gateway currently only allows the values within the mapping - return unless PAYMENT_DATA_SOURCE_MAPPING[three_d_secure[:source].to_sym] + def add_three_d_secure(xml, card_or_token, options) + return unless (three_d_secure = options[:three_d_secure]) - xml.hps :SecureECommerce do - xml.hps :PaymentDataSource, PAYMENT_DATA_SOURCE_MAPPING[three_d_secure[:source].to_sym] - xml.hps :TypeOfPaymentData, '3DSecure' # Only type currently supported - xml.hps :PaymentData, three_d_secure[:cavv] if three_d_secure[:cavv] - # the gateway only allows a single character for the ECI - xml.hps :ECommerceIndicator, strip_leading_zero(three_d_secure[:eci]) if three_d_secure[:eci] - xml.hps :XID, three_d_secure[:xid] if three_d_secure[:xid] + xml.hps :Secure3D do + xml.hps :Version, three_d_secure[:version] + xml.hps :AuthenticationValue, three_d_secure[:cavv] if three_d_secure[:cavv] + xml.hps :ECI, strip_leading_zero(three_d_secure[:eci]) if three_d_secure[:eci] + xml.hps :DirectoryServerTxnId, three_d_secure[:ds_transaction_id] if three_d_secure[:ds_transaction_id] end end diff --git a/test/remote/gateways/remote_hps_test.rb b/test/remote/gateways/remote_hps_test.rb index 9f7a0e08c24..d5343cf751e 100644 --- a/test/remote/gateways/remote_hps_test.rb +++ b/test/remote/gateways/remote_hps_test.rb @@ -362,7 +362,6 @@ def test_transcript_scrubbing_with_cryptogram credit_card = network_tokenization_credit_card( '4242424242424242', payment_cryptogram: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', - verification_value: nil, eci: '05', source: :apple_pay ) @@ -435,56 +434,6 @@ def test_successful_auth_with_apple_pay_raw_cryptogram_without_eci assert_equal 'Success', response.message end - def test_successful_purchase_with_android_pay_raw_cryptogram_with_eci - credit_card = network_tokenization_credit_card( - '4242424242424242', - payment_cryptogram: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', - verification_value: nil, - eci: '05', - source: :android_pay - ) - assert response = @gateway.purchase(@amount, credit_card, @options) - assert_success response - assert_equal 'Success', response.message - end - - def test_successful_purchase_with_android_pay_raw_cryptogram_without_eci - credit_card = network_tokenization_credit_card( - '4242424242424242', - payment_cryptogram: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', - verification_value: nil, - source: :android_pay - ) - assert response = @gateway.purchase(@amount, credit_card, @options) - assert_success response - assert_equal 'Success', response.message - end - - def test_successful_auth_with_android_pay_raw_cryptogram_with_eci - credit_card = network_tokenization_credit_card( - '4242424242424242', - payment_cryptogram: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', - verification_value: nil, - eci: '05', - source: :android_pay - ) - assert response = @gateway.authorize(@amount, credit_card, @options) - assert_success response - assert_equal 'Success', response.message - end - - def test_successful_auth_with_android_pay_raw_cryptogram_without_eci - credit_card = network_tokenization_credit_card( - '4242424242424242', - payment_cryptogram: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', - verification_value: nil, - source: :android_pay - ) - assert response = @gateway.authorize(@amount, credit_card, @options) - assert_success response - assert_equal 'Success', response.message - end - def test_successful_purchase_with_google_pay_raw_cryptogram_with_eci credit_card = network_tokenization_credit_card( '4242424242424242', diff --git a/test/unit/gateways/hps_test.rb b/test/unit/gateways/hps_test.rb index 1f8832e7ab7..ad8ac0552fd 100644 --- a/test/unit/gateways/hps_test.rb +++ b/test/unit/gateways/hps_test.rb @@ -639,21 +639,21 @@ def test_three_d_secure_visa options = { three_d_secure: { + version: '2.2.0', cavv: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', eci: '05', - xid: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' + ds_transaction_id: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' } } response = stub_comms(@gateway, :ssl_request) do @gateway.purchase(@amount, @credit_card, options) end.check_request do |_method, _endpoint, data, _headers| - assert_match(/(.*)<\/hps:SecureECommerce>/, data) - assert_match(/Visa 3DSecure<\/hps:PaymentDataSource>/, data) - assert_match(/3DSecure<\/hps:TypeOfPaymentData>/, data) - assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data) - assert_match(/5<\/hps:ECommerceIndicator>/, data) - assert_match(/#{options[:three_d_secure][:xid]}<\/hps:XID>/, data) + assert_match(/(.*)<\/hps:Secure3D>/, data) + assert_match(/#{options[:three_d_secure][:version]}<\/hps:Version>/, data) + assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data) + assert_match(/5<\/hps:ECI>/, data) + assert_match(/#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data) end.respond_with(successful_charge_response) assert_success response @@ -666,21 +666,21 @@ def test_three_d_secure_mastercard options = { three_d_secure: { + version: '2.2.0', cavv: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', eci: '05', - xid: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' + ds_transaction_id: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' } } response = stub_comms(@gateway, :ssl_request) do @gateway.purchase(@amount, @credit_card, options) end.check_request do |_method, _endpoint, data, _headers| - assert_match(/(.*)<\/hps:SecureECommerce>/, data) - assert_match(/MasterCard 3DSecure<\/hps:PaymentDataSource>/, data) - assert_match(/3DSecure<\/hps:TypeOfPaymentData>/, data) - assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data) - assert_match(/5<\/hps:ECommerceIndicator>/, data) - assert_match(/#{options[:three_d_secure][:xid]}<\/hps:XID>/, data) + assert_match(/(.*)<\/hps:Secure3D>/, data) + assert_match(/#{options[:three_d_secure][:version]}<\/hps:Version>/, data) + assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data) + assert_match(/5<\/hps:ECI>/, data) + assert_match(/#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data) end.respond_with(successful_charge_response) assert_success response @@ -695,19 +695,17 @@ def test_three_d_secure_discover three_d_secure: { cavv: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', eci: '5', - xid: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' + ds_transaction_id: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' } } response = stub_comms(@gateway, :ssl_request) do @gateway.purchase(@amount, @credit_card, options) end.check_request do |_method, _endpoint, data, _headers| - assert_match(/(.*)<\/hps:SecureECommerce>/, data) - assert_match(/Discover 3DSecure<\/hps:PaymentDataSource>/, data) - assert_match(/3DSecure<\/hps:TypeOfPaymentData>/, data) - assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data) - assert_match(/5<\/hps:ECommerceIndicator>/, data) - assert_match(/#{options[:three_d_secure][:xid]}<\/hps:XID>/, data) + assert_match(/(.*)<\/hps:Secure3D>/, data) + assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data) + assert_match(/5<\/hps:ECI>/, data) + assert_match(/#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data) end.respond_with(successful_charge_response) assert_success response @@ -722,19 +720,17 @@ def test_three_d_secure_amex three_d_secure: { cavv: 'EHuWW9PiBkWvqE5juRwDzAUFBAk=', eci: '05', - xid: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' + ds_transaction_id: 'TTBCSkVTa1ZpbDI1bjRxbGk5ODE=' } } response = stub_comms(@gateway, :ssl_request) do @gateway.purchase(@amount, @credit_card, options) end.check_request do |_method, _endpoint, data, _headers| - assert_match(/(.*)<\/hps:SecureECommerce>/, data) - assert_match(/AMEX 3DSecure<\/hps:PaymentDataSource>/, data) - assert_match(/3DSecure<\/hps:TypeOfPaymentData>/, data) - assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data) - assert_match(/5<\/hps:ECommerceIndicator>/, data) - assert_match(/#{options[:three_d_secure][:xid]}<\/hps:XID>/, data) + assert_match(/(.*)<\/hps:Secure3D>/, data) + assert_match(/#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data) + assert_match(/5<\/hps:ECI>/, data) + assert_match(/#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data) end.respond_with(successful_charge_response) assert_success response