Introduction

Document Overview

This document describes how to integrate your website with the SALT Credit Card API. This document provides a step-by-step guide to completing the integration process as well as information on test and configuration tools available to you.


Abbreviations, Definitions, and Acronyms

The following is a list of abbreviations, acronyms, and terms that are used throughout this document:

Abbreviations, Definitions, and Acronyms
Term Definition
API Application Programming Interface
Approval (or Authorization) Code Code obtained from the credit card processing network that is required to complete any credit card transaction. Note that the Approval/Authorization code is not a guarantee of acceptance or payment of a transaction. Receipt of an approval/authorization code does not mean that the merchant will not receive a chargeback for that transaction.
CVV2 (a.k.a. CVD) Card Verification Value. A three or four digit code which is printed on a credit card, but which is not a part of the card number.
Elavon Company providing access to the credit card payment processing network, c/o SALT.
HTML Hyper Text Markup Language
HTTPS Secure Hyper Text Transfer Protocol
Issuer A Bank/Financial Institution issuing credit cards
SSL Secure Sockets Layer

Credit Card API Workflow

To get a better understanding of what is involved in the integration process, you should first understand the workflow of the SALT Credit Card API.

The SALT Credit Card API Solution workflow consists of four phases, as illustrated in the following diagram:

  1. When the customer is ready to checkout and pay for their order, you collect the customer credit card information on your website.
  2. You then obtain approval for the payment by invoking the SALT API with the customer credit card information.
  3. SALT API Handler will process the request through the credit card network. The result of the payment approval will be returned to you from the SALT API.
  4. You generate and display a receipt to the customer.

Integration At-a-Glance

At-a-glance, the process of integrating with the Credit Card API consists of the following steps:

Step Description
1) SALT Sandbox Environment Accessing/familiarizing yourself with the SALT Sandbox environment.
2) Working with the SALT API Writing the HTML POST that will allow you to send transactions to the SALT Payment Handler.
3) Working with Receipts Writing HTML/web scripting code to display the receipt from transaction data returned by the API.
4) Certification Working with SALT to ensure that your completed web application meets the requirements set out by Elavon for any merchant using credit card payment processing.
5) Going into Production Moving from the Sandbox environment to the production environment.

The SALT Sandbox Environment

The SALT Sandbox Environment is a environment mirroring the production environment that allows you to perform testing and integration before going into production.

If you don't yet have a Sandbox account, you can create one by following the link below!

Create a SALT Sandbox Account

SALT Sandbox Environment
URL Description
SALT Merchant Management Website https://test.saltpayments.com/merchantmanagement/ Allows you to perform administrative tasks such as viewing transaction activity and configuring your services.
SALT Payment Gateway https://test.saltpayments.com/gateway/creditcard/processor.do Receives Credit Card API requests

The SALT Merchant Management Console requires a login, which consists of a Username and Password set by you when creating your Sandbox account. You can change your password at any time.


Finding Your Merchant Credentials

In order to process payments through your Sandbox account, you will need to retrieve your Sandbox Merchant Credentials - merchantId and apiToken. To find your credentials:

  1. Login to the SALT Sandbox Merchant Management Console at https://test.saltpayments.com/merchantmanagement/
  2. Click the 'Services' link in the main menu. A list of all of your services will be displayed.
  3. Click the Service to view your merchantId and apiToken.

Working With the SALT Core API

You will need to use the SALT Credit Card API to perform credit card transactions.

Client Library

Before working with the SALT Core API, ensure that you have downloaded the client library file to your computer. The Core API consists of a single package package com.salt.payment.client.creditcard.api with two main classes:

  • HttpsCreditCardService - Calls the SALT Payment Gateway to process credit card transactions, such as purchases, voids, and refunds.
  • CreditCardReceipt - A container class for the HttpsCreditCardService method response.

These classes and their methods will be described in full in the following sections.

IMPORTANT: This document discusses development using the Java version of the Core API. For examples using other languages, including Microsoft .NET and PHP, please see the Appendix.

The HttpsCreditCardService

To process a credit card transaction, you will need to construct an instance of the HttpsCreditCardService class as follows:

Core API: HttpsCreditCardService Constructor
HttpsCreditCardService(merchant, url)
Name Type Description
merchant Merchant Contains your merchant credentials. See Table 3.2.
url String(255) URL to the SALT Core API handler. In the environment this ishttps://test.saltpayments.com/gateway/creditcard/processor.do
NOTE: If you are using the HttpsCreditCardService from API versions 1.3.1 or older, the old constructors are still supported but are now considered deprecated.
Core API: Merchant Constructor
Merchant(merchantId, apiToken [, storeId])
Name Type Description
merchantId Integer Merchant ID as assigned to you by SALT (can check this in the Merchant Management Website).
apiToken String(20) API Token as assigned to you by SALT (can check this in the Merchant Management Website)
storeId
OPTIONAL
String(50) Store ID field that can be used to identify/group transactions. Optional field.

After you have created a new instance of HttpsCreditCardService, you can use it to process transactions.


Purchase

To perform a credit card purchase you will invoke the singlePurchase() method:

Core API: HttpsCreditCardService.singlePurchase() Method
HttpsCreditCardService.singlePurchase(orderId, creditCard, amount, verificationRequest)
Name Type Description
orderId String(32) Merchant assigned orderId. Must be unique.
creditCard CreditCard Credit Card information (see Table 3.4)
amount Long Amount of the purchase in cents. Do NOT include a $ or any decimal place. (e.g. if your purchase is $10.00, then send 1000 as the total).
verificationRequest VerificationRequest Credit Card Verification request information, null if not used. See Section 5 for details on how to use this field.
Returns:
CreditCardReceipt The results of the purchase request

The customer credit card information is submitted using the data object CreditCard. The basic constructor is shown below.

CreditCard Class (Basic Constructor)
CreditCard Constructor Parameters
Name Type Description
creditCardNumber Long Credit Card Number
expiryDate Short Credit Card Expiry Date in MMYY format

To use advanced features such as Address Verification System and CVV, you will have to use the full constructor that provides additional fields. See Section 5.1 for details.

The CreditCardReceipt object contains the results of the Purchase:

Core API: CreditCardReceipt Class
CreditCardReceipt
Field Type Description
getApprovalInfo() ApprovalInfo Transaction approval information
getAvsResponse() AvsResponse The AVS response from processing the purchase, or null if AVS was not enabled or no response. See Section 5
getCardBrand() Integer

Returns the brand of the credit card, as a number:

1=Visa, 2=MasterCard, 3=AMEX, 4=Discover, 5=Diners, 6=JCB, 7=Other

getCvv2Response() Cvv2Response The CVV2 response from processing the purchase, or null if CVV2 was not enabled or no response. See Section 5
getDebugMessage() String(255) Debug message, if applicable
getErrorCode() String(128) Error code, if applicable
getErrorMessage() String(255) Error message, if applicable
getOrderId() String(32) Merchant-assigned orderId
getPeriodicPurchaseInfo() PeriodicPurchaseInfo Information about the periodic purchase, if this was a periodic purchase transaction
getProcessedDateTime() Date Date/time when the transaction was processed
getSanitizedCardNumber() String(20) Storage/display-safe version of the credit card number. E.g. 424242****4242
getTransactionId() Long SALT TransactionId for this transaction
isApproved() Boolean Returns true if the request was approved, otherwise the request was declined due to some error.

The ApprovalInfo object contains the transaction approval information of the Transaction:

Core API: ApprovalInfo Class
ApprovalInfo
Field Type Description
getApprovalCode() String Credit Card Approval Code
getAuthorizedAmount() Long Amount authorized on approval, in cents
getReferenceNumber() Integer Credit Card approval Reference Number
getTraceNumber() Integer Credit Card approval Trace Number

Void and Refund

You may need to void or refund a purchase made by a customer from time to time. You can do this programmatically through the Core API (see below) but if you don't need/want to, you can perform refunds manually through the Merchant Management Website.

What is a Void? What is a Refund?

Void
Cancels a transaction, preventing it from being settled. A Void can only be performed on a transaction belonging to the current batch, before the current batch is closed (i.e. before the end of day).
Refund
Returns funds from a previously settled purchase to the customer. Refunds can only be performed on a purchase that is part of an already-closed batch.

Core API: HttpsCreditCardService.voidTransaction() Method
HttpsCreditCardService.voidTransaction(transactionId, transactionOrderId)
Name Type Description
transactionId Long The SALT transactionId of the transaction to void
transactionOrderId String(32) The orderId previously assigned to the transaction that is to be voided. This is an extra check to prevent inadvertent voiding of a transaction. Not null.
Returns:
CreditCardReceipt The results of the void request
Core API: HttpsCreditCardService.refund() Method
HttpsCreditCardService.refund(purchaseId, purchaseOrderId, refundOrderId, amount)
Name Type Description
purchaseId Long The SALT transactionId of the purchase to void
purchaseOrderId String(32)

The order id previously assigned to the purchase that is to be refunded. This is an extra check to prevent inadvertent refunding of a purchase. Not null.

refundOrderId String(32) The merchant assigned orderId to be attached to this refund request. Will be generated if null.
amount Long

Amount to refund in cents. Do NOT include a $ or any decimal place. (e.g. if your purchase is $10.00, then send 1000 as the total). This value does NOT have to match the original purchase amount.

Returns:
CreditCardReceipt The results of the Refund Request

The CreditCardReceipt object is the same as is described in Section 3.3.

Void/Refund Notes and Restrictions

Credit Card Void and Refund operations are subject to the following restrictions/conditions:

  • Only transactions belonging to a batch that has not yet been closed may be voided. Once a batch has closed, you may only refund that transaction. Conversely transactions belonging to a batch that has not yet been closed may not be refunded.
  • You may only Refund/Void a Purchase that has been approved successfully. Any declined/erroneous/cancelled Purchases cannot be refunded or voided.
  • You may perform multiple refunds against a given Purchase (example scenario: the customer incrementally returns parts of their order, and you refund the cost of each increment when it is received)
  • You can void a refund request, providing it belongs to a batch that has not yet been closed.

Manual Void/Refund Using the Merchant Management Website

If you do not need/want to perform Void/Refund operations programmatically, you can always perform them manually using the Merchant Management Website:

  1. Login to the SALT Merchant Management Website at https://test.saltpayments.com/merchantmanagement/
  2. Select the Void/Refund link under the Terminal section.
  3. Search for the Purchase transaction that you wish to void/refund (by date, Store ID, etc)
  4. When you find the transaction to void/refund, press the void or refund button
  5. If you are performing a Refund, you will be asked to enter the amount to refund (the default is the original purchase amount).
  6. Press the Submit Void or Submit Refund button.

Periodic/Recurring Payments

You can use SALT Periodic Purchase features when the customer is billed periodically, or when splitting payment into a number of separate payments.

Creating a Recurring Payment

In the API version 1.4 and below, calling recurringPurchase() will automatically create, verify and process the transaction. However, starting in 2.0, recurringPurchase() will only create and verify the transaction. The funds are not immediately captured from the customer credit card until executeRecurringPurchase() is explicitly called.

You can set up a customer for recurring billing by using the recurringPurchase() method:

Core API: HttpsCreditCardService.recurringPurchase() Method
HttpsCreditCardService.recurringPurchase(periodicPurchaseInfo, creditCard, storageTokenId, verificationRequest)
Name Type Description
periodicPurchaseInfo PeriodicPurchaseInfo Defines periodic-specific information, such as schedule, dates, and customer ID. See Table 3.10.
creditCard CreditCard Credit Card information (see Table 3.4). If storageTokenId is provided, this will be ignored
storageTokenId String Storage Token ID specifying the stored credit card to use for this purchase. Takes precedence over the creditCard field.
verificationRequest Verification Request Credit Card Verification request information, null if not used. Note that CVV2 will not be stored/used in recurring purchases. See Section 5 for details on how to use this field.
Returns:
CreditCardReceipt The results of the purchase request.

The periodicPurchaseInfo object is constructed as follows:

Core API: PeriodicPurchaseInfo Class (Full Constructor)
PeriodicPurchaseInfo Constructor Parameters
Name Type Description
periodicTransactionId Long SALT recurring purchase ID returned when the purchase was originally created. Not applicable to new recurring purchases
state State

One of IN_PROGRESS, ON_HOLD, CANCELLED. Note a cancelled payment will not be run again and cannot be further modified. Not applicable to new recurring purchases.

schedule Schedule The schedule on which to issue payments. See Table 3.11. If null, will default to monthly payments.
perPaymentAmount Long

Per-payment amount of the in cents. Do NOT include a $ or any decimal place. (e.g. if your purchase is $10.00, then send 1000 as the total).

orderId String(32) Merchant assigned orderId. Must be unique. Cannot be modified after the first payment has been issued.
customerId String(32) Optional meta field that can be used to describe a customer
startDate Date

The date of when to issue the first payment. If this date is null or in the past, then the first payment will be issued immediately. Cannot be modified after the first payment has been issued.

endDate Date The date of when to end the payments. A payment will not be issued if it falls on this date.
nextPaymentDate Date Change when the next payment will occur. Must be set between the start and end date (as currently defined or as modified by their respective parameters). Not used in a new recurring payment (startDate defines first payment date).
Parameters Outside of the full constructor
ExecutionType enum

Has a value of either MANUAL or AUTO

  • AUTO = the recurring purchase will execute immediately.
  • MANUAL = the recurring purchase will not run unless first explicitly executed via executeRecurringPurchase().

If not provided, will default to MANUAL

setExecutionType(ExecutionType executionType) Sets the execution type to either manual or auto
getExecutionType() ExecutionType Returns the value of the execution type
installmentNumber Integer

The value of the instalment the periodic purchase transaction is on. (e.g. if there are 4 instalments, and the card is charged for the second time, the installmentNumber = 2)

setInstallmentNumber(Integer installmentNumber)
getInstallmentNumber() Integer Returns the installmentNumber

You can define a custom schedule for when to issue recurring payments:

Core API: Schedule Class (Basic Constructor)
Schedule Constructor Parameters
Name Type Description
scheduleType ScheduleType Schedule based on days, weeks, or months (See Table 3.12 ScheduleType Enumeration)
intervalLength Short Payments will be issued every number of days/weeks/months
ScheduleType Enumeration
ScheduleType
Value Description
MONTH Schedule based on months
WEEK Schedule based on weeks
DAY Schedule based on days

So for example, if you create a Schedule using scheduleType = WEEK and intervalLength = 2, then payments will be issued every two weeks.

Executing Recurring Payments

Once a recurring purchase has been successfully created (with recurringPurchase() ), it can be executed by calling the executeRecurringPurchase() method.

HttpsCreditCardService.executeRecurringPurchase() method
HttpsCreditCardService.executeRecurringPurchase(recurringPurchaseId, cvv2)
Name Type Description
recurringPurchaseId Long SALT recurring purchase ID returned when the purchase was originally created.
cvv2 String Card Verification Value/Card Verification Digits. This parameter provides optional verification when performing this transaction
Returns:
CreditCardReceipt The results of the transaction

Managing Recurring Payments

There are additional operations available that you can use to manage your recurring payments.

Putting a Payment on Hold (and Resuming a Payment on Hold)

Putting a hold on a recurring payment means that further payments will be suspended until the recurring payment is resumed. You can resume payments by calling the resumeRecurringPurchase() method.

Core API: HttpsCreditCardService.holdRecurringPurchase() Method
HttpsCreditCardService.holdRecurringPurchase(recurringPurchaseId)
Name Type Description
recurringPurchaseId Long SALT recurring purchase ID returned when the purchase was originally created.
Returns:
CreditCardReceipt The results of the hold
Core API: HttpsCreditCardService.resumeRecurringPurchase() Method
HttpsCreditCardService.resumeRecurringPurchase(recurringPurchaseId)
Name Type Description
recurringPurchaseId Long SALT recurring purchase ID returned when the purchase was originally created.
Returns:
CreditCardReceipt The results of the hold
Cancelling a Payment

You can cancel a payment entirely by calling the cancelRecurringPurchase() method. This means that no further payments will be made regardless of whether the payment has reached its endDate. Note that you cannot resume or otherwise update a cancelled payment.

Core API: HttpsCreditCardService.cancelRecurringPurchase() Method
HttpsCreditCardService.cancelRecurringPurchase(recurringPurchaseId)
Name Type Description
recurringPurchaseId Long SALT recurring purchase ID returned when the purchase was originally created.
Returns:
CreditCardReceipt The results of the cancellation
Updating Recurring Payment Details

To update the payment details of a recurring purchase such as when a customer credit card expires/is changed, you can use the updateRecurringPurchase() method. Note that you cannot update a recurring purchase that has been cancelled or that has completed.

If any parameters provided are null, the existing corresponding fields will not be updated.

Core API: HttpsCreditCardService.updateRecurringPurchase() Method
HttpsCreditCardService.updateRecurringPurchase(periodicPurchaseInfo, creditCard, storageTokenId, verificationRequest)
Name Type Description
periodicPurchaseInfo PeriodicPurchaseInfo Defines periodic-specific information, such as schedule, dates, and customer ID. See Table 3.10.
creditCard CreditCard Credit Card information (see Table 3.4). If storageTokenId is provided, this will be ignored
storageTokenId String(32) Storage Token ID specifying the stored credit card to use for this purchase. Takes precedence over the creditCard field.
verificationRequest VerificationRequest Credit Card Verification request information, null if not used. Note that CVV2 will not be stored/used in recurring purchases. See Section 5 for details on how to use this field.
Returns:
CreditCardReceipt The results of the update request
Miscellaneous

The queryRecurringPurchase() method is a convenience method that you can use to check the current status of a recurring purchase, including the last successful payment made.

Core API: HttpsCreditCardService.queryRecurringPurchase() Method
HttpsCreditCardService.queryRecurringPurchase(recurringPurchaseId)
Name Type Description
recurringPurchaseId Long SALT recurring purchase ID returned when the purchase was originally created.
Returns:
CreditCardReceipt The results of the query retrieve the PeriodicPurchaseInfo field for periodic purchase fields.

The PeriodicPurchaseInfo object contains a subset of the fields from the class:

  • periodicTransactionId the ID when the periodic purchase was originally created
  • state current state of the periodic purchase
  • nextPaymentDate next date the payment will be run
  • lastPaymentId the transaction ID of the last successful payment run. You can use this ID to run a verifyTransaction() to retrieve the transaction information.
Manual Periodic Payments Using the Merchant Management Website

If you do not need/want to manage Periodic Payments programmatically, you can always perform them manually using the Merchant Management Website:

  1. Login to the SALT Merchant Management Website at https://test.saltpayments.com/merchantmanagement/
  2. Select the Periodic Purchases Link under the Terminal section.
  3. You can add a new Periodic Purchase by pressing the add a New Periodic Purchase link
  4. You can view/update existing Periodic Purchases by using the search form (by date, order Id, etc)

Transaction Verification

In certain cases when you are unsure of the results of the transaction, such as when a transaction times out, you may need to double-check its status. You can run the verifyTransaction() method to perform this check. This method returns a receipt containing the results of the transaction.

Core API: HttpsCreditCardService.verifyTransaction() Method
HttpsCreditCardService.verifyTransaction(transactionId, transactionOrderId)
Name Type Description
transactionId Long The SALT transactionId of the transaction to verify
transactionOrderId String(32) The orderId assigned to the transaction.
Returns:
CreditCardReceipt The results of the transaction verification request

You must specify at least one of the transactionId or transactionOrderId arguments.

Note that if the specified transaction cannot be found, you will receive a not-found C111_TRANSACTION_DOES_NOT_EXIST error in the receipt, as opposed to the results of the transaction.


Credit Card Verification

Use the verifyCreditCard() method to check the validity of a credit card without charging the customer (i.e. a $0.00 transaction). A CreditCardReceipt object is returned, containing information about the card validity, Secure Storage information if the card uses Secure Storage and Fraud information if the card uses the Advanced Fraud Suite.

IMPORTANT: American Express currently does not support card verification with a $0.00 value transaction. For Amex cards, you will have to use a small-value singlePurchase() ($1.00 is sufficient) instead.
Core API: HttpsCreditCardService.verifyCreditCard() Method
HttpsCreditCardService.verifyCreditCard(creditCard, verificationRequest)
Name Type Description
creditCard CreditCard Credit Card information (see Table 3.4)
verificationRequest Verification Request Credit Card Verification request information, null if not used. See Section 5 for details on how to use this field.
Returns:
CreditCardReceipt The results of the verifyCreditCard request. (See Table 3.21)

Closing Batches

All batches are closed automatically every night at 12:00 am EST. If for some reason you want to close a batch manually during the day, this may be done by invoking the closeBatch() method. Note that this will NOT prevent the automatic daily batch closure.

HttpsCreditCardService.closeBatch()
Returns:
CreditCardReceipt The results of the batch close

Updating Fraud

Applies only when using the Advanced Fraud Sute. This function allows you to update fraud service with the appropriate credit card authorization status if you are using a non-SALT payment processing service.

Core API: HttpsCreditCardService.updateFraud() Method
HttpsCreditCardService.updateFraud(Long transactionId, String fraudSessionId, String auth)
Name Type Description
transactionId Long Transaction ID number of the transaction whose fraud authentication is being updated. Cannot be null.
fraudSessionId String Fraud Session ID string. Cannot be null. Used to track which merchant is preforming the fraud update.
auth String Auth string. If null, will decline the update request.
Returns:
CreditCardReceipt The results of the fraud update

Receipts

When a transaction has been completed, you must display a receipt to your customer. The following section describes the requirements of a receipt.

What do I need to display in a Receipt?

The required receipt fields listed below include the corresponding CreditCardReceipt field name as returned by SALT (where applicable). Note that there are different fields to be displayed depending on if the transaction was successful or unsuccessful.

In the case of a Successful Transaction, you must display:

  • Your Merchant Name
  • That the transaction was successful? (based on if isApproved() == true)
  • Invoice Number (getOrderId())
  • Amount of the transaction (getApprovalInfo().getAuthorizedAmount() field, be sure to convert back to dollars/cents and also to include currency)
  • Date of the transaction (getProcessedDateTime())
  • Approval Code (getApprovalInfo().getApprovalCode())
  • A button/link allowing the user to print the receipt page
  • Also, optionally:
    • Last 4 digits of the Credit Card Number (never display the entire Credit Card number)
    • A button/link allowing the customer to return to your home page/account page etc

In the case of an Unsuccessful Transaction, you must display:

  • Your Merchant Name
  • That the transaction was unsuccessful?(based on if isApproved() == false)
  • Date of the transaction (getProcessedDateTime())
  • About payment retries:
    • If you allow the customer to try a different payment option (e.g.INTERAC Online) or to retry Credit Card payment, then indicate to the customer that they can retry payment (provide a link to the retry page or display the actual retry options).
    • Otherwise display a clear statement that the order has been cancelled.
  • Also, optionally: Invoice Number (getOrderId())

Do NOT display the Approval Code or Card Number to the customer on an Unsuccessful Transaction.

Example Receipt/Error Pages

An example of an appropriate receipt for a successful transaction is shown below:

An Example Receipt Screen:
Example Receipt Screen

This receipt shows all required information, a print page link, and a return link. You can use this as a reference for the generation of your own receipt.

Below are two examples of an appropriate error page for an unsuccessful transaction:

Example Error Screen With Payment Retry:
Example Unsuccessful Receipt Screen

Example Error Screen With No Payment Retry (Order Cancellation):
Example Unsuccessful Receipt Screen (no retry)


Advanced Core API Features

Credit Card Security Features

To use the Client API Credit Card security features, you will need to use the full constructor for the CreditCard class, which includes additional data fields.

CreditCard Constructor Parameters
Name Type Description
creditCardNumber Long Credit Card Number
expiryDate Short Credit Card Expiry Date
cvv2 String Card Verification Value/Card Verification Digits
street String Cardholder street address
zip String Cardholder zip/postal code
secureCode String Verified by Visa/MasterCard SecureCode value
cardHolderName String Credit Card Holder Name

Card Verification Value (CVV2)

The Card Verification Value (sometimes known as CVV2 or CVN is a security feature for credit card transactions, giving increased protection against credit card fraud. It is a series of digits (3 or 4) that can be usually found on the back of a credit card.

Many card issuers will decline a transaction if the CVV2 is not provided. If the value provided by the customer does not match the value on file with the card issuer, the issuer may decline the transaction (although this is not always the case).

Using CVV2

To use CVV2, you must

  1. Collect and include the CVV2 value as part of the CreditCard object
  2. Create a VerificationRequest with the Cvv2Request parameter set to CVV2_PRESENT.
  3. Call the singlePurchase() method with the VerificationRequest.
Cvv2Request
Value Description Indicator*
CVV2_NOT_SUBMITTED CVV2 value is deliberately bypassed or is not provided by the merchant. 0
CVV2_PRESENT Cardholder states that the CVV2 value is present on the card and can be verified. 1
CVV2_PRESENT_BUT_ILLEGIBLE Cardholder states that the CVV2 value is present on the card but it is illegible. 2
CARD_HAS_NO_CVV2 Cardholder states that the card has no value imprint. 9

* Denotes the indicator digit typically associated with CVV2 verification. Is not needed when using this API, but may be referred to in other documentation.

An example of a singlePurchase() with CVV2 checking is shown below:

import com.salt.payment.client.creditcard.api.*;
:
:
int merchantId=12345; // as assigned by SALT
String apiToken="DNZHRC6dNgppYYzR"; // as assigned by SALT
long pan=4242424242424242L;
short expiry=1212;
String invoice="order-12345"; // merchant invoice/orderId
String cvv2="888"; // CVV2 digits
long amount=3420; // in cents
HttpsCreditCardService ccService = new HttpsCreditCardService(
  new Merchant(merchantId, apiToken),  "https://test.saltpayments.com/gateway/creditcard/processor.do");
// specify additional credit card parameters
CreditCard creditCard = new CreditCard(pan, expiry, cvv2, null, null);
// specify the VerificationRequest contains an AvsRequest and/or Cvv2Request
VerificationRequest verify = new VerificationRequest(
  null,
  Cvv2Request.CVV2_PRESENT,
  );
CreditCardReceipt receipt =
  ccService.singlePurchase(invoice, creditCard, amount, verify);
:
:
// Extract Results from CreditCardReceipt...
:
:
// Verification results from CreditCardReceipt...
Cvv2Response cvv2Response = receipt.getCvv2Response();
:
:

The results of the CVV2 check are returned as a Cvv2Response object as part of the CreditCardReceipt.

Cvv2Response
Field (Accessor) Type Description
getCode() String CVV2 Response Code
getMessage() String CVV2 Response Message

The CVV2 response code will denote a match/mismatch:

Code Description Match
M CVV2 Match Match
N CVV2 No Match

Mismatch

P Not Processed Unknown
S Issuer indicates that CVV2 data should be present on the card, but the merchant has indicated data is not present on the card Unknown
U Issuer has not certified for CVV2 or Issuer has not provided Visa with the CVV2 encryption keys Unknown
<blank> CVV2 was not performed, occurs if you did not provide a cvv2 or an invalid cvv2 value Unknown

Note that if a CVV2 check results in a mismatch or is not supported by the cardholder financial institution, this does NOT necessarily mean that a transaction will be declined. Some financial institutions may decline but others will not. CVV2 gives you additional information on which you can base your decision whether or not to accept the transaction as legitimate . If the financial institution does not decline the transaction, and you choose not to accept the transaction, you must issue a void against it. (See Section 3.4 on how to perform a void)

Address Verification System (AVS)

Address Verification System (AVS) provides additional security by comparing a given billing address against the address on file at the cardholder financial institution. If an AVS check indicates that the address does not fully match, you may have cause to suspect a possibly fraudulent transaction.

The result of an AVS check is a letter code indicating the degree of match, which can be full, partial, or a mismatch. Some financial institutions, in particular those outside the US, Canada, and UK, may not support AVS checking which can result in a corresponding not supportedmresponse code being returned.

Note that if an AVS check results in a mismatch or is not supported by the cardholder financial institution, this does NOT necessarily mean that a transaction will be rejected. AVS only gives you additional information on which you can base your decision whether or not to accept the transaction as legitimate. If you choose not to accept the transaction, you must issue a void against it

Using AVS

To use AVS, you must

  1. Collect and include the customer zip/postal code and address as part of the CreditCard object
  2. Create a VerificationRequest with the AvsRequest parameter set.
  3. Call the singlePurchase() method with the VerificationRequest.
AvsRequest
Value Description
VERIFY_STREET_AND_ZIP Verify that both specified street number & name (combined) and zip/postal code of the cardholder matches the values in the cardholder issuer file.
VERIFY_ZIP_ONLY Verify that specified zip/postal code of the cardholder matches the value in the cardholder issuer file. If this is specified, address will not be verified

An example of a singlePurchase() with AVS checking is shown below:

import com.salt.payment.client.creditcard.api.*;
:
:
int merchantId=12345; // as assigned by SALT
String apiToken="DNZHRC6dNgppYYzR"; // as assigned by SALT
long pan=4242424242424242L;
short expiry=1212;
String invoice="order-12345"; // merchant invoice/orderId
String avsStreet="123 Easy Street"; // AVS Street number and name
String avsZip="A1B2C3"; // AVS ZIP/Postal code
long amount=3420; // in cents
HttpsCreditCardService ccService = new HttpsCreditCardService(
  new Merchant(merchantId, apiToken),  "https://test.saltpayments.com/gateway/creditcard/processor.do");
// specify additional credit card parameters
CreditCard creditCard = new CreditCard(pan, expiry, null, avsStreet, avsZip);
// specify the VerificationRequest contains an AvsRequest and/or Cvv2Request
VerificationRequest verify = new VerificationRequest(
  AvsRequest.VERIFY_STREET_AND_ZIP,
  null
);
CreditCardReceipt receipt =
  ccService.singlePurchase(invoice, creditCard, amount, verify);
:
:
// Extract Results from CreditCardReceipt...
:
:
// Verification results from CreditCardReceipt...
AvsResponse avsResponse = receipt.getAvsResponse();
:
:

The results of the AVS request are returned as an AvsResponse object as part of the CreditCardReceipt.

AvsResponse
Field (Accessor) Type Description
getAvsErrorCode() String The code of the error that prevented AVS from being performed, or null if no error
getAvsErrorMessage() String The message of the error that prevented AVS from being performed, or null if no error
getAvsResponseCode() String The standard alphabetic AVS response code (see Table 5.7)
getZipType() String The type of the zip (either zip or postal code) or null if there was an AVS error
isAvsPerformed() Boolean true if AVS was performed, false if it wasn't
isStreetFormatValid() Boolean true if the street format is valid, false otherwise
isStreetFormatValidAndMatched() Boolean true if the street format is valid and matches
isZipFormatValid() Boolean true if the zip/postal code format is valid, false otherwise
isZipFormatValidAndMatched() Boolean true if the zip/postal code format is valid and matches

The getResponseCode() field indicates: a full match (both address and zip/postal match), a partial match (one field matches), a mismatch (both do not match), or unknown (AVS may be unavailable/unsupported by this cardholder bank).

Code Description Match
A Street address matches, but zip/postal does not (Domestic) Partial
B Street address matches, but postal code not verified (International) Partial
C Street address and postal code do not match (International)

Mismatch

D, M Street address and postal code match (International) Full Match
E AVS data invalid or not allowed for this card type Unknown
G Non-US bank does not support AVS Unknown
I Address not verified Unknown
N Street address and postal code do not match (Domestic)

Mismatch

P Postal code matches, but street address not verified (International) Partial
R System unavailable (Domestic) Unknown
S Bank Does not support AVS (Domestic) Unknown
U Address information unavailable. Returned if the US bank does not support non-US AVS or if the AVS in a US bank is not functioning properly. Unknown
W, Z Street address does not match, but zip code matches (Domestic) Partial
X, Y Street address and zip code match (Domestic) Full Match
<blank> AVS was not performed, occurs if you did not provide a billing address Unknown
Suggestions for Interpreting/Handling an AVS Response

AVS is not a foolproof security feature, so even if a full match is obtained, there is no guarantee that a transaction is not fraudulent. However, a partial, or better yet, full match makes it more likely that whoever is submitting the transaction is the real cardholder (since they have access to the correct address information, which typically only appears the cardholder statement).

Below are some suggestions for the interpretation/handling of AVS responses. Please note that these are just suggestions and the ultimate decision of whether or not to accept a transaction is still up to you. Also remember that if you do not want to accept a transaction, you must void it yourself.

  • Partial Match Typically if the user has one part of the address correct, they probably know the entire address. Of course, a full match is more reassuring, but sometimes a partial match occurs because of differences in the formats of the entered address and the address on file (for example, sometimes the cardholder may enter the unit number before their street number).
  • Mismatch You probably should not accept this transaction without confirming with the cardholder directly.
  • Unknown If the cardholder address is international, you may see this result. If you typically do business with international customers, then this will be expected. Otherwise, you may want to consider whether or not to accept the transaction.

Secure Storage API

With the Secure Storage API, merchants can remotely store credit card and other sensitive customer data with SALT to increase security and reduce the scope of PCI Compliance.

When information is stored with SALT, a Storage Token (which identifies the information in secure storage) is returned in response. This Storage Token can be used for all subsequent transactions including purchases and credit card verification.

Storing Customer Information (Creating a Storage Token)

HttpsCreditCardService.addToStorage(paymentProfile, storageTokenId)
Name Type Description
storageTokenId String(32) Optional. Specifies the identifier (storage token) for the stored information. Must be unique. If not provided, SALT will auto-generate one for you.
paymentProfile PaymentProfile Contains the customer information to be stored. See Table 5.9 for details
Returns:
StorageReceipt The results of the storage request

The PaymentProfile class contains a CreditCard data object as well as a CustomerProfile data object. The basic constructor is shown below.

PaymentProfile Constructor Parameters
Name Type Description
creditCard CreditCard Contains Credit Card information, optional. However, if you intend to run transactions with this PaymentProfile you must provide this field.
customerProfile CustomerProfile Contains Customer information, optional. See Table 5.10 for details

The CreditCard class is described in Table 5.1. Note that CVV2 will not be stored, even if specified.

The CustomerProfile class allows you to store various customer details such as name and address. All fields are completely optional you can choose to store any or all of the following fields:

CustomerProfile
Field Type Description
setFirstName() String Customer first name
setLastName() String Customer last name
setAddress1() String Address 1 (first line of address)
setAddress2() String Address 2 (second line of address)
setCity() String City
setProvince() String Province/State
setPostal() String Postal/ZIP Code
setCountry() String Country
setPhoneNumber() String Customer Phone Number
setFaxNumber() String Customer Fax Number
setWebsite() String Customer website
setLegalName() String Customer Company Legal Name
setTradeName() String Customer Company Trade Name

An example of storing customer data (credit card and customer profile) is shown below:

import com.salt.payment.client.creditcard.api.*;
:
:
int merchantId=12345; // as assigned by SALT
String apiToken="DNZHRC6dNgppYYzR"; // as assigned by SALT
String storageTokenId="myToken-001"; // will be used to identify the storage record
long ccNumber=4242424242424242L; // Credit Card Number
short ccExpiry=1212; // Credit Card Expiry
String firstName="John"; // Customer first name
String lastName="Smith"; // Customer last name
String address1="123 Easy Street"; // Customer address1
String postal="A1B2C3"; // Customer Postal code
String phone="4165551234"; // Customer phone number
HttpsCreditCardService ccService = new HttpsCreditCardService(
    new Merchant(merchantId, apiToken), "https://test.saltpayments.com/gateway/creditcard/processor.do");
// credit card to store
CreditCard creditCard = new CreditCard(ccNumber, ccExpiry);
// customer profile details to store
CustomerProfile customerProfile = new CustomerProfile();
customerProfile.setFirstName(firstName);
customerProfile.setLastName(lastName);
customerProfile.setAddress1(address1);
customerProfile.setPostal(postal);
customerProfile.setPhoneNumber(phone);

// put together data into a payment profile
PaymentProfile paymentProfile = new PaymentProfile(creditCard, customerProfile);

// Store the data under the specified storageTokenId
StorageReceipt receipt =
  ccService.addToStorage(storageTokenId, paymentProfile);
:
:
// Use Results from StorageReceipt...
if (receipt.isApproved()) {
  :
  :
}

The results of the storage request are returned as a StorageReceipt object. This is a data class similar to the CreditCardReceipt, and contains the following fields:

StorageReceipt
Field Type Description
getDebugMessage() String Debug message, if applicable
getErrorCode() String Error code, if applicable
getErrorMessage() String Error message, if applicable
getProcessedDateTime() Date Date/time when the transaction was processed
getPaymentProfile() PaymentProfile Payment profile retrieved or updates (via the storage query or update methods). For creation/deletion, this field is null
getStorageTokenId() String(32) The storageTokenId used. For storage record creation where no storageTokenId was specified, this will contain the value of the SALT-generated storageTokenId.
isApproved() Boolean Returns true if the request was approved, otherwise the request was declined due to some error.

Running a Transaction with a Storage Token

Once you have created a Storage Token, you can use it in place of a CreditCard object in any transaction that requires a credit card. The SALT Gateway will use the storageTokenId to look up the stored credit card information, which in turn will be used in the transaction.

IMPORTANT: Credit card information is required to be stored in order to run transactions with the storage token. If you do not provide this information when creating/updating the storage record (for example, if you are just storing the customer profile), then you will be unable to use that storage token to run a transaction

To use the storageTokenId, all you need to do is call the appropriate Storage Token transaction methods (which are the same as the credit card methods, just replacing the credit card with the token). The Storage Token singlePurchase() is shown below:

HttpsCreditCardService.singlePurchase(orderId, storageTokenId, amount, verificationRequest)
Name Type Description
orderId String(32) Merchant assigned orderId. Must be unique.
storageTokenId String(32) Storage Token ID as returned to you/specified by you when the storage record was created, will specify the stored credit card to use for this purchase.
amount Long Amount of the purchase in cents. Do NOT include a $ or any decimal place. (e.g. if your purchase is $10.00, then send 1000 as the total).
verificationRequest Verification Request Credit Card Verification request information, null if not used. See Section 5.1 for details on how to use this field. Note that because CVV2 is not stored, you cannot specify a CVV2 check.
Returns:
CreditCardReceipt The results of the purchase request

There is a method that can provide the merchant a combined transaction for both purchase and secure storage creation.

HttpsCreditCardService.singlePurchase(orderId, storageTokenId, amount, verificationRequest)
Name Type Description
orderId String(32) Merchant assigned orderId. Must be unique.
creditCard CreditCard Credit Card information (see Table 3.4)
amount Long Amount of the purchase in cents. Do NOT include a $ or any decimal place. (e.g. if your purchase is $10.00, then send 1000 as the total).
verificationRequest Verification Request Credit Card Verification request information, null if not used. See Section 5.1 for details on how to use this field. Note that because CVV2 is not stored, you cannot specify a CVV2 check.
storageTokenId String(32) The secure storage token id that will be used to create storage record for this credit card.
Returns:
CreditCardReceipt The results of the purchase request

The other methods that can use the storageTokenId are:

  • recurringPurchase (orderId, storageTokenId, perPaymentAmount, startDate, endDate, schedule, verificationRequest)
  • updateRecurringPurchase (recurringPurchaseId, storageTokenId, perPaymentAmount, verificationRequest)
  • verifyCreditCard (storageTokenId, verificationRequest)
  • verifyCreditCard (creditCard, verificationRequest, storageTokenId)

Querying for Stored Information

You can query and retrieve the contents of any previously stored customer information.

HttpsCreditCardService.queryStorage(storageTokenId)
Name Type Description
storageTokenId String(32) The Storage Token ID of the stored information to retrieve.
Returns:
StorageReceipt The results of the query request

You can access the data through StorageReceipt.getPaymentProfile() and then retrieving the contained creditCard and/or customerProfile.

IMPORTANT: For security purposes, the credit card number returned will always be only the last 4 digits of the full credit card number. All other data will be returned in its original form, including the card expiry date and all of the customer profile information.
Updating and Deleting Stored Information

If you need to update/modify a stored record:

HttpsCreditCardService.updateStorage(storageTokenId, paymentProfile)
Name Type Description
storageTokenId String(32) The Storage Token ID of the stored information to update.
paymentProfile PaymentProfile Customer information to be stored. Will overwrite any existing customer information.
Returns:
StorageReceipt The results of the update request

The provided PaymentProfile will overwrite any existing data. If a null value is provided for the PaymentProfile creditCard or customerProfile parameters, then the corresponding stored data will be deleted. Note that even if you delete all of the data, the record itself will still exist (but be blank).

If you need to delete a stored record altogether:

HttpsCreditCardService.deleteFromStorage(storageTokenId)
Name Type Description
storageTokenId String(32) The Storage Token ID of the stored information to delete.
Returns:
StorageReceipt The results of the delete request

Deleting a record will free up the associated storageTokenId for re-use.


Non-Page Specific Requirements

General Requirements

  • Domain: The domain of the merchant website must be registered to the merchant

Customer Notification of Transaction Results

The customer must have a means to receive notification of the results of a transaction through a separate channel in addition to display on screen. This is to ensure that even in the case of an accident such as the customer closing their browser, the customer will still be able to determine if the transaction succeeded or failed.

Suggested means of implementing such a feature:

  • Email Notification: Send an email notification/receipt to the customer, in both success and failure cases. The email should contain the same information as on the receipt.
  • Self-Serve: Allow the customer to check the status of their transaction through a website or other such system.

If you do not already have such a feature it is recommended that the Email Notification method be used for ease of implementation.

Security and Privacy

Your store must make a Privacy Statement/Policy clearly available to the customer. A Privacy Statement should tell the customer:

  • What kinds of personal information are being collected,
  • What purpose(s) this information is used for,
  • How this information is protected, and
  • Under what circumstances this information is shared (if at all)

You must adhere to the following security and privacy requirements:

  • SSL Certificate: Your website must use at least 128-bit SSL encryption with a valid Certificate. In particular the page where the customer enters their credit card information must be secured.
    • The ownership status on the SSL Certificate should be registered to the merchant or the developer of the website.
  • Consumer Information: You may collect a consumer personal information so long as
    • You do not retain the customer credit card information. You may only collect this information for the sole purpose of submitting a transaction through the Client API, afterwards it must not be stored.
    • You have procedures to control access/protect personal information
  • Code of Practice: Adhere to the Canadian Code of Practice for Consumer Protection in Electronic Commerce: http://cmcweb.ca/epic/internet/incmc-cmc.nsf/en/fe00064e.html

Certification

Credit card associations, including Visa and Mastercard, require that all merchants offering online credit card payment follow a set of standard guidelines for implementation. The process of verifying that your website meets the card association requirements is known as Certification.

Approval for processing may be contingent on meeting these guidelines, depending on your credit card processor.


Approval

A full Approval requires a fully-functional, secure and complete e-commerce website to be created by the merchant. Since you will want to obtain some kind of approval before actually starting integration, you will typically go for a Conditional Approval first if supported by your processor (see below).


Conditional Approval

A Conditional Approval can be granted to a merchant who has not yet integrated their site with the SALT Payment Gateway. A Conditional Approval means that you are guaranteed a full Approval so long as the payment portion of your site is completed.

As long as the informational parts of your website are complete (product, return/refund policy, delivery policy, and privacy policy), you can be conditionally approved.

Important notes about Conditional Approval:

  • It allows you to process REAL credit card payments
  • It will expire after a set time period if full approval is not obtained by that point, your entire application will have to be re-submitted. A typical validity period is 30 days.
  • No integration is required to obtain Conditional Approval

Certification Checklist

Each merchant implementation must undergo a brief certification process to obtain approval. To complete certification, you will need to supply SALT with:

  • The URL to your credit card store implementation

  • Any instructions (logins, registration etc) needed to complete a test purchase

SALT and the processor will conduct a review of your site, and once this is complete you will receive the appropriate approval(s). Please ensure that you have met all website requirements before submitting your request.

The following self-assessment checklist summarizes the requirements that need to be met:

Requirement Description
Correlation between business and product/service There should be a correlation between the registered merchant name and the product/service offered.
Customer service contact provided There must be a clear posting of a Customer Service Telephone # or Email Address.
Return/Refund policy Return/refund policy is clearly stated on the merchant website.
Delivery policy The merchant's delivery methods and timing are clearly described
*Display correct receipt

The receipt presented to the customer after a successful or unsuccessful transaction must contain certain fields. Make sure to follow the guidelines presented in the Receipts section.

*Display timeout warning (if applicable)

Display a warning message to the customer if the customer has < 30 minutes to complete payment (e.g. their session times out).

If there is no such restriction, no message needs to be displayed

Product/service description The product/service offered for sale is clearly described
*Display correct currency Must indicate the currency of payment (e.g. USD, CAD). Explicitly indicate the currency type on the payment total
English language option There must be an English translation option for foreign language websites
*Customer Notification You must have some way for a customer to be notified/determine the status of a transaction. Follow the requirements presented in the Non-page-specific requirements section.
Age Verification The website includes an age Verification process for products sold that require age verification (alcohol, tobacco etc.).
Customer Ready? The website must be ready to accept real orders from customers at the website URL specified in your application the site should NOT use language/pages that imply that it is coming soon or under construction or use a testing URL (e.g. www.yourdomain.com/test)
Privacy Policy Make sure a privacy policy/statement is clearly stated on your website.
*Secure Payment Page

Ensure that you have an SSL Certificate protecting your payment information entry page. Follow the requirements presented in the Non-page-specific requirements section.

* Required for full approval, but not required for conditional approval


Moving to Production

Once certification is complete, you will be ready to move to the SALT Production environment. Moving to the Production environment involves changing the API handler URL to the production URL, and verifying your configuration settings in the production Merchant Management Website.

Production Site URL
SALT Merchant Management Website https://manage.saltpayments.com/merchantmanagement/
Payment API Handler https://gateway.saltpayments.com/gateway/creditcard/processor.do

When you want to move to production:

  1. Notify SALT so that we can enable your account on our production system.
  2. Where you invoke the SALT Client API, change the SALT API Handler URL from https://test.saltpayments.com/gateway/creditcard/processor.do to https://gateway.saltpayments.com/gateway/creditcard/processor.do.
  3. Finally, verify that your account is enabled and that your configurations are correct by logging into the production Merchant Management Website at https://manage.saltpayments.com/merchantmanagement/.

Appendix

Differences Between INTERAC Online and Credit Card Integration

The INTERAC Online and Credit Card Client API integrations are similar, with a few minor differences listed below:

Area INTERAC Online Credit Card
Client API URL Ends with iop/merchantprocessor.do Ends with cc/processor.do
Purchase Transaction Is created through an HTTP POST to the SALT Payment Handler Is performed directly through the SALT Client API
Entry of Payment Information Banking information is entered at the customer online banking website, it is not seen by the merchant Credit card information is entered into your website (but must not be retained)
Transaction Types Purchase, Refund (there is no Void or Periodic Purchase in IOP) Purchase, Refund, Void, Periodic Purchase, Secure Storage
Secure Payment Page Not required because no banking information is entered on your website. Page where credit card information is entered on your website must be protected by a valid SSL certificate

Client API for Other Programming Languages

Microsoft .NET

The SALT Client API is available for Microsoft .NET (for both .NET Framework versions 1.1 and 2.0). Below is a sample code fragment of a single purchase with the .NET Client API (in C#):

using com.salt.payment.client.creditcard.api;
:
:
int merchantId=12345; // your SALT merchantId
string apiToken="a3fer6321asdf1HY"; // your SALT API token
long pan = 4242424242424242; // Credit Card Number
short expiry = 1212; // Credit Card Expiry
string invoice="unique invoice"; // assign a unique invoice number
long amount = 10000; // amount of txn

HttpsCreditCardService ccService = new HttpsCreditCardService(new Merchant(merchantId, apiToken), "https://test.saltpayments.com/gateway/creditcard/processor.do");
CreditCard creditCard = new CreditCard(pan, expiry);
CreditCardReceipt resp = null;
resp = ccService.singlePurchase(invoice, creditCard, amount, null);

if(resp.isApproved()){
    Console.WriteLine("TransactionId: {0}",resp.getTransactionId());
    Console.WriteLine("ApprovalInfo: {0}", resp.getApprovalInfo().ToString());
} else {
    // display error for debugging: it is recommended not to display full error
    // message to external user
    Console.WriteLine("Error Code: {0} Message: {1}",
    resp.getErrorCode(),resp.getErrorMessage());
}
Package and Versioning

The SALT Credit Card Client API for Microsoft .NET package will contain the following:

  • admeriscc[dot net version].dll (where dot net version = version of .NET Framework)
  • CCGatewayTest.exe tests credit card functions
  • StorageGatewayTest.exe tests secure storage functions

Copy the admeriscc*.dll to your web bin folder. The Test executable files are provided so that you can quickly test some of the gateway functions from the command line. Run the executable(s) with no arguments for usage instructions.

PHP

The SALT Client API is available for PHP 4.3 (or greater). Below is a sample code fragment of a single purchase with the PHP Client API.

<?php
    include "HttpsCreditCardService.php";
    :
    :
    $merchantId=12345; // your SALT merchantId
    $apiToken="a3fer6321asdf1HY"; // your SALT API token
    $pan = 4242424242424242; // Credit Card Number
    $expiry = 1212; // Credit Card Expiry
    $invoice="unique invoice"; // assign a unique invoice number
    $amount = 10000; // amount of txn
    $ccService = new HttpsCreditCardService($merchantId, $apiToken,
        "https://test.saltpayments.com/gateway/creditcard/processor.do");
    $creditCard = new CreditCard($pan, $expiry);
    $resp = $ccService->singlePurchase($invoice, $creditCard, $amount, null);
    if($resp->isApproved()){
        print_r($resp->params);
    } else {
        // display error for debugging: it not recommended to display full error
        // message to external users
        echo "Error Code: " . $resp->getErrorCode() . "Message: " .
        $resp->getErrorMessage();
    }
?>

Below is an example of a Single Purchase with Secure Storage in PHP:

<?php
    include "HttpsCreditCardService.php";
    :
    :
    $merchantId=12345; // your SALT merchantId
    $apiToken="a3fer6321asdf1HY"; // your SALT API token
    $pan = 4242424242424242; // Credit Card Number
    $expiry = 1212; // Credit Card Expiry
    $invoice="unique invoice"; // assign a unique invoice number
    $amount = 10000; // amount of txn
    $storage="token123"
    // Credit Card Storage Token Id
    $ccService = new HttpsCreditCardService($merchantId, $apiToken,
        "https://test.saltpayments.com/gateway/creditcard/processor.do");
    $creditCard = new CreditCard($pan, $expiry);
    $resp = $ccService->singlePurchase($invoice, $creditCard, $amount, null, $storageTokenId);
    if($resp->isApproved()){
        print_r($resp->params);
    } else {
        // display error for debugging: it is recommended not to display full error
        // message to external user
        echo "Error Code: " . $resp->getErrorCode() . "Message: " .
        $resp->getErrorMessage();
    }
?>