class ActiveMerchant::Billing::PayuLatamGateway

Constants

BRAND_MAP
MINIMUMS

Public Class Methods

new(options = {}) click to toggle source
Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 34
def initialize(options = {})
  requires!(options, :merchant_id, :account_id, :api_login, :api_key, :payment_country)
  super
end

Public Instance Methods

authorize(amount, payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 45
def authorize(amount, payment_method, options = {})
  post = {}
  auth_or_sale(post, 'AUTHORIZATION', amount, payment_method, options)
  commit('auth', post)
end
capture(amount, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 51
def capture(amount, authorization, options = {})
  post = {}

  add_credentials(post, 'SUBMIT_TRANSACTION', options)
  add_transaction_elements(post, 'CAPTURE', options)
  add_reference(post, authorization)

  if !amount.nil? && amount.to_f != 0.0
    post[:transaction][:additionalValues] ||= {}
    post[:transaction][:additionalValues][:TX_VALUE] = invoice_for(amount, options)[:TX_VALUE]
  end

  commit('capture', post)
end
purchase(amount, payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 39
def purchase(amount, payment_method, options = {})
  post = {}
  auth_or_sale(post, 'AUTHORIZATION_AND_CAPTURE', amount, payment_method, options)
  commit('purchase', post)
end
refund(amount, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 76
def refund(amount, authorization, options = {})
  post = {}

  add_credentials(post, 'SUBMIT_TRANSACTION', options)

  if options[:partial_refund]
    add_transaction_elements(post, 'PARTIAL_REFUND', options)
    post[:transaction][:additionalValues] ||= {}
    post[:transaction][:additionalValues][:TX_VALUE] = invoice_for(amount, options)[:TX_VALUE]
  else
    add_transaction_elements(post, 'REFUND', options)
  end

  add_reference(post, authorization)
  commit('refund', post)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 123
def scrub(transcript)
  transcript.
    gsub(%r((\"creditCard\\\":{\\\"number\\\":\\\")\d+), '\1[FILTERED]').
    gsub(%r((\"securityCode\\\":\\\")\d+), '\1[FILTERED]').
    gsub(%r((\"apiKey\\\":\\\")\w+), '\1[FILTERED]')
end
store(payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 103
def store(payment_method, options = {})
  post = {}

  add_credentials(post, 'CREATE_TOKEN')
  add_payment_method_to_be_tokenized(post, payment_method, options)

  commit('store', post)
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 119
def supports_scrubbing?
  true
end
verify(credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 93
def verify(credit_card, options = {})
  minimum = MINIMUMS[options[:currency].upcase] if options[:currency]
  amount = options[:verify_amount] || minimum || 100

  MultiResponse.run(:use_first_response) do |r|
    r.process { authorize(amount, credit_card, options) }
    r.process(:ignore_result) { void(r.authorization, options) }
  end
end
verify_credentials() click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 112
def verify_credentials
  post = {}
  add_credentials(post, 'GET_PAYMENT_METHODS')
  response = commit('verify_credentials', post)
  response.success?
end
void(authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 66
def void(authorization, options = {})
  post = {}

  add_credentials(post, 'SUBMIT_TRANSACTION', options)
  add_transaction_elements(post, 'VOID', options)
  add_reference(post, authorization)

  commit('void', post)
end

Private Instance Methods

add_buyer(post, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 203
def add_buyer(post, payment_method, options)
  buyer = {}
  if buyer_hash = options[:buyer]
    buyer[:fullName] = buyer_hash[:name]
    buyer[:dniNumber] = buyer_hash[:dni_number]
    buyer[:dniType] = buyer_hash[:dni_type]
    buyer[:merchantBuyerId] = buyer_hash[:merchant_buyer_id]
    buyer[:cnpj] = buyer_hash[:cnpj] if @options[:payment_country] == 'BR'
    buyer[:emailAddress] = buyer_hash[:email]
    buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone_number] if options[:shipping_address]) || ''
    buyer[:shippingAddress] = shipping_address_fields(options) if options[:shipping_address]
  else
    buyer[:fullName] = payment_method.name.strip
    buyer[:dniNumber] = options[:dni_number]
    buyer[:dniType] = options[:dni_type]
    buyer[:merchantBuyerId] = options[:merchant_buyer_id]
    buyer[:cnpj] = options[:cnpj] if @options[:payment_country] == 'BR'
    buyer[:emailAddress] = options[:email]
    buyer[:contactPhone] = (options[:billing_address][:phone] if options[:billing_address]) || (options[:shipping_address][:phone_number] if options[:shipping_address]) || ''
    buyer[:shippingAddress] = shipping_address_fields(options) if options[:shipping_address]
  end
  post[:transaction][:order][:buyer] = buyer
end
add_credentials(post, command, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 144
def add_credentials(post, command, options = {})
  post[:test] = test? unless command == 'CREATE_TOKEN'
  post[:language] = options[:language] || 'en'
  post[:command] = command
  merchant = {}
  merchant[:apiLogin] = @options[:api_login]
  merchant[:apiKey] = @options[:api_key]
  post[:merchant] = merchant
end
add_extra_parameters(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 313
def add_extra_parameters(post, options)
  extra_parameters = {}
  extra_parameters[:INSTALLMENTS_NUMBER] = options[:installments_number] || 1
  extra_parameters[:EXTRA1] = options[:extra_1] if options[:extra_1]
  extra_parameters[:EXTRA2] = options[:extra_2] if options[:extra_2]
  extra_parameters[:EXTRA3] = options[:extra_3] if options[:extra_3]
  post[:transaction][:extraParameters] = extra_parameters
end
add_invoice(post, money, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 241
def add_invoice(post, money, options)
  post[:transaction][:order][:additionalValues] = invoice_for(money, options)
end
add_order(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 165
def add_order(post, options)
  order = {}
  order[:accountId] = @options[:account_id]
  order[:partnerId] = options[:partner_id] if options[:partner_id]
  order[:referenceCode] = options[:order_id] || generate_unique_id
  order[:description] = options[:description] || 'Compra en ' + @options[:merchant_id]
  order[:language] = options[:language] || 'en'
  order[:shippingAddress] = shipping_address_fields(options) if options[:shipping_address]
  post[:transaction][:order] = order
end
add_payer(post, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 176
def add_payer(post, payment_method, options)
  address = options[:billing_address]
  payer = {}
  payer[:fullName] = payment_method.name.strip
  payer[:contactPhone] = address[:phone] if address && address[:phone]
  payer[:dniNumber] = options[:dni_number] if options[:dni_number]
  payer[:dniType] = options[:dni_type] if options[:dni_type]
  payer[:emailAddress] = options[:email] if options[:email]
  payer[:birthdate] = options[:birth_date] if options[:birth_date] && @options[:payment_country] == 'MX'
  payer[:billingAddress] = billing_address_fields(options)
  post[:transaction][:payer] = payer
end
add_payment_method(post, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 286
def add_payment_method(post, payment_method, options)
  if payment_method.is_a?(String)
    brand, token = split_authorization(payment_method)
    credit_card = {}
    credit_card[:securityCode] = options[:cvv] if options[:cvv]
    credit_card[:processWithoutCvv2] = true if options[:cvv].blank?
    post[:transaction][:creditCard] = credit_card
    post[:transaction][:creditCardTokenId] = token
    post[:transaction][:paymentMethod] = brand.upcase
  else
    credit_card = {}
    credit_card[:number] = payment_method.number
    credit_card[:securityCode] = payment_method.verification_value || options[:cvv]
    credit_card[:expirationDate] = format(payment_method.year, :four_digits).to_s + '/' + format(payment_method.month, :two_digits).to_s
    credit_card[:name] = payment_method.name.strip
    credit_card[:processWithoutCvv2] = true if add_process_without_cvv2(payment_method, options)
    post[:transaction][:creditCard] = credit_card
    post[:transaction][:paymentMethod] = codensa_bin?(payment_method.number) ? 'CODENSA' : BRAND_MAP[payment_method.brand.to_s]
  end
end
add_payment_method_to_be_tokenized(post, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 331
def add_payment_method_to_be_tokenized(post, payment_method, options)
  credit_card_token = {}
  credit_card_token[:payerId] = options[:payer_id] || generate_unique_id
  credit_card_token[:name] = payment_method.name.strip
  credit_card_token[:identificationNumber] = options[:dni_number]
  credit_card_token[:paymentMethod] = BRAND_MAP[payment_method.brand.to_s]
  credit_card_token[:number] = payment_method.number
  credit_card_token[:expirationDate] = format(payment_method.year, :four_digits).to_s + '/' + format(payment_method.month, :two_digits).to_s
  post[:creditCardToken] = credit_card_token
end
add_process_without_cvv2(payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 307
def add_process_without_cvv2(payment_method, options)
  return true if payment_method.verification_value.blank? && options[:cvv].blank?

  false
end
add_reference(post, authorization) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 322
def add_reference(post, authorization)
  order_id, transaction_id = split_authorization(authorization)
  order = {}
  order[:id] = order_id
  post[:transaction][:order] = order
  post[:transaction][:parentTransactionId] = transaction_id
  post[:transaction][:reason] = 'n/a'
end
add_signature(post) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 266
def add_signature(post)
  post[:transaction][:order][:signature] = signature_from(post)
end
add_transaction_elements(post, type, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 154
def add_transaction_elements(post, type, options)
  transaction = {}
  transaction[:paymentCountry] = @options[:payment_country]
  transaction[:type] = type
  transaction[:ipAddress] = options[:ip] || ''
  transaction[:userAgent] = options[:user_agent] if options[:user_agent]
  transaction[:cookie] = options[:cookie] if options[:cookie]
  transaction[:deviceSessionId] = options[:device_session_id] if options[:device_session_id]
  post[:transaction] = transaction
end
auth_or_sale(post, transaction_type, amount, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 132
def auth_or_sale(post, transaction_type, amount, payment_method, options)
  add_credentials(post, 'SUBMIT_TRANSACTION', options)
  add_transaction_elements(post, transaction_type, options)
  add_order(post, options)
  add_buyer(post, payment_method, options)
  add_invoice(post, amount, options)
  add_signature(post)
  add_payment_method(post, payment_method, options)
  add_payer(post, payment_method, options)
  add_extra_parameters(post, options)
end
authorization_from(action, response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 430
def authorization_from(action, response)
  case action
  when 'store'
    [
      response['creditCardToken']['paymentMethod'],
      response['creditCardToken']['creditCardTokenId']
    ].compact.join('|')
  when 'verify_credentials'
    nil
  else
    [
      response['transactionResponse']['orderId'],
      response['transactionResponse']['transactionId']
    ].compact.join('|')
  end
end
billing_address_fields(options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 189
def billing_address_fields(options)
  return unless address = options[:billing_address]

  billing_address = {}
  billing_address[:street1] = address[:address1]
  billing_address[:street2] = address[:address2]
  billing_address[:city] = address[:city]
  billing_address[:state] = address[:state]
  billing_address[:country] = address[:country] unless address[:country].blank?
  billing_address[:postalCode] = address[:zip] if @options[:payment_country] == 'MX'
  billing_address[:phone] = address[:phone]
  billing_address
end
codensa_bin?(number) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 282
def codensa_bin?(number)
  number.start_with?('590712')
end
commit(action, params) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 342
def commit(action, params)
  raw_response = ssl_post(url, post_data(params), headers)
  response = parse(raw_response)
rescue ResponseError => e
  raw_response = e.response.body
  response_error(raw_response)
rescue JSON::ParserError
  unparsable_response(raw_response)
else
  success = success_from(action, response)
  Response.new(
    success,
    message_from(action, success, response),
    response,
    authorization: success ? authorization_from(action, response) : nil,
    error_code: success ? nil : error_from(action, response),
    test: test?
  )
end
error_from(action, response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 451
def error_from(action, response)
  case action
  when 'store'
    response['creditCardToken']['errorDescription'] if response['creditCardToken']
  when 'verify_credentials'
    response['error'] || 'FAILED'
  else
    response['transactionResponse']['paymentNetworkResponseCode'] || response['transactionResponse']['errorCode'] if response['transactionResponse']
  end
end
headers() click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 362
def headers
  {
    'Content-Type' => 'application/json',
    'Accept' => 'application/json'
  }
end
invoice_for(money, options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 245
def invoice_for(money, options)
  tx_value = {}
  tx_value[:value] = amount(money)
  tx_value[:currency] = options[:currency] || currency(money)

  tx_tax = {}
  tx_tax[:value] = options[:tax] || '0'
  tx_tax[:currency] = options[:currency] || currency(money)

  tx_tax_return_base = {}
  tx_tax_return_base[:value] = options[:tax_return_base] || '0'
  tx_tax_return_base[:currency] = options[:currency] || currency(money)

  additional_values = {}
  additional_values[:TX_VALUE] = tx_value
  additional_values[:TX_TAX] = tx_tax if @options[:payment_country] == 'CO'
  additional_values[:TX_TAX_RETURN_BASE] = tx_tax_return_base if @options[:payment_country] == 'CO'

  additional_values
end
message_from(action, success, response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 395
def message_from(action, success, response)
  case action
  when 'store'
    message_from_store(success, response)
  when 'verify_credentials'
    message_from_verify_credentials(success)
  else
    message_from_transaction_response(success, response)
  end
end
message_from_store(success, response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 406
def message_from_store(success, response)
  return response['code'] if success

  error_description = response['creditCardToken']['errorDescription'] if response['creditCardToken']
  response['error'] || error_description || 'FAILED'
end
message_from_transaction_response(success, response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 419
def message_from_transaction_response(success, response)
  response_code = response.dig('transactionResponse', 'responseCode') || response.dig('transactionResponse', 'pendingReason')
  return response_code if success
  return response_code + ' | ' + response.dig('transactionResponse', 'paymentNetworkResponseErrorMessage') if response.dig('transactionResponse', 'paymentNetworkResponseErrorMessage')
  return response.dig('transactionResponse', 'responseMessage') if response.dig('transactionResponse', 'responseMessage')
  return response['error'] if response['error']
  return response_code if response_code

  'FAILED'
end
message_from_verify_credentials(success) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 413
def message_from_verify_credentials(success)
  return 'VERIFIED' if success

  'FAILED'
end
parse(body) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 378
def parse(body)
  JSON.parse(body)
end
post_data(params) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 369
def post_data(params)
  params.merge(test: test?)
  params.to_json
end
response_error(raw_response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 462
def response_error(raw_response)
  response = parse(raw_response)
rescue JSON::ParserError
  unparsable_response(raw_response)
else
  return Response.new(
    false,
    message_from('', false, response),
    response,
    test: test?
  )
end
shipping_address_fields(options) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 227
def shipping_address_fields(options)
  return unless address = options[:shipping_address]

  shipping_address = {}
  shipping_address[:street1] = address[:address1]
  shipping_address[:street2] = address[:address2]
  shipping_address[:city] = address[:city]
  shipping_address[:state] = address[:state]
  shipping_address[:country] = address[:country]
  shipping_address[:postalCode] = address[:zip]
  shipping_address[:phone] = address[:phone_number]
  shipping_address
end
signature_from(post) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 270
def signature_from(post)
  signature_string = [
    @options[:api_key],
    @options[:merchant_id],
    post[:transaction][:order][:referenceCode],
    post[:transaction][:order][:additionalValues][:TX_VALUE][:value],
    post[:transaction][:order][:additionalValues][:TX_VALUE][:currency]
  ].compact.join('~')

  Digest::MD5.hexdigest(signature_string)
end
split_authorization(authorization) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 447
def split_authorization(authorization)
  authorization.split('|')
end
success_from(action, response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 382
def success_from(action, response)
  case action
  when 'store'
    response['code'] == 'SUCCESS' && response['creditCardToken'] && response['creditCardToken']['creditCardTokenId'].present?
  when 'verify_credentials'
    response['code'] == 'SUCCESS'
  when 'refund', 'void'
    response['code'] == 'SUCCESS' && response['transactionResponse'] && (response['transactionResponse']['state'] == 'PENDING' || response['transactionResponse']['state'] == 'APPROVED')
  else
    response['code'] == 'SUCCESS' && response['transactionResponse'] && (response['transactionResponse']['state'] == 'APPROVED')
  end
end
unparsable_response(raw_response) click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 475
def unparsable_response(raw_response)
  message = 'Invalid JSON response received from PayuLatamGateway. Please contact PayuLatamGateway if you continue to receive this message.'
  message += " (The raw response returned by the API was #{raw_response.inspect})"
  return Response.new(false, message)
end
url() click to toggle source
# File lib/active_merchant/billing/gateways/payu_latam.rb, line 374
def url
  test? ? test_url : live_url
end