MeldCX Agent Payments API
Terminology
Term | Description |
---|---|
Payment Gateways | Is the interface responsible for crafting the transaction message and handling the responses |
Payment Terminal | Is the peripheral device responsible for providing the payload ‘card data’ to the Gateway |
Configuration
The payment API supports configuring the various properties of the API Engine, Gateway and Terminal using the following configuration mechanisms:
- Application manifest,
manifest.json
file stored in the root of your application folder (alongsideindex.html
) - Account Preferences
- Device Options
- Display Options
- Explicit configuration via
Agent.Payments.setConfiguration
,Agent.Payments.setGatewayConfiguration
andAgent.Payments.setTerminalConfiguration
The available configuration properties are as follows
Property Name | Optional | Description | Supported Values | Default Value | Example Value |
---|---|---|---|---|---|
Payment.Gateways | No | List of comma seperated values, defines the available payment gateways | MockGateway, FreedomPayFreeway | null | MockGateway |
Payment.Terminal | Yes | This only required when you are using a non dynamically discoverable terminal such as the MockTerminal | MockTerminal | null | MockTerminal |
There are additional values for each Terminal and Gateway see the Payment Terminals section for the various Terminal configuration options and the Payment Gateways section for the various Gateway configuration options.
Payment Terminals
Some terminals require configuration to setup the devices for Styling, Behavioural restrictions and other configuration.
Available Terminals
The currently terminals supported by MeldCX are:
Model | Configuration Name | Capabilities |
---|---|---|
IDTech VP6800 | IDTechVP6800 | MSR, EMV with PIN, Contact with PIN, Apple Pay, Google Pay, Manual Entry |
IDTech VP8800 | IDTechVP8800 | MSR, EMV with PIN, Contact with PIN, Apple Pay, Google Pay, Manual Entry |
MockTerminal | MockTerminal | N/A |
Configuration
Configuration of the terminals can be done using any of the configuration mechanisms listed in Configuration, the configuration is structured as follows:
Configuration Key | Optional | Configuration Value |
---|---|---|
Payment.{Configuration Name} | No | See Independant Terminal Section |
Payment.Terminal.PairMode | No (Choose 1) | Silent, Interactive |
Payment.Terminal.PairStrategy | No (Choose 1) | serialNumberOnly, keyOnly, serialNumberAndKeys (Silent), CodeOnScreen (Interactive) |
Pairing Payment Terminal/Pin Pad
It is necessary to ensure that the terminal we are communicating with is authorised in order to do this we use the process of pairing to validate the terminal.
If the Payments Engine has not paired with a device it will be in the TerminalPairingFailed
state which can be validated using the Agent.Payments.status()
function.
Pairing Mode
The following pairing modes are supported:
- Silent - Doesn't require any user interaction to pair with the terminal
- Interactive - Requires user interaction to pair the terminal
Configuration Key | Optional | Configuration Value |
---|---|---|
Payment.Terminal.PairMode | No (Choose 1) | Silent, Interactive |
Pairing Strategy
The supported pairing strategies are as follows:
Pairing Mode - Interactive
The following Interactive pairing strategies are available:
Note: These are available only if using the Interactive Pairing Mode.
Option Name | Option Value | Optional |
---|---|---|
Payment.Terminal.PairStrategy | codeOnScreen | No |
Interactive Pairing Stragegy - Code On Screen
Using the Agent.Payments.pairInteractiveCommence()
function to invoke the device to go into pairing mode and show a pairing code on screen.
Call the Agent.Payments.pairInteractiveComplete()
function and provide the pairingCode
as the property on the object provided to the function for example.
await Agent.Payments.pairInteractiveCommence();
// Pairing Code will be displayed on terminal screen
const result = await Agent.Payments.pairInteractiveComplete({pairingCode: 123456});
if (result) console.log('Pairing Succeeded');
else console.log('Pairing Failed');
// Validate that the pairing succeeded and that the Payments Engine is ready to take payments
const status = await Agent.Payments.status();
if (status.message === 'Ready') console.log('Payments Engine is ready!');
else console.log('Payments Engine is not ready');
The Agent will then store unique identification information about this pinpad and trust the device automatically from this point forward until Agent.Payments.unPair()
is called.
Silent Pairing Strategies
The following Silent pairing strategies are available.
Configuration Key | Configuration Value | Optional |
---|---|---|
Payment.Terminal.PairStrategy | serialOnly, keyOnly, serialNumberAndKeys | No (Choose One) |
Serial Number Only
This strategy enables pairing based on matching the serial number only.
This can be configured in the device options as follows:
Option Name | Option Value | Optional |
---|---|---|
Payment.Terminal.PairStrategy | serialNumberOnly | No |
Payment.Terminal.SerialNumber | Device Serial Number | No |
Encryption Key Only
This strategy enables pairing based on matching the Encyrption Key KSN and Type.
This can be configured in the device options as follows:
Option Name | Option Value | Optional |
---|---|---|
Payment.Terminal.PairStrategy | keyOnly | No |
Payment.Terminal.PairStrategy.ksn | Encryption Key KSN | No |
Payment.Terminal.PairStrategy.type | Encryption Key Type | No |
Serial Number and Encryption Key
This strategy enables pairing based on matching the serial number and the Encyrption Key KSN and Type.
This can be configured in the device options as follows:
Option Name | Option Value | Optional |
---|---|---|
Payment.Terminal.PairStrategy | serialNumberAndKeys | No |
Payment.Terminal.SerialNumber | ID Tech Device Serial Number | No |
Payment.Terminal.PairStrategy.ksn | Encryption Key KSN | No |
Payment.Terminal.PairStrategy.type | Encryption Key Type | No |
Silent Pairing
Silent Pairing is run automatically or can be invoked using the Agent.Payments.pairSilent()
function, this will resolve to true
or false
depending on if the pairing was a success.
Interactive Pairing
Interactive Pairing is invoked manually using the Agent.Payments.pairInteractiveCommence()
function and providing any neccessary parameters, this will invoke the terminal to start the interactive pairing sequence. To complete the interactive pairing simply call Agent.Payments.pairInteractiveComplete()
function and provide any neccessary parameters (see independant terminal section.)
IDTech VP6800 & VP8800
Option Name | Description | Available Values | Example | Optional |
---|---|---|---|---|
Payment.IDTechVP6800.interfaces | Define which interfaces/mechanisms to use for payment transactions, comma seperated. | MSR, Contact, Contactless | MSR | No |
Payment.IDTechVP8800.interfaces | Define which interfaces/mechanisms to use for payment transactions, comma seperated. | MSR, Contact, Contactless | MSR | No |
Mock Terminal
You can invoke failure modes by making a transaction with the total value in the charges set to the corresponding value in the table below.
Failure Mode | Total Value |
---|---|
Rejected | 1.66 |
Payment Gateways
The available payment gateways are:
- FreedomPay Freeway
- Mock Gateway
Mock Gateway
The mock gateway is intended to be used for debugging, testing and setting up your initial integration with this API.
Configuration
You can invoke failure modes by making a transaction with the total value in the charges set to the corresponding value in the table below.
Failure Mode | Total Value |
---|---|
Declined | 1.66 |
You can configure other aspects of the mock gateway using configuration options, see below.
Name | Supported Values | Notes | Optional |
---|---|---|---|
status | Status.Up, Status.Down | Emulate the status of the Gatreay. Can be imported using import {Status} from '@meldcx/agent-payments'; |
Yes |
defaultLoter | 1000+ | The amount of time in milliseconds to wait between transaction stages | Yes |
FreedomPay Freeway
Configuration
The following configuration options are available for the FreedomPay Freeway gateway:
The payment API supports a heirarchical system that applies the configuration in a cascading order of the following: manifest.json, Account Preferences, Device Options and Display Options.
The bulk of these options should be pre-configured as account preferences, however some values such as terminalId may be kiosk specific.
Option Name | Option Value | Option Example |
---|---|---|
Payment.FreedomPayFreeway.storeID | The Store ID value provided by FreedomPay | 1234 |
Payment.FreedomPayFreeway.terminalId | The Terminal ID value provided by FreedomPay | 7890 |
Payment.FreedomPayFreeway.maxFreewaySvrDelta | Allowable time diff between FP svr and client | 60000 |
Payment.FreedomPayFreeway.endpoint | The SOAP API Endpoint to be used | https://cs.uat.freedompay.com/Freeway/Service.asmx |
Payment.FreedomPayFreeway.endpointHealthUrl | The SOAP API Health Endpoint to be used | https://cs.uat.freedompay.com/Freeway/HealthCheck.ashx |
Payment.FreedomPayFreeway.cardStorEndpointUrl | The SOAP API Endpoint for CardStor | https://cs.uat.freedompay.com/CardStor/CardStorService.asmx |
Payment.FreedomPayFreeway.currency | The currency to use. | USD |
Payment.FreedomPayFreeway.industryType | The Industry Type (See FreedomPay Documents) | hotel |
Payment.FreedomPayFreeway.platform | The OS being used** | ChromeOS |
Payment.FreedomPayFreeway.hostname | The Host name of the kiosk device** | New York Marriott Downtown - Kiosk 1 |
Payment.FreedomPayFreeway.deviceId | The ID of the Register/Kiosk Device* | 1234567 |
* This will be populated automatically by MeldCX (can be overridden) and will reference the MeldCX Unique device ID.
** This will be populated automatically by MeldCX (can be overridden).
You can invoke failure modes by making a transaction with the total value in the charges set to the corresponding value in the table below.
Failure Mode | Total Value |
---|---|
Declined | 55.01 |
Failure | 55.06 |
Delayed | 55.03 |
Errors
FreedomPay Freeway Errors will have the following format:
Exception Name | Code | Description |
---|---|---|
PaymentGatewayException | {FreedomPay Freeway Specific} | See Freedompay error guide here |
Minimum Configuration with ID Tech VP6800 & VP8800 Payment Terminals
The Minimum configuration required for the payments setup in development is as follows:
Option Name | Option Value | |
---|---|---|
Payment.Gateways | MockGateway | |
Payment.IDTechVP6800.interfaces | MSR | * FOR VP6800 ONLY |
Payment.IDTechVP8800.interfaces | MSR | * FOR VP8800 ONLY |
Payment.Terminal.PairStrategy | serialNumberOnly | |
Payment.Terminal.PairMode | Silent | |
Payment.Terminal.SerialNumber | {Serial No off the back of the terminal} |
Minimum Configuration without Payment Terminal
Option Name | Option Value |
---|---|
Payment.Gateways | MockGateway |
Payment.Terminal | MockTerminal |
Transaction Types
The available transaction types are as follows:
Type | Code |
---|---|
Payment | 1 |
Capture | 2 |
PreAuth | 4 |
Credit | 8 |
Refund | 16 |
Token | 32 |
These Transaction types can be referenced using the Agent.Payments.TransactionType
property or imported from the @meldcx/agent-payments
NPM library as follows:
import {TransactionType} from '@meldcx/agent-payments';
Reference Information
All transactions require that you provide reference information for tracking the state and maintaing records of your transactions. The supported fields for the reference information object are as follows:
Name | Description | Optional |
---|---|---|
id | A generic ID | Yes |
invoiceNumber | An invoice number | No (FreedomPay) |
invoiceDate | A related invoice date in ISO-8601 Date Format | No (FreedomPay) |
Some gateways require different information to be provide as the reference for the transaction, below is a list of reference information required by each gateway implemented by MeldCX
Gateway | Required reference fields |
---|---|
MockGateway | Any |
FreedomPay Freeway | invoiceNumber (MAX 20 CHARS), invoiceDate |
Charges
All transactions require that you provide a charges object containing all of the charges to be applied.
Name | Description | Optional |
---|---|---|
total | The total amount to charge | No (Yes for Credit and Void Transactions) |
tax | The amount of tax in this charge | Yes |
tip | The tip amount in this charge | Yes |
cashout | The amount of cash out in this charge | Yes |
credit | The amount to credit | Yes (No for Credit Transaction) |
Performing Transactions
Performing a transaction is done using the Agent.Payments.startTransaction()
function.
To peform a payment transaction you need to provide the following parameters:
- Transaction Type (See Transaction Types)
- Reference Information (See Reference Information)
- Charges (See Charges)
- Optional Configuration
Payment Transaction
Performing a Payment Transaction can be done like so:
import {PaymentException} from '@meldcx/agent-payments';
import Agent from '@meldcx/agent';
import moment from 'moment';
const agent = new Agent();
const transactionType = agent.Payments.TransactionType.Payment;
const reference = { invoiceNumber: 'ABC1234DEF', invoiceDate: (new Date()).toISOString() };
const charges = { total: 100, tax: 10 };
try {
const result = await agent.Payments.startTransaction(transactionType, reference, charges, options);
console.log('Transaction Was Approved', result);
} catch (ex) {
if (ex instanceof TransactionRejectedException) {
const {responseCode, code} = ex;
console.log(`Transaction was rejected: ${code} with response code: ${responseCode}`);
return;
}
console.log(`Some other error occurred: ${ex.code}`);
}
Performing a pre-auth Transaction can be done like so, additionally we have added line items for this pre-auth:
import {PaymentException} from '@meldcx/agent-payments';
import Agent from '@meldcx/agent';
import moment from 'moment';
const agent = new Agent();
const transactionType = agent.Payments.TransactionType.PreAuth;
const reference = { invoiceNumber: 'DEF383832', invoiceDate: (new Date()).toISOString() };
const charges = { total: 100, tax: 10 };
// NOTE: Items are not mandatory, they only need to be provided once for a given transaction reference. i.e. Provided with pre-auth but absent from capture.
const items = [
{
folioNumber: 7741234,
expectedDuration: 2,
noShow: false,
checkinDate: moment().toISOString(),
checkoutDate: moment().add(2, 'days').toISOString(),
extraChargeType: 'M',
roomRate: 50,
roomTax: 5,
extraChargeTotal: 0
}
];
const options = { items };
try {
const result = await agent.Payments.startTransaction(transactionType, reference, charges, options);
console.log('Transaction Was Approved', result);
} catch (ex) {
if (ex instanceof TransactionRejectedException) {
const {responseCode, code} = ex;
console.log(`Transaction was rejected: ${code} with response code: ${responseCode}`);
return;
}
console.log(`Some other error occurred: ${ex.code}`);
}
Capturing a prior transaction
import {PaymentException} from '@meldcx/agent-payments';
import Agent from '@meldcx/agent';
const agent = new Agent();
let transactionType = agent.Payments.TransactionType.PreAuth;
const reference = { invoiceNumber: 'DEF383832', invoiceDate: (new Date()).toISOString() };
const charges = { total: 100, tax: 10 };
let result = await agent.Payments.startTransaction(transactionType, reference, charges);
reference.id = result.response.requestID;
transactionType = agent.Payments.TransactionType.Capture;
result = await agent.Payments.startTransaction(transactionType, reference, charges);
Making a Credit transaction:
import {PaymentException} from '@meldcx/agent-payments';
import Agent from '@meldcx/agent';
const agent = new Agent();
const transactionType = agent.Payments.TransactionType.Credit;
const reference = { invoiceNumber: 'DEF383832', invoiceDate: (new Date()).toISOString() };
const charges = { total: 100};
try {
const result = await agent.Payments.startTransaction(transactionType, reference, charges);
console.log('Transaction Was Approved', result);
} catch (ex) {
if (ex instanceof TransactionRejectedException) {
const {responseCode, code} = ex;
console.log(`Transaction was rejected: ${code} with response code: ${responseCode}`);
return;
}
console.log(`Some other error occurred: ${ex.code}`);
}
Cancel a Transaction:
Note: If the transaction doesn't cancel, you may still need to make a reversal/credit transaction.
import {PaymentException} from '@meldcx/agent-payments';
import Agent from '@meldcx/agent';
const agent = new Agent();
const transactionType = agent.Payments.TransactionType.Capture;
const reference = { invoiceNumber: 'DEF383832', invoiceDate: (new Date()).toISOString() };
const charges = { total: 100, tax: 10 };
try {
setTimeout(() => agent.Payments.cancelTransaction(reference));
const result = await agent.Payments.startTransaction(transactionType, reference, charges);
console.log('Transaction Was Approved', result);
} catch (ex) {
if (ex instanceof AgentCancelledException) {
const {code} = ex;
console.log(`Transaction was cancelled: ${code}`);
return;
}
console.log(`Some other error occurred: ${ex.code}`);
}
Making a PreAuth and Token transaction:
import {PaymentException} from '@meldcx/agent-payments';
import Agent from '@meldcx/agent';
const agent = new Agent();
const transactionType = agent.Payments.TransactionType.PreAuth | agent.Payments.TransactionType.Token;
const reference = { invoiceNumber: 'DEF383832', invoiceDate: (new Date()).toISOString() };
const charges = { total: 50};
try {
const result = await agent.Payments.startTransaction(transactionType, reference, charges);
console.log('Transaction Was Approved', result);
console.log('Token is:', result.response.token);
} catch (ex) {
if (ex instanceof TransactionRejectedException) {
const {responseCode, code} = ex;
console.log(`Transaction was rejected: ${code} with response code: ${responseCode}`);
return;
}
console.log(`Some other error occurred: ${ex.code}`);
}
Voiding a prior transaction:
import {PaymentException} from '@meldcx/agent-payments';
import Agent from '@meldcx/agent';
const agent = new Agent();
let transactionType = agent.Payments.TransactionType.PreAuth;
const reference = { invoiceNumber: 'DEF383832', invoiceDate: (new Date()).toISOString() };
const charges = { total: 50};
let result = await agent.Payments.startTransaction(transactionType, reference, charges);
reference.id = result.response.requestID;
transactionType = agent.Payments.TransactionType.Void;
result = await agent.Payments.startTransaction(transactionType, reference, charges);
Transaction Status
You can listen to transaction status updates by register an event listener using the function onTransactionStatus
and example of this is below:
Agent.Payments.onTransactionStatus((reference, status) => {
console.log(`Transaction with reference ${JSON.stringify(reference)} has status ${JSON.stringify(status)})`);
});
Transaction Result
The transaction result will have the following properites:
Name | Path | Description | Example Value |
---|---|---|---|
Charges | charges | The charges requested | {total: 4, tax: 1} |
Masked PAN | cardInfo.maskedPAN | The masked PAN of the Card Provided | {..., cardInfo: {..., maskedPAN: '541333******0011'}} |
Card Holder Name | cardInfo.cardHolderName | The card holder name on the Card | {..., cardInfo: {..., cardHolderName: 'UAT USA/TEST CARD 10'}} |
Card Type Code | cardInfo.cardType.code | The code of the Card Type | {..., cardType: {..., code: 1}} |
Card Type | cardInfo.cardType.type | The string type of the Card | {..., cardType: {..., type: 'VISA'}} |
Card Expiry Month | cardInfo.cardExpiry.month | The Expiry Month of the Card | {..., cardExpiry: {..., month: 12}} |
Card Expiry Year | cardInfo.cardExpiry.year | The Expiry Year of the Card | {..., cardExpiry: {..., year: 2022}} |
Reference Invoice No | cardInfo.reference.invoiceNumber | The Invoice No provided | {..., reference: {..., invoiceNumber: '1024'}} |
Reference Invoice Date | cardInfo.reference.invoiceDate | The Invoice Date provided | {..., reference: {..., invoiceDate: '2019-12-23T04:35:04.636Z'}} |
Transaction ID | transactionID | The MeldCX Internsal ID of the transaction | {..., transactionId: '99e4f3bb-e6f9-4ad4-9ca3-5398b0bd7b54'} |
Approved | approved | If this transaction was approved | {..., approved: true} |
Gateway Request ID | response.requestID | The Request ID from the Gateway | {..., response: {..., requestID: '01Z6HT2V0R01U67LG1LOM4POFBRGJ8OI'}} |
Gateway Result Code | response.resultCode | The Response Code from the Gateway | {..., response: {..., resultCode: 200}} |
Gateway Authorization Code | response.authorizationCode | The Response Code from the Gateway | {..., response: {..., authorizationCode: '621575'}} |
Gateway Authorization Date | response.authorizationDateTime | The Response Code from the Gateway | {..., response: {..., authorizationDateTime: '2020-01-17T05:22:35.6164684Z'}} |
Receipt | response.receipt | The Receipt for this Transaction | {..., response: {..., receipt: 'RECEIPT EXAMPLE....'}} |
Gateway Specific Response | response.gatewayResponse | The Raw response from the Gateway | {..., gatewayResponse: {...}} |
Token | response.token | The Token value for Token Transactions | {..., response: {..., token: '9680082379174111'}} |
A full example response object is show below:
{
"charges": {
"total": 4
},
"cardInfo": {
"maskedPAN": "541333******0011",
"cardHolderName": "UAT USA/TEST CARD 10",
"cardType": {
"code": 1,
"type": "Mastercard"
},
"cardExpiry": {
"month": 12,
"year": 2022
},
"entryMethod": {"code": 1, "type": "MSR"}
},
"reference": {
"invoiceNumber": "e0f2619f-5f3c-4f83-8",
"invoiceDate": "2019-12-23T04:35:04.636Z"
},
"transactionId": "99e4f3bb-e6f9-4ad4-9ca3-5398b0bd7b54",
"approved": true,
"response": {
"token": "9680082379174111",
"requestID": "01Z6HT2V0R01U67LG1LOM4POFBRGJ8OI",
"receipt": "************* AUTHORIZATION *************\n APPROVED\n\nTotal: $4.00\n\nCard Type: MASTERCARD\nCard Entry: MAG STRIPE\nAcct #: 541333******0011\nApproval Code: 621575",
"resultCode": 200,
"authorizationCode": "621575",
"authorizationDateTime": "2020-01-17T05:22:35.6164684Z"
},
"gatewayResponse": {}
}
Entry Methods
Entry Method | Code |
---|---|
None | 0 |
MSR | 1 |
Chip | 2 |
EMVContactless | 4 |
Manual | 8 |
RFID | 16 |
Scanned | 32 |
Loyalty | 64 |
Errors
Exception Name | Code | Description |
---|---|---|
PaymentException | Payment.InvalidCharge | Thrown when an invalid charge value is passed to the Start Transaction function |
PaymentException | Payment.NotReady | Thrown when the payments engine is not ready to process transaction |
PaymentException | Payment.NoTerminal | Thrown when no terminal is present or configured |
PaymentException | Payment.TerminalPairingFailed | Thrown when a request to pair fails |
PaymentException | Payment.CancelFailed | Thrown when an attempt to cancel a transaction fails. |
PaymentException | Payment.TransactionCancelled | Thrown when a transaction is cancelled |
PaymentException | Payment.TransactionInProgress | Thrown when a transaction is in progress but you attempt to make another |
PaymentGatewayException | UnknownTransactionType | Thrown when an unkown transaction type is provided |
PaymentGatewayException | Gateway.Down | Thrown when the payment gateway is down |
PaymentGatewayException | Gateway.TransactionNotCancellable | Thrown when a transaction cannot be cancelled |
TransactionRejectedException | {Gateway Specific Code} | Thrown when a transaction is rejected/declined by the gateway |
DisconnectedException | Terminal.Disconnected | Thrown when the payment terminal is disconnected |
PaymentTerminalException | Terminal.PairingInProgress | Thrown when attempting to pair when a pairing process is already running |
AgentTimedOutException | Agent.TimedOutException | Thrown when an API call times out, when an operation takes longer than expected |
PaymentGatewayException | Misc | See Gateway Specific Section here |
PaymentTerminalException | Misc | See Terminal Specific Section here |
Common Errors
Problem | Pinpad | Gateway | Exception Name | Code | Description/Reason |
---|---|---|---|---|---|
Bad Mag Strip Read | VP6800 | N/A | PaymentTerminalException | EMV_RESULT_CODE_MSR_CARD_ERROR_FALLBACK | Bad magnetic strip read or faulty stripe |
Card Expired | N/A | Freeway | TransactionRejectedException | 233 | This will depend on the bank Test with 55.01 |
Card Swiped | VP6800 | TBC | TBC | TBC | |
Processing Failure | N/A | Freeway | PaymentGatewayException | 150 | This will depend on the bank Test with 55.02 |
Debit Card Rejection | VP6800 | N/A | TBC | TBC | To be Confirmed |
Emulator
A Payments emulation component has been developed for the Agent Emulator, this can be found in the Payments section of the Emulator Menu.
Emulating Payment System State
Under the section titled System there is a drop down list from which you can set the state of the Payments System, the following states correspond to these errors being throw by the system:
State | Error | Code |
---|---|---|
Initialising | PaymentException | Payment.NotReady |
Ready | N/A (No Error) | N/A (No Error) |
GatewayOffline | PaymentGatewayException | Gateway.Down |
TerminalOffline | PaymentException | Payment.NoTerminal |
TerminalPairingFailed | PaymentException | Payment.TerminalPairingFailed |
ErrorGateway | PaymentException | Payment.NotReady |
ErrorTerminal | PaymentException | Payment.NotReady |
ErrorConfiguration | PaymentException | Payment.NotReady |
Emulating Gateway State
Under the section titled Gateway there are 2 drop down lists:
- The first allows you to set the state of the Gateway API.
- The second allows you to set the gateway action for the transactions it receives.
Gateway State and Errors:
State | Error | Code |
---|---|---|
Up | N/A (No Error) | N/A (No Error) |
Down | PaymentGatewayException | Gateway.Down |
Unknown | PaymentGatewayException | Gateway.Down |
Gateway Result/Actions:
State | Error | Code |
---|---|---|
Accept | N/A (No Error) | N/A (No Error) |
Decline | TransactionRejectedException | Transaction.Rejected |
Error | PaymentGatewayException | Gateway specific error code |
Emulating Terminal State
The Status column shows the emulated display of the payment terminal and the prompts that the user would see.
The Input Method column contains a drop down list that allows you to select the emulated input method for the card, this may be MSR, Chip and EMV.
The Swipe, Tap, Insert button allows you to invoke the Swipe, Tap or Insert action. This buttons action changes based on the Input Method you select.
The CV Trigger Limit designates the amount the charge to the card can be before it triggers a Card Holder Verification request, this only applies to transaction of type Tap & Insert (EMV Transactions).
Working with EMV
EMV mantains much stricter and safer controls over what transactions are supported and the conditions around verifying the cardholder before releasing the data stored on the card, if certain conditions are met the customer may be prompted to enter their PIN or to perform some other kind of verification.
We have added support to emulate this behaviour in our Emulator. When the transaction amount is greater than or equal to that specified in the CV Trigger Limit drop down list, the emulator will trigger the "CVM Required" event, you can listen to this as follows:
Agent.Payments.onCVMRequested((cvMethod: CVMethod, reference: TransactionReference) => {
console.log(`The transaction with reference: ${reference.invoiceNumber} is requesting to perform Cardholder Verification via ${CVMMethod.type}`);
// At this time the emulator only returns a Cardholder Verification method of type 'ONLINE_PIN'.
}));
Additionally you can emulate a successful Cardholder Verification by clicking on the CV Verify button which will temporarily replace the Insert/Tap button.
The transaction result will reflect the differing presentation methods with the result.cardInfo.entryMethod
objects values differing depending on the Entry method
Terminal Errors
We have added support for emulating a wide variety of payment terminal errors:
Connectivity Errors
The Connectivity column contains a drop down that allows you to switch the connectivity state of the payment terminal.
Driver & Terminal Errors
Status Errors
Name | Code | Message |
---|---|---|
PaymentTerminalException | STATUS_CODE_00 | STATUS_CODE_00: OK |
PaymentTerminalException | STATUS_CODE_01 | STATUS_CODE_01: Incorrect Header Tag |
PaymentTerminalException | STATUS_CODE_02 | STATUS_CODE_02: Unknown Command |
PaymentTerminalException | STATUS_CODE_03 | STATUS_CODE_03: Unknown Sub-command |
PaymentTerminalException | STATUS_CODE_04 | STATUS_CODE_04: CRC Error in Frame |
PaymentTerminalException | STATUS_CODE_05 | STATUS_CODE_05: Incorrect Parameter |
PaymentTerminalException | STATUS_CODE_06 | STATUS_CODE_06: Parameter Not Supported |
PaymentTerminalException | STATUS_CODE_07 | STATUS_CODE_07: Incorrect Data Format |
PaymentTerminalException | STATUS_CODE_08 | STATUS_CODE_08: Timeout |
PaymentTerminalException | STATUS_CODE_0A | STATUS_CODE_0A: Failed |
PaymentTerminalException | STATUS_CODE_0B | STATUS_CODE_0B: Command not Allowed |
PaymentTerminalException | STATUS_CODE_0C | STATUS_CODE_0C: Sub-command not Allowed |
PaymentTerminalException | STATUS_CODE_0D | STATUS_CODE_0D: Buffer Overflow |
PaymentTerminalException | STATUS_CODE_0E | STATUS_CODE_0E: User Interface Event |
PaymentTerminalException | STATUS_CODE_0F | STATUS_CODE_0F: Decryption Error |
PaymentTerminalException | STATUS_CODE_16 | STATUS_CODE_16: Busy |
PaymentTerminalException | STATUS_CODE_20 | STATUS_CODE_20: Directory not found |
PaymentTerminalException | STATUS_CODE_21 | STATUS_CODE_21: Length error |
PaymentTerminalException | STATUS_CODE_22 | STATUS_CODE_22: Transaction Declined |
PaymentTerminalException | STATUS_CODE_23 | STATUS_CODE_23: Request Online Auth |
PaymentTerminalException | STATUS_CODE_24 | STATUS_CODE_24: OK – DesFire |
PaymentTerminalException | STATUS_CODE_25 | STATUS_CODE_25: OK – ViVOComm |
PaymentTerminalException | STATUS_CODE_27 | STATUS_CODE_27: File too big |
PaymentTerminalException | STATUS_CODE_28 | STATUS_CODE_28: No space |
PaymentTerminalException | STATUS_CODE_30 | STATUS_CODE_30: Request Online Auth |
PaymentTerminalException | STATUS_CODE_31 | STATUS_CODE_31: Request Online PIN |
PaymentTerminalException | STATUS_CODE_32 | STATUS_CODE_32: Request Signature |
PaymentTerminalException | STATUS_CODE_33 | STATUS_CODE_33: Advice Required |
PaymentTerminalException | STATUS_CODE_34 | STATUS_CODE_34: Reversal Required |
PaymentTerminalException | STATUS_CODE_35 | STATUS_CODE_35: Advice and Reversal Required |
PaymentTerminalException | STATUS_CODE_36 | STATUS_CODE_36: No Advice or Reversal Required |
PaymentTerminalException | STATUS_CODE_39 | STATUS_CODE_39: Reserved |
PaymentTerminalException | STATUS_CODE_3A | STATUS_CODE_3A: Fallback from Contact (ICC) to Magstripe |
PaymentTerminalException | STATUS_CODE_3B | STATUS_CODE_3B: Fallback from Contactless to Contact |
PaymentTerminalException | STATUS_CODE_3C | STATUS_CODE_3C: Fallback from Contactless to Magstripe |
PaymentTerminalException | STATUS_CODE_3D | STATUS_CODE_3D: Fallback from Contactless to Other Interface |
PaymentTerminalException | STATUS_CODE_41 | STATUS_CODE_41: Unknown SAM Error |
PaymentTerminalException | STATUS_CODE_42 | STATUS_CODE_42: Invalid data detected by SAM |
PaymentTerminalException | STATUS_CODE_43 | STATUS_CODE_43: Incomplete data detected by SAM |
PaymentTerminalException | STATUS_CODE_44 | STATUS_CODE_44: CA Public Key Failed Hash Check |
PaymentTerminalException | STATUS_CODE_45 | STATUS_CODE_45: Invalid key hash algorithm |
PaymentTerminalException | STATUS_CODE_46 | STATUS_CODE_46: Invalid key encryption algorithm |
PaymentTerminalException | STATUS_CODE_47 | STATUS_CODE_47: Invalid modulus length |
PaymentTerminalException | STATUS_CODE_48 | STATUS_CODE_48: Invalid exponent |
PaymentTerminalException | STATUS_CODE_49 | STATUS_CODE_49: Key already exists |
PaymentTerminalException | STATUS_CODE_4A | STATUS_CODE_4A: No space for new RID |
PaymentTerminalException | STATUS_CODE_4B | STATUS_CODE_4B: Key not found |
PaymentTerminalException | STATUS_CODE_4C | STATUS_CODE_4C: Crypto not responding |
PaymentTerminalException | STATUS_CODE_4D | STATUS_CODE_4D: Crypto communication error |
PaymentTerminalException | STATUS_CODE_4E | STATUS_CODE_4E: Key slots full for this RID |
PaymentTerminalException | STATUS_CODE_4F | STATUS_CODE_4F: All key slots are full |
PaymentTerminalException | STATUS_CODE_50 | STATUS_CODE_50: Key data is bad or corrupt |
PaymentTerminalException | STATUS_CODE_51 | STATUS_CODE_51: Keys out of sync |
PaymentTerminalException | STATUS_CODE_55 | STATUS_CODE_55: Illegal duplicate data set |
PaymentTerminalException | STATUS_CODE_56 | STATUS_CODE_56: Indication to fail the transaction to Pass Through Mode |
PaymentTerminalException | STATUS_CODE_57 | STATUS_CODE_57: No payment transaction occurred. The response is loyalty only. |
PaymentTerminalException | STATUS_CODE_58 | STATUS_CODE_58: Contactless Data Exchange |
PaymentTerminalException | STATUS_CODE_59 | STATUS_CODE_59: Request Authentication |
PaymentTerminalException | STATUS_CODE_60 | STATUS_CODE_60: Data not exist |
PaymentTerminalException | STATUS_CODE_A1 | STATUS_CODE_A1: No PAN data avaiable |
PaymentTerminalException | STATUS_CODE_A2 | STATUS_CODE_A2: MSR Error See IDTech doco |
Transaction Errors
Name | Code | Message |
---|---|---|
PaymentTerminalException | TRANSACTION_ERROR_01 | TRANSACTION_ERROR_01: Out of Sequence Command |
PaymentTerminalException | TRANSACTION_ERROR_02 | TRANSACTION_ERROR_02: Go to Contact Interface |
PaymentTerminalException | TRANSACTION_ERROR_03 | TRANSACTION_ERROR_03: Transaction Amount is Zero |
PaymentTerminalException | TRANSACTION_ERROR_04 | TRANSACTION_ERROR_04: Go to Other Interface |
PaymentTerminalException | TRANSACTION_ERROR_05 | TRANSACTION_ERROR_05: Go to Nearby Contact Interface |
PaymentTerminalException | TRANSACTION_ERROR_06 | TRANSACTION_ERROR_06: Go to Magstripe Interface |
PaymentTerminalException | TRANSACTION_ERROR_20 | TRANSACTION_ERROR_20: RF State Error |
PaymentTerminalException | TRANSACTION_ERROR_21 | TRANSACTION_ERROR_21: Collision Error |
PaymentTerminalException | TRANSACTION_ERROR_23 | TRANSACTION_ERROR_23: Amount over Max Limit |
PaymentTerminalException | TRANSACTION_ERROR_25 | TRANSACTION_ERROR_25: Card Blocked |
PaymentTerminalException | TRANSACTION_ERROR_26 | TRANSACTION_ERROR_26: Card Expired |
PaymentTerminalException | TRANSACTION_ERROR_27 | TRANSACTION_ERROR_27: Unsupported Card |
PaymentTerminalException | TRANSACTION_ERROR_30 | TRANSACTION_ERROR_30: Card did not respond |
PaymentTerminalException | TRANSACTION_ERROR_40 | TRANSACTION_ERROR_40: Unkown Data Element |
PaymentTerminalException | TRANSACTION_ERROR_41 | TRANSACTION_ERROR_41: Required Data Element(s) Missing |
PaymentTerminalException | TRANSACTION_ERROR_42 | TRANSACTION_ERROR_42: Card Generated AAC |
PaymentTerminalException | TRANSACTION_ERROR_43 | TRANSACTION_ERROR_43: Card Generated ARQC |
PaymentTerminalException | TRANSACTION_ERROR_44 | TRANSACTION_ERROR_44: SDA/DDA Failed |
PaymentTerminalException | TRANSACTION_ERROR_50 | TRANSACTION_ERROR_50: SDA/DDA/CDDA Failed |
PaymentTerminalException | TRANSACTION_ERROR_51 | TRANSACTION_ERROR_51: SDA/DDA/CDDA Failed |
PaymentTerminalException | TRANSACTION_ERROR_52 | TRANSACTION_ERROR_52: SDA Failed (SSAD) |
PaymentTerminalException | TRANSACTION_ERROR_53 | TRANSACTION_ERROR_53: DDA/CDDA Failed |
PaymentTerminalException | TRANSACTION_ERROR_54 | TRANSACTION_ERROR_54: DDA/CDDA Failed |
PaymentTerminalException | TRANSACTION_ERROR_55 | TRANSACTION_ERROR_55: Processing Restrictions Failed |
PaymentTerminalException | TRANSACTION_ERROR_56 | TRANSACTION_ERROR_56: TRM Failed |
PaymentTerminalException | TRANSACTION_ERROR_57 | TRANSACTION_ERROR_57: Cardholder Verification Failed |
PaymentTerminalException | TRANSACTION_ERROR_58 | TRANSACTION_ERROR_58: TAA Failed |
PaymentTerminalException | TRANSACTION_ERROR_61 | TRANSACTION_ERROR_61: SD Memory Error |
PaymentTerminalException | TRANSACTION_ERROR_70 | TRANSACTION_ERROR_70: Contact EMV Error |
PaymentTerminalException | TRANSACTION_ERROR_80 | TRANSACTION_ERROR_80: No Merchants |
PaymentTerminalException | TRANSACTION_ERROR_81 | TRANSACTION_ERROR_81: Data Element Parse Error |
PaymentTerminalException | TRANSACTION_ERROR_82 | TRANSACTION_ERROR_82: Merchant Data Error |
PaymentTerminalException | TRANSACTION_ERROR_83 | TRANSACTION_ERROR_83: System Memory Error |
PaymentTerminalException | TRANSACTION_ERROR_84 | TRANSACTION_ERROR_84: Application Skip Error |
PaymentTerminalException | TRANSACTION_ERROR_85 | TRANSACTION_ERROR_85: Application Version Error |
EMV Errors
The EMV Errors will be returned in the form of {CEMV_APP_ERROR_FN}.{CEMV_APP_ERROR_STATE}
Name | Code |
---|---|
PaymentTerminalException | {CEMV_APP_ERROR_FN}.{CEMV_APP_ERROR_STATE} |
CEMV_APP_ERROR_FN Code |
---|
CEMV_APP_ERROR_FN_NONE |
CEMV_APP_ERROR_FN_CEMV_INITIALIZE |
CEMV_APP_ERROR_FN_CEMV_INITIATE_TRANSACTION |
CEMV_APP_ERROR_FN_CEMV_BUILD_CANDIDATE_LIST |
CEMV_APP_ERROR_FN_CEMV_FINAL_APPLICATION_SELECTION |
CEMV_APP_ERROR_FN_CEMV_INITIATE_APPLICATION |
CEMV_APP_ERROR_FN_CEMV_READ_APPLICATION_DATA |
CEMV_APP_ERROR_FN_CEMV_OFFLINE_DATA_AUTHENTICATION |
CEMV_APP_ERROR_FN_CEMV_PROCESS_RESTRICTIONS |
CEMV_APP_ERROR_FN_CEMV_CARDHOLDER_VERIFICATION |
CEMV_APP_ERROR_FN_CEMV_CARDHOLDER_VERIFICATION_CONTINUE |
CEMV_APP_ERROR_FN_CEMV_TERMINAL_RISK_MANAGEMENT |
CEMV_APP_ERROR_FN_CEMV_TERMINAL_ACTION_ANALYSIS |
CEMV_APP_ERROR_FN_CEMV_CARD_ACTION_ANALYSIS |
CEMV_APP_ERROR_FN_CEMV_COMPLETION |
CEMV_APP_ERROR_FN_CEMV_TRANSACTION_MODE |
CEMV_APP_ERROR_FN_CEMV_GET_APPLICATION_NAME |
CEMV_APP_ERROR_FN_CEMV_SET_DATA_ELEMENTS |
CEMV_APP_ERROR_FN_CEMV_GET_DATA_ELEMENTS |
CEMV_APP_ERROR_FN_CEMV_UPDATE_EMV_KERNEL_CONFIG_FILE |
CEMV_APP_ERROR_FN_UI_DISPLAY_CLEAR |
CEMV_APP_ERROR_FN_UI_DISLAY_TEXT |
CEMV_APP_ERROR_FN_UI_DISPLAY_BUTTON |
CEMV_APP_ERROR_FN_UI_LIST_CREATE |
CEMV_APP_ERROR_FN_UI_LIST_ADD_ITEM |
CEMV_APP_ERROR_FN_UI_LIST_READ_BUTTON |
CEMV_APP_ERROR_FN_UI_LIST_GET_SELECTED_ITEM |
CEMV_APP_ERROR_FN_PCI_START_CUSTOM_DISPLAY_MODE |
CEMV_APP_ERROR_STATE Code |
---|
CEMV_APP_ERROR_STATE_NONE |
CEMV_APP_ERROR_STATE_SERIAL_COMM |
CEMV_APP_ERROR_STATE_VALIDATE_COMMAND |
CEMV_APP_ERROR_STATE_TRANSACTION |
CEMV_APP_ERROR_STATE_CANDIDATE_SELECTION |
CEMV_APP_ERROR_STATE_DISPLAY_APP_MENU |
CEMV_APP_ERROR_STATE_LOAD_CONFIG_GROUP |
CEMV_APP_ERROR_STATE_CARD_REMOVAL |
CEMV_APP_ERROR_STATE_UNKNOWN |