lib/active_merchant/billing/gateways/ebanx.rb
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class EbanxGateway < Gateway
self.test_url = 'https://sandbox.ebanxpay.com/ws/'
self.live_url = 'https://api.ebanxpay.com/ws/'
self.supported_countries = %w(BR MX CO CL AR PE BO EC)
self.default_currency = 'USD'
self.supported_cardtypes = %i[visa master american_express discover diners_club elo hipercard]
self.homepage_url = 'http://www.ebanx.com/'
self.display_name = 'EBANX'
TAGS = ['Spreedly']
URL_MAP = {
purchase: 'direct',
authorize: 'direct',
capture: 'capture',
refund: 'refund',
void: 'cancel',
store: 'token',
inquire: 'query',
verify: 'verifycard'
}
HTTP_METHOD = {
purchase: :post,
authorize: :post,
capture: :get,
refund: :post,
void: :get,
store: :post,
inquire: :get,
verify: :post
}
def initialize(options = {})
requires!(options, :integration_key)
super
end
def purchase(money, payment, options = {})
post = { payment: {} }
add_integration_key(post)
add_operation(post)
add_invoice(post, money, options)
add_customer_data(post, payment, options)
add_card_or_token(post, payment, options)
add_address(post, options)
add_customer_responsible_person(post, payment, options)
add_additional_data(post, options)
commit(:purchase, post)
end
def authorize(money, payment, options = {})
post = { payment: {} }
add_integration_key(post)
add_operation(post)
add_invoice(post, money, options)
add_customer_data(post, payment, options)
add_card_or_token(post, payment, options)
add_address(post, options)
add_customer_responsible_person(post, payment, options)
add_additional_data(post, options)
post[:payment][:creditcard][:auto_capture] = false
commit(:authorize, post)
end
def capture(money, authorization, options = {})
post = {}
add_integration_key(post)
post[:hash] = authorization
post[:amount] = amount(money) if options[:include_capture_amount].to_s == 'true'
commit(:capture, post)
end
def refund(money, authorization, options = {})
post = {}
add_integration_key(post)
add_operation(post)
add_authorization(post, authorization)
post[:amount] = amount(money)
post[:description] = options[:description]
commit(:refund, post)
end
def void(authorization, options = {})
post = {}
add_integration_key(post)
add_authorization(post, authorization)
commit(:void, post)
end
def store(credit_card, options = {})
post = {}
add_integration_key(post)
customer_country(post, options)
add_payment_type(post)
post[:creditcard] = payment_details(credit_card)
commit(:store, post)
end
def verify(credit_card, options = {})
post = {}
add_integration_key(post)
add_payment_type(post)
customer_country(post, options)
post[:card] = payment_details(credit_card)
post[:device_id] = options[:device_id] if options[:device_id]
commit(:verify, post)
end
def inquire(authorization, options = {})
post = {}
add_integration_key(post)
add_authorization(post, authorization)
commit(:inquire, post)
end
def supports_scrubbing?
true
end
def scrub(transcript)
transcript.
gsub(/(integration_key\\?":\\?")(\w*)/, '\1[FILTERED]').
gsub(/(card_number\\?":\\?")(\d*)/, '\1[FILTERED]').
gsub(/(card_cvv\\?":\\?")(\d*)/, '\1[FILTERED]')
end
private
def add_integration_key(post)
post[:integration_key] = @options[:integration_key].to_s
end
def add_operation(post)
post[:operation] = 'request'
end
def add_authorization(post, authorization)
post[:hash] = authorization
end
def add_customer_data(post, payment, options)
post[:payment][:name] = customer_name(payment, options)
post[:payment][:email] = options[:email]
post[:payment][:document] = options[:document]
post[:payment][:birth_date] = options[:birth_date] if options[:birth_date]
end
def add_customer_responsible_person(post, payment, options)
post[:payment][:person_type] = options[:person_type] if options[:person_type]
if options[:person_type]&.casecmp('business')&.zero?
post[:payment][:responsible] = {}
post[:payment][:responsible][:name] = options[:responsible_name] if options[:responsible_name]
post[:payment][:responsible][:document] = options[:responsible_document] if options[:responsible_document]
post[:payment][:responsible][:birth_date] = options[:responsible_birth_date] if options[:responsible_birth_date]
end
end
def add_address(post, options)
if address = options[:billing_address] || options[:address]
post[:payment][:address] = address[:address1].split[1..-1].join(' ') if address[:address1]
post[:payment][:street_number] = address[:address1].split.first if address[:address1]
post[:payment][:city] = address[:city]
post[:payment][:state] = address[:state]
post[:payment][:zipcode] = address[:zip]
post[:payment][:country] = address[:country].downcase
post[:payment][:phone_number] = address[:phone]
end
end
def add_invoice(post, money, options)
post[:payment][:amount_total] = amount(money)
post[:payment][:currency_code] = (options[:currency] || currency(money))
post[:payment][:merchant_payment_code] = Digest::MD5.hexdigest(options[:order_id])
post[:payment][:instalments] = options[:instalments] || 1
post[:payment][:order_number] = options[:order_id][0..39] if options[:order_id]
end
def add_card_or_token(post, payment, options)
payment = payment.split('|')[0] if payment.is_a?(String)
add_payment_type(post[:payment])
post[:payment][:creditcard] = payment_details(payment)
post[:payment][:creditcard][:soft_descriptor] = options[:soft_descriptor] if options[:soft_descriptor]
end
def add_payment_type(post)
post[:payment_type_code] = 'creditcard'
end
def payment_details(payment)
if payment.is_a?(String)
{ token: payment }
else
{
card_number: payment.number,
card_name: payment.name,
card_due_date: "#{payment.month}/#{payment.year}",
card_cvv: payment.verification_value
}
end
end
def add_additional_data(post, options)
post[:device_id] = options[:device_id] if options[:device_id]
post[:metadata] = options[:metadata] if options[:metadata]
post[:metadata] = {} if post[:metadata].nil?
post[:metadata][:merchant_payment_code] = options[:order_id] if options[:order_id]
post[:processing_type] = options[:processing_type] if options[:processing_type]
post[:payment][:tags] = TAGS
end
def parse(body)
JSON.parse(body)
end
def commit(action, parameters)
url = url_for((test? ? test_url : live_url), action, parameters)
response = parse(ssl_request(HTTP_METHOD[action], url, post_data(action, parameters), headers(parameters)))
success = success_from(action, response)
Response.new(
success,
message_from(action, response),
response,
authorization: authorization_from(action, parameters, response),
test: test?,
error_code: error_code_from(response, success)
)
end
def headers(params)
processing_type = params[:processing_type]
commit_headers = { 'x-ebanx-client-user-agent': "ActiveMerchant/#{ActiveMerchant::VERSION}" }
add_processing_type_to_commit_headers(commit_headers, processing_type) if processing_type == 'local'
commit_headers
end
def add_processing_type_to_commit_headers(commit_headers, processing_type)
commit_headers['x-ebanx-api-processing-type'] = processing_type
end
def success_from(action, response)
status = response.dig('payment', 'status')
case action
when :purchase, :capture, :refund
status == 'CO'
when :authorize
status == 'PE'
when :void
status == 'CA'
when :verify
response.dig('card_verification', 'transaction_status', 'code') == 'OK'
when :store, :inquire
response.dig('status') == 'SUCCESS'
else
false
end
end
def message_from(action, response)
return response['status_message'] if response['status'] == 'ERROR'
if action == :verify
response.dig('card_verification', 'transaction_status', 'description')
else
response.dig('payment', 'transaction_status', 'description')
end
end
def authorization_from(action, parameters, response)
if action == :store
if success_from(action, response)
"#{response.try(:[], 'token')}|#{response['payment_type_code']}"
else
response.try(:[], 'token')
end
else
response.try(:[], 'payment').try(:[], 'hash')
end
end
def post_data(action, parameters = {})
return nil if requires_http_get(action)
return convert_to_url_form_encoded(parameters) if action == :refund
"request_body=#{parameters.to_json}"
end
def url_for(hostname, action, parameters)
return "#{hostname}#{URL_MAP[action]}?#{convert_to_url_form_encoded(parameters)}" if requires_http_get(action)
"#{hostname}#{URL_MAP[action]}"
end
def requires_http_get(action)
return true if %i[capture void inquire].include?(action)
false
end
def convert_to_url_form_encoded(parameters)
parameters.map do |key, value|
next if value != false && value.blank?
"#{key}=#{value}"
end.compact.join('&')
end
def error_code_from(response, success)
unless success
return response['status_code'] if response['status'] == 'ERROR'
response.try(:[], 'payment').try(:[], 'transaction_status').try(:[], 'code')
end
end
def customer_country(post, options)
if country = options[:country] || (options[:billing_address][:country] if options[:billing_address])
post[:country] = country.downcase
end
end
def customer_name(payment, options)
address_name = options[:billing_address][:name] if options[:billing_address] && options[:billing_address][:name]
if payment.is_a?(String)
address_name || 'Not Provided'
else
payment.name
end
end
end
end
end