class ActiveMerchant::Billing::DataCashGateway

Constants

AUTH_TYPE

Different Card Transaction Types

CANCEL_TYPE
DATACASH_SUCCESS

Datacash success code

FULFILL_TYPE
POLICY_ACCEPT

Constant strings for use in the ExtendedPolicy complex element for CV2 checks

POLICY_REJECT
PRE_TYPE
REFUND_TYPE
TRANSACTION_REFUND_TYPE

Public Class Methods

new(options = {}) click to toggle source

Creates a new DataCashGateway

The gateway requires that a valid login and password be passed in the options hash.

Options

  • :login – The Datacash account login.

  • :password – The Datacash account password.

  • :test => true or false – Use the test or live Datacash url.

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

Public Instance Methods

authorize(money, authorization_or_credit_card, options = {}) click to toggle source

Performs an authorization, which reserves the funds on the customer's credit card, but does not charge the card.

Parameters

  • money The amount to be authorized as an Integer value in cents.

  • authorization_or_credit_card

    The continuous authority reference or CreditCard details for the transaction.

  • options A hash of optional parameters.

    • :order_id A unique reference for this order (corresponds to merchantreference in datacash documentation)

    • :set_up_continuous_authority

      Set to true to set up a recurring historic transaction account be set up. Only supported for :visa, :master and :american_express card types See www.datacash.com/services/recurring/historic.php for more details of historic transactions.

    • :address

      billing address for card

The continuous authority reference will be available in response#params if you have requested one

# File lib/active_merchant/billing/gateways/data_cash.rb, line 99
def authorize(money, authorization_or_credit_card, options = {})
  requires!(options, :order_id)

  if authorization_or_credit_card.is_a?(String)
    request = build_purchase_or_authorization_request_with_continuous_authority_reference_request(AUTH_TYPE, money, authorization_or_credit_card, options)
  else
    request = build_purchase_or_authorization_request_with_credit_card_request(PRE_TYPE, money, authorization_or_credit_card, options)
  end

  commit(request)
end
capture(money, authorization, options = {}) click to toggle source

Captures the funds from an authorized transaction.

Parameters

  • money – The amount to be captured as anInteger value in cents.

  • authorization – The authorization returned from the previous authorize request.

# File lib/active_merchant/billing/gateways/data_cash.rb, line 117
def capture(money, authorization, options = {})
  commit(build_void_or_capture_request(FULFILL_TYPE, money, authorization, options))
end
credit(money, reference_or_credit_card, options = {}) click to toggle source

Refund to a card

Parameters

  • money The amount to be refunded as an Integer value in cents. Set to nil for a full refund on existing transaction.

  • reference_or_credit_card The credit card you want to refund OR the datacash_reference for the existing transaction you are refunding

  • options Are ignored when refunding via reference to an existing transaction, otherwise

    • :order_id A unique reference for this order (corresponds to merchantreference in datacash documentation)

    • :address

      billing address for card

# File lib/active_merchant/billing/gateways/data_cash.rb, line 141
def credit(money, reference_or_credit_card, options = {})
  if reference_or_credit_card.is_a?(String)
    ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
    refund(money, reference_or_credit_card)
  else
    request = build_refund_request(money, reference_or_credit_card, options)
    commit(request)
  end
end
purchase(money, authorization_or_credit_card, options = {}) click to toggle source

Perform a purchase, which is essentially an authorization and capture in a single operation.

Parameters

  • money The amount to be authorized as an Integer value in cents.

  • authorization_or_credit_card

    The continuous authority reference or CreditCard details for the transaction.

  • options A hash of optional parameters.

    • :order_id A unique reference for this order (corresponds to merchantreference in datacash documentation)

    • :set_up_continuous_authority

      Set to true to set up a recurring historic transaction account be set up.
      Only supported for :visa, :master and :american_express card types
      See http://www.datacash.com/services/recurring/historic.php for more details of historic transactions.
    • :address

      billing address for card

The continuous authority reference will be available in response#params if you have requested one

# File lib/active_merchant/billing/gateways/data_cash.rb, line 71
def purchase(money, authorization_or_credit_card, options = {})
  requires!(options, :order_id)

  if authorization_or_credit_card.is_a?(String)
    request = build_purchase_or_authorization_request_with_continuous_authority_reference_request(AUTH_TYPE, money, authorization_or_credit_card, options)
  else
    request = build_purchase_or_authorization_request_with_credit_card_request(AUTH_TYPE, money, authorization_or_credit_card, options)
  end

  commit(request)
end
refund(money, reference, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/data_cash.rb, line 151
def refund(money, reference, options = {})
  commit(build_transaction_refund_request(money, reference))
end
void(authorization, options = {}) click to toggle source

Void a previous transaction

Parameters

  • authorization - The authorization returned from the previous authorize request.

# File lib/active_merchant/billing/gateways/data_cash.rb, line 126
def void(authorization, options = {})
  request = build_void_or_capture_request(CANCEL_TYPE, nil, authorization, options)

  commit(request)
end

Private Instance Methods

add_authentication(xml) click to toggle source

Adds the authentication element to the passed builder xml doc

Parameters:

-xml: Builder document that is being built up

Returns:

-none: The results is stored in the passed xml document
# File lib/active_merchant/billing/gateways/data_cash.rb, line 448
def add_authentication(xml)
  xml.tag! :Authentication do
    xml.tag! :client, @options[:login]
    xml.tag! :password, @options[:password]
  end
end
add_credit_card(xml, credit_card, address) click to toggle source

Add credit_card details to the passed XML Builder doc

Parameters:

-xml: Builder document that is being built up
-credit_card: ActiveMerchant::Billing::CreditCard object
-billing_address: Hash containing all of the billing address details

Returns:

-none: The results is stored in the passed xml document
# File lib/active_merchant/billing/gateways/data_cash.rb, line 465
def add_credit_card(xml, credit_card, address)

  xml.tag! :Card do

    # DataCash calls the CC number 'pan'
    xml.tag! :pan, credit_card.number
    xml.tag! :expirydate, format_date(credit_card.month, credit_card.year)

    # optional values - for Solo etc
    if [ 'switch', 'solo' ].include?(card_brand(credit_card).to_s)

      xml.tag! :issuenumber, credit_card.issue_number unless credit_card.issue_number.blank?

      if !credit_card.start_month.blank? && !credit_card.start_year.blank?
        xml.tag! :startdate, format_date(credit_card.start_month, credit_card.start_year)
      end
    end

    xml.tag! :Cv2Avs do
      xml.tag! :cv2, credit_card.verification_value if credit_card.verification_value?
      if address
        xml.tag! :street_address1, address[:address1] unless address[:address1].blank?
        xml.tag! :street_address2, address[:address2] unless address[:address2].blank?
        xml.tag! :street_address3, address[:address3] unless address[:address3].blank?
        xml.tag! :street_address4, address[:address4] unless address[:address4].blank?
        xml.tag! :postcode, address[:zip] unless address[:zip].blank?
      end

      # The ExtendedPolicy defines what to do when the passed data
      # matches, or not...
      #
      # All of the following elements MUST be present for the
      # xml to be valid (or can drop the ExtendedPolicy and use
      # a predefined one
      xml.tag! :ExtendedPolicy do
        xml.tag! :cv2_policy,
        :notprovided =>   POLICY_REJECT,
        :notchecked =>    POLICY_REJECT,
        :matched =>       POLICY_ACCEPT,
        :notmatched =>    POLICY_REJECT,
        :partialmatch =>  POLICY_REJECT
        xml.tag! :postcode_policy,
        :notprovided =>   POLICY_ACCEPT,
        :notchecked =>    POLICY_ACCEPT,
        :matched =>       POLICY_ACCEPT,
        :notmatched =>    POLICY_REJECT,
        :partialmatch =>  POLICY_ACCEPT
        xml.tag! :address_policy,
        :notprovided =>   POLICY_ACCEPT,
        :notchecked =>    POLICY_ACCEPT,
        :matched =>       POLICY_ACCEPT,
        :notmatched =>    POLICY_REJECT,
        :partialmatch =>  POLICY_ACCEPT
      end
    end
  end
end
build_purchase_or_authorization_request_with_continuous_authority_reference_request(type, money, authorization, options) click to toggle source

Create the xml document for an 'auth' or 'pre' transaction with continuous authorization

Final XML should look like:

<Request>

<Transaction>
  <ContAuthTxn type="historic" />
  <TxnDetails>
    <merchantreference>3851231</merchantreference>
    <capturemethod>cont_auth</capturemethod>
    <amount currency="GBP">18.50</amount>
  </TxnDetails>
  <HistoricTxn>
    <reference>4500200040925092</reference>
    <method>auth</method>
  </HistoricTxn>
</Transaction>
<Authentication>
  <client>99000001</client>
  <password>mypasswd</password>
</Authentication>

</Request>

Parameters:

-type must be 'auth' or 'pre'
-money - A money object with the price and currency
-authorization - The authorization containing a continuous authority reference previously set up on a credit card
-options:
  :order_id is the merchant reference number

Returns:

-xml: Builder document containing the markup
# File lib/active_merchant/billing/gateways/data_cash.rb, line 331
def build_purchase_or_authorization_request_with_continuous_authority_reference_request(type, money, authorization, options)
  parsed_authorization = parse_authorization_string(authorization)
  raise ArgumentError, "The continuous authority reference is required for continuous authority transactions" if parsed_authorization[:ca_reference].blank?

  xml = Builder::XmlMarkup.new :indent => 2
  xml.instruct!
  xml.tag! :Request do
    add_authentication(xml)
    xml.tag! :Transaction do
      xml.tag! :ContAuthTxn, :type => 'historic'
      xml.tag! :HistoricTxn do
        xml.tag! :reference, parsed_authorization[:ca_reference]
        xml.tag! :method, type
      end
      xml.tag! :TxnDetails do
        xml.tag! :merchantreference, format_reference_number(options[:order_id])
        xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money)
        xml.tag! :capturemethod, 'cont_auth'
      end
    end
  end
  xml.target!
end
build_purchase_or_authorization_request_with_credit_card_request(type, money, credit_card, options) click to toggle source

Create the xml document for an 'auth' or 'pre' transaction with a credit card

Final XML should look like:

<Request>

<Authentication>
  <client>99000000</client>
  <password>*******</password>
</Authentication>
<Transaction>
  <TxnDetails>
    <merchantreference>123456</merchantreference>
    <amount currency="EUR">10.00</amount>
  </TxnDetails>
  <CardTxn>
    <Card>
      <pan>4444********1111</pan>
      <expirydate>03/04</expirydate>
      <Cv2Avs>
        <street_address1>Flat 7</street_address1>
        <street_address2>89 Jumble
             Street</street_address2>
        <street_address3>Mytown</street_address3>
        <postcode>AV12FR</postcode>
        <cv2>123</cv2>
         <ExtendedPolicy>
           <cv2_policy notprovided="reject"
                        notchecked="accept"
                        matched="accept"
                        notmatched="reject"
                        partialmatch="reject"/>
           <postcode_policy notprovided="reject"
                        notchecked="accept"
                        matched="accept"
                        notmatched="reject"
                        partialmatch="accept"/>
           <address_policy notprovided="reject"
                        notchecked="accept"
                        matched="accept"
                        notmatched="reject"
                        partialmatch="accept"/>
         </ExtendedPolicy>
      </Cv2Avs>
    </Card>
    <method>auth</method>
  </CardTxn>
</Transaction>

</Request>

Parameters:

-type must be 'auth' or 'pre'
-money - A money object with the price and currency
-credit_card - The credit_card details to use
-options:
  :order_id is the merchant reference number
  :billing_address is the billing address for the cc
  :address is the delivery address

Returns:

-xml: Builder document containing the markup
# File lib/active_merchant/billing/gateways/data_cash.rb, line 273
def build_purchase_or_authorization_request_with_credit_card_request(type, money, credit_card, options)
  xml = Builder::XmlMarkup.new :indent => 2
  xml.instruct!
  xml.tag! :Request do
    add_authentication(xml)

    xml.tag! :Transaction do
      if options[:set_up_continuous_authority]
        xml.tag! :ContAuthTxn, :type => 'setup'
      end
      xml.tag! :CardTxn do
        xml.tag! :method, type
        add_credit_card(xml, credit_card, options[:billing_address])
      end
      xml.tag! :TxnDetails do
        xml.tag! :merchantreference, format_reference_number(options[:order_id])
        xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money)
        xml.tag! :capturemethod, 'ecomm'
      end
    end
  end
  xml.target!
end
build_refund_request(money, credit_card, options) click to toggle source

Create the xml document for a full or partial refund with

Final XML should look like:

<Request>

<Authentication>
  <client>99000001</client>
  <password>*****</password>
</Authentication>
<Transaction>
  <CardTxn>
    <Card>
      <pan>633300*********1</pan>
      <expirydate>04/06</expirydate>
      <startdate>01/04</startdate>
    </Card>
    <method>refund</method>
  </CardTxn>
  <TxnDetails>
    <merchantreference>1000001</merchantreference>
    <amount currency="GBP">95.99</amount>
  </TxnDetails>
</Transaction>

</Request>

# File lib/active_merchant/billing/gateways/data_cash.rb, line 420
def build_refund_request(money, credit_card, options)
  xml = Builder::XmlMarkup.new :indent => 2
  xml.instruct!
  xml.tag! :Request do
    add_authentication(xml)
    xml.tag! :Transaction do
      xml.tag! :CardTxn do
        xml.tag! :method, REFUND_TYPE
        add_credit_card(xml, credit_card, options[:billing_address])
      end
      xml.tag! :TxnDetails do
        xml.tag! :merchantreference, format_reference_number(options[:order_id])
        xml.tag! :amount, amount(money)
      end
    end
  end
  xml.target!
end
build_transaction_refund_request(money, authorization) click to toggle source

Create the xml document for a full or partial refund transaction with

Final XML should look like:

<Request>

<Authentication>
  <client>99000001</client>
  <password>*******</password>
</Authentication>
<Transaction>
  <HistoricTxn>
    <method>txn_refund</method>
    <reference>12345678</reference>
  </HistoricTxn>
  <TxnDetails>
    <amount>10.00</amount>
  </TxnDetails>
</Transaction>

</Request>

# File lib/active_merchant/billing/gateways/data_cash.rb, line 375
def build_transaction_refund_request(money, authorization)
  parsed_authorization = parse_authorization_string(authorization)
  xml = Builder::XmlMarkup.new :indent => 2
  xml.instruct!
  xml.tag! :Request do
    add_authentication(xml)
    xml.tag! :Transaction do
      xml.tag! :HistoricTxn do
        xml.tag! :reference, parsed_authorization[:reference]
        xml.tag! :method, TRANSACTION_REFUND_TYPE
      end
      unless money.nil?
        xml.tag! :TxnDetails do
          xml.tag! :amount, amount(money)
        end
      end
    end
  end
  xml.target!
end
build_void_or_capture_request(type, money, authorization, options) click to toggle source

Create the xml document for a 'cancel' or 'fulfill' transaction.

Final XML should look like: <Request>

<Authentication>
  <client>99000001</client>
  <password>******</password>
</Authentication>
<Transaction>
  <TxnDetails>
    <amount>25.00</amount>
  </TxnDetails>
  <HistoricTxn>
    <reference>4900200000000001</reference>
    <authcode>A6</authcode>
    <method>fulfill</method>
  </HistoricTxn>
</Transaction>

</Request>

Parameters:

  • type must be FULFILL_TYPE or CANCEL_TYPE

  • money - optional - Integer value in cents

  • authorization - the Datacash authorization from a previous succesful authorize transaction

  • options

    • order_id - A unique reference for the transaction

Returns:

-Builder xml document
# File lib/active_merchant/billing/gateways/data_cash.rb, line 186
def build_void_or_capture_request(type, money, authorization, options)
  parsed_authorization = parse_authorization_string(authorization)
  xml = Builder::XmlMarkup.new :indent => 2
  xml.instruct!
  xml.tag! :Request do
    add_authentication(xml)

    xml.tag! :Transaction do
      xml.tag! :HistoricTxn do
        xml.tag! :reference, parsed_authorization[:reference]
        xml.tag! :authcode, parsed_authorization[:auth_code]
        xml.tag! :method, type
      end

      if money
        xml.tag! :TxnDetails do
          xml.tag! :merchantreference, format_reference_number(options[:order_id])
          xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money)
          xml.tag! :capturemethod, 'ecomm'
        end
      end
    end
  end
  xml.target!
end
commit(request) click to toggle source

Send the passed data to DataCash for processing

Parameters:

-request: The XML data that is to be sent to Datacash

Returns:

- ActiveMerchant::Billing::Response object
# File lib/active_merchant/billing/gateways/data_cash.rb, line 531
def commit(request)
  response = parse(ssl_post(test? ? self.test_url : self.live_url, request))

  Response.new(response[:status] == DATACASH_SUCCESS, response[:reason], response,
    :test => test?,
    :authorization => "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}"
  )
end
format_date(month, year) click to toggle source

Returns a date string in the format Datacash expects

Parameters:

-month: integer, the month
-year: integer, the year

Returns:

-String: date in MM/YY format
# File lib/active_merchant/billing/gateways/data_cash.rb, line 549
def format_date(month, year)
  "#{format(month,:two_digits)}/#{format(year, :two_digits)}"
end
format_reference_number(number) click to toggle source
# File lib/active_merchant/billing/gateways/data_cash.rb, line 590
def format_reference_number(number)
  number.to_s.gsub(/[^A-Za-z0-9]/, '').rjust(6, "0").first(30)
end
parse(body) click to toggle source

Parse the datacash response and create a Response object

Parameters:

-body: The XML returned from Datacash

Returns:

-a hash with all of the values returned in the Datacash XML response
# File lib/active_merchant/billing/gateways/data_cash.rb, line 561
def parse(body)

  response = {}
  xml = REXML::Document.new(body)
  root = REXML::XPath.first(xml, "//Response")

  root.elements.to_a.each do |node|
    parse_element(response, node)
  end

  response
end
parse_authorization_string(authorization) click to toggle source
# File lib/active_merchant/billing/gateways/data_cash.rb, line 594
def parse_authorization_string(authorization)
  reference, auth_code, ca_reference = authorization.to_s.split(';')
  {:reference => reference, :auth_code => auth_code, :ca_reference => ca_reference}
end
parse_element(response, node) click to toggle source

Parse an xml element

Parameters:

-response: The hash that the values are being returned in
-node: The node that is currently being read

Returns:

  • none (results are stored in the passed hash)

# File lib/active_merchant/billing/gateways/data_cash.rb, line 582
def parse_element(response, node)
  if node.has_elements?
    node.elements.each{|e| parse_element(response, e) }
  else
    response[node.name.underscore.to_sym] = node.text
  end
end