class ActiveMerchant::Billing::CredoraxGateway

Constants

ACTIONS
CARD_TYPES
NETWORK_TOKENIZATION_CARD_SOURCE
RESPONSE_MESSAGES

Public Class Methods

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

Public Instance Methods

add_3ds_2_optional_fields(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 249
def add_3ds_2_optional_fields(post, options)
  three_ds = options[:three_ds_2] || {}

  if three_ds.has_key?(:optional)
    three_ds[:optional].each do |key, value|
      normalized_value = normalize(value)
      next if normalized_value.nil?

      next if key == :'3ds_homephonecountry' && !(options[:billing_address] && options[:billing_address][:phone])

      post[key] = normalized_value unless post[key]
    end
  end

  post
end
authorize(amount, payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 157
def authorize(amount, payment_method, options = {})
  post = {}
  add_invoice(post, amount, options)
  add_payment_method(post, payment_method, options)
  add_customer_data(post, options)
  add_email(post, options)
  add_3d_secure(post, options)
  add_3ds_2_optional_fields(post, options)
  add_echo(post, options)
  add_submerchant_id(post, options)
  add_stored_credential(post, options)
  add_processor(post, options)
  add_authorization_details(post, options)

  commit(:authorize, post)
end
capture(amount, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 174
def capture(amount, authorization, options = {})
  post = {}
  add_invoice(post, amount, options)
  add_reference(post, authorization)
  add_customer_data(post, options)
  add_echo(post, options)
  add_submerchant_id(post, options)
  add_processor(post, options)

  commit(:capture, post)
end
credit(amount, payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 217
def credit(amount, payment_method, options = {})
  post = {}
  add_invoice(post, amount, options)
  add_payment_method(post, payment_method, options)
  add_customer_data(post, options)
  add_email(post, options)
  add_echo(post, options)
  add_submerchant_id(post, options)
  add_transaction_type(post, options)
  add_processor(post, options)
  add_customer_name(post, options)

  commit(:credit, post)
end
purchase(amount, payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 141
def purchase(amount, payment_method, options = {})
  post = {}
  add_invoice(post, amount, options)
  add_payment_method(post, payment_method, options)
  add_customer_data(post, options)
  add_email(post, options)
  add_3d_secure(post, options)
  add_3ds_2_optional_fields(post, options)
  add_echo(post, options)
  add_submerchant_id(post, options)
  add_stored_credential(post, options)
  add_processor(post, options)

  commit(:purchase, post)
end
refund(amount, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 198
def refund(amount, authorization, options = {})
  post = {}
  add_invoice(post, amount, options)
  add_reference(post, authorization)
  add_customer_data(post, options)
  add_echo(post, options)
  add_submerchant_id(post, options)
  add_processor(post, options)
  add_email(post, options)
  add_recipient(post, options)

  if options[:referral_cft]
    add_customer_name(post, options)
    commit(:referral_cft, post)
  else
    commit(:refund, post)
  end
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 243
def scrub(transcript)
  transcript.
    gsub(%r((b1=)\d+), '\1[FILTERED]').
    gsub(%r((b5=)\d+), '\1[FILTERED]')
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 239
def supports_scrubbing?
  true
end
verify(credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 232
def verify(credit_card, options = {})
  MultiResponse.run(:use_first_response) do |r|
    r.process { authorize(100, credit_card, options) }
    r.process(:ignore_result) { void(r.authorization, options) }
  end
end
void(authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 186
def void(authorization, options = {})
  post = {}
  add_customer_data(post, options)
  reference_action = add_reference(post, authorization)
  add_echo(post, options)
  add_submerchant_id(post, options)
  post[:a1] = generate_unique_id
  add_processor(post, options)

  commit(:void, post, reference_action)
end

Private Instance Methods

add_3d_secure(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 358
def add_3d_secure(post, options)
  if (options[:eci] && options[:xid]) || (options[:three_d_secure] && options[:three_d_secure][:version]&.start_with?('1'))
    add_3d_secure_1_data(post, options)
  elsif options[:execute_threed] && options[:three_ds_2]
    three_ds_2_options = options[:three_ds_2]
    browser_info = three_ds_2_options[:browser_info]
    post[:'3ds_initiate'] = options[:three_ds_initiate] || '01'
    post[:f23] = options[:f23] if options[:f23]
    post[:'3ds_purchasedate'] = Time.now.utc.strftime('%Y%m%d%I%M%S')
    options.dig(:stored_credential, :initiator) == 'merchant' ? post[:'3ds_channel'] = '03' : post[:'3ds_channel'] = '02'
    post[:'3ds_reqchallengeind'] = options[:three_ds_reqchallengeind] if options[:three_ds_reqchallengeind]
    post[:'3ds_redirect_url'] = three_ds_2_options[:notification_url]
    post[:'3ds_challengewindowsize'] = options[:three_ds_challenge_window_size] || '03'
    post[:d5] = browser_info[:user_agent]
    post[:'3ds_transtype'] = options[:three_ds_transtype] || '01'
    post[:'3ds_browsertz'] = browser_info[:timezone]
    post[:'3ds_browserscreenwidth'] = browser_info[:width]
    post[:'3ds_browserscreenheight'] = browser_info[:height]
    post[:'3ds_browsercolordepth'] = browser_info[:depth].to_s == '30' ? '32' : browser_info[:depth]
    post[:d6] = browser_info[:language]
    post[:'3ds_browserjavaenabled'] = browser_info[:java]
    post[:'3ds_browseracceptheader'] = browser_info[:accept_header]
    add_complete_shipping_address(post, options[:shipping_address]) if options[:shipping_address]
  elsif options[:three_d_secure]
    add_normalized_3d_secure_2_data(post, options)
  end
end
add_3d_secure_1_data(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 386
def add_3d_secure_1_data(post, options)
  if three_d_secure_options = options[:three_d_secure]
    post[:i8] = build_i8(
      three_d_secure_options[:eci],
      three_d_secure_options[:cavv],
      three_d_secure_options[:xid]
    )
    post[:'3ds_version'] = three_d_secure_options[:version]&.start_with?('1') ? '1.0' : three_d_secure_options[:version]
  else
    post[:i8] = build_i8(options[:eci], options[:cavv], options[:xid])
    post[:'3ds_version'] = options[:three_ds_version].nil? || options[:three_ds_version]&.start_with?('1') ? '1.0' : options[:three_ds_version]
  end
end
add_authorization_details(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 446
def add_authorization_details(post, options)
  post[:a10] = options[:authorization_type] if options[:authorization_type]
  post[:a11] = options[:multiple_capture_count] if options[:multiple_capture_count]
end
add_complete_shipping_address(post, shipping_address) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 400
def add_complete_shipping_address(post, shipping_address)
  return if shipping_address.values.any?(&:blank?)

  post[:'3ds_shipaddrstate'] = shipping_address[:state]
  post[:'3ds_shipaddrpostcode'] = shipping_address[:zip]
  post[:'3ds_shipaddrline2'] = shipping_address[:address2]
  post[:'3ds_shipaddrline1'] = shipping_address[:address1]
  post[:'3ds_shipaddrcountry'] = shipping_address[:country]
  post[:'3ds_shipaddrcity'] = shipping_address[:city]
end
add_customer_data(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 319
def add_customer_data(post, options)
  post[:d1] = options[:ip] || '127.0.0.1'
  if (billing_address = options[:billing_address])
    post[:c5]   = billing_address[:address1]  if billing_address[:address1]
    post[:c7]   = billing_address[:city]      if billing_address[:city]
    post[:c10]  = billing_address[:zip]       if billing_address[:zip]
    post[:c8]   = billing_address[:state]     if billing_address[:state]
    post[:c9]   = billing_address[:country]   if billing_address[:country]
    post[:c2]   = billing_address[:phone]     if billing_address[:phone]
  end
end
add_customer_name(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 353
def add_customer_name(post, options)
  post[:j5] = options[:first_name] if options[:first_name]
  post[:j13] = options[:last_name] if options[:last_name]
end
add_echo(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 426
def add_echo(post, options)
  # The d2 parameter is used during the certification process
  # See remote tests for full certification test suite
  post[:d2] = options[:echo] unless options[:echo].blank?
end
add_email(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 339
def add_email(post, options)
  post[:c3] = options[:email] || 'unspecified@example.com'
end
add_invoice(post, money, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 268
def add_invoice(post, money, options)
  currency = options[:currency] || currency(money)

  post[:a4] = localized_amount(money, currency)
  post[:a1] = generate_unique_id
  post[:a5] = currency
  post[:h9] = options[:order_id]
  post[:i2] = options[:billing_descriptor] if options[:billing_descriptor]
end
add_network_tokenization_card(post, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 294
def add_network_tokenization_card(post, payment_method, options)
  post[:b21] = NETWORK_TOKENIZATION_CARD_SOURCE[payment_method.source.to_s]
  post[:token_eci] = post[:b21] == 'vts_mdes_token' ? '07' : nil
  post[:token_eci] = options[:eci] || payment_method&.eci || (payment_method.brand.to_s == 'master' ? '00' : '07')
  post[:token_crypto] = payment_method&.payment_cryptogram if payment_method.source.to_s == 'network_token'
end
add_normalized_3d_secure_2_data(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 411
def add_normalized_3d_secure_2_data(post, options)
  three_d_secure_options = options[:three_d_secure]

  post[:i8] = build_i8(
    three_d_secure_options[:eci],
    three_d_secure_options[:cavv]
  )
  post[:'3ds_version'] = three_d_secure_options[:version] == '2' ? '2.0' : three_d_secure_options[:version]
  post[:'3ds_dstrxid'] = three_d_secure_options[:ds_transaction_id]
end
add_payment_method(post, payment_method, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 284
def add_payment_method(post, payment_method, options)
  post[:c1] = payment_method&.name || ''
  add_network_tokenization_card(post, payment_method, options) if payment_method.is_a? NetworkTokenizationCreditCard
  post[:b2] = CARD_TYPES[payment_method.brand] || ''
  post[:b1] = payment_method.number
  post[:b5] = payment_method.verification_value
  post[:b4] = format(payment_method.year, :two_digits)
  post[:b3] = format(payment_method.month, :two_digits)
end
add_processor(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 441
def add_processor(post, options)
  post[:r1] = options[:processor] if options[:processor]
  post[:r2] = options[:processor_merchant_id] if options[:processor_merchant_id]
end
add_recipient(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 343
def add_recipient(post, options)
  return unless options[:recipient_street_address] || options[:recipient_city] || options[:recipient_province_code] || options[:recipient_country_code]

  recipient_country_code = options[:recipient_country_code]&.length == 3 ? options[:recipient_country_code] : Country.find(options[:recipient_country_code]).code(:alpha3).value if options[:recipient_country_code]
  post[:j6] = options[:recipient_street_address] if options[:recipient_street_address]
  post[:j7] = options[:recipient_city] if options[:recipient_city]
  post[:j8] = options[:recipient_province_code] if options[:recipient_province_code]
  post[:j9] = recipient_country_code
end
add_reference(post, authorization) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 331
def add_reference(post, authorization)
  response_id, authorization_code, request_id, action = authorization.split(';')
  post[:g2] = response_id
  post[:g3] = authorization_code
  post[:g4] = request_id
  action || :authorize
end
add_stored_credential(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 301
def add_stored_credential(post, options)
  add_transaction_type(post, options)
  # if :transaction_type option is not passed, then check for :stored_credential options
  return unless (stored_credential = options[:stored_credential]) && options.dig(:transaction_type).nil?

  if stored_credential[:initiator] == 'merchant'
    case stored_credential[:reason_type]
    when 'recurring'
      post[:a9] = stored_credential[:initial_transaction] ? '1' : '2'
    when 'installment', 'unscheduled'
      post[:a9] = '8'
    end
    post[:g6] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
  else
    post[:a9] = '9'
  end
end
add_submerchant_id(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 432
def add_submerchant_id(post, options)
  post[:h3] = options[:submerchant_id] if options[:submerchant_id]
end
add_transaction_type(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 436
def add_transaction_type(post, options)
  post[:a9] = options[:transaction_type] if options[:transaction_type]
  post[:a2] = '3' if options.dig(:metadata, :manual_entry)
end
build_i8(eci, cavv = nil, xid = nil) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 422
def build_i8(eci, cavv = nil, xid = nil)
  "#{eci}:#{cavv || 'none'}:#{xid || 'none'}"
end
commit(action, params, reference_action = nil) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 465
def commit(action, params, reference_action = nil)
  raw_response = ssl_post(url, post_data(action, params, reference_action))
  response = parse(raw_response)

  Response.new(
    success_from(response),
    message_from(response),
    response,
    authorization: "#{response['Z1']};#{response['Z4']};#{response['A1']};#{action}",
    avs_result: AVSResult.new(code: response['Z9']),
    cvv_result: CVVResult.new(response['Z14']),
    test: test?
  )
end
message_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 515
def message_from(response)
  if success_from(response)
    'Succeeded'
  else
    RESPONSE_MESSAGES[response['Z6']] || response['Z3'] || 'Unable to read error message'
  end
end
parse(body) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 507
def parse(body)
  CGI::parse(body).map { |k, v| [k.upcase, v.first] }.to_h
end
post_data(action, params, reference_action) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 489
def post_data(action, params, reference_action)
  params.keys.each { |key| params[key] = params[key].to_s }
  params[:M] = @options[:merchant_id]
  params[:O] = request_action(action, reference_action)
  params[:K] = sign_request(params)
  params.map { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join('&')
end
request_action(action, reference_action) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 497
def request_action(action, reference_action)
  return ACTIONS["#{reference_action}_#{action}".to_sym] if reference_action

  ACTIONS[action]
end
sign_request(params) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 480
def sign_request(params)
  params = params.sort
  values = params.map do |param|
    value = param[1].gsub(/[<>()\\]/, ' ')
    value.strip
  end
  Digest::MD5.hexdigest(values.join + @options[:cipher_key])
end
success_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 511
def success_from(response)
  response['Z2'] == '0'
end
url() click to toggle source
# File lib/active_merchant/billing/gateways/credorax.rb, line 503
def url
  test? ? test_url : live_url
end