CheckoutResult
CheckoutResult represents the outcome of a checkout. It uses a discriminated union (TypeScript), an enum (Swift), a sealed class (Kotlin), or a status enum on a result class (Dart) so you can exhaustively handle every case.
Statuses by platform
Section titled “Statuses by platform”| Status | Web / React / React Native | Flutter / iOS / Android |
|---|---|---|
successful |
Yes | Yes |
cancelled |
Yes | Yes |
failed |
Yes | Yes |
pending |
Yes | No |
The pending status is only returned on web-based platforms where the browser can close before the provider confirms the transaction. On native platforms, the checkout always resolves to a terminal state.
TypeScript
Section titled “TypeScript”type CheckoutResult = | SuccessfulCheckoutResult | CancelledCheckoutResult | FailedCheckoutResult | PendingCheckoutResult;
interface SuccessfulCheckoutResult { status: "successful"; provider: string; reference: string; transactionId?: string; message?: string; raw: unknown;}
interface CancelledCheckoutResult { status: "cancelled"; provider: string; reference?: string; raw?: unknown;}
interface FailedCheckoutResult { status: "failed"; provider: string; reference?: string; error: SanwoErrorInfo; raw?: unknown;}
interface PendingCheckoutResult { status: "pending"; provider: string; reference?: string; raw?: unknown;}Handling results (TypeScript)
Section titled “Handling results (TypeScript)”const result = await sanwo({ amount: 500000, currency: "NGN", customer: { email: "customer@example.com" },});
switch (result.status) { case "successful": console.log(`Paid! Ref: ${result.reference}`); // result.transactionId, result.message, result.raw break; case "cancelled": console.log("User closed checkout"); break; case "failed": console.error(`Error: ${result.error.message}`); if (result.error.recoverable) { // safe to retry } break; case "pending": // verify server-side using result.reference console.log(`Pending — verify ref: ${result.reference}`); break;}enum CheckoutStatus { successful, cancelled, failed }
class CheckoutResult { final CheckoutStatus status; final String? reference; final String? transactionId; final String? message; final Map<String, dynamic> data;
CheckoutResult({ required this.status, this.reference, this.transactionId, this.message, this.data = const {}, });}Handling results (Dart)
Section titled “Handling results (Dart)”final result = await sanwo( context: context, options: CheckoutOptions( amount: 500000, currency: 'NGN', customer: CheckoutCustomer(email: 'customer@example.com'), ),);
switch (result.status) { case CheckoutStatus.successful: print('Paid! Ref: ${result.reference}'); print('Transaction ID: ${result.transactionId}'); break; case CheckoutStatus.cancelled: print('User cancelled'); break; case CheckoutStatus.failed: print('Payment failed: ${result.message}'); break;}enum CheckoutResult { case successful(SuccessData) case cancelled(provider: String, reference: String?) case failed(provider: String, reference: String?, error: SanwoError)}
struct SuccessData { let provider: String let reference: String let transactionId: String? let raw: Any?}Handling results (Swift)
Section titled “Handling results (Swift)”sanwo(from: self, options: options) { result in switch result { case .successful(let data): print("Paid! Ref: \(data.reference)") if let txnId = data.transactionId { print("Transaction ID: \(txnId)") } case .cancelled(let provider, let reference): print("Cancelled by user (provider: \(provider))") case .failed(let provider, let reference, let error): print("Failed: \(error.message)") }}Kotlin
Section titled “Kotlin”sealed class CheckoutResult { data class Successful( val provider: String, val reference: String, val transactionId: String? = null, val raw: Any? = null, ) : CheckoutResult()
data class Cancelled( val provider: String, val reference: String? = null, ) : CheckoutResult()
data class Failed( val provider: String, val reference: String? = null, val error: SanwoErrorInfo, ) : CheckoutResult()}Handling results (Kotlin)
Section titled “Handling results (Kotlin)”when (result) { is CheckoutResult.Successful -> { Log.d("Sanwo", "Paid! Ref: ${result.reference}") result.transactionId?.let { Log.d("Sanwo", "Transaction ID: $it") } } is CheckoutResult.Cancelled -> { Log.d("Sanwo", "User cancelled") } is CheckoutResult.Failed -> { Log.e("Sanwo", "Failed: ${result.error.message}") if (result.error.recoverable) { // safe to retry } }}SanwoErrorInfo
Section titled “SanwoErrorInfo”Returned inside FailedCheckoutResult (web) and CheckoutResult.Failed (native).
interface SanwoErrorInfo { code: SanwoErrorCode; message: string; provider?: string; recoverable: boolean; cause?: unknown;}| Field | Type | Description |
|---|---|---|
code |
SanwoErrorCode |
Machine-readable error code. See table below. |
message |
string |
Human-readable error description. |
provider |
string? |
Provider that raised the error, if applicable. |
recoverable |
boolean |
true if the checkout can be retried without changes. |
cause |
unknown? |
The original error/exception from the provider SDK. |
SanwoErrorCode
Section titled “SanwoErrorCode”All 12 error codes with descriptions:
| Code | Description |
|---|---|
UNKNOWN |
An unexpected error occurred that does not match any known category. |
NETWORK_ERROR |
Network request failed (timeout, DNS, connectivity). |
PROVIDER_ERROR |
The payment provider returned an error. |
INVALID_AMOUNT |
The amount is invalid (zero, negative, or non-numeric). |
INVALID_CURRENCY |
The currency code is not supported or malformed. |
INVALID_CUSTOMER |
Customer data is missing or invalid (e.g. no email). |
INVALID_KEY |
The public key is invalid, expired, or does not match the provider. |
CHECKOUT_TIMEOUT |
The checkout exceeded the configured timeout duration. |
PROVIDER_NOT_FOUND |
No provider was configured or the provider package is missing. |
TEMPLATE_ERROR |
The provider’s HTML template failed to load or render. |
BRIDGE_ERROR |
Communication between the checkout UI and the host app broke down. |
CANCELLED_BY_SYSTEM |
The checkout was cancelled by the OS or system (e.g. app backgrounded on mobile). |