Skip to content

Commit

Permalink
BraintreeBlue: Support Apple and Google Pay recurring
Browse files Browse the repository at this point in the history
COMP-71

Adds support for Apple Pay and Google Pay recurring

Test Summary
Local:

Unit:

Remote:
  • Loading branch information
KenderBolivarT committed Sep 13, 2024
1 parent 52f3401 commit 8d577ba
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 23 deletions.
66 changes: 44 additions & 22 deletions lib/active_merchant/billing/gateways/braintree_blue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -958,9 +958,9 @@ def add_payment_method(parameters, credit_card_or_vault_id, options)
if credit_card_or_vault_id.is_a?(NetworkTokenizationCreditCard)
case credit_card_or_vault_id.source
when :apple_pay
add_apple_pay(parameters, credit_card_or_vault_id)
add_apple_pay(parameters, credit_card_or_vault_id, options)
when :google_pay
add_google_pay(parameters, credit_card_or_vault_id)
add_google_pay(parameters, credit_card_or_vault_id, options)
else
add_network_tokenization_card(parameters, credit_card_or_vault_id)
end
Expand Down Expand Up @@ -991,29 +991,51 @@ def add_credit_card(parameters, payment_method)
}
end

def add_apple_pay(parameters, payment_method)
parameters[:apple_pay_card] = {
number: payment_method.number,
expiration_month: payment_method.month.to_s.rjust(2, '0'),
expiration_year: payment_method.year.to_s,
cardholder_name: payment_method.name,
cryptogram: payment_method.payment_cryptogram,
eci_indicator: payment_method.eci
}
def add_apple_pay(parameters, payment_method, options)
if options.dig(:stored_credential, :initiator) == 'merchant'
parameters[:apple_pay_card] = {
number: payment_method.number,
expiration_month: payment_method.month.to_s.rjust(2, '0'),
expiration_year: payment_method.year.to_s,
cardholder_name: payment_method.name,
eci_indicator: payment_method.eci
}
else
parameters[:apple_pay_card] = {
number: payment_method.number,
expiration_month: payment_method.month.to_s.rjust(2, '0'),
expiration_year: payment_method.year.to_s,
cardholder_name: payment_method.name,
cryptogram: payment_method.payment_cryptogram,
eci_indicator: payment_method.eci
}
end
end

def add_google_pay(parameters, payment_method)
def add_google_pay(parameters, payment_method, options)
Braintree::Version::Major < 3 ? pay_card = :android_pay_card : pay_card = :google_pay_card
parameters[pay_card] = {
number: payment_method.number,
cryptogram: payment_method.payment_cryptogram,
expiration_month: payment_method.month.to_s.rjust(2, '0'),
expiration_year: payment_method.year.to_s,
google_transaction_id: payment_method.transaction_id,
source_card_type: payment_method.brand,
source_card_last_four: payment_method.last_digits,
eci_indicator: payment_method.eci
}
if options.dig(:stored_credential, :initiator) == 'merchant'
parameters[pay_card] = {
number: payment_method.number,
expiration_month: payment_method.month.to_s.rjust(2, '0'),
expiration_year: payment_method.year.to_s,
google_transaction_id: payment_method.transaction_id,
source_card_type: payment_method.brand,
source_card_last_four: payment_method.last_digits,
eci_indicator: payment_method.eci
}
else
parameters[pay_card] = {
number: payment_method.number,
cryptogram: payment_method.payment_cryptogram,
expiration_month: payment_method.month.to_s.rjust(2, '0'),
expiration_year: payment_method.year.to_s,
google_transaction_id: payment_method.transaction_id,
source_card_type: payment_method.brand,
source_card_last_four: payment_method.last_digits,
eci_indicator: payment_method.eci
}
end
end

def add_network_tokenization_card(parameters, payment_method)
Expand Down
16 changes: 16 additions & 0 deletions test/remote/gateways/remote_braintree_blue_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,7 @@ def test_unsuccessful_google_pay_purchase_and_return_payment_details
transaction_id: '123456789',
eci: '05'
)

assert response = @gateway.purchase(204700, credit_card, @options)
assert_failure response
assert_equal('2047 : Call Issuer. Pick Up Card.', response.params['braintree_transaction']['additional_processor_response'])
Expand All @@ -1431,6 +1432,21 @@ def test_successful_apple_pay_purchase_with_prepaid_debit_issuing_bank
assert_equal 'Unknown', response.params['braintree_transaction']['apple_pay_details']['issuing_bank']
end

def test_successful_apple_pay_recurring_payment
network_tokenized_credit_card = network_tokenization_credit_card(
'4111111111111111',
brand: 'visa',
eci: '05',
transaction_id: '123',
source: :apple_pay,
payment_cryptogram: 'EHuWW9PiBkWvqE5juRwDzAUFBAk='
)
apple_pay_options = @options.merge(stored_credential: { initiator: 'customer', reason_type: 'recurring_first', initial_transaction: true })

assert response = @gateway.purchase(@amount, network_tokenized_credit_card, apple_pay_options)
assert_success response
end

def test_unsuccessful_apple_pay_purchase_and_return_payment_details
credit_card = network_tokenization_credit_card(
'4111111111111111',
Expand Down
77 changes: 76 additions & 1 deletion test/unit/gateways/braintree_blue_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1052,13 +1052,88 @@ def test_apple_pay_card
brand: 'visa',
transaction_id: '123',
eci: '05',
payment_cryptogram: '111111111100cryptogram'
payment_cryptogram: '111111111100cryptogram',
source: :apple_pay
)

response = @gateway.authorize(100, credit_card, test: true, order_id: '1')
assert_equal 'transaction_id', response.authorization
end

def test_apple_pay_card_recurring
Braintree::TransactionGateway.any_instance.expects(:sale).
with(
amount: '1.00',
order_id: '1',
customer: { id: nil, email: nil, phone: nil,
first_name: 'Longbob', last_name: 'Longsen' },
options: { store_in_vault: false, submit_for_settlement: nil, hold_in_escrow: nil },
custom_fields: nil,
apple_pay_card: {
number: '4111111111111111',
expiration_month: '09',
expiration_year: (Time.now.year + 1).to_s,
cardholder_name: 'Longbob Longsen',
eci_indicator: '05'
},
external_vault: {
status: 'vaulted',
previous_network_transaction_id: '123ABC'
},
transaction_source: 'recurring'
).
returns(braintree_result(id: 'transaction_id'))

apple_pay = network_tokenization_credit_card(
'4111111111111111',
brand: 'visa',
transaction_id: '123',
eci: '05',
payment_cryptogram: '111111111100cryptogram',
source: :apple_pay
)

response = @gateway.authorize(100, apple_pay, { test: true, order_id: '1', stored_credential: stored_credential(:merchant, :recurring, id: '123ABC') })
assert_equal 'transaction_id', response.authorization
end

def test_google_pay_card_recurring
Braintree::TransactionGateway.any_instance.expects(:sale).
with(
amount: '1.00',
order_id: '1',
customer: { id: nil, email: nil, phone: nil,
first_name: 'Longbob', last_name: 'Longsen' },
options: { store_in_vault: false, submit_for_settlement: nil, hold_in_escrow: nil },
custom_fields: nil,
google_pay_card: {
number: '4111111111111111',
expiration_month: '09',
expiration_year: (Time.now.year + 1).to_s,
google_transaction_id: '1234567890',
source_card_type: 'visa',
source_card_last_four: '1111',
eci_indicator: '05'
},
external_vault: {
status: 'vaulted',
previous_network_transaction_id: '123ABC'
},
transaction_source: 'recurring'
).
returns(braintree_result(id: 'transaction_id'))
google_pay = network_tokenization_credit_card(
'4111111111111111',
brand: 'visa',
eci: '05',
payment_cryptogram: '111111111100cryptogram',
source: :google_pay,
transaction_id: '1234567890'
)
response = @gateway.authorize(100, google_pay, { test: true, order_id: '1', stored_credential: stored_credential(:merchant, :recurring, id: '123ABC') })
assert_equal 'transaction_id', response.authorization
end

def test_google_pay_card
Braintree::TransactionGateway.any_instance.expects(:sale).
with(
Expand Down

0 comments on commit 8d577ba

Please sign in to comment.