Web / JavaScript
Installation
Section titled “Installation”npm i @sanwohq/web @sanwohq/paystackReplace @sanwohq/paystack with whichever provider you need (@sanwohq/flutterwave, @sanwohq/razorpay, etc.).
Quick start
Section titled “Quick start”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);}createSanwo(config)
Section titled “createSanwo(config)”Returns a callable SanwoInstance.
Config options
Section titled “Config options”| 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 |
Calling the instance
Section titled “Calling the instance”const result = await sanwo(checkoutOptions);Checkout options
Section titled “Checkout options”| 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 |
Checkout result
Section titled “Checkout result”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;}Events
Section titled “Events”Subscribe to lifecycle events with sanwo.on(). It returns an unsubscribe function.
const unsub = sanwo.on("success", (data) => { console.log("Payment succeeded:", data.reference);});
// laterunsub();Available events
Section titled “Available events”| 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 |
Instance methods & properties
Section titled “Instance methods & properties”| 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 |
Framework examples
Section titled “Framework examples”<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><script setup>import { ref } from "vue";import { createSanwo } from "@sanwohq/web";import { paystack } from "@sanwohq/paystack";
const sanwo = createSanwo({ provider: paystack, publicKey: "pk_test_xxxxxxxxxxxx",});
const paying = ref(false);
async function pay() { paying.value = true; const result = await sanwo({ amount: 500000, currency: "NGN", customer: { email: "customer@example.com" }, }); paying.value = false;
if (result.status === "successful") { alert("Paid! Ref: " + result.reference); }}</script>
<template> <button @click="pay" :disabled="paying"> {{ paying ? "Processing…" : "Pay ₦5,000" }} </button></template><script> import { createSanwo } from "@sanwohq/web"; import { paystack } from "@sanwohq/paystack";
const sanwo = createSanwo({ provider: paystack, publicKey: "pk_test_xxxxxxxxxxxx", });
let paying = false;
async function pay() { paying = true; const result = await sanwo({ amount: 500000, currency: "NGN", customer: { email: "customer@example.com" }, }); paying = false;
if (result.status === "successful") { alert("Paid! Ref: " + result.reference); } }</script>
<button on:click={pay} disabled={paying}> {paying ? "Processing…" : "Pay ₦5,000"}</button>Provider-specific options
Section titled “Provider-specific options”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.