Cordova SDK — Integration Guide
Fetch the integration-path skill for machine-readable setup guidance and code examples: /.well-known/skills/paths/cordova.md
What is this integration path?
The Handpoint Cordova plugin (cordova-plugin-handpoint) brings payment capabilities to cross-platform Cordova and Ionic applications. It supports both PAX SmartPOS terminals (via Cloud) and HiLite Bluetooth readers.
Choose this path when your team is already building in Cordova or Ionic and wants payment without a separate native SDK.
When to use it
| ✅ Good fit | ❌ Not a good fit |
|---|---|
| Your app is built with Cordova or Ionic | You're building a native Android app — use the Android PAX or Android HiLite path |
| You need a single codebase for Android and iOS | You need iOS + HiLite — the iOS HiLite path is the native option |
| You're targeting PAX Cloud or HiLite Bluetooth | You need advanced pre-auth — not supported on HiLite via Cordova |
Backoffice REST API operations — tip adjustment, reversals, refunds, MOTO charges, batch management, deferred tokenization — are available alongside any integration path you choose. They go server-side directly to the payment gateway with no terminal or SDK required. Subject only to acquirer support.
Capabilities not available on HiLite via Cordova
- Pre-authorization
- MOTO / remote sale on-terminal
How it works
Your Cordova / Ionic App
│ HAPI.sale({ amount, currency })
▼
cordova-plugin-handpoint
│ Cloud (PAX) or Bluetooth (HiLite)
▼
PAX Terminal or HiLite Reader
│ chip / tap / swipe + P2PE
▼
handpoint.endOfTransaction DOM event
Authentication
| Credential | Purpose | Provisioned by |
|---|---|---|
apiKey | Merchant API key for Cloud connection | Handpoint Integration Support |
sharedSecret | For Bluetooth (HiLite) — authenticates to reader | Handpoint Integration Support |
Setup
1. Request credentials
Contact your Handpoint Integration Support engineer for:
- A merchant API key (PAX Cloud) or shared secret (HiLite)
- A PAX DEMO terminal or HiLite reader
2. Install the plugin
Cordova:
cordova plugin add cordova-plugin-handpoint
Ionic:
npm install cordova-plugin-handpoint
ionic cap sync
3. Initialise
// PAX SmartPOS (Cloud path)
handpoint.setup({
sharedSecret: 'YOUR_SHARED_SECRET',
automaticReconnection: true
}, successCallback, errorCallback);
// HiLite Bluetooth path
handpoint.setup({
sharedSecret: 'YOUR_SHARED_SECRET',
automaticReconnection: true
}, successCallback, errorCallback);
Call handpoint.setup() once on app start. Do not re-initialise per transaction.
4. Register event listeners
// Transaction result
document.addEventListener('handpoint.endOfTransaction', function(event) {
const result = event.detail.transactionResult;
handleResult(result);
});
// Device discovery (HiLite Bluetooth path)
document.addEventListener('handpoint.deviceDiscoveryFinished', function(event) {
const devices = event.detail.devices;
if (devices.length > 0) {
HAPI.connect({ deviceName: devices[0].name }, success, error);
}
});
5. Connect to a terminal
PAX Cloud:
// Connect by device name (serial-model format)
HAPI.connect({ deviceName: '0821032395-PAXA920' }, successCallback, errorCallback);
HiLite Bluetooth — discovery:
HAPI.startMonitoring(successCallback, errorCallback);
// deviceDiscoveryFinished event fires with the list
Your first transaction
// Amount in smallest currency unit — £10.00 = 1000
HAPI.sale({
amount: 1000,
currency: 'GBP',
customerReference: 'ORDER-123'
}, successCallback, errorCallback);
// Result arrives in handpoint.endOfTransaction event
Reading the result
document.addEventListener('handpoint.endOfTransaction', function(event) {
const result = event.detail.transactionResult;
const status = result.finStatus; // 'AUTHORISED', 'DECLINED', etc.
const txId = result.transactionID; // store for reversals and refunds
switch (status) {
case 'AUTHORISED':
db.markPaid(txId);
break;
case 'DECLINED':
case 'CANCELLED':
case 'FAILED':
db.clearPending();
break;
case 'UNDEFINED':
// Do not retry — recover via getTransactionStatus
startBackgroundRecovery(savedTransactionReference);
break;
}
});
UNDEFINED indicates no result was received (e.g. connection dropped after card tap). The transaction may have processed. Always recover via HAPI.getTransactionStatus() before retrying.
Transaction recovery
Always save a transactionReference you generate before starting any operation.
const transactionReference = generateUUID();
db.savePendingTransaction(transactionReference);
HAPI.sale({
amount: 1000,
currency: 'GBP',
transactionReference: transactionReference
}, success, error);
On UNDEFINED or app restart with a pending reference:
function startBackgroundRecovery(ref) {
HAPI.getTransactionStatus(
{ transactionReference: ref },
function(result) {
if (result.finStatus === 'IN_PROGRESS' || result.finStatus === 'UNDEFINED') {
// Poll again in 10 s
setTimeout(() => startBackgroundRecovery(ref), 10_000);
return;
}
// Wait 60 s before acting (covers PARTIAL_APPROVAL window)
setTimeout(() => {
if (result.finStatus === 'AUTHORISED') {
sendReversal(result.transactionID);
}
db.clearPending(ref);
}, 60_000);
},
function(error) {
console.error('getTransactionStatus error:', error);
}
);
}
// On app startup
const pending = db.getPendingTransaction();
if (pending) startBackgroundRecovery(pending.ref);
→ Full implementation: Transaction Recovery — Cordova SDK
Operations available
| Operation | Method |
|---|---|
| Sale | HAPI.sale({ amount, currency, customerReference? }) |
| Refund | HAPI.refund({ amount, currency, originalTransactionID? }) |
| Reversal | HAPI.reversal({ originalTransactionID, amount? }) |
| Pre-Authorization | HAPI.preAuthorization({ amount, currency }) — PAX only |
| Pre-Auth Capture | HAPI.preAuthorizationCapture({ amount, originalTransactionID }) — PAX only |
| Pre-Auth Reversal | HAPI.preAuthorizationReversal({ originalTransactionID }) — PAX only |
| Tip Adjustment | HAPI.tipAdjustment({ tipAmount, originalTransactionID }) |
| Get Transaction Status | HAPI.getTransactionStatus({ transactionReference }) |
| Stop Transaction | HAPI.stopCurrentTransaction() |
Acquirer-specific availability: see your acquirer's page for supported features: EPI · PAYSAFE · EmerchantPay · Paystrax.
Test amounts
Pass amounts in minor units (cents / pence). Use the full trigger table — including partial approval (3757) and timeout (3768) — from Development Hardware: Testing with trigger amounts. Any amount not in the table approves.
Validation & certification
Required for every integration:
-
transactionReferencegenerated and persisted before eachHAPI.sale()call — scoping rules -
handpoint.endOfTransactionlistener registered before any transaction starts -
UNDEFINEDrecovery flow implemented and tested - App-restart recovery — pending reference polled on startup
- Partial approval handled —
PARTIAL_APPROVALdetected; collect split tender or send automatic reversal (partial approval guide)
→ Full scenario checklist: Validate your integration
→ Error codes: Error codes
See Also
- Cordova Objects Reference — full type definitions for transaction results, options, and enums
- Cordova Events Reference — all SDK callback events and their payloads