diff --git a/CHANGELOG b/CHANGELOG index 79cef2fc3bd..aee70445e52 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -100,6 +100,7 @@ * Nuvei: Fix send savePM in false by default [javierpedrozaing] #5353 * Decidir and DecicirPlus: Add the wallet_id field [yunnydang] #5354 * Worldpay: Update where to pass shopperIPAddress [almalee24] #5348 +* Braintree: Account for BraintreeError [almalee24] #5346 == Version 1.137.0 (August 2, 2024) * Unlock dependency on `rexml` to allow fixing a CVE (#5181). diff --git a/lib/active_merchant/billing/gateways/braintree_blue.rb b/lib/active_merchant/billing/gateways/braintree_blue.rb index dcd5906a4b4..0d74be854f1 100644 --- a/lib/active_merchant/billing/gateways/braintree_blue.rb +++ b/lib/active_merchant/billing/gateways/braintree_blue.rb @@ -1061,26 +1061,33 @@ def add_bank_account_to_customer(payment_method, options) } ) - verified = result.success? && result.payment_method&.verified - message = message_from_result(result) - message = not_verified_reason(result.payment_method) unless verified - + success = bank_account_verified?(result) + resp_body = if result.respond_to?(:payment_method) + { + customer_vault_id: options[:customer], + bank_account_token: result.payment_method&.token, + verified: success + } + end Response.new( - verified, - message, - { - customer_vault_id: options[:customer], - bank_account_token: result.payment_method&.token, - verified: - }, - authorization: result.payment_method&.token + success, + message_from_bank_account_result(success, result), + resp_body || {}, + authorization: (result.payment_method&.token if result.respond_to?(:payment_method)) ) end - def not_verified_reason(bank_account) - return unless bank_account.verifications.present? + def bank_account_verified?(result) + return false unless result.respond_to?(:payment_method) + + result.success? && result.payment_method&.verified + end + + def message_from_bank_account_result(success, response) + return message_from_result(response) if !response.respond_to?(:payment_method) || success + return unless response.payment_method.verifications.present? - verification = bank_account.verifications.first + verification = response.payment_method.verifications.first "verification_status: [#{verification.status}], processor_response: [#{verification.processor_response_code}-#{verification.processor_response_text}]" end diff --git a/test/unit/gateways/braintree_blue_test.rb b/test/unit/gateways/braintree_blue_test.rb index 26a13670bee..1d74fad7431 100644 --- a/test/unit/gateways/braintree_blue_test.rb +++ b/test/unit/gateways/braintree_blue_test.rb @@ -1173,6 +1173,38 @@ def test_unsuccessful_transaction_returns_id_when_available assert response.authorization.present? end + def test_unsuccessful_adding_bank_account_to_customer + bank_account = check({ account_number: '1000000002', routing_number: '011000015' }) + options = { + billing_address: { + address1: '1670', + address2: '1670 NW 82ND AVE', + city: 'Miami', + state: 'FL', + zip: '32191' + }, + ach_mandate: 'ACH Mandate', + merchant_account_id: 'merchant_account_id' + } + customer = stub( + credit_cards: [stub_everything], + email: 'email', + phone: '321-654-0987', + first_name: 'John', + last_name: 'Smith' + ) + customer.stubs(:id).returns('123') + + Braintree::CustomerGateway.any_instance.expects(:create).returns(Braintree::SuccessfulResult.new(customer:)) + Braintree::ClientTokenGateway.any_instance.expects(:generate).returns('IntcImNsaWVudF90b2tlblwiOlwiMTIzNFwifSI=') + ActiveMerchant::Billing::TokenNonce.any_instance.expects(:ssl_request).returns(JSON.generate(token_bank_response)) + Braintree::PaymentMethodGateway.any_instance.expects(:create).returns(braintree_error_result(message: 'US bank account is not accepted by merchant account.')) + + assert response = @gateway.store(bank_account, options) + refute response.success? + assert_equal response.message, 'US bank account is not accepted by merchant account.' + end + def test_unsuccessful_transaction_returns_message_when_available Braintree::TransactionGateway.any_instance. expects(:sale). @@ -1658,6 +1690,24 @@ def standard_purchase_params } end + def token_bank_response + { + 'data' => { + 'tokenizeUsBankAccount' => { + 'paymentMethod' => { + 'id' => 'tokenusbankacct_bc_zrg45z_7wz95v_nscrks_q4zpjs_5m7', + 'details' => { + 'last4' => '0125' + } + } + } + }, + 'extensions' => { + 'requestId' => '769b26d5-27e4-4602-b51d-face8b6ffdd5' + } + } + end + def success_create_token_nonce <<-RESPONSE [Braintree]