diff --git a/lib/bambora/bank/batch_report_messages.rb b/lib/bambora/bank/batch_report_messages.rb new file mode 100644 index 0000000..1fa6845 --- /dev/null +++ b/lib/bambora/bank/batch_report_messages.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +module Bambora + module Bank + module BatchReportMessages + ## + # Adds message text to the response as per the Bambora Docs: + # https://help.na.bambora.com/hc/en-us/articles/115010510248-Batch-reporting + MESSAGES = { + '1' => 'Invalid bank number', + '2' => 'Invalid branch number', + '3' => 'Invalid account number', + '4' => 'Invalid transaction amount', + '5' => 'Reference number too long', + '6' => 'Invalid due date', + '7' => 'Due date out of valid date range', + '8' => 'Customer name truncated to 32 characters', + '9' => 'Customer name missing', + '10' => 'Duplicate transaction matching bank account', + '11' => 'Zero, negative or non-numeric amount', + '12' => 'Invalid bank and/or branch number', + '13' => 'Payee/drawee name cannot be spaces', + '14' => 'Invalid payment code', + '15' => 'Invalid transaction type', + '16' => 'Account Closed', + '17' => 'NSF – Debit declined due to insufficient funds.', + '18' => 'Transaction rejected by Bank', + '19' => 'Invalid bank, branch, or account number', + '20' => 'Refused by payor', + '21' => 'Funds not cleared', + '22' => 'Account Frozen', + '23' => 'Payment Stopped', + '24' => 'Transaction Cancelled', + '25' => 'Cannot Trace', + '26' => 'Incorrect Payor/Payee Name', + '27' => 'Payor/Payee Deceased', + '28' => 'Invalid transit routing number', + '29' => 'Invalid Account Type', + '30' => 'Transaction type not permitted', + '31' => 'No Checking Privileges', + '33' => 'Edit Reject', + '35' => 'Reserved Return Code', + '36' => 'Payment Recalled', + '38' => 'Not in accordance with agreement – Personal', + '39' => 'Agreement revoked – Personal', + '40' => 'No pre-notification – Personal', + '41' => 'Not in accordance with agreement – Business', + '42' => 'Agreement revoked – Business', + '43' => 'No pre-notification – Business', + '44' => 'Customer Initiated Return Credit Only', + '45' => 'Currency/Account Mismatch', + '46' => 'No Debit Allowed', + '47' => 'Interbank – Returned Item', + '48' => 'Routing as entered, account modified', + '49' => 'Routing as entered, repair of account unknown', + '50' => 'Routing as entered, account unknown', + '51' => 'Routing number modified, account as entered', + '52' => 'Routing number modified, account modified', + '53' => 'Routing number modified, repair of account unknown', + '54' => 'Routing number modified, account unknown', + '55' => 'ACH Unavailable for account', + '56' => 'Customer code invalid/missing payment info', + '58' => 'Profile status is closed or disabled', + '59' => 'Invalid SEC code', + '60' => 'Invalid Account Identifier', + '61' => 'Invalid Account Identifier', + '62' => 'Reference Number is Missing', + '63' => 'Invalid Customer Country Code', + '64' => 'Invalid Bank Country Code', + '65' => 'Invalid Bank Name', + '66' => 'Bank Name is Missing', + '67' => 'Addendum not allowed, too long, or has invalid characters', + '68' => 'Invalid Bank Descriptor', + '69' => 'Invalid Customer Name', + '70' => 'Transaction rejected - contact support', + '71' => 'Refund Request by End Customer', + '72' => 'Blocked due to a Notice of Change', + }.freeze + end + end +end diff --git a/lib/bambora/bank/batch_report_resource.rb b/lib/bambora/bank/batch_report_resource.rb index 103b235..1f9ddde 100644 --- a/lib/bambora/bank/batch_report_resource.rb +++ b/lib/bambora/bank/batch_report_resource.rb @@ -7,6 +7,8 @@ module Bank # # @see https://dev.na.bambora.com/docs/guides/batch_payment/report/ class BatchReportResource + include Bambora::Bank::BatchReportMessages + DEFAULT_REQUEST_PARAMS = { rpt_format: 'JSON', rpt_version: '2.0', @@ -51,11 +53,20 @@ def initialize(client:, api_key:) # # @params profile_data [Hash] with values as noted in the example. def show(report_data) - client.post(path: sub_path, body: batch_report_body(report_data)) + add_messages_to_response( + client.post(path: sub_path, body: batch_report_body(report_data)), + ) end private + def add_messages_to_response(response) + response.dig(:response, :record).map! do |record| + record.merge!(messages: record[:messageId].split(',').map { |id| MESSAGES[id] }) + end + response + end + def batch_report_body(request_data) DEFAULT_REQUEST_PARAMS.merge(request_data).merge( merchant_id: client.merchant_id, diff --git a/lib/bambora/client.rb b/lib/bambora/client.rb index 2925949..ff19dc0 100644 --- a/lib/bambora/client.rb +++ b/lib/bambora/client.rb @@ -42,6 +42,7 @@ require 'bambora/v1/payment_resource' require 'bambora/v1/profile_resource' require 'bambora/bank/payment_profile_resource' +require 'bambora/bank/batch_report_messages' require 'bambora/bank/batch_report_resource' module Bambora diff --git a/lib/bambora/factories/response_adapter_factory.rb b/lib/bambora/factories/response_adapter_factory.rb index 5f3c67e..77eac49 100644 --- a/lib/bambora/factories/response_adapter_factory.rb +++ b/lib/bambora/factories/response_adapter_factory.rb @@ -11,7 +11,7 @@ def for(response) when 'application/json' Bambora::JSONResponse.new(response) when 'text/html' - # Currently, the only endpoint that responds wit text/html is /scripts/payment_profiles.asp + # Currently, the only endpoint that responds with text/html is /scripts/payment_profiles.asp Bambora::Bank::Adapters::PaymentProfileResponse.new(response) else raise Bambora::Client::Error, "Unknown Content Type: #{content_type}. Response Body: #{response.body}" end diff --git a/spec/bambora/bank/batch_report_resource_spec.rb b/spec/bambora/bank/batch_report_resource_spec.rb index 6b80b8a..1104de6 100644 --- a/spec/bambora/bank/batch_report_resource_spec.rb +++ b/spec/bambora/bank/batch_report_resource_spec.rb @@ -14,20 +14,75 @@ module Bank let(:headers) { { 'Authorization' => 'Passcode MTpmYWtla2V5', 'Sub-Merchant-ID' => sub_merchant_id } } let(:response_body) do { - code: 1, - message: 'Hup...want...buy.', - customer_code: 'aaa111', - validation: { - id: '', - approved: 1, - message_id: 1, - message: '', - auth_code: '', - trans_date: '', - order_number: '', - type: '', - amount: 0, - cvd_id: 123, + response: { + version: '1.0', + code: 1, + message: 'Report generated', + records: { + total: 3, + }, + record: [ + { + rowId: 1, + merchantId: 300_202_779, + batchId: 10_000_000, + transId: 1, + itemNumber: 1, + payeeName: 'General Motors', + reference: '1000070001', + operationType: 'C', + amount: 10_000, + stateId: 2, + stateName: 'Scheduled', + statusId: 1, + statusName: 'Validated/Approved', + bankDescriptor: '', + messageId: '', + customerCode: '', + settlementDate: '2017-08-09', + returnedDate: '', + returnType: '', + eftId: 0, + }, + ], + }, + } + end + + let(:expected_response) do + { + response: { + version: '1.0', + code: 1, + message: 'Report generated', + records: { + total: 3, + }, + record: [ + { + rowId: 1, + merchantId: 300_202_779, + batchId: 10_000_000, + transId: 1, + itemNumber: 1, + payeeName: 'General Motors', + reference: '1000070001', + operationType: 'C', + amount: 10_000, + stateId: 2, + stateName: 'Scheduled', + statusId: 1, + statusName: 'Validated/Approved', + bankDescriptor: '', + messageId: '', + messages: [], + customerCode: '', + settlementDate: '2017-08-09', + returnedDate: '', + returnType: '', + eftId: 0, + }, + ], }, } end @@ -37,7 +92,7 @@ module Bank 'Bambora::Rest::XMLClient', merchant_id: merchant_id, sub_merchant_id: sub_merchant_id, - post: true, + post: response_body, ) end @@ -77,10 +132,96 @@ module Bank } end - before { reports.show(request_data) } + context 'with no messageId' do + it 'sends `post` to the client with the correct data' do + reports.show(request_data) + expect(client).to have_received(:post).with(posted_data) + end + + it 'returns the expected response' do + expect(reports.show(request_data)).to eq expected_response + end + end + + context 'with messageIds' do + let(:response_body) do + { + response: { + version: '1.0', + code: 1, + message: 'Report generated', + records: { + total: 3, + }, + record: [ + { + rowId: 1, + merchantId: 300_202_779, + batchId: 10_000_000, + transId: 1, + itemNumber: 1, + payeeName: 'General Motors', + reference: '1000070001', + operationType: 'C', + amount: 10_000, + stateId: 2, + stateName: 'Scheduled', + statusId: 1, + statusName: 'Validated/Approved', + bankDescriptor: '', + messageId: '1,2', + customerCode: '', + settlementDate: '2017-08-09', + returnedDate: '', + returnType: '', + eftId: 0, + }, + ], + }, + } + end + + let(:expected_response) do + { + response: { + version: '1.0', + code: 1, + message: 'Report generated', + records: { + total: 3, + }, + record: [ + { + rowId: 1, + merchantId: 300_202_779, + batchId: 10_000_000, + transId: 1, + itemNumber: 1, + payeeName: 'General Motors', + reference: '1000070001', + operationType: 'C', + amount: 10_000, + stateId: 2, + stateName: 'Scheduled', + statusId: 1, + statusName: 'Validated/Approved', + bankDescriptor: '', + messageId: '1,2', + messages: ['Invalid bank number', 'Invalid branch number'], + customerCode: '', + settlementDate: '2017-08-09', + returnedDate: '', + returnType: '', + eftId: 0, + }, + ], + }, + } + end - it 'sends `post` to the client with the correct data' do - expect(client).to have_received(:post).with(posted_data) + it 'returns the expected response' do + expect(reports.show(request_data)).to eq expected_response + end end end end