Skip to content

Web / JavaScript

Terminal window
npm i @sanwohq/web @sanwohq/paystack

Replace @sanwohq/paystack with whichever provider you need (@sanwohq/flutterwave, @sanwohq/razorpay, etc.).

import { createSanwo } from "@sanwohq/web";
import { paystack } from "@sanwohq/paystack";
const sanwo = createSanwo({
provider: paystack,
publicKey: "pk_test_xxxxxxxxxxxx",
});
const result = await sanwo({
amount: 500000, // 5,000.00 NGN in kobo
currency: "NGN",
customer: { email: "customer@example.com" },
});
if (result.status === "successful") {
console.log("Paid!", result.reference);
}

Returns a callable SanwoInstance.

Option Type Required Default Description
provider SanwoProvider Yes Imported provider (e.g. paystack)
publicKey string Yes Your provider public/API key
debug boolean No false Log internal events to console
timeout number No 120 Seconds before checkout auto-cancels
containerId string No DOM element ID to render checkout into instead of a modal
const result = await sanwo(checkoutOptions);
Option Type Required Description
amount number Yes Amount in minor units (kobo, cents, paisa)
currency string Yes ISO 4217 currency code
customer { email: string } Yes Customer details
reference string No Your unique transaction reference
channels string[] No Allowed payment channels
metadata Record<string, unknown> No Arbitrary metadata
sanwoProviderOptions Record<string, unknown> No Provider-specific options passed through to the underlying SDK

The result is a discriminated union on status:

type CheckoutResult =
| { status: "successful"; reference: string; providerResponse: unknown }
| { status: "cancelled" }
| { status: "failed"; error: string }
| { status: "pending"; reference: string };
switch (result.status) {
case "successful":
// result.reference, result.providerResponse
break;
case "cancelled":
// user closed the checkout
break;
case "failed":
// result.error
break;
case "pending":
// result.reference — verify server-side
break;
}

Subscribe to lifecycle events with sanwo.on(). It returns an unsubscribe function.

const unsub = sanwo.on("success", (data) => {
console.log("Payment succeeded:", data.reference);
});
// later
unsub();
Event Payload When
started CheckoutOptions Checkout initiated
opened Modal/container visible
loaded Provider UI finished loading
success { reference, providerResponse } Payment successful
cancelled User dismissed checkout
failed { error } Payment failed
closed Checkout UI removed from DOM
API Description
sanwo.close() Tears down the current checkout UI
sanwo.destroy() Calls close() and removes all event listeners
sanwo.providerId Read-only string — the provider’s identifier
sanwo.currentState Read-only string — current checkout state
<button id="pay">Pay ₦5,000</button>
<script type="module">
import { createSanwo } from "@sanwohq/web";
import { paystack } from "@sanwohq/paystack";
const sanwo = createSanwo({
provider: paystack,
publicKey: "pk_test_xxxxxxxxxxxx",
});
document.getElementById("pay").addEventListener("click", async () => {
const result = await sanwo({
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
});
alert(result.status);
});
</script>

Pass provider-specific configuration through sanwoProviderOptions:

const result = await sanwo({
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
sanwoProviderOptions: {
// These are passed directly to the provider SDK
split_code: "SPL_xxxxxxxx",
},
});

Refer to your provider’s documentation for available options.