require 'nokogiri' module ActiveMerchant #:nodoc: module Billing #:nodoc: class MaxipagoGateway < Gateway API_VERSION = '3.1.1.15' self.live_url = 'https://api.maxipago.net/UniversalAPI/postXML' self.test_url = 'https://testapi.maxipago.net/UniversalAPI/postXML' self.supported_countries = ['BR'] self.default_currency = 'BRL' self.money_format = :dollars self.supported_cardtypes = %i[visa master discover american_express diners_club] self.homepage_url = 'http://www.maxipago.com/' self.display_name = 'maxiPago!' def initialize(options = {}) requires!(options, :login, :password) super end def purchase(money, creditcard, options = {}) commit(:sale) do |xml| add_auth_purchase(xml, money, creditcard, options) end end def authorize(money, creditcard, options = {}) commit(:auth) do |xml| add_auth_purchase(xml, money, creditcard, options) end end def capture(money, authorization, options = {}) commit(:capture) do |xml| add_order_id(xml, authorization) add_reference_num(xml, options) xml.payment do add_amount(xml, money, options) end end end def void(authorization, options = {}) _, transaction_id = split_authorization(authorization) commit(:void) do |xml| xml.transactionID transaction_id end end def refund(money, authorization, options = {}) commit(:return) do |xml| add_order_id(xml, authorization) add_reference_num(xml, options) xml.payment do add_amount(xml, money, options) end end end def verify(creditcard, options = {}) MultiResponse.run(:use_first_response) do |r| r.process { authorize(100, creditcard, options) } r.process(:ignore_result) { void(r.authorization, options) } end end def supports_scrubbing? true end def scrub(transcript) transcript. gsub(%r(()[^<]*())i, '\1[FILTERED]\2'). gsub(%r(()[^<]*())i, '\1[FILTERED]\2'). gsub(%r(()[^<]*())i, '\1[FILTERED]\2') end private def commit(action, &block) request = build_xml_request(action, &block) response = parse(ssl_post(url, request, 'Content-Type' => 'text/xml')) Response.new( success?(response), message_from(response), response, test: test?, authorization: authorization_from(response) ) end def url test? ? self.test_url : self.live_url end def build_xml_request(action) builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') builder.send('transaction-request') do |xml| xml.version '3.1.1.15' xml.verification do xml.merchantId @options[:login] xml.merchantKey @options[:password] end xml.order do xml.send("#{action}!") do yield(xml) end end end builder.to_xml(indent: 2) end def success?(response) response[:response_code] == '0' end def message_from(response) response[:error_message] || response[:response_message] || response[:processor_message] || response[:error_msg] end def authorization_from(response) "#{response[:order_id]}|#{response[:transaction_id]}" end def split_authorization(authorization) authorization.split('|') end def parse(body) xml = REXML::Document.new(body) response = {} xml.root.elements.to_a.each do |node| parse_element(response, node) end response end def parse_element(response, node) if node.has_elements? node.elements.each { |element| parse_element(response, element) } else response[node.name.underscore.to_sym] = node.text end end def add_auth_purchase(xml, money, creditcard, options) add_processor_id(xml) xml.fraudCheck('N') add_reference_num(xml, options) xml.transactionDetail do xml.payType do xml.creditCard do xml.number(creditcard.number) xml.expMonth(creditcard.month) xml.expYear(creditcard.year) xml.cvvNumber(creditcard.verification_value) end end end xml.payment do add_amount(xml, money, options) add_installments(xml, options) end add_billing_address(xml, creditcard, options) end def add_reference_num(xml, options) xml.referenceNum(options[:order_id] || generate_unique_id) end def add_amount(xml, money, options) xml.chargeTotal(amount(money)) xml.currencyCode(options[:currency] || currency(money) || default_currency) end def add_processor_id(xml) if test? xml.processorID(1) else xml.processorID(@options[:processor_id] || 4) end end def add_installments(xml, options) if options.has_key?(:installments) && options[:installments] > 1 xml.creditInstallment do xml.numberOfInstallments options[:installments] xml.chargeInterest 'N' end end end def add_billing_address(xml, creditcard, options) address = options[:billing_address] return unless address xml.billing do xml.name creditcard.name xml.address address[:address1] if address[:address1] xml.address2 address[:address2] if address[:address2] xml.city address[:city] if address[:city] xml.state address[:state] if address[:state] xml.postalcode address[:zip] if address[:zip] xml.country address[:country] if address[:country] xml.phone address[:phone] if address[:phone] end end def add_order_id(xml, authorization) order_id, = split_authorization(authorization) xml.orderID order_id end end end end