# frozen_string_literal: true require 'active_merchant/billing/response' require_relative 'avs_result' # Response object that all actions on the gateway should return module SolidusPaypalBraintree class Response < ActiveMerchant::Billing::Response # def initialize(success, message, params = {}, options = {}) class << self private :new # @param result [Braintree::SuccessfulResult, Braintree::ErrorResult] def build(result) result.success? ? build_success(result) : build_failure(result) end private def build_success(result) transaction = result.transaction new(true, transaction.status, {}, response_options(transaction)) end def build_failure(result) transaction = result.transaction options = response_options(transaction).update( # For error responses we want to have the CVV code cvv_result: transaction&.cvv_response_code ) new(false, error_message(result), result.params, options) end def response_options(transaction) # Some error responses do not have a transaction return {} if transaction.nil? { authorization: transaction.id, avs_result: SolidusPaypalBraintree::AVSResult.build(transaction), # As we do not provide the CVV while submitting the transaction (for PCI compliance reasons), # we need to ignore the only response we get back (I = not provided). # Otherwise Solidus thinks this payment is risky. cvv_result: nil } end def error_message(result) if result.errors.any? result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ") else transaction_error_message(result.transaction) end end # Human readable error message for transaction responses def transaction_error_message(transaction) case transaction.status when 'gateway_rejected' I18n.t(transaction.gateway_rejection_reason, scope: 'solidus_paypal_braintree.gateway_rejection_reasons', default: "#{transaction.status.humanize} #{transaction.gateway_rejection_reason.humanize}") when 'processor_declined' I18n.t(transaction.processor_response_code, scope: 'solidus_paypal_braintree.processor_response_codes', default: "#{transaction.processor_response_text} (#{transaction.processor_response_code})") when 'settlement_declined' I18n.t(transaction.processor_settlement_response_code, scope: 'solidus_paypal_braintree.processor_settlement_response_codes', default: "#{transaction.processor_settlement_response_text} (#{transaction.processor_settlement_response_code})") # rubocop:disable Layout/LineLength else I18n.t(transaction.status, scope: 'solidus_paypal_braintree.transaction_statuses', default: transaction.status.humanize) end end end end end