class ActiveMerchant::Billing::MercuryGateway

The Mercury gateway integration by default requires that the Mercury account being used has tokenization turned. This enables the use of capture/refund/void without having to pass the credit card back in each time. Only the “OneTime” tokenization is used; there is no use of “Recurring” tokenization.

If you don't wish to enable Mercury tokenization, you can pass :tokenization => false as an option when creating the gateway. If you do so, then passing a :credit_card option to capture and refund will become mandatory.

Constants

CARD_CODES
ENVELOPE_NAMESPACES
STANDARD_ERROR_CODE_MAPPING
SUCCESS_CODES
URLS

Public Class Methods

new(options = {}) click to toggle source
Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/mercury.rb, line 31
def initialize(options = {})
  requires!(options, :login, :password)
  @use_tokenization = (!options.has_key?(:tokenization) || options[:tokenization])
  super
end

Public Instance Methods

authorize(money, credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 51
def authorize(money, credit_card, options = {})
  requires!(options, :order_id)

  request = build_non_authorized_request('PreAuth', money, credit_card, options.merge(:authorized => money))
  commit('PreAuth', request)
end
capture(money, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 58
def capture(money, authorization, options = {})
  requires!(options, :credit_card) unless @use_tokenization

  request = build_authorized_request('PreAuthCapture', money, authorization, options[:credit_card], options.merge(:authorized => money))
  commit('PreAuthCapture', request)
end
credit(money, credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 44
def credit(money, credit_card, options = {})
  requires!(options, :order_id)

  request = build_non_authorized_request('Return', money, credit_card, options)
  commit('Return', request)
end
purchase(money, credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 37
def purchase(money, credit_card, options = {})
  requires!(options, :order_id)

  request = build_non_authorized_request('Sale', money, credit_card, options)
  commit('Sale', request)
end
refund(money, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 65
def refund(money, authorization, options = {})
  requires!(options, :credit_card) unless @use_tokenization

  request = build_authorized_request('Return', money, authorization, options[:credit_card], options)
  commit('Return', request)
end
store(credit_card, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 79
def store(credit_card, options={})
  request = build_card_lookup_request(credit_card, options)
  commit('CardLookup', request)
end
void(authorization, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 72
def void(authorization, options={})
  requires!(options, :credit_card) unless @use_tokenization

  request = build_authorized_request('VoidSale', nil, authorization, options[:credit_card], options)
  commit('VoidSale', request)
end

Private Instance Methods

add_address(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 210
def add_address(xml, options)
  if billing_address = options[:billing_address] || options[:address]
    xml.tag! 'AVS' do
      xml.tag! 'Address', billing_address[:address1]
      xml.tag! 'Zip', billing_address[:zip]
    end
  end
end
add_amount(xml, money, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 177
def add_amount(xml, money, options = {})
  xml.tag! 'Amount' do
    xml.tag! 'Purchase', amount(money)
    xml.tag! 'Tax', options[:tax] if options[:tax]
    xml.tag! 'Authorize', amount(options[:authorized]) if options[:authorized]
    xml.tag! 'Gratuity', amount(options[:tip]) if options[:tip]
  end
end
add_credit_card(xml, credit_card, action) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 195
def add_credit_card(xml, credit_card, action)
  xml.tag! 'Account' do
    if credit_card.track_data.present?
      xml.tag! 'Track1', credit_card.track_data
    else
      xml.tag! 'AcctNo', credit_card.number
      xml.tag! 'ExpDate', expdate(credit_card)
    end
  end
  xml.tag! 'CardType', CARD_CODES[credit_card.brand] if credit_card.brand

  include_cvv = !%w(Return PreAuthCapture).include?(action) && !credit_card.track_data.present?
  xml.tag! 'CVVData', credit_card.verification_value if(include_cvv && credit_card.verification_value)
end
add_customer_data(xml, options) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 167
def add_customer_data(xml, options)
  xml.tag! 'IpAddress', options[:ip] if options[:ip]
  if options[:customer]
    xml.tag! "TranInfo" do
      xml.tag! 'CustomerCode', options[:customer]
    end
  end
  xml.tag! 'MerchantID', @options[:login]
end
add_invoice(xml, invoice_no, ref_no, options) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 153
def add_invoice(xml, invoice_no, ref_no, options)
  xml.tag! 'InvoiceNo', invoice_no
  xml.tag! 'RefNo', (ref_no || invoice_no)
  xml.tag! 'OperatorID', options[:merchant] if options[:merchant]
  xml.tag! 'Memo', options[:description] if options[:description]
end
add_reference(xml, record_no) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 160
def add_reference(xml, record_no)
  if @use_tokenization
    xml.tag! "Frequency", "OneTime"
    xml.tag! "RecordNo", record_no
  end
end
authorization_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 291
def authorization_from(response)
  dollars, cents = (response[:purchase] || "").split(".").collect{|e| e.to_i}
  dollars ||= 0
  cents ||= 0
  [
    response[:invoice_no],
    response[:ref_no],
    response[:auth_code],
    response[:acq_ref_data],
    response[:process_data],
    response[:record_no],
    ((dollars * 100) + cents).to_s
  ].join(";")
end
build_authorized_request(action, money, authorization, credit_card, options) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 107
def build_authorized_request(action, money, authorization, credit_card, options)
  xml = Builder::XmlMarkup.new

  invoice_no, ref_no, auth_code, acq_ref_data, process_data, record_no, amount = split_authorization(authorization)
  ref_no = "1" if ref_no.blank?

  xml.tag! "TStream" do
    xml.tag! "Transaction" do
      xml.tag! 'TranType', 'Credit'
      if action == 'PreAuthCapture'
        xml.tag! "PartialAuth", "Allow"
      end
      xml.tag! 'TranCode', (@use_tokenization ? (action + "ByRecordNo") : action)
      add_invoice(xml, invoice_no, ref_no, options)
      add_reference(xml, record_no)
      add_customer_data(xml, options)
      add_amount(xml, (money || amount.to_i), options)
      add_credit_card(xml, credit_card, action) if credit_card
      add_address(xml, options)
      xml.tag! 'TranInfo' do
        xml.tag! "AuthCode", auth_code
        xml.tag! "AcqRefData", acq_ref_data
        xml.tag! "ProcessData", process_data 
      end
    end
  end
  xml = xml.target!
end
build_card_lookup_request(credit_card, options) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 136
def build_card_lookup_request(credit_card, options)
  xml = Builder::XmlMarkup.new

  xml.tag! "TStream" do
    xml.tag! "Transaction" do
      xml.tag! 'TranType', 'CardLookup'
      xml.tag! 'RecordNo', 'RecordNumberRequested'
      xml.tag! 'Frequency', 'OneTime'

      xml.tag! 'Memo', options[:description]
      add_customer_data(xml, options)
      add_credit_card(xml, credit_card, options)
    end
  end
  xml.target!
end
build_header() click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 264
def build_header
  {
    "SOAPAction" => "http://www.mercurypay.com/CreditTransaction",
    "Content-Type" => "text/xml; charset=utf-8"
  }
end
build_non_authorized_request(action, money, credit_card, options) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 86
def build_non_authorized_request(action, money, credit_card, options)
  xml = Builder::XmlMarkup.new

  xml.tag! "TStream" do
    xml.tag! "Transaction" do
      xml.tag! 'TranType', 'Credit'
      xml.tag! 'TranCode', action
      if action == 'PreAuth' || action == 'Sale'
        xml.tag! "PartialAuth", "Allow"
      end
      add_invoice(xml, options[:order_id], nil, options)
      add_reference(xml, "RecordNumberRequested")
      add_customer_data(xml, options)
      add_amount(xml, money, options)
      add_credit_card(xml, credit_card, action)
      add_address(xml, options) unless credit_card.track_data.present?
    end
  end
  xml = xml.target!
end
build_soap_request(body) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 247
def build_soap_request(body)
  xml = Builder::XmlMarkup.new

  xml.instruct!
  xml.tag! 'soap:Envelope', ENVELOPE_NAMESPACES do
    xml.tag! 'soap:Body' do
      xml.tag! 'CreditTransaction', 'xmlns' => homepage_url do
        xml.tag! 'tran' do
          xml << escape_xml(body)
        end
        xml.tag! 'pw', @options[:password]
      end
    end
  end
  xml.target!
end
commit(action, request) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 273
def commit(action, request)
  response = parse(action, ssl_post(endpoint_url, build_soap_request(request), build_header))

  success = SUCCESS_CODES.include?(response[:cmd_status])
  message = success ? 'Success' : message_from(response)

  Response.new(success, message, response,
    :test => test?,
    :authorization => authorization_from(response),
    :avs_result => { :code => response[:avs_result] },
    :cvv_result => response[:cvv_result],
    :error_code => success ? nil : STANDARD_ERROR_CODE_MAPPING[response[:dsix_return_code]])
end
endpoint_url() click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 243
def endpoint_url
  URLS[test? ? :test : :live]
end
escape_xml(xml) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 317
def escape_xml(xml)
  "\n<![CDATA[\n#{xml}\n]]>\n"
end
hashify_xml!(xml, response) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 225
def hashify_xml!(xml, response)
  xml = REXML::Document.new(xml)

  xml.elements.each("//CmdResponse/*") do |node|
    response[node.name.underscore.to_sym] = node.text
  end

  xml.elements.each("//TranResponse/*") do |node|
    if node.name.to_s == "Amount"
      node.elements.each do |amt|
        response[amt.name.underscore.to_sym] = amt.text
      end
    else
      response[node.name.underscore.to_sym] = node.text
    end
  end
end
message_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 287
def message_from(response)
  response[:text_response]
end
parse(action, body) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 219
def parse(action, body)
  response = {}
  hashify_xml!(unescape_xml(body), response)
  response
end
split_authorization(authorization) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 306
def split_authorization(authorization)
  invoice_no, ref_no, auth_code, acq_ref_data, process_data, record_no, amount = authorization.split(";")
  [invoice_no, ref_no, auth_code, acq_ref_data, process_data, record_no, amount]
end
unescape_xml(escaped_xml) click to toggle source
# File lib/active_merchant/billing/gateways/mercury.rb, line 321
def unescape_xml(escaped_xml)
  escaped_xml.gsub(/\&gt;/,'>').gsub(/\&lt;/,'<')
end