Customer service
866.999.VPAY (8729)

Ruby library

exact4r is a Ruby Gem providing access to our Web Services API allowing for submission of financial transactions via REST, JSON or SOAP.

Set up

First, download and install the Ruby Transaction Processing GEM. 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"

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"

Get info on 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

  # 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

Re-use 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

Rake tasks

  • spec
    Run all test in spec/ folder (default)
  • rdoc
    Generate rdoc html in doc/
  • gem
    Build gem

ColdFusion

Sample ColdFusion code


<!---
       Coldfusion sample for HMAC-MD5 hash generation.
       The hash obtained and the payment data are used in the POST form
(not shown here - see http://kb.e-xact.com/questions.php?questionid=60#exshort for details).

       This is Verified on ColdFusion 8, Developer Edition, on Ubuntu 8.04 / Hardy Heron
--->

<cfoutput>

<!---set the fields required.
 note utc time (x_fp_timestamp) is a time in seconds since Jan 1 1970 based on GMT timezone
--->

       <cfset x_fp_timestamp           = "1219853058">
       <cfset x_transaction_key        = "PLEASE REPLACE WITH CURRENT TRANSACTION KEY">
       <cfset x_login                  = "WSP-TEST-01-01">
       <cfset x_amount                 = "30">
       <cfset x_currency_code          = "CAD">
       <cfset x_line_items             = "">
       <cfset x_fp_sequence            = "344155">
       <cfset x_invoice_num            = "123">

<!---a number of the fields are strung together and then hashed into a
new hash field that is submitted in place of the password.  This way
the password and merchant account are never both submitted --->

       <cfset hmac_data        = x_login>
       <cfset hmac_data        = hmac_data &#038; "^" &#038; x_fp_sequence>
       <cfset hmac_data        = hmac_data &#038; "^" &#038; x_fp_timestamp>
       <cfset hmac_data        = hmac_data &#038; "^" &#038; x_amount>
       <cfset hmac_data        = hmac_data &#038; "^" &#038; x_currency_code>

<!---now hash this data string with the transaction key --->
<cfset x_fp_hash = java_hmac(x_transaction_key, hmac_data)>
<h2>Hash obtained </h2>
<ul>
<b> #x_fp_hash# </b>
</ul>

</cfoutput>

<cffunction name="java_hmac" returntype="string" access="public" output="false">
  <cfargument name="signKey" type="string" required="true" />
  <cfargument name="signMessage" type="string" required="true" />

  <cfset var jMsg = JavaCast("string",arguments.
signMessage).getBytes("UTF8") />
  <cfset var jKey = JavaCast("string",arguments.signKey).getBytes("UTF8") />

  <cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec") />
  <cfset var mac = createObject("java","javax.crypto.Mac") />

  <cfset key = key.init(jKey,"HmacMD5") />

  <cfset mac = mac.getInstance(key.getAlgorithm()) />
  <cfset mac.init(key) />
  <cfset mac.update(jMsg) />

  <cfreturn LCase(BinaryEncode(mac.doFinal(), 'Hex')) />
</cffunction>


JAVA client library

Getting started

You can use a java client library called exact4j to process transactions in a java environment quickly and easily.

  1. Download the core from java.net
  2. Review the sample code below and create the needed code to test transactions.

Use the following test credentials:

ExactID = A00049-01
Password = test1

Purchase

final Transporter trans = new Transporter("https://api.e-xact.com", null);
final Request request = new Request(TransactionType.Purchase);
//required fields
request.setExactId(exactID);
request.setPassword(password);
request.setAmount(dollarAmount);
request.setCardholderName(cardHoldersName);
request.setCardNumber(card_Number);
request.setCardExpiryDate(expiry_Date); //MMYY format

//optional fields
request.setUserName(userName);
request.setClientEmail(client_Email);
request.setReference3(reference_3);
request.setCustomerRef(customer_Ref);
request.setReferenceNo(reference_No);
request.setLanguage(com.exact.ews.transaction.enums.Language.English);

try {
    resp = trans.submit(request);
} catch (Exception e) {
    e.printStackTrace();
    System.out.println("Submitting purchase failed");
}

System.out.println(resp.getExactResponseCode());

Refund

final Transporter trans = new Transporter("https://api.e-xact.com", null);
final Request request = new Request(TransactionType.Refund);

//required fields
request.setExactId(exactID);
request.setPassword(password);
request.setAmount(dollarAmount);
request.setCardholderName(cardHoldersName);
request.setCardNumber(card_Number);
request.setCardExpiryDate(expiry_Date); //MMYY format

request.setUserName(userName);
request.setClientEmail(client_Email);
request.setReference3(reference_3);
request.setCustomerRef(customer_Ref);
request.setReferenceNo(reference_No);
request.setLanguage(com.exact.ews.transaction.enums.Language.English);

try {
    resp = trans.submit(request);
} catch (Exception e) {
    e.printStackTrace();
    System.out.println("Submitting refund failed");
}

System.out.println(resp.getExactResponseCode());

Pre-Authorization

final Transporter trans = new Transporter("https://api.e-xact.com", null);
final Request request = new Request(TransactionType.PreAuth);

//required fields
request.setExactId(exactID);
request.setPassword(password);
request.setAmount(dollarAmount);
request.setCardholderName(cardHoldersName);
request.setCardNumber(card_Number);
request.setCardExpiryDate(expiry_Date); //MMYY format

request.setUserName(userName);
request.setClientEmail(client_Email);
request.setReference3(reference_3);
request.setCustomerRef(customer_Ref);
request.setReferenceNo(reference_No);
request.setLanguage(com.exact.ews.transaction.enums.Language.English);

try {     resp = trans.submit(request);
} catch (Exception e) {     e.printStackTrace();
    System.out.println("Submitting preauth failed");
}

System.out.println(resp.getExactResponseCode());
System.out.println("Authorization num: " + resp.getRequest().getAuthorizationNum());

Pre-Authorization completion

if (authNum == null) {
throw new IllegalArgumentException("Exception - authNum nil while trying completion");
}

//preauth-completion
final Transporter trans = new Transporter("https://api.e-xact.com", null);
final Request request = new Request(TransactionType.PreAuthCompletion);

//required fields
request.setExactId(exactID);
request.setPassword(password);
request.setAmount(dollarAmount);
request.setCardholderName(cardHoldersName);
request.setCardNumber(card_Number);
request.setCardExpiryDate(expiry_Date); //MMYY format
request.setAuthorizationNum(authNum);

request.setUserName(userName);
request.setClientEmail(client_Email);
request.setReference3(reference_3);
request.setCustomerRef(customer_Ref);
request.setReferenceNo(reference_No);
request.setLanguage(com.exact.ews.transaction.enums.Language.English);

try {
    resp = trans.submit(request);
} catch (Exception e) {
    e.printStackTrace();
    System.out.println("Submitting preauth completion failed");
}

System.out.println(resp.getExactResponseCode());
System.out.println("Authorization num: " + resp.getRequest().getAuthorizationNum());

PHP hosted payment pages

Sample PHP code


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>
      E-xact Transactions: Websecure Payment Form Example - php
    </title>
  </head>
  <body>

    <a href="http://www.e-xact.com"><img style="border: none" alt="E-xact Powered" /
src="http://e-xact.com/wp-content/themes/orange/images/E-xact_Logo_Blue.png" title="E-xact Powered"></a>
<h1>
    E-xact Transactions: Websecure Payment Form Example - php
  </h1>


  Disclaimer: this sample program is meant for guidance. There are no warranties about its functionality.
  


    Click the "Pay" button to submit a test request to https://checkout.e-xact.com/pay.
  
<form action="https://checkout.e-xact.com/pay" method="POST">

<?
      // Use mhash function to compute the hash.
      function hmac($key, $data) {
       return (bin2hex (mhash(MHASH_MD5, $data, $key)));
      }

      // If loading this page results in an error:
      //
      //    "Fatal error: Call to undefined function: mhash() in ....."
      //
      // this means that the php installation does not provide the mhash function to compute the HMAC digest
      // Then rename this method to hmac, and comment out the hmac function above
      // If the error doesn't occur, simply delete the following method
      function hmac_when_mhash_is_not_available($key, $data)
      {
         // RFC 2104 HMAC implementation for php to compute the MD5 HMAC.
         // Credit: Lance Rushing - http://www.php.net/manual/en/function.mhash.php

         $b = 64; // byte length for MD5
         if (strlen($key) > $b) {
             $key = pack("H*",md5($key));
         }
         $key  = str_pad($key, $b, chr(0x00));
         $ipad = str_pad('', $b, chr(0x36));
         $opad = str_pad('', $b, chr(0x5c));
         $k_ipad = $key ^ $ipad ;
         $k_opad = $key ^ $opad;

         return md5($k_opad  . pack("H*",md5($k_ipad . $data)));
      }

      $x_login = "WSP-#####-##";  //  Take from Payment Page ID in Payment Pages interface
      $transaction_key = "########################"; // Take from Payment Pages configuration interface
      $x_amount = "595.99";
      $x_currency_code = "USD"; // Needs to agree with the currency of the payment page
      srand(time()); // initialize random generator for x_fp_sequence
      $x_fp_sequence = rand(1000, 100000) + 123456;
      $x_fp_timestamp = time(); // needs to be in UTC. Make sure webserver produces UTC

      // The values that contribute to x_fp_hash
      $hmac_data = $x_login . "^" . $x_fp_sequence . "^" . $x_fp_timestamp . "^" . $x_amount . "^" . /
$x_currency_code;
      $x_fp_hash = hmac($transaction_key, $hmac_data);

      echo ('
<input type="hidden" name="x_login" value="' . $x_login . '">' );
      echo ('
<input type="hidden" name="x_amount" value="' . $x_amount . '">' );
      echo ('
<input type="hidden" name="x_fp_sequence" value="' . $x_fp_sequence . '">' );
      echo ('
<input type="hidden" name="x_fp_timestamp" value="' . $x_fp_timestamp . '">' );
      echo ('
<input type="hidden" name="x_fp_hash" value="' . $x_fp_hash . '">' );
      echo ('
<input type="hidden" name="x_currency_code" value="' . $x_currency_code . '">');
?>
<input type="hidden" name="x_show_form" value="PAYMENT_FORM">
<input type="hidden" name="x_test_request" value="TRUE">
<input type="hidden" name="x_line_item" value="1<|>Photo Plus Camera<|>Photo Plus Camera, 1 Year /
Warranty<|>1<|>595.99<|>NO">
<input type="submit" value="Pay with E-xact Transactions">
    </form>

  </body>
</html>


Add payment processing to your PHP application

Processing credit card payments with your PHP application and VersaPay is easy! To process a transaction with your PHP application, review the sample code:

Sample PHP code


<?php
/**
*
* A PHP server is required for this sample code and can be downloaded from http://www.php.net
* PHP 5.1.2 was used for this code.
*
* PHP Extensions required:
*		php_openssl.dll 		- allows the use of https connections
*								- required files:
*									libeay32.dll	- included in the PHP 5.1.2 package
*									ssleay32.dll	- inlcuded in the PHP 5.1.2 package
*		php_openssl.dll should be inside the 'ext' directory under the PHP installation directory and the required
*		dependancies are in the root of the PHP installation directory.
* 		The dependencies should be placed in a directory which is part of the windows path or placed in the 'system32' of
*		the Windows installation directory.
*		php_openssl.dll extension should be enabled in the PHP.ini file used to setup the PHP server.
*
*		php_soap.dll			- allows the soap communication with the transaction server.
*
*		php_soap.dll should be inside the 'ext' directory under the PHP installation directory.
*		php_soap.dll extension should be enabled in the PHP.ini file used to setup the PHP server.
*
* For setup of PHP server and activation of PHP extensions please refer to the installation manual included in the
* PHP 5.1.2 package download.
**/

$trxnProperties = array(
  "Secure_AuthResult"=>"",
  "Ecommerce_Flag"=>"",
  "XID"=>"",
  "ExactID"=>$_POST["ddlPOS_ExactID"],
//Test Gateway Username CAD="A00049-01"
  "CAVV"=>"",
  "Password"=>"test1",
//Test Gateway Password CAD="test1"
  "CAVV_Algorithm"=>"",
  "Transaction_Type"=>$_POST["ddlPOS_Transaction_Type"],
//Transaction Code I.E. Purchase="00" Pre-Authorization="01" etc.
  "Reference_No"=>$_POST["tbPOS_Reference_No"],
  "Customer_Ref"=>$_POST["tbPOS_Customer_Ref"],
  "Reference_3"=>$_POST["tbPOS_Reference_3"],
  "Client_IP"=>"",
//This value is only used for fraud investigation.
  "Client_Email"=>$_POST["tb_Client_Email"],
//This value is only used for fraud investigation.
  "Language"=>$_POST["ddlPOS_Language"],
//English="en" French="fr"
  "Card_Number"=>$_POST["tbPOS_Card_Number"],
//For Testing, Use Test#s VISA="4111111111111111" MasterCard="5500000000000004" etc.
  "Expiry_Date"=>$_POST["ddlPOS_Expiry_Date_Month"] . $_POST["ddlPOS_Expiry_Date_Year"],
//This value should be in the format MM/YY.
  "CardHoldersName"=>$_POST["tbPOS_CardHoldersName"],
  "Track1"=>"",
  "Track2"=>"",
  "Authorization_Num"=>$_POST["tbPOS_Authorization_Num"],
  "Transaction_Tag"=>$_POST["tbPOS_Transaction_Tag"],
  "DollarAmount"=>$_POST["tbPOS_DollarAmount"],
  "VerificationStr1"=>$_POST["tbPOS_VerificationStr1"],
  "VerificationStr2"=>"",
  "CVD_Presence_Ind"=>"",
  "Secure_AuthRequired"=>"",

  // Level 2 fields
  "ZipCode"=>$_POST["tbPOS_ZipCode"],
  "Tax1Amount"=>$_POST["tbPOS_Tax1Amount"],
  "Tax1Number"=>$_POST["tbPOS_Tax1Number"],
  "Tax2Amount"=>$_POST["tbPOS_Tax2Amount"],
  "Tax2Number"=>$_POST["tbPOS_Tax2Number"],

  "SurchargeAmount"=>$_POST["tbPOS_SurchargeAmount"],
//Used for debit transactions only
  "PAN"=>$_POST["tbPOS_PAN"]
//Used for debit transactions only
  );

$trxn = array("Transaction"=>$trxnProperties);

$client = new SoapClient
("https://secure2.e-xact.com/vplug-in/transaction/rpc-enc/service.asmx?wsdl");
$trxnResult = $client->__soapCall('SendAndCommit', $trxn);

if($client->fault){
    // there was a fault, inform
    print "<B>FAULT:  Code: {$client->faultcode} <BR />";
    print "String: {$client->faultstring} </B>";
    $trxnResult["CTR"] = "There was an error while processing. No TRANSACTION DATA IN CTR!";
}
//Uncomment the following commented code to display the full results.

echo "<H3><U>Transaction Properties BEFORE Processing</U></H3>";
echo "<TABLE border='0'>\n";
echo " <TR><TD><B>Property</B></TD><TD><B>Value</B></TD></TR>\n";
foreach($trxnProperties as $key=>$value){
    echo " <TR><TD>$key</TD><TD>:$value</TD></TR>\n";
}
echo "</TABLE>\n";

echo "<H3><U>Transaction Properties AFTER Processing</U></H3>";
echo "<TABLE border='0'>\n";
echo " <TR><TD><B>Property</B></TD><TD><B>Value</B></TD></TR>\n";
foreach($trxnResult as $key=>$value){
    $value = nl2br($value);
    echo " <TR><TD valign='top'>$key</TD><TD>:$value</TD></TR>\n";
}
echo "</TABLE>\n";

// kill object
unset($client);
?>

Integrate a C# .NET web application

Integration options

  1. SOAP Integration: This is our preferred method of integration as it is purely based on web standards. We have a SOAP compliant Web Service that accepts HTTP POSTS as per the API available here.
  2. .NET Component: This is the preferred method for C# applications but is more time consuming and takes about 10 hours. The instructions for this are available at http://download.chasepaymentech.com
  3. The hosted checkout page: This is the simplest integration and should take 1-3 hours.

How hosted checkout works:

Instructions of how to integrate hosted checkout into your application:


Sample code for generating the hash for HCO using C#

To generate x_fp_hash using C#, please see the snippet below:

Sample code for generating the hash for HCO using C#

To generate x_fp_hash using C#, please see the snippet below: 

using System;
using System.Security;
using System.Security.Cryptography;
using System.Text;

class CalculateHash {

 static void Main() {
   StringBuilder sb = new StringBuilder();
   // x_login^x_fp_sequence^x_fp_timestamp^x_amount^x_currency
   String x_login = "WSP-ACTIV-70";
   String x_fp_sequence = "123";
   String x_fp_timestamp = "1228774539";
   String x_amount = "100.00";
   String x_currency = ""; // default empty

   sb.Append(x_login)
     .Append("^")
     .Append(x_fp_sequence)
     .Append("^")
     .Append(x_fp_timestamp)
     .Append("^")
     .Append(x_amount)
     .Append("^")
     .Append(x_currency);

   // Convert string to array of bytes.
   byte[] data = Encoding.UTF8.GetBytes(sb.ToString());

   // key
   byte[] key =  Encoding.UTF8.GetBytes("V0WX5fK~o6eEhr7hbs3ZeyxS");

   // Create HMAC-MD5 Algorithm;
   HMACMD5 hmac = new HMACMD5(key);

   // Compute hash.
   byte[] hashBytes = hmac.ComputeHash(data);

   // Convert to HEX string.
   String  x_fp_hash = System.BitConverter.ToString(hashBytes).Replace("-", "");

   String msg = String.Format("x_login = {0}, x_fp_sequence = {1}, x_fp_timestamp = {2},
   x_amount = {3}, x_currency= {4}.\n x_fp_hash = {5}", x_login, x_fp_sequence,
   x_fp_timestamp, x_amount, x_currency, x_fp_hash);
   System.Console.WriteLine(msg);

 }
}

  • Payment processing products

    Move money with our electronic funds transfer service and credit card processing products.

    Learn more about our payment processing products

    Products

  • Profit Magazine ranks VersaPay No. 1

    We’re honored to be ranked number 1 on Profit Magazine’s PROFIT HOT…
    Continue reading