class ActiveMerchant::Billing::SageGateway

Constants

SOURCE_CARD
SOURCE_ECHECK
TRANSACTIONS

Public Class Methods

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

Public Instance Methods

authorize(money, credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 30
def authorize(money, credit_card, options = {})
  post = {}
  add_credit_card(post, credit_card)
  add_transaction_data(post, money, options)
  commit(:authorization, post, SOURCE_CARD)
end
capture(money, reference, options = {}) click to toggle source

The money amount is not used. The entire amount of the initial authorization will be captured.

# File lib/active_merchant/billing/gateways/sage.rb, line 53
def capture(money, reference, options = {})
  post = {}
  add_reference(post, reference)
  commit(:capture, post, SOURCE_CARD)
end
credit(money, payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 66
def credit(money, payment_method, options = {})
  post = {}
  if card_brand(payment_method) == 'check'
    source = SOURCE_ECHECK
    add_check(post, payment_method)
    add_check_customer_data(post, options)
  else
    source = SOURCE_CARD
    add_credit_card(post, payment_method)
  end
  add_transaction_data(post, money, options)
  commit(:credit, post, source)
end
purchase(money, payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 37
def purchase(money, payment_method, options = {})
  post = {}
  if card_brand(payment_method) == 'check'
    source = SOURCE_ECHECK
    add_check(post, payment_method)
    add_check_customer_data(post, options)
  else
    source = SOURCE_CARD
    add_credit_card(post, payment_method)
  end
  add_transaction_data(post, money, options)
  commit(:purchase, post, source)
end
refund(money, reference, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 80
def refund(money, reference, options={})
  post = {}
  add_reference(post, reference)
  add_transaction_data(post, money, options)
  commit(:refund, post, SOURCE_CARD)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 99
def scrub(transcript)
  force_utf8(transcript).
    gsub(%r((M_id=)[^&]*), '\1[FILTERED]').
    gsub(%r((M_key=)[^&]*), '\1[FILTERED]').
    gsub(%r((C_cardnumber=)[^&]*), '\1[FILTERED]').
    gsub(%r((C_cvv=)[^&]*), '\1[FILTERED]').
    gsub(%r((C_rte=)[^&]*), '\1[FILTERED]').
    gsub(%r((C_acct=)[^&]*), '\1[FILTERED]').
    gsub(%r((C_ssn=)[^&]*), '\1[FILTERED]').
    gsub(%r((<ns1:CARDNUMBER>).+(</ns1:CARDNUMBER>)), '\1[FILTERED]\2').
    gsub(%r((<ns1:M_ID>).+(</ns1:M_ID>)), '\1[FILTERED]\2').
    gsub(%r((<ns1:M_KEY>).+(</ns1:M_KEY>)), '\1[FILTERED]\2')
end
store(credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 87
def store(credit_card, options = {})
  vault.store(credit_card, options)
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 95
def supports_scrubbing?
  true
end
unstore(identification, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 91
def unstore(identification, options = {})
  vault.unstore(identification, options)
end
void(reference, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 59
def void(reference, options = {})
  post = {}
  add_reference(post, reference)
  source = reference.split(';').last
  commit(:void, post, source)
end

Private Instance Methods

account_type(check) click to toggle source

DDA for Checking SAV for Savings 

# File lib/active_merchant/billing/gateways/sage.rb, line 168
def account_type(check)
  case check.account_type
  when 'checking' then 'DDA'
  when 'savings'  then 'SAV'
  else raise ArgumentError, "Unknown account type #{check.account_type}"
  end
end
add_addresses(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 229
def add_addresses(post, options)
  billing_address   = options[:billing_address] || options[:address] || {}

  post[:C_address]    = billing_address[:address1]
  post[:C_city]       = billing_address[:city]
  post[:C_state]      = empty?(billing_address[:state]) ? 'Outside of US' : billing_address[:state]
  post[:C_zip]        = billing_address[:zip]
  post[:C_country]    = billing_address[:country]
  post[:C_telephone]  = billing_address[:phone]
  post[:C_fax]        = billing_address[:fax]
  post[:C_email]      = options[:email]

  if shipping_address = options[:shipping_address]
    post[:C_ship_name]    = shipping_address[:name]
    post[:C_ship_address] = shipping_address[:address1]
    post[:C_ship_city]    = shipping_address[:city]
    post[:C_ship_state]   = shipping_address[:state]
    post[:C_ship_zip]     = shipping_address[:zip]
    post[:C_ship_country] = shipping_address[:country]
  end
end
add_amount(post, money) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 221
def add_amount(post, money)
  post[:T_amt] = amount(money)
end
add_check(post, check) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 129
def add_check(post, check)
  post[:C_first_name]   = check.first_name
  post[:C_last_name]    = check.last_name
  post[:C_rte]          = check.routing_number
  post[:C_acct]         = check.account_number
  post[:C_check_number] = check.number
  post[:C_acct_type]    = account_type(check)
end
add_check_customer_data(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 138
def add_check_customer_data(post, options)
  # Required  Customer Type – (NACHA Transaction Class)
  # CCD for Commercial, Merchant Initiated
  # PPD for Personal, Merchant Initiated
  # WEB for Internet, Consumer Initiated
  # RCK for Returned Checks
  # ARC for Account Receivable Entry
  # TEL for TelephoneInitiated
  post[:C_customer_type] = 'WEB'

  # Optional  10  Digit Originator  ID – Assigned  By for  each transaction  class  or  business  purpose. If  not provided, the default Originator ID for the specific  Customer Type will be applied. 
  post[:C_originator_id] = options[:originator_id]

  # Optional  Transaction Addenda
  post[:T_addenda] = options[:addenda]

  # Required  Check  Writer  Social  Security  Number  (  Numbers Only, No Dashes ) 
  post[:C_ssn] = options[:ssn].to_s.gsub(/[^\d]/, '')

  post[:C_dl_state_code] = options[:drivers_license_state]
  post[:C_dl_number]     = options[:drivers_license_number]
  post[:C_dob]           = format_birth_date(options[:date_of_birth])
end
add_credit_card(post, credit_card) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 122
def add_credit_card(post, credit_card)
  post[:C_name]       = credit_card.name
  post[:C_cardnumber] = credit_card.number
  post[:C_exp]        = expdate(credit_card)
  post[:C_cvv]        = credit_card.verification_value if credit_card.verification_value?
end
add_customer_data(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 225
def add_customer_data(post, options)
  post[:T_customer_number] = options[:customer] if Float(options[:customer]) rescue nil
end
add_invoice(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 210
def add_invoice(post, options)
  post[:T_ordernum] = (options[:order_id] || generate_unique_id).slice(0, 20)
  post[:T_tax] = amount(options[:tax]) unless empty?(options[:tax])
  post[:T_shipping] = amount(options[:shipping]) unless empty?(options[:shipping])
end
add_reference(post, reference) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 216
def add_reference(post, reference)
  ref, _ = reference.to_s.split(';')
  post[:T_reference] = ref
end
add_transaction_data(post, money, options) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 251
def add_transaction_data(post, money, options)
  add_amount(post, money)
  add_invoice(post, options)
  add_addresses(post, options)
  add_customer_data(post, options)
end
authorization_from(response, source) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 278
def authorization_from(response, source)
  "#{response[:reference]};#{source}"
end
commit(action, params, source) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 258
def commit(action, params, source)
  url = url(params, source)
  response = parse(ssl_post(url, post_data(action, params)), source)

  Response.new(success?(response), response[:message], response,
    :test => test?,
    :authorization => authorization_from(response, source),
    :avs_result => { :code => response[:avs_result] },
    :cvv_result => response[:cvv_result]
  )
end
force_utf8(string) click to toggle source

use the same method as in pay_conex

# File lib/active_merchant/billing/gateways/sage.rb, line 116
def force_utf8(string)
  return nil unless string
  binary = string.encode('BINARY', invalid: :replace, undef: :replace, replace: '?')   # Needed for Ruby 2.0 since #encode is a no-op if the string is already UTF-8. It's not needed for Ruby 2.1 and up since it's not a no-op there.
  binary.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
end
format_birth_date(date) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 162
def format_birth_date(date)
  date.respond_to?(:strftime) ? date.strftime('%m/%d/%Y') : date
end
parse(data, source) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 176
def parse(data, source)
  source == SOURCE_ECHECK ? parse_check(data) : parse_credit_card(data)
end
parse_check(data) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 180
def parse_check(data)
  response = {}
  response[:success]          = data[1, 1]
  response[:code]             = data[2, 6].strip
  response[:message]          = data[8, 32].strip
  response[:risk]             = data[40, 2]
  response[:reference]        = data[42, 10]

  extra_data = data[53...-1].split("\034")
  response[:order_number] = extra_data[0]
  response[:authentication_indicator] = extra_data[1]
  response[:authentication_disclosure] = extra_data[2]
  response
end
parse_credit_card(data) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 195
def parse_credit_card(data)
  response = {}
  response[:success]          = data[1, 1]
  response[:code]             = data[2, 6]
  response[:message]          = data[8, 32].strip
  response[:front_end]        = data[40, 2]
  response[:cvv_result]       = data[42, 1]
  response[:avs_result]       = data[43, 1].strip
  response[:risk]             = data[44, 2]
  response[:reference]        = data[46, 10]

  response[:order_number], response[:recurring] = data[57...-1].split("\034")
  response
end
post_data(action, params = {}) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 286
def post_data(action, params = {})
  params[:M_id]  = @options[:login]
  params[:M_key] = @options[:password]
  params[:T_code] = TRANSACTIONS[action]

  params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&')
end
success?(response) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 282
def success?(response)
  response[:success] == 'A'
end
url(params, source) click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 270
def url(params, source)
  if source == SOURCE_ECHECK
    "#{live_url}/eftVirtualCheck.dll?transaction"
  else
    "#{live_url}/eftBankcard.dll?transaction"
  end
end
vault() click to toggle source
# File lib/active_merchant/billing/gateways/sage.rb, line 294
def vault
  @vault ||= SageVault.new(@options, self)
end