Skip to main content

Transaction States & Lifecycle

A Transaction State represents the precise financial and operational stage of a payment attempt as it moves through the SolydFlow revenue engine.


The SolydFlow Unified State Machine​

SolydFlow normalizes payment quirks across all gateways into eight distinct states:

1. Transient (Non-Final) States​

StateDescriptionEntitlement Status
INITIALIZEDThe intent was generated by the SDK. Awaiting user interaction.Locked 🔒
PENDING_CHALLENGEWaiting on user action (e.g., bank OTP, 3D-Secure modal, or M-Pesa USSD PIN entry).Locked 🔒
PROCESSINGPayment submitted. The payment rail is clearing funds with the issuing bank.Locked 🔒
UNRESOLVEDPayment initiated, but user closed app or callback timed out without final confirmation.Held in Review ⏳
RECOVERINGThe SolydFlow Sweeper is actively polling the provider's REST verification endpoint.Held in Review ⏳
Never Assume Failure on Non-Final States

If a user closes their browser or their mobile data drops while in PROCESSING or UNRESOLVED, never display a "Payment Failed" error. The transaction is routed into RECOVERING and will settle automatically once consensus is established.


2. Authoritative (Final) States​

StateDescriptionEntitlement Status
SETTLED_CONSENSUSFinal Success. The payment is cryptographically verified by the Consensus Engine.Unlocked ✅
FAILED_DECLINEDFinal Failure. Gateway confirmed insufficient funds, expired card, or invalid PIN.Locked 🔒
REVOKED_REFUNDFinal Reversal. A dispute, chargeback, or admin refund cancelled the transaction.Revoked ❌

Gateway Normalization Matrix​

Different gateways use conflicting nomenclature for similar payment conditions. SolydFlow maps them to unified states:

ScenarioPaystack StateFlutterwave StateStripe StateM-Pesa (Daraja)SolydFlow Normalized State
STK / OTP Promptsend_otppending-otprequires_actionSTK SentPENDING_CHALLENGE
Dropped Callbackongoing / Noneunknown / NoneprocessingNo WebhookUNRESOLVED
Verified SuccesssuccesssuccessfulsucceededResultCode: 0SETTLED_CONSENSUS
User CancelledabandonedcancelledcanceledResultCode: 1032FAILED_DECLINED
Bank Chargebackreversedchargebackcharge.disputeReversalREVOKED_REFUND

How Your Application Should Handle States​

Your client-side code should never parse gateway status strings. Rely on the SDK's high-level entitlement methods:

State Handling Best Practice (Flutter)
Future<void> handlePurchaseFlow(BuildContext context, String packageId) async {
// 1. Initiate purchase - SDK manages INITIALIZED, PENDING, & PROCESSING
final CustomerInfo? info = await SolydFlow.purchasePackage(context, packageId);

// 2. User dismissed modal before submitting
if (info == null) {
debugPrint("Purchase modal dismissed.");
return;
}

// 3. Evaluate Authoritative Settlement
if (info.activeEntitlements["pro_access"] == true) {
// SETTLED_CONSENSUS achieved
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("🎉 Pro access unlocked!")),
);
} else {
// SDK will quietly recover in background if state is UNRESOLVED
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Verifying payment... Check back shortly.")),
);
}
}