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