Skip to content

Commit

Permalink
Checkout: Add support for several customer data fields
Browse files Browse the repository at this point in the history
CER-595

Ran into a lot of tricky data collisions and had to do some finagling to make sure existing test cases would pass. I left open two possibilities for passing in the phone number depending on how users would like to pass it in: manually via options or via the phone number that’s attached to credit card billing data on the payment method.

It’s possible to pay with a stored payment method which would be a `String`. In this case there’s no name data attached so added some guarding against NoMethodErrors that were resulting from trying to call payment_method.name.

Remote Tests:
92 tests, 221 assertions, 3 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
96.7391% passed

Unit Tests:
57 tests, 319 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed

Local Tests:
5516 tests, 77434 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
  • Loading branch information
rachelkirk committed Jun 20, 2023
1 parent 7fbffa0 commit 66ba752
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
10 changes: 10 additions & 0 deletions lib/active_merchant/billing/gateways/checkout_v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def build_auth_or_purchase(post, amount, payment_method, options)
add_authorization_type(post, options)
add_payment_method(post, payment_method, options)
add_customer_data(post, options)
add_extra_customer_data(post, payment_method, options)
add_shipping_address(post, options)
add_stored_credential_options(post, options)
add_transaction_data(post, options)
Expand Down Expand Up @@ -239,6 +240,15 @@ def add_customer_data(post, options)
end
end

# created a separate method for these fields because they should not be included
# in all transaction types that include methods with source and customer fields
def add_extra_customer_data(post, payment_method, options)
post[:source][:phone] = {}
post[:source][:phone][:number] = options[:phone] || options.dig(:billing_address, :phone) || options.dig(:billing_address, :phone_number)
post[:source][:phone][:country_code] = options[:phone_country_code] if options[:phone_country_code]
post[:customer][:name] = payment_method.name if payment_method.respond_to?(:name)
end

def add_shipping_address(post, options)
if address = options[:shipping_address]
post[:shipping] = {}
Expand Down
36 changes: 27 additions & 9 deletions test/remote/gateways/remote_checkout_v2_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ def setup
authentication_response_status: 'Y'
}
)
@extra_customer_data = @options.merge(
phone_country_code: '1',
phone: '9108675309'
)
end

def test_transcript_scrubbing
Expand Down Expand Up @@ -312,8 +316,8 @@ def test_successful_purchase_includes_avs_result
response = @gateway.purchase(@amount, @credit_card, @options)
assert_success response
assert_equal 'Succeeded', response.message
assert_equal 'G', response.avs_result['code']
assert_equal 'Non-U.S. issuing bank does not support AVS.', response.avs_result['message']
assert_equal 'S', response.avs_result['code']
assert_equal 'U.S.-issuing bank does not support AVS.', response.avs_result['message']
end

def test_successful_purchase_includes_avs_result_via_oauth
Expand All @@ -328,8 +332,8 @@ def test_successful_authorize_includes_avs_result
response = @gateway.authorize(@amount, @credit_card, @options)
assert_success response
assert_equal 'Succeeded', response.message
assert_equal 'G', response.avs_result['code']
assert_equal 'Non-U.S. issuing bank does not support AVS.', response.avs_result['message']
assert_equal 'S', response.avs_result['code']
assert_equal 'U.S.-issuing bank does not support AVS.', response.avs_result['message']
end

def test_successful_purchase_includes_cvv_result
Expand All @@ -339,6 +343,12 @@ def test_successful_purchase_includes_cvv_result
assert_equal 'Y', response.cvv_result['code']
end

def test_successful_purchase_with_extra_customer_data
response = @gateway.purchase(@amount, @credit_card, @extra_customer_data)
assert_success response
assert_equal 'Succeeded', response.message
end

def test_successful_authorize_includes_cvv_result
response = @gateway.authorize(@amount, @credit_card, @options)
assert_success response
Expand Down Expand Up @@ -432,7 +442,15 @@ def test_successful_purchase_with_shipping_address
end

def test_successful_purchase_without_phone_number
response = @gateway.purchase(@amount, @credit_card, billing_address: address.update(phone: ''))
response = @gateway.purchase(@amount, @credit_card, billing_address: address.update(phone: nil))
assert_success response
assert_equal 'Succeeded', response.message
end

def test_successful_purchase_without_name
credit_card = credit_card('4242424242424242', verification_value: '100', month: '6', year: Time.now.year + 1, first_name: nil, last_name: nil)
response = @gateway.purchase(@amount, credit_card, @options)
assert_equal response.params['source']['name'], ''
assert_success response
assert_equal 'Succeeded', response.message
end
Expand All @@ -446,7 +464,7 @@ def test_successful_purchase_with_ip
def test_failed_purchase
response = @gateway.purchase(100, @credit_card_dnh, @options)
assert_failure response
assert_equal 'Declined - Do Not Honour', response.message
assert_equal 'Invalid Card Number', response.message
end

def test_failed_purchase_via_oauth
Expand All @@ -470,7 +488,7 @@ def test_avs_failed_authorize
def test_invalid_shipping_address
response = @gateway.authorize(@amount, @credit_card, shipping_address: address.update(country: 'Canada'))
assert_failure response
assert_equal 'request_invalid: address_country_invalid', response.message
assert_equal 'request_invalid: country_address_invalid', response.message
end

def test_successful_authorize_and_capture
Expand Down Expand Up @@ -827,8 +845,8 @@ def test_failed_verify
def test_expired_card_returns_error_code
response = @gateway.purchase(@amount, @expired_card, @options)
assert_failure response
assert_equal 'processing_error: card_expired', response.message
assert_equal 'processing_error: card_expired', response.error_code
assert_equal 'request_invalid: card_expired', response.message
assert_equal 'request_invalid: card_expired', response.error_code
end

def test_successful_purchase_with_idempotency_key
Expand Down
35 changes: 33 additions & 2 deletions test/unit/gateways/checkout_v2_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def setup
})
@credit_card = credit_card
@amount = 100
@token = '2MPedsuenG2o8yFfrsdOBWmOuEf'
end

def test_successful_purchase
Expand Down Expand Up @@ -413,6 +414,36 @@ def test_successful_purchase_with_stored_credentials_merchant_initiated_transact
assert_equal 'Succeeded', response.message
end

def test_successful_purchase_with_extra_customer_data
stub_comms(@gateway, :ssl_request) do
options = {
phone_country_code: '1',
billing_address: address
}
@gateway.purchase(@amount, @credit_card, options)
end.check_request do |_method, _endpoint, data, _headers|
request = JSON.parse(data)
assert_equal request['source']['phone']['number'], '(555)555-5555'
assert_equal request['source']['phone']['country_code'], '1'
assert_equal request['customer']['name'], 'Longbob Longsen'
end.respond_with(successful_purchase_response)
end

def test_no_customer_name_included_in_token_purchase
stub_comms(@gateway, :ssl_request) do
options = {
phone_country_code: '1',
billing_address: address
}
@gateway.purchase(@amount, @token, options)
end.check_request do |_method, _endpoint, data, _headers|
request = JSON.parse(data)
assert_equal request['source']['phone']['number'], '(555)555-5555'
assert_equal request['source']['phone']['country_code'], '1'
refute_includes data, 'name'
end.respond_with(successful_purchase_response)
end

def test_successful_purchase_with_metadata
response = stub_comms(@gateway, :ssl_request) do
options = {
Expand Down Expand Up @@ -810,7 +841,7 @@ def test_purchase_supports_alternate_credit_card_implementation
alternate_credit_card = alternate_credit_card_class.new

alternate_credit_card.expects(:credit_card?).returns(true)
alternate_credit_card.expects(:name).returns(@credit_card.name)
alternate_credit_card.expects(:name).at_least_once.returns(@credit_card.name)
alternate_credit_card.expects(:number).returns(@credit_card.number)
alternate_credit_card.expects(:verification_value).returns(@credit_card.verification_value)
alternate_credit_card.expects(:first_name).at_least_once.returns(@credit_card.first_name)
Expand All @@ -826,7 +857,7 @@ def test_authorize_supports_alternate_credit_card_implementation
alternate_credit_card = alternate_credit_card_class.new

alternate_credit_card.expects(:credit_card?).returns(true)
alternate_credit_card.expects(:name).returns(@credit_card.name)
alternate_credit_card.expects(:name).at_least_once.returns(@credit_card.name)
alternate_credit_card.expects(:number).returns(@credit_card.number)
alternate_credit_card.expects(:verification_value).returns(@credit_card.verification_value)
alternate_credit_card.expects(:first_name).at_least_once.returns(@credit_card.first_name)
Expand Down

0 comments on commit 66ba752

Please sign in to comment.