lib/active_merchant/billing/gateways/pagarme.rb
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class PagarmeGateway < Gateway
self.live_url = 'https://api.pagar.me/1/'
self.supported_countries = ['BR']
self.default_currency = 'BRL'
self.money_format = :cents
self.supported_cardtypes = %i[visa master american_express discover diners_club]
self.homepage_url = 'https://pagar.me/'
self.display_name = 'Pagar.me'
STANDARD_ERROR_CODE_MAPPING = {
'refused' => STANDARD_ERROR_CODE[:card_declined],
'processing_error' => STANDARD_ERROR_CODE[:processing_error]
}
def initialize(options = {})
requires!(options, :api_key)
@api_key = options[:api_key]
super
end
def purchase(money, payment_method, options = {})
post = {}
add_amount(post, money)
add_payment_method(post, payment_method)
add_metadata(post, options)
commit(:post, 'transactions', post)
end
def authorize(money, payment_method, options = {})
post = {}
add_amount(post, money)
add_payment_method(post, payment_method)
add_metadata(post, options)
post[:capture] = false
commit(:post, 'transactions', post)
end
def capture(money, authorization, options = {})
return Response.new(false, 'Não é possível capturar uma transação sem uma prévia autorização.') if authorization.nil?
post = {}
commit(:post, "transactions/#{authorization}/capture", post)
end
def refund(money, authorization, options = {})
return Response.new(false, 'Não é possível estornar uma transação sem uma prévia captura.') if authorization.nil?
void(authorization, options)
end
def void(authorization, options = {})
return Response.new(false, 'Não é possível estornar uma transação autorizada sem uma prévia autorização.') if authorization.nil?
post = {}
commit(:post, "transactions/#{authorization}/refund", post)
end
def verify(payment_method, options = {})
MultiResponse.run(:use_first_response) do |r|
r.process { authorize(127, payment_method, options) }
r.process(:ignore_result) { void(r.authorization, options) }
end
end
def supports_scrubbing?
true
end
def scrub(transcript)
transcript.
gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
gsub(%r((card_number=)\d+), '\1[FILTERED]').
gsub(%r((card_cvv=)\d+), '\1[FILTERED]')
end
private
def add_amount(post, money)
post[:amount] = amount(money)
end
def add_payment_method(post, payment_method)
post[:payment_method] = 'credit_card'
add_credit_card(post, payment_method)
end
def add_credit_card(post, credit_card)
post[:card_number] = credit_card.number
post[:card_holder_name] = credit_card.name
post[:card_expiration_date] = "#{credit_card.month}/#{credit_card.year}"
post[:card_cvv] = credit_card.verification_value
end
def add_metadata(post, options = {})
post[:metadata] = {}
post[:metadata][:order_id] = options[:order_id]
post[:metadata][:ip] = options[:ip]
post[:metadata][:customer] = options[:customer]
post[:metadata][:invoice] = options[:invoice]
post[:metadata][:merchant] = options[:merchant]
post[:metadata][:description] = options[:description]
post[:metadata][:email] = options[:email]
end
def parse(body)
JSON.parse(body)
end
def post_data(params)
return nil unless params
params.map do |key, value|
next if value != false && value.blank?
if value.is_a?(Hash)
h = {}
value.each do |k, v|
h["#{key}[#{k}]"] = v unless v.blank?
end
post_data(h)
elsif value.is_a?(Array)
value.map { |v| "#{key}[]=#{CGI.escape(v.to_s)}" }.join('&')
else
"#{key}=#{CGI.escape(value.to_s)}"
end
end.compact.join('&')
end
def headers(options = {})
{
'Authorization' => 'Basic ' + Base64.encode64(@api_key.to_s + ':x').strip,
'User-Agent' => "Pagar.me/1 ActiveMerchant/#{ActiveMerchant::VERSION}",
'Accept-Encoding' => 'deflate'
}
end
def api_request(method, endpoint, parameters = nil, options = {})
raw_response = response = nil
begin
raw_response = ssl_request(method, self.live_url + endpoint, post_data(parameters), headers(options))
response = parse(raw_response)
rescue ResponseError => e
raw_response = e.response.body
response = response_error(raw_response)
rescue JSON::ParserError
response = json_error(raw_response)
end
response
end
def commit(method, url, parameters, options = {})
response = api_request(method, url, parameters, options)
Response.new(
success_from(response),
message_from(response),
response,
authorization: authorization_from(response),
test: test?,
error_code: error_code_from(response)
)
end
def response_error(raw_response)
parse(raw_response)
rescue JSON::ParserError
json_error(raw_response)
end
def json_error(raw_response)
msg = 'Resposta inválida retornada pela API do Pagar.me. Por favor entre em contato com suporte@pagar.me se você continuar recebendo essa mensagem.'
msg += " (A resposta retornada pela API foi #{raw_response.inspect})"
{
'errors' => [{
'message' => msg
}]
}
end
def success_from(response)
success_purchase = response.key?('status') && response['status'] == 'paid'
success_authorize = response.key?('status') && response['status'] == 'authorized'
success_refund = response.key?('status') && response['status'] == 'refunded'
success_purchase || success_authorize || success_refund
end
def failure_from(response)
response.key?('status') && response['status'] == 'refused'
end
def message_from(response)
if success_from(response)
case response['status']
when 'paid'
'Transação aprovada'
when 'authorized'
'Transação autorizada'
when 'refunded'
'Transação estornada'
else
"Transação com status '#{response['status']}'"
end
elsif failure_from(response)
'Transação recusada'
elsif response.key?('errors')
response['errors'][0]['message']
else
msg = json_error(response)
msg['errors'][0]['message']
end
end
def authorization_from(response)
response['id'] if success_from(response)
end
def test?
@api_key.start_with?('ak_test')
end
def error_code_from(response)
if failure_from(response)
STANDARD_ERROR_CODE_MAPPING['refused']
elsif response.key?('errors')
STANDARD_ERROR_CODE_MAPPING['processing_error']
end
end
end
end
end