exact4r

A gem which provides access to E-xact’s Web Services API, allowing the submission of financial transactions via REST, JSON or SOAP.

Getting Started

To submit requests to our transaction processing service, you must first have a Gateway ID, and a password. Test logins are as follows:

Account 1:  :gateway_id => "A00049-01", :password => "test1"
Account 2:  :gateway_id => "A00427-01", :password => "testus"

1. Submit a transaction

require 'rubygems'
require 'exact4r'

# build a purchase request
request = EWS::Transaction::Request.new({
  :transaction_type => :purchase,
  :amount => 10.50,
  :cardholder_name => "Simon Brown",
  :cc_number => "4111111111111111",
  :cc_expiry => "1012",             # MUST be MMYY format
  :gateway_id => "XXXXXXX",         # which gateway to submit the request to
  :password => "YYYYYY"             # your password for that gateway
})

transporter = EWS::Transporter.new
response = transporter.submit(request)  # submits using REST (XML) by default

# submit using JSON, or
response = transporter.submit(request, :json)

# submit using SOAP, or
response = transporter.submit(request, :soap)

# submit explicitly via REST
response = transporter.submit(request, :rest)

# The response object is independent of type of transport chosen.
# We decode the payload into a regular object
response.transaction_tag    # 1234
response.exact_resp_code    # "00"
response.exact_message      # "Transaction Normal"
response.bank_resp_code     # "00"
response.bank_message       # "APPROVED"

2. Find information on an existing transaction

require 'rubygems'
require 'exact4r'

# build a purchase request
request = EWS::Transaction::Request.new({
  :transaction_type => :purchase,
  :amount => 10.50,
  :cardholder_name => "Simon Brown",
  :cc_number => "4111111111111111",
  :cc_expiry => "1012",             # MUST be MMYY format
  :gateway_id => "XXXXXXX",         # which gateway to submit the request to
  :password => "YYYYYY"             # your password for that gateway
})

transporter = EWS::Transporter.new
response = transporter.submit(request)  # submits using REST (XML) by default

# you need to know the transaction tag of the transaction you are looking for
find_request = EWS::Transaction::Request.new({
  :transaction_type => :transaction_details,
  :transaction_tag => response.transaction_tag,
  :gateway_id => "XXXXXXX",
  :password => "YYYYYY"
})

find_response = transporter.submit(find_request, :json)  # again, can choose your transport type as before
find_response.cc_number          # 4111111111111111
find_response.amount             # 10.50

3. Re-using a Transporter

require 'rubygems'
require 'exact4r'

# The transporter object can be re-used across multiple transactions, so set it up once
# and forget about it.
# In this example, we will continue to use E-xact's default web-service URL, but we
# will specify a default transport_type of :soap
transporter = EWS::Transporter.new("https://api.e-xact.com/", {:transaction_type => :soap})

# now let's submit do a recurring seed purchase...
rsp_req = EWS::Transaction::Request.new({
  :transaction_type => :recurring_seed_purchase,
  :amount => 12.00,
  :cardholder_name => "Simon Brown",
  :cc_number => "4111111111111111",
  :cc_expiry => "1012",
  :gateway_id => "XXXXXX",
  :password => "YYYYYY"
})

rsp_resp = transporter.submit(rsp_req)
raise "Seed Purchase failed" unless rsp_resp.approved?

# ...then do multiple refunds against it
1.upto(10) do
  rf_req = EWS::Transaction::Request.new({
    :transaction_type => :tagged_refund,
    :transaction_tag => rsp_resp.transaction_tag,   # need to know which transaction we're refunding against...
    :authorization_num => rsp_resp.authorization_num,           # and its authorization_num
    :amount => 1.00,                                # refund a dollar at a time  
    :gateway_id => "XXXXXX",
    :password => "YYYYYY"
  })
  rf_resp = transporter.submit(rf_req)
  raise "Refund failed: #{rf_resp.exact_resp_code}, #{rf_resp.exact_message}" unless rf_resp.approved?
end

4. Using the AVS API

Allowable AVS params are:

  • :avs_street_address => “7501ELMST.”

  • :avs_unit_no => “801”

  • :avs_po_box => nil # P.O. Box or street address may be specified, but not both

  • :avs_postal_code => “90210”

  • :avs_test_flag => “X” # AVS test flag (optional)

Test Flags

In order to simulate an AVS response in the test environment, set the :avs_test_flag to the AVS result code you would like returned. The AVS result is a one-character response that indicates the degree of match for the provided address. The following AVS responses are currently supported:

North American Response Codes

AVS Code - ABS Definition - Explanation
  • X - Exact match, 9 digit zip - Street Address, and 9 digit ZIP Code match

  • Y - Exact match, 5 digit zip - Street Address, and 5 digit ZIP Code match

  • A - Partial match - Street Address matches, ZIP Code does not

  • W - Partial match - ZIP Code matches, Street Address does not

  • Z - Partial match - 5 digit ZIP Code match only

  • N - No match - No Address or ZIP Code match

  • U - Unavailable - Address information is unavailable for that account number, or the card issuer does not support

  • G - Service Not supported, non-US Issuer does not participate

  • R - Retry - Issuer system unavailable, retry later

  • E - Not a mail or phone order

  • S - Service not supported

International Response Codes

AVS Code - ABS Definition and Explanation
  • G - Global non-AVS participant

  • B - Address matches only

  • C - Address and Postal Code do not match

  • D - Address and Postal Code match

  • F - Address and Postal Code match (UK only)

  • I - Address information not verified for international transaction

  • M - Address and Postal Code match

  • P - Postal Code matches only

Code Sample

avs_params = {
  :avs_test_flag => 'N', 
  :avs_street_address => '123BROWNSTREET',
  :avs_unit_no => '4,
  :avs_po_box => nil,
  :avs_postal_code => '902101234'
}

tx_params = {
  :transaction_type => :purchase,
  :amount => 10.50,
  :cardholder_name => "Simon Brown",
  :cc_number => "4111111111111111",
  :cc_expiry => "1012",
  :gateway_id => "XXXXXXX",
  :password => "YYYYYY"
}.merge(avs_params)

request = EWS::Transaction::Request.new(tx_params)

transporter = EWS::Transporter.new("https://api.e-xact.com/")
response = transporter.submit(request)

response.cc_verification_str1.should == "N123BROWNSTREET4902101234"
response.avs.should == N