Transaction Lifecycle
How a payment moves from start to finish
Every transaction goes through these statuses.
State Diagram
pending -> processing -> successful
-> failed
-> cancelledStatus Definitions
pending
The transaction has been created in the Nylon Pay system but has not yet been sent to the payment provider. This is the initial state for all new transactions.
Note: During this state, you can still modify certain transaction details before it moves forward.
processing
The transaction has been submitted to the payment provider and is awaiting completion. For mobile money payments, this typically means the customer has received a PIN prompt or is completing authentication.
Note: Transactions in
processingstate may take minutes or hours to complete depending on the payment method and customer action.
successful
The payment provider has confirmed the transaction. Funds have moved (or will move shortly) and the transaction is complete.
Terminal state: No further status changes will occur for this transaction.
failed
The payment was rejected by the provider or the customer declined to complete payment. Common reasons include insufficient funds, invalid credentials, or provider-side errors.
Terminal state: Failed transactions may be eligible for retry with corrected details.
cancelled
The transaction was cancelled before completion. Cancellation can occur through explicit user action, merchant cancellation via API, or system cancellation due to timeout.
Terminal state: Cancelled transactions cannot be restarted.
Operator Transaction ID
When a payment reaches a terminal status (successful or failed), the transaction record may include an operatorTid field. This is the transaction identifier from the underlying payment operator (the telco or bank that processed the payment).
Use operatorTid to cross-validate customer payment claims. A customer who says they paid can provide their operator receipt, and you can match the ID against the operatorTid on the transaction.
The field is null until the operator reports it, and may not be available for all payment methods.
Status Summary
| Status | Meaning | Terminal | Can Retry |
|---|---|---|---|
pending | Created, not yet sent | No | N/A |
processing | Sent to provider, awaiting customer | No | N/A |
successful | Payment confirmed | Yes | No |
failed | Payment rejected | Yes | Yes (with corrections) |
cancelled | Cancelled before completion | Yes | No |
Transition Triggers
| Transition | Trigger |
|---|---|
pending -> processing | SDK submits transaction to provider |
processing -> successful | Provider confirms payment |
processing -> failed | Provider rejects or customer declines |
processing -> cancelled | Timeout reached or explicit cancellation |
pending -> cancelled | Explicit cancellation before submission |
SDK Event Mapping
The SDK exposes events that correspond to these status changes:
| Status Change | SDK Event | When to Use |
|---|---|---|
| Transaction created | (initial state) | Log transaction start |
pending -> processing | payment.on('processing', ...) | Show "Processing" UI |
processing -> successful | payment.on('success', ...) | Fulfill order, show success |
processing -> failed | payment.on('failed', ...) | Show error, offer retry |
processing -> cancelled | payment.on('cancelled', ...) | Show cancellation message |
| Any error | payment.on('error', ...) | Log error, notify support |
Example: Handling Status Changes
const payment = await nylonPay.collectPayment({
amount: 5000,
currency: 'UGX',
description: 'Product purchase',
customer: {
name: 'John Doe',
phoneNumber: '+256700000000'
},
reference: crypto.randomUUID(),
});
payment.on('processing', () => {
// Update UI: "Awaiting customer confirmation"
updateOrderStatus('waiting_for_payment');
});
payment.on('success', ({ transaction }) => {
// Fulfill order
if (transaction) {
fulfillOrder(transaction.reference);
}
sendConfirmationEmail();
});
payment.on('failed', () => {
// Show error message
showErrorMessage('Payment failed. Please try again.');
});
payment.on('cancelled', () => {
// Clean up
cancelOrder();
showMessage('Payment was cancelled.');
});
payment.on('error', (data) => {
// Log for debugging
console.error('Payment error:', data.error);
notifySupport(data);
});