module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class BraspagGateway < Gateway
TEST_URL = 'https://homologacao.pagador.com.br/webservice/pagador.asmx'
LIVE_URL = 'https://www.pagador.com.br/webservice/pagador.asmx'
self.supported_countries = ['BR']
self.supported_cardtypes = [:visa, :master, :american_express]
self.default_currency = 'BRL'
self.homepage_url = 'http://www.braspag.com.br'
self.display_name = 'Braspag'
# map credit card to the Braspag expected representation
CREDIT_CARD_CODES = {
:visa => 22,
:master => 23,
:american_express => 18
}
# Creates a new BraspagGateway
#
# The gateway requires that a valid login
# in the +options+ hash.
#
# ==== Options
#
# * :login -- The Braspag Merchant ID (REQUIRED)
# * :test -- +true+ or +false+. If true, perform transactions against the test server.
# Otherwise, perform transactions against the production server.
def initialize(options = {})
requires!(options, :login)
@options = options
super
end
# Performs an authorization, which reserves the funds on the customer's credit card, but does not
# charge the card.
#
# ==== Parameters
#
# * money -- The amount to be authorized as an Integer value in cents.
# * creditcard -- The CreditCard details for the transaction.
#
# ==== Options
#
# * :order_id - A unique reference for this order (REQUIRED).
def authorize(money, creditcard, options = {})
post = PostData.new
add_invoice(post, options)
add_amount(post, money)
add_creditcard(post, money, creditcard)
add_customer_data(post, creditcard)
add_extra_data(post)
commit(:authorize, post)
end
# Captures the funds from an authorized transaction.
#
# ==== Parameters
# * money -- The amount to be captured as an Integer value in cents.
# * authorization - The authorization string returned from the initial authorization
#
# ==== Options
#
# * :order_id - A unique reference for this order (REQUIRED).
def capture(money, authorization, options = {})
if authorization.success?
post = PostData.new
add_invoice(post, options)
commit(:capture, post)
else
authorization
end
end
# Perform a purchase, which is essentially an authorization and capture in a single operation.
#
# ==== Parameters
#
# * money -- The amount to be purchased as an Integer value in cents.
# * creditcard -- The CreditCard details for the transaction.
# * options -- A hash of optional parameters.
def purchase(money, creditcard, options = {})
capture(money, authorize(money, creditcard, options), options)
end
# Void a transaction.
#
# ==== Parameters
# * authorization - The authorization string returned from the initial authorization or purchase.
#
# ==== Options
#
# * :order_id - A unique reference for this order (REQUIRED).
def void(authorization, options = {})
if authorization.success?
requires!(options, :order_id)
post = PostData.new
post[:order] = options[:order_id]
commit(:void_transaction, post)
else
authorization
end
end
private
def add_invoice(post, options)
requires!(options, :order_id)
post[:orderId] = options[:order_id]
end
def add_amount(post, money)
post[:amount] = format_amount(money)
end
def add_creditcard(post, money, creditcard)
post[:paymentMethod] = CREDIT_CARD_CODES[card_brand(creditcard).to_sym]
post[:holder] = creditcard.name
post[:cardNumber] = creditcard.number
post[:expiration] = "#{format(creditcard.month, :two_digits)}/#{format(creditcard.year, :two_digits)}"
post[:securityCode] = creditcard.verification_value
end
def add_customer_data(post, creditcard)
post[:customerName] = creditcard.name
end
def add_extra_data(post)
post[:numberPayments] = 1
post[:typePayment] = 0
end
def test?
@options[:test] || super
end
def commit(action, parameters)
parameters[:merchantId] = @options[:login]
response = parse(ssl_post(service_url(action), parameters.to_post_data), action)
Response.new(success?(response), response[:message], response,
:authorization => response[:authorisationNumber],
:order_id => parameters[:orderId]
)
end
def success?(response)
%w(0 1).include? response[:status]
end
# Parse Braspag response xml into a convinient hash
def parse(xml, action)
#
#
# decimal
# string
# string
# string
# unsignedByte
# string
#
root_element = action == :void_transaction ? "PagadorVoidReturn" : "PagadorReturn"
response = {}
xml = REXML::Document.new(xml)
xml.elements.each("//#{root_element}/*") do |node|
response[node.name.to_sym] = node.text
end unless xml.root.nil?
response
end
def service_url(action)
"#{test? ? TEST_URL : LIVE_URL}/#{action.to_s.classify}"
end
def format_amount(amount)
(amount / 100).to_s.sub ".", ","
end
end
end
end