class ActiveMerchant::Billing::CenposGateway

Constants

STANDARD_ERROR_CODE_MAPPING

Public Class Methods

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

Public Instance Methods

authorize(amount, payment_method, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 30
def authorize(amount, payment_method, options={})
  post = {}
  add_invoice(post, amount, options)
  add_payment_method(post, payment_method)
  add_customer_data(post, options)

  commit('Auth', post)
end
capture(amount, authorization, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 39
def capture(amount, authorization, options={})
  post = {}
  add_invoice(post, amount, options)
  add_reference(post, authorization)
  add_customer_data(post, options)

  commit('SpecialForce', post)
end
credit(amount, payment_method, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 68
def credit(amount, payment_method, options={})
  post = {}
  add_invoice(post, amount, options)
  add_payment_method(post, payment_method)

  commit('Credit', post)
end
purchase(amount, payment_method, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 21
def purchase(amount, payment_method, options={})
  post = {}
  add_invoice(post, amount, options)
  add_payment_method(post, payment_method)
  add_customer_data(post, options)

  commit('Sale', post)
end
refund(amount, authorization, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 59
def refund(amount, authorization, options={})
  post = {}
  add_invoice(post, amount, options)
  add_reference(post, authorization)
  add_customer_data(post, options)

  commit('SpecialReturn', post)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 87
def scrub(transcript)
  transcript.
    gsub(%r((<acr1:CardNumber>)[^<]+(<))i, '\1[FILTERED]\2').
    gsub(%r((<acr1:CardVerificationNumber>)[^<]+(<))i, '\1[FILTERED]\2').
    gsub(%r((<acr:Password>)[^<]+(<))i, '\1[FILTERED]\2')
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 83
def supports_scrubbing?
  true
end
verify(credit_card, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 76
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/cenpos.rb, line 48
def void(authorization, options={})
  post = {}
  add_void_required_elements(post)
  add_reference(post, authorization)
  add_remembered_amount(post, authorization)
  add_tax(post, options)
  add_order_id(post, options)

  commit('Void', post)
end

Private Instance Methods

add_customer_data(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 114
def add_customer_data(post, options)
  if(billing_address = (options[:billing_address] || options[:address]))
    post[:CustomerEmailAddress] = billing_address[:email]
    post[:CustomerPhone] = billing_address[:phone]
    post[:CustomerBillingAddress] = billing_address[:address1]
    post[:CustomerCity] = billing_address[:city]
    post[:CustomerState] = billing_address[:state]
    post[:CustomerZipCode] = billing_address[:zip]
  end
end
add_invoice(post, money, options) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 96
def add_invoice(post, money, options)
  post[:Amount] = amount(money)
  post[:CurrencyCode] = options[:currency] || currency(money)
  post[:InvoiceDetail] = options[:invoice_detail] if options[:invoice_detail]
  post[:CustomerCode] = options[:customer_code] if options[:customer_code]
  add_order_id(post, options)
  add_tax(post, options)
end
add_order_id(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 130
def add_order_id(post, options)
  post[:InvoiceNumber] = options[:order_id]
end
add_payment_method(post, payment_method) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 105
def add_payment_method(post, payment_method)
  post[:NameOnCard] = payment_method.name
  post[:CardNumber] = payment_method.number
  post[:CardVerificationNumber] = payment_method.verification_value
  post[:CardExpirationDate] = format(payment_method.month, :two_digits) + format(payment_method.year, :two_digits)
  post[:CardLastFourDigits] = payment_method.last_digits
  post[:MagneticData] = payment_method.track_data if payment_method.track_data
end
add_reference(post, authorization) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 138
def add_reference(post, authorization)
  reference_number, last_four_digits = split_authorization(authorization)
  post[:ReferenceNumber] = reference_number
  post[:CardLastFourDigits] = last_four_digits
end
add_remembered_amount(post, authorization) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 144
def add_remembered_amount(post, authorization)
  post[:Amount] = split_authorization(authorization).last
end
add_tax(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 134
def add_tax(post, options)
  post[:TaxAmount] = amount(options[:tax] || 0)
end
add_void_required_elements(post) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 125
def add_void_required_elements(post)
  post[:GeoLocationInformation] = nil
  post[:IMEI] = nil
end
authorization_from(request, response) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 256
def authorization_from(request, response)
  [ response[:reference_number], request[:CardLastFourDigits], request[:Amount] ].join('|')
end
avs_result_code(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 283
def avs_result_code(xml)
  billing_address_elem = validation_result_element(xml, 'Billing Address')
  zip_code_elem = validation_result_element(xml, 'Zip Code')

  return nil unless billing_address_elem && zip_code_elem

  billing_matches = avs_result_matches(billing_address_elem)
  zip_matches = avs_result_matches(zip_code_elem)

  if billing_matches && zip_matches
    'D'
  elsif !billing_matches && zip_matches
    'P'
  elsif billing_matches && !zip_matches
    'B'
  else
    'C'
  end
end
avs_result_from_xml(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 273
def avs_result_from_xml(xml)
  ActiveMerchant::Billing::AVSResult.new(code: avs_result_code(xml))
end
avs_result_matches(elem) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 303
def avs_result_matches(elem)
  validation_result_matches?(*validation_result_element_text(elem.parent))
end
build_request(post) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 189
def build_request(post)
  xml = Builder::XmlMarkup.new :indent => 8
  xml.tag!('acr:MerchantId', post.delete(:MerchantId))
  xml.tag!('acr:Password', post.delete(:Password))
  xml.tag!('acr:UserId', post.delete(:UserId))
  post.sort.each do |field, value|
    xml.tag!("acr1:#{field}", value)
  end
  envelope(xml.target!)
end
commit(action, post) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 148
def commit(action, post)
  post[:MerchantId] = @options[:merchant_id]
  post[:Password] = @options[:password]
  post[:UserId] = @options[:user_id]
  post[:TransactionType] = action

  data = build_request(post)
  begin
    xml = ssl_post(self.live_url, data, headers)
    raw = parse(xml)
  rescue ActiveMerchant::ResponseError => e
    if(e.response.code == '500' && e.response.body.start_with?('<s:Envelope'))
      raw = {
        message: 'See transcript for detailed error description.'
      }
    else
      raise
    end
  end

  succeeded = success_from(raw[:result])
  Response.new(
    succeeded,
    message_from(succeeded, raw),
    raw,
    authorization: authorization_from(post, raw),
    error_code: error_code_from(succeeded, raw),
    test: test?,
    cvv_result: cvv_result_from_xml(xml),
    avs_result: avs_result_from_xml(xml)
  )
end
cvv_result_code(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 277
def cvv_result_code(xml)
  cvv = validation_result_element(xml, 'CVV')
  return nil unless cvv
  validation_result_matches?(*validation_result_element_text(cvv.parent)) ? 'M' : 'N'
end
cvv_result_from_xml(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 269
def cvv_result_from_xml(xml)
  ActiveMerchant::Billing::CVVResult.new(cvv_result_code(xml))
end
envelope(body) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 200
      def envelope(body)
        <<-EOS
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:acr="http://schemas.datacontract.org/2004/07/Acriter.ABI.CenPOS.EPayment.VirtualTerminal.Common" xmlns:acr1="http://schemas.datacontract.org/2004/07/Acriter.ABI.CenPOS.EPayment.VirtualTerminal.v6.Common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header/>
   <soapenv:Body>
      <tem:ProcessCreditCard>
         <tem:request>
           #{body}
         </tem:request>
      </tem:ProcessCreditCard>
   </soapenv:Body>
</soapenv:Envelope>
        EOS
      end
error_code_from(succeeded, response) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 265
def error_code_from(succeeded, response)
  succeeded ? nil : STANDARD_ERROR_CODE_MAPPING[response[:result]]
end
headers() click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 181
def headers
  {
    'Accept-Encoding' => 'identity',
    'Content-Type'  => 'text/xml;charset=UTF-8',
    'SOAPAction'  => 'http://tempuri.org/Transactional/ProcessCreditCard'
  }
end
message_from(succeeded, response) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 239
def message_from(succeeded, response)
  if succeeded
    'Succeeded'
  else
    response[:message] || 'Unable to read error message'
  end
end
parse(xml) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 215
def parse(xml)
  response = {}

  doc = Nokogiri::XML(xml)
  doc.remove_namespaces!
  body = doc.xpath('//ProcessCreditCardResult')
  body.children.each do |node|
    if node.elements.size == 0
      response[node.name.underscore.to_sym] = node.text
    else
      node.elements.each do |childnode|
        name = "#{node.name.underscore}_#{childnode.name.underscore}"
        response[name.to_sym] = childnode.text
      end
    end
  end unless doc.root.nil?

  response
end
split_authorization(authorization) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 260
def split_authorization(authorization)
  reference_number, last_four_digits, original_amount = authorization.split('|')
  [reference_number, last_four_digits, original_amount]
end
success_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 235
def success_from(response)
  response == '0'
end
validation_result_element(xml, name) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 307
def validation_result_element(xml, name)
  doc = Nokogiri::XML(xml)
  doc.remove_namespaces!
  doc.at_xpath("//ParameterValidationResultList//ParameterValidationResult//Name[text() = '#{name}']")
end
validation_result_element_text(element) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 313
def validation_result_element_text(element)
  result_text = element.elements.detect { |elem|
    elem.name == 'Result'
  }.children.detect(&:text).text

  result_text.split(';').collect(&:strip)
end
validation_result_matches?(present, match) click to toggle source
# File lib/active_merchant/billing/gateways/cenpos.rb, line 321
def validation_result_matches?(present, match)
  present.downcase.start_with?('present') &&
    match.downcase.start_with?('match')
end