diff --git a/lib/active_merchant/billing/gateways/checkout_v2.rb b/lib/active_merchant/billing/gateways/checkout_v2.rb index f31a16e9257..e11a5a9566f 100644 --- a/lib/active_merchant/billing/gateways/checkout_v2.rb +++ b/lib/active_merchant/billing/gateways/checkout_v2.rb @@ -57,6 +57,7 @@ def credit(amount, payment, options = {}) add_instruction_data(post, options) add_payout_sender_data(post, options) add_payout_destination_data(post, options) + add_metadata(post, options) commit(:credit, post, options) end @@ -580,10 +581,17 @@ def response(action, succeeded, response, options = {}, source_id = nil) error_code: error_code_from(succeeded, body, options), test: test?, avs_result: avs_result(response), - cvv_result: cvv_result(response) + cvv_result: cvv_result(response), + pending: pending_result(response, action) ) end + def pending_result(response, action) + return unless action == :credit + + response['status'] == 'Pending' + end + def headers(action, options) auth_token = @options[:access_token] ? "Bearer #{@options[:access_token]}" : @options[:secret_key] auth_token = @options[:public_key] if action == :tokens @@ -664,7 +672,9 @@ def message_from(succeeded, response, options) if succeeded 'Succeeded' elsif response['error_type'] - response['error_type'] + ': ' + response['error_codes'].first + return response['error_type'] unless response['error_codes'] + + "#{response['error_type']}: #{response['error_codes'].first}" else response_summary = response['response_summary'] || response.dig('actions', 0, 'response_summary') response_summary || response['response_code'] || response['status'] || response['message'] || 'Unable to read error message' diff --git a/lib/active_merchant/billing/response.rb b/lib/active_merchant/billing/response.rb index bfa3fab0dc5..5b9a5308920 100644 --- a/lib/active_merchant/billing/response.rb +++ b/lib/active_merchant/billing/response.rb @@ -4,7 +4,7 @@ class Error < ActiveMerchantError # :nodoc: end class Response - attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result, :error_code, :emv_authorization, :network_transaction_id + attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result, :error_code, :emv_authorization, :network_transaction_id, :pending def success? @success @@ -30,6 +30,7 @@ def initialize(success, message, params = {}, options = {}) @error_code = options[:error_code] @emv_authorization = options[:emv_authorization] @network_transaction_id = options[:network_transaction_id] + @pending = options[:pending] || false @avs_result = if options[:avs_result].kind_of?(AVSResult) options[:avs_result].to_hash diff --git a/test/remote/gateways/remote_checkout_v2_test.rb b/test/remote/gateways/remote_checkout_v2_test.rb index b46ad64bb3f..d720463cec8 100644 --- a/test/remote/gateways/remote_checkout_v2_test.rb +++ b/test/remote/gateways/remote_checkout_v2_test.rb @@ -904,6 +904,7 @@ def test_successful_credit response = @gateway_oauth.credit(@amount, @credit_card, @options.merge({ source_type: 'currency_account', source_id: 'ca_spwmped4qmqenai7hcghquqle4', account_holder_type: 'individual' })) assert_success response assert_equal 'Succeeded', response.message + assert_equal true, response.primary_response.pending end def test_successful_money_transfer_payout_via_credit_individual_account_holder_type @@ -912,6 +913,7 @@ def test_successful_money_transfer_payout_via_credit_individual_account_holder_t response = @gateway_oauth.credit(@amount, @credit_card, @payout_options.merge(account_holder_type: 'individual', payout: true)) assert_success response assert_equal 'Succeeded', response.message + assert_equal true, response.primary_response.pending end def test_successful_money_transfer_payout_via_credit_corporate_account_holder_type diff --git a/test/unit/gateways/checkout_v2_test.rb b/test/unit/gateways/checkout_v2_test.rb index 9f7e74a52a1..b04eff25b0f 100644 --- a/test/unit/gateways/checkout_v2_test.rb +++ b/test/unit/gateways/checkout_v2_test.rb @@ -1,4 +1,5 @@ require 'test_helper' + class CheckoutV2Test < Test::Unit::TestCase include CommStub @@ -799,7 +800,8 @@ def test_successfully_passes_fund_type_and_fields funds_transfer_type: 'FD', source_type: 'currency_account', source_id: 'ca_spwmped4qmqenai7hcghquqle4', - account_holder_type: 'individual' + account_holder_type: 'individual', + metadata: { transaction_token: '123' } } response = stub_comms(@gateway, :ssl_request) do @gateway.credit(@amount, @credit_card, options) @@ -811,6 +813,7 @@ def test_successfully_passes_fund_type_and_fields assert_equal request['destination']['account_holder']['type'], options[:account_holder_type] assert_equal request['destination']['account_holder']['first_name'], @credit_card.first_name assert_equal request['destination']['account_holder']['last_name'], @credit_card.last_name + assert_equal request['metadata']['transaction_token'], '123' end.respond_with(successful_credit_response) assert_success response end @@ -1038,6 +1041,15 @@ def test_error_code_returned assert_match(/request_invalid: card_expired/, response.error_code) end + def test_error_type_without_error_code_returned + response = stub_comms(@gateway, :ssl_request) do + @gateway.purchase(@amount, @credit_card) + end.respond_with(error_type_without_error_codes_response) + + assert_failure response + assert_match(/request_invalid/, response.error_code) + end + def test_4xx_error_message @gateway.expects(:ssl_request).raises(error_4xx_response) @@ -1471,6 +1483,14 @@ def error_code_response ) end + def error_type_without_error_codes_response + %( + { + "request_id": "e5a3ce6f-a4e9-4445-9ec7-e5975e9a6213","error_type": "request_invalid" + } + ) + end + def error_4xx_response mock_response = Net::HTTPUnauthorized.new('1.1', '401', 'Unauthorized') mock_response.stubs(:body).returns('')