Skip to content

Commit

Permalink
HPs: Update NetworkTokenizationCreditCard flow
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Alma Malambo committed Aug 9, 2024
1 parent 72d2a33 commit fa0e772
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 119 deletions.
71 changes: 31 additions & 40 deletions lib/active_merchant/billing/gateways/hps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}

Expand All @@ -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
Expand Down Expand Up @@ -110,7 +106,8 @@ def scrub(transcript)
gsub(%r((<hps:SecretAPIKey>)[^<]*(<\/hps:SecretAPIKey>))i, '\1[FILTERED]\2').
gsub(%r((<hps:PaymentData>)[^<]*(<\/hps:PaymentData>))i, '\1[FILTERED]\2').
gsub(%r((<hps:RoutingNumber>)[^<]*(<\/hps:RoutingNumber>))i, '\1[FILTERED]\2').
gsub(%r((<hps:AccountNumber>)[^<]*(<\/hps:AccountNumber>))i, '\1[FILTERED]\2')
gsub(%r((<hps:AccountNumber>)[^<]*(<\/hps:AccountNumber>))i, '\1[FILTERED]\2').
gsub(%r((<hps:Cryptogram>)[^<]*(<\/hps:Cryptogram>))i, '\1[FILTERED]\2')
end

private
Expand All @@ -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
Expand Down Expand Up @@ -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, strip_leading_zero(payment_method.eci) 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

Expand Down
51 changes: 0 additions & 51 deletions test/remote/gateways/remote_hps_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down Expand Up @@ -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',
Expand Down
52 changes: 24 additions & 28 deletions test/unit/gateways/hps_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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>(.*)<\/hps:SecureECommerce>/, data)
assert_match(/<hps:PaymentDataSource>Visa 3DSecure<\/hps:PaymentDataSource>/, data)
assert_match(/<hps:TypeOfPaymentData>3DSecure<\/hps:TypeOfPaymentData>/, data)
assert_match(/<hps:PaymentData>#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data)
assert_match(/<hps:ECommerceIndicator>5<\/hps:ECommerceIndicator>/, data)
assert_match(/<hps:XID>#{options[:three_d_secure][:xid]}<\/hps:XID>/, data)
assert_match(/<hps:Secure3D>(.*)<\/hps:Secure3D>/, data)
assert_match(/<hps:Version>#{options[:three_d_secure][:version]}<\/hps:Version>/, data)
assert_match(/<hps:AuthenticationValue>#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data)
assert_match(/<hps:ECI>5<\/hps:ECI>/, data)
assert_match(/<hps:DirectoryServerTxnId>#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data)
end.respond_with(successful_charge_response)

assert_success response
Expand All @@ -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>(.*)<\/hps:SecureECommerce>/, data)
assert_match(/<hps:PaymentDataSource>MasterCard 3DSecure<\/hps:PaymentDataSource>/, data)
assert_match(/<hps:TypeOfPaymentData>3DSecure<\/hps:TypeOfPaymentData>/, data)
assert_match(/<hps:PaymentData>#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data)
assert_match(/<hps:ECommerceIndicator>5<\/hps:ECommerceIndicator>/, data)
assert_match(/<hps:XID>#{options[:three_d_secure][:xid]}<\/hps:XID>/, data)
assert_match(/<hps:Secure3D>(.*)<\/hps:Secure3D>/, data)
assert_match(/<hps:Version>#{options[:three_d_secure][:version]}<\/hps:Version>/, data)
assert_match(/<hps:AuthenticationValue>#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data)
assert_match(/<hps:ECI>5<\/hps:ECI>/, data)
assert_match(/<hps:DirectoryServerTxnId>#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data)
end.respond_with(successful_charge_response)

assert_success response
Expand All @@ -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>(.*)<\/hps:SecureECommerce>/, data)
assert_match(/<hps:PaymentDataSource>Discover 3DSecure<\/hps:PaymentDataSource>/, data)
assert_match(/<hps:TypeOfPaymentData>3DSecure<\/hps:TypeOfPaymentData>/, data)
assert_match(/<hps:PaymentData>#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data)
assert_match(/<hps:ECommerceIndicator>5<\/hps:ECommerceIndicator>/, data)
assert_match(/<hps:XID>#{options[:three_d_secure][:xid]}<\/hps:XID>/, data)
assert_match(/<hps:Secure3D>(.*)<\/hps:Secure3D>/, data)
assert_match(/<hps:AuthenticationValue>#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data)
assert_match(/<hps:ECI>5<\/hps:ECI>/, data)
assert_match(/<hps:DirectoryServerTxnId>#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data)
end.respond_with(successful_charge_response)

assert_success response
Expand All @@ -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>(.*)<\/hps:SecureECommerce>/, data)
assert_match(/<hps:PaymentDataSource>AMEX 3DSecure<\/hps:PaymentDataSource>/, data)
assert_match(/<hps:TypeOfPaymentData>3DSecure<\/hps:TypeOfPaymentData>/, data)
assert_match(/<hps:PaymentData>#{options[:three_d_secure][:cavv]}<\/hps:PaymentData>/, data)
assert_match(/<hps:ECommerceIndicator>5<\/hps:ECommerceIndicator>/, data)
assert_match(/<hps:XID>#{options[:three_d_secure][:xid]}<\/hps:XID>/, data)
assert_match(/<hps:Secure3D>(.*)<\/hps:Secure3D>/, data)
assert_match(/<hps:AuthenticationValue>#{options[:three_d_secure][:cavv]}<\/hps:AuthenticationValue>/, data)
assert_match(/<hps:ECI>5<\/hps:ECI>/, data)
assert_match(/<hps:DirectoryServerTxnId>#{options[:three_d_secure][:ds_transaction_id]}<\/hps:DirectoryServerTxnId>/, data)
end.respond_with(successful_charge_response)

assert_success response
Expand Down

0 comments on commit fa0e772

Please sign in to comment.