class ActiveMerchant::Billing::CecabankJsonGateway

Constants

CECA_ACTIONS_DICTIONARY
CECA_INITIATOR
CECA_REASON_TYPES
CECA_SCA_TYPES

Public Instance Methods

authorize(money, creditcard, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 35
def authorize(money, creditcard, options = {})
  handle_purchase(:authorize, money, creditcard, options)
end
capture(money, identification, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 39
def capture(money, identification, options = {})
  authorization, operation_number, _money = identification.split('#')

  post = {}
  options[:operation_number] = operation_number
  add_auth_invoice_data(:capture, post, money, authorization, options)

  commit('compra', post)
end
purchase(money, creditcard, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 49
def purchase(money, creditcard, options = {})
  handle_purchase(:purchase, money, creditcard, options)
end
refund(money, identification, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 59
def refund(money, identification, options = {})
  authorization, operation_number, _money = identification.split('#')
  options[:operation_number] = operation_number
  handle_cancellation(:refund, money, authorization, options)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 65
def scrub(transcript)
  return '' if transcript.blank?

  before_message = transcript.gsub(%r(\\\")i, "'").scan(/{[^>]*}/).first.gsub("'", '"')
  request_data = JSON.parse(before_message)

  if @options[:encryption_key]
    params = parse(request_data['parametros'])
    sensitive_fields = decrypt_sensitive_fields(params['encryptedData'])
    filtered_params = filter_params(sensitive_fields)
    params['encryptedData'] = encrypt_sensitive_fields(filtered_params)
  else
    params = filter_params(decode_params(request_data['parametros']))
  end

  request_data['parametros'] = encode_params(params)
  before_message = before_message.gsub(%r(\")i, '\\\"')
  after_message = request_data.to_json.gsub(%r(\")i, '\\\"')
  transcript.sub(before_message, after_message)
end
void(identification, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 53
def void(identification, options = {})
  authorization, operation_number, money = identification.split('#')
  options[:operation_number] = operation_number
  handle_cancellation(:void, money.to_i, authorization, options)
end

Private Instance Methods

add_auth_invoice_data(action, post, money, authorization, options) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 130
def add_auth_invoice_data(action, post, money, authorization, options)
  params = post[:parametros] ||= {}
  params[:accion] = CECA_ACTIONS_DICTIONARY[action]
  params[:referencia] = authorization

  add_invoice(post, money, options)
end
add_creditcard(post, creditcard) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 162
def add_creditcard(post, creditcard)
  params = post[:parametros] ||= {}

  payment_method = {
    pan: creditcard.number,
    caducidad: strftime_yyyymm(creditcard)
  }
  if CreditCard.brand?(creditcard.number) == 'american_express'
    payment_method[:csc] = creditcard.verification_value
  else
    payment_method[:cvv2] = creditcard.verification_value
  end

  @options[:encryption_key] ? params[:encryptedData] = payment_method : params.merge!(payment_method)
end
add_encryption(post) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 138
def add_encryption(post)
  post[:cifrado] = CECA_ENCRIPTION
  post[:parametros][:encryptedData] = encrypt_sensitive_fields(post[:parametros][:encryptedData]) if @options[:encryption_key]
end
add_invoice(post, money, options) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 155
def add_invoice(post, money, options)
  post[:parametros][:numOperacion] = options[:operation_number] || options[:order_id]
  post[:parametros][:importe] = amount(money)
  post[:parametros][:tipoMoneda] = CECA_CURRENCIES_DICTIONARY[options[:currency] || currency(money)].to_s
  post[:parametros][:exponente] = 2.to_s
end
add_merchant_data(post) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 147
def add_merchant_data(post)
  params = post[:parametros] ||= {}

  params[:merchantID] = @options[:merchant_id]
  params[:acquirerBIN] = @options[:acquirer_bin]
  params[:terminalID] = @options[:terminal_id]
end
add_signature(post, params_encoded, options) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 143
def add_signature(post, params_encoded, options)
  post[:firma] = Digest::SHA2.hexdigest(@options[:cypher_key].to_s + params_encoded)
end
add_stored_credentials(post, creditcard, options) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 178
def add_stored_credentials(post, creditcard, options)
  return unless stored_credential = options[:stored_credential]

  return if options[:exemption_type].blank? && !(stored_credential[:reason_type] && stored_credential[:initiator])

  params = post[:parametros] ||= {}
  params[:exencionSCA] = 'MIT'

  requires!(stored_credential, :reason_type, :initiator)
  reason_type = CECA_REASON_TYPES[stored_credential[:reason_type].to_sym]
  initiator = CECA_INITIATOR[stored_credential[:initiator].to_sym]
  params[:tipoCOF] = reason_type
  params[:inicioRec] = initiator
  if initiator == :S
    requires!(options, :recurring_frequency)
    params[:finRec] = options[:recurring_end_date] || strftime_yyyymm(creditcard)
    params[:frecRec] = options[:recurring_frequency]
  end

  network_transaction_id = options[:network_transaction_id].present? ? options[:network_transaction_id] : stored_credential[:network_transaction_id]
  params[:mmppTxId] = network_transaction_id unless network_transaction_id.blank?
end
add_three_d_secure(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 201
def add_three_d_secure(post, options)
  params = post[:parametros] ||= {}
  return unless three_d_secure = options[:three_d_secure]

  params[:exencionSCA] ||= CECA_SCA_TYPES.fetch(options[:exemption_type]&.to_sym, :NONE)

  three_d_response = {
    exemption_type: options[:exemption_type],
    three_ds_version: three_d_secure[:version],
    directory_server_transaction_id: three_d_secure[:ds_transaction_id],
    acs_transaction_id: three_d_secure[:acs_transaction_id],
    authentication_response_status: three_d_secure[:authentication_response_status],
    three_ds_server_trans_id: three_d_secure[:three_ds_server_trans_id],
    ecommerce_indicator: three_d_secure[:eci],
    enrolled: three_d_secure[:enrolled]
  }

  if @options[:encryption_key]
    params[:encryptedData].merge!({ authentication_value: three_d_secure[:cavv] })
  else
    three_d_response[:authentication_value] = three_d_secure[:cavv]
  end

  three_d_response[:amount] = post[:parametros][:importe]
  params[:ThreeDsResponse] = three_d_response.to_json
end
authorization_from(response, auth_options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 297
def authorization_from(response, auth_options = {})
  return unless response[:parametros]

  [
    response[:parametros][:referencia],
    auth_options[:operation_number],
    auth_options[:amount]
  ].join('#')
end
commit(action, post) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 228
def commit(action, post)
  auth_options = {
    operation_number: post.dig(:parametros, :numOperacion),
    amount: post.dig(:parametros, :importe)
  }

  add_encryption(post)
  add_merchant_data(post)

  params_encoded = encode_post_parameters(post)
  add_signature(post, params_encoded, options)

  response = parse(ssl_post(url(action), post.to_json, headers))
  response[:parametros] = parse(response[:parametros]) if response[:parametros]

  Response.new(
    success_from(response),
    message_from(response),
    response,
    authorization: authorization_from(response, auth_options),
    network_transaction_id: network_transaction_id_from(response),
    test: test?,
    error_code: error_code_from(response)
  )
end
decode_params(params) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 283
def decode_params(params)
  Base64.decode64(params)
end
decrypt_sensitive_fields(data) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 97
def decrypt_sensitive_fields(data)
  cipher = OpenSSL::Cipher.new('AES-256-CBC').decrypt
  cipher.key = [@options[:encryption_key]].pack('H*')
  cipher.iv = @options[:initiator_vector]&.split('')&.map(&:to_i)&.pack('c*')
  cipher.update([data].pack('H*')) + cipher.final
end
encode_params(params) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 279
def encode_params(params)
  Base64.strict_encode64(params.is_a?(Hash) ? params.to_json : params)
end
encode_post_parameters(post) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 275
def encode_post_parameters(post)
  post[:parametros] = encode_params(post[:parametros])
end
encrypt_sensitive_fields(data) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 104
def encrypt_sensitive_fields(data)
  cipher = OpenSSL::Cipher.new('AES-256-CBC').encrypt
  cipher.key = [@options[:encryption_key]].pack('H*')
  cipher.iv = @options[:initiator_vector]&.split('')&.map(&:to_i)&.pack('c*')
  encrypted = cipher.update(data.to_json) + cipher.final
  encrypted.unpack1('H*')
end
error_code_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 311
def error_code_from(response)
  (response[:codResult] || :paramsEntradaError) unless success_from(response)
end
filter_params(params) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 88
def filter_params(params)
  params.
    gsub(%r(("pan\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
    gsub(%r(("caducidad\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
    gsub(%r(("cvv2\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
    gsub(%r(("csc\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
    gsub(%r(("authentication_value\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]')
end
handle_cancellation(action, money, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 123
def handle_cancellation(action, money, authorization, options = {})
  post = {}
  add_auth_invoice_data(action, post, money, authorization, options)

  commit('anulacion', post)
end
handle_purchase(action, money, creditcard, options) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 112
def handle_purchase(action, money, creditcard, options)
  post = { parametros: { accion: CECA_ACTIONS_DICTIONARY[action] } }

  add_invoice(post, money, options)
  add_creditcard(post, creditcard)
  add_stored_credentials(post, creditcard, options)
  add_three_d_secure(post, options)

  commit('compra', post)
end
headers() click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 262
def headers
  {
    'Content-Type' => 'application/json',
    'Host' => host
  }
end
host() click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 258
def host
  URI.parse(url('')).host
end
message_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 291
def message_from(response)
  return response[:parametros].to_json if success_from(response)

  response[:paramsEntradaError] || response[:idProceso]
end
network_transaction_id_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 307
def network_transaction_id_from(response)
  response.dig(:parametros, :mmppTxId)
end
parse(string) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 269
def parse(string)
  JSON.parse(string).with_indifferent_access
rescue JSON::ParserError
  parse(decode_params(string))
end
success_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 287
def success_from(response)
  response[:codResult].blank?
end
url(action) click to toggle source
# File lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb, line 254
def url(action)
  (test? ? self.test_url : self.live_url) + action
end