Provider Interface
Every provider package (e.g. @sanwohq/paystack, sanwo_flutterwave) exports a SanwoProviderDefinition object. This page documents that shape and the underlying template/bridge system.
SanwoProviderDefinition
Section titled “SanwoProviderDefinition”| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
Yes | Unique identifier (e.g. "paystack", "flutterwave") |
name |
string |
Yes | Internal name used in logs and events |
displayName |
string |
Yes | Human-readable name (e.g. "Paystack", "Flutterwave") |
template |
string |
Yes | HTML template with {{sanwoBridge}} and {{params}} placeholders |
website |
string? |
No | Provider’s website URL |
documentation |
string? |
No | Provider’s documentation URL |
supportedCurrencies |
string[]? |
No | ISO 4217 currency codes the provider supports |
supportedCountries |
string[]? |
No | ISO 3166 country codes the provider supports |
paymentMethods |
string[]? |
No | Payment methods the provider supports (e.g. "card", "bank_transfer") |
amountInMinorUnit |
boolean? |
No | Whether the provider natively expects minor units. If false, Sanwo auto-converts from minor to major units before passing to the template. |
TypeScript
Section titled “TypeScript”interface SanwoProviderDefinition { id: string; name: string; displayName: string; template: string; website?: string; documentation?: string; supportedCurrencies?: string[]; supportedCountries?: string[]; paymentMethods?: string[]; amountInMinorUnit?: boolean;}class SanwoProviderDefinition { final String id; final String name; final String displayName; final String template; final String? website; final String? documentation; final List<String>? supportedCurrencies; final List<String>? supportedCountries; final List<String>? paymentMethods; final bool? amountInMinorUnit;
SanwoProviderDefinition({ required this.id, required this.name, required this.displayName, required this.template, this.website, this.documentation, this.supportedCurrencies, this.supportedCountries, this.paymentMethods, this.amountInMinorUnit, });}struct SanwoProviderDefinition { let id: String let name: String let displayName: String let template: String var website: String? = nil var documentation: String? = nil var supportedCurrencies: [String]? = nil var supportedCountries: [String]? = nil var paymentMethods: [String]? = nil var amountInMinorUnit: Bool? = nil}Kotlin
Section titled “Kotlin”data class SanwoProviderDefinition( val id: String, val name: String, val displayName: String, val template: String, val website: String? = null, val documentation: String? = null, val supportedCurrencies: List<String>? = null, val supportedCountries: List<String>? = null, val paymentMethods: List<String>? = null, val amountInMinorUnit: Boolean? = null,)Template system
Section titled “Template system”The template field contains an HTML string that loads the provider’s checkout SDK and wires it up to Sanwo’s bridge. Two placeholders are injected at render time:
{{params}}
Section titled “{{params}}”Replaced with a JSON object containing the checkout parameters:
{ "amount": 500000, "currency": "NGN", "publicKey": "pk_test_xxxxxxxxxxxx", "reference": "sanwo_1719849600_a1b2c3", "customer": { "email": "customer@example.com" }}If amountInMinorUnit is false on the provider definition, the amount value is auto-converted to major units before injection (e.g. 500000 kobo becomes 5000).
{{sanwoBridge}}
Section titled “{{sanwoBridge}}”Replaced with a platform-specific JavaScript snippet that defines a sanwoBridge function. This function sends messages from the checkout iframe/webview back to the host application.
Example template
Section titled “Example template”<!DOCTYPE html><html><head> <script src="https://js.paystack.co/v2/inline.js"></script></head><body> <script> {{sanwoBridge}}
const params = {{params}};
const handler = PaystackPop.setup({ key: params.publicKey, email: params.customer.email, amount: params.amount, currency: params.currency, ref: params.reference, onSuccess: (response) => { sanwoBridge({ type: "sanwo", event: "success", data: response }); }, onCancel: () => { sanwoBridge({ type: "sanwo", event: "cancelled", data: {} }); }, onLoad: () => { sanwoBridge({ type: "sanwo", event: "loaded", data: {} }); }, });
handler.openIframe(); </script></body></html>Bridge mechanisms
Section titled “Bridge mechanisms”Each platform injects a different sanwoBridge implementation via the {{sanwoBridge}} placeholder:
| Platform | Bridge mechanism | Injected code |
|---|---|---|
| Web | Parent window postMessage | window.parent.postMessage(...) |
| React Native | WebView postMessage | window.ReactNativeWebView.postMessage(...) |
| Flutter | JavaScript channel | messageHandler.postMessage(...) |
| iOS | WKWebView message handler | window.webkit.messageHandlers.sanwo.postMessage(...) |
| Android | JavaScript interface | JSBridge.showMessageInNative(...) |
Bridge message format
Section titled “Bridge message format”All bridges send messages with the same shape:
interface SanwoBridgeMessage { type: "sanwo"; event: "success" | "cancelled" | "closed" | "error" | "loaded"; data: Record<string, unknown>;}| Event | When | Typical data contents |
|---|---|---|
success |
Payment completed | { reference, transactionId, ... } (provider-specific) |
cancelled |
User dismissed checkout | {} |
closed |
Checkout UI torn down | {} |
error |
Provider error occurred | { message, code?, ... } |
loaded |
Provider SDK finished loading | {} |
The host SDK parses these messages and translates them into the platform-specific CheckoutResult.
Amount conversion
Section titled “Amount conversion”When amountInMinorUnit is true (or omitted), the amount is passed through unchanged. When false, Sanwo divides by 100 before injecting into {{params}}:
amountInMinorUnit |
You pass | Template receives | Example provider |
|---|---|---|---|
true (default) |
500000 |
500000 |
Paystack |
false |
500000 |
5000 |
Flutterwave, Monnify |
This ensures you always work with minor units in your application code, regardless of what the provider SDK expects.