Skip to content

Commit

Permalink
Worldpay: Support apple pay recurring
Browse files Browse the repository at this point in the history
COMP-73

Adds support for Apple Pay MIT recurring

Test Summary
Local:

Unit:
125 tests, 702 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed

Remote:
111 tests, 479 assertions, 2 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
98.1982% passed
  • Loading branch information
KenderBolivarT committed Sep 19, 2024
1 parent 8e14454 commit bb2a7b7
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 5 deletions.
32 changes: 27 additions & 5 deletions lib/active_merchant/billing/gateways/worldpay.rb
Original file line number Diff line number Diff line change
Expand Up @@ -663,14 +663,24 @@ def add_network_tokenization_card(xml, payment_method, options)
end
name = card_holder_name(payment_method, options)
xml.cardHolderName name if name.present?
xml.cryptogram payment_method.payment_cryptogram unless options[:wallet_type] == :google_pay
xml.cryptogram payment_method.payment_cryptogram if should_send_payment_cryptogram?(options, payment_method)
eci = eci_value(payment_method, options)
xml.eciIndicator eci if eci.present?
end
add_stored_credential_options(xml, options)
end
end

def should_send_payment_cryptogram?(options, payment_method)
!(
wallet_type_google_pay?(options) ||
(
payment_method_apple_pay?(payment_method) &&
options.dig(:stored_credential, :initiator) == 'merchant'
)
)
end

def add_card_or_token(xml, payment_method, options)
xml.paymentDetails credit_fund_transfer_attribute(options) do
if options[:payment_type] == :token
Expand Down Expand Up @@ -1040,16 +1050,28 @@ def payment_details(payment_method, options = {})
when String
token_type_and_details(payment_method)
else
type = network_token?(payment_method) || options[:wallet_type] == :google_pay ? :network_token : :credit
type = network_token?(payment_method, options) ? :network_token : :credit

{ payment_type: type }
end
end

def network_token?(payment_method)
payment_method.respond_to?(:source) &&
def network_token?(payment_method, options)
(payment_method.respond_to?(:source) &&
payment_method.respond_to?(:payment_cryptogram) &&
payment_method.respond_to?(:eci)
payment_method.respond_to?(:eci)) ||
wallet_type_google_pay?(options) ||
payment_method_apple_pay?(payment_method)
end

def payment_method_apple_pay?(payment_method)
return false unless payment_method.is_a?(NetworkTokenizationCreditCard)

payment_method.source == :apple_pay
end

def wallet_type_google_pay?(options)
options[:wallet_type] == :google_pay
end

def token_type_and_details(token)
Expand Down
24 changes: 24 additions & 0 deletions test/remote/gateways/remote_worldpay_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def setup
sub_tax_id: '987-65-4321'
}
}

@apple_pay_network_token = network_tokenization_credit_card(
'4895370015293175',
month: 10,
Expand Down Expand Up @@ -669,6 +670,29 @@ def test_successful_auth_and_capture_with_gateway_specific_recurring_stored_cred
assert_success capture
end

def test_successful_recurring_purchase_with_apple_pay_credentials
stored_credential_params = stored_credential(:initial, :recurring, :merchant)
assert auth = @gateway.authorize(@amount, @apple_pay_network_token, @options.merge({ stored_credential: stored_credential_params }))
assert_success auth
assert auth.authorization
assert auth.params['scheme_response']
assert auth.params['transaction_identifier']

assert capture = @gateway.capture(@amount, auth.authorization, authorization_validated: true)
assert_success capture

@options[:order_id] = generate_unique_id
@options[:stored_credential] = stored_credential(:used, :recurring, :merchant, network_transaction_id: auth.params['transaction_identifier'])

assert next_auth = @gateway.authorize(@amount, @apple_pay_network_token, @options)
assert next_auth.authorization
assert next_auth.params['scheme_response']
assert next_auth.params['transaction_identifier']

assert capture = @gateway.capture(@amount, next_auth.authorization, authorization_validated: true)
assert_success capture
end

def test_successful_authorize_with_3ds_with_normalized_stored_credentials
session_id = generate_unique_id
stored_credential_params = stored_credential(:initial, :unscheduled, :merchant)
Expand Down
17 changes: 17 additions & 0 deletions test/unit/gateways/worldpay_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,23 @@ def test_authorize_prefers_options_for_ntid
assert_success response
end

def test_authorize_recurring_apple_pay_with_ntid
stored_credential_params = stored_credential(:used, :recurring, :merchant, network_transaction_id: '3812908490218390214124')

@options.merge({
stored_credential: stored_credential_params,
stored_credential_transaction_id: '000000000000020005060720116005060',
wallet_type: :apple_pay
})
response = stub_comms do
@gateway.authorize(@amount, @apple_play_network_token, @options)
end.check_request do |_endpoint, data, _headers|
assert_match %r(<EMVCO_TOKEN-SSL type="APPLEPAY">), data
refute_match %r(<cryptogram>), data
end.respond_with(successful_authorize_response)
assert_success response
end

def test_successful_inquire_with_order_id
response = stub_comms do
@gateway.inquire(nil, { order_id: @options[:order_id].to_s })
Expand Down

0 comments on commit bb2a7b7

Please sign in to comment.