Skip to content

React Native

Terminal window
npm i @sanwohq/react-native @sanwohq/paystack react-native-webview
Package Minimum version
react >= 18
react-native >= 0.70
react-native-webview >= 11

For iOS, run npx pod-install after installing.

import { SanwoProvider } from "@sanwohq/react-native";
import { paystack } from "@sanwohq/paystack";
export default function App() {
return (
<SanwoProvider provider={paystack} publicKey="pk_test_xxxxxxxxxxxx">
<CheckoutScreen />
</SanwoProvider>
);
}
import { useSanwoCheckout } from "@sanwohq/react-native";
import { View, Button, Alert } from "react-native";
function CheckoutScreen() {
const { checkout, isLoading, result } = useSanwoCheckout();
async function pay() {
const res = await checkout({
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
});
if (res.status === "successful") {
Alert.alert("Payment successful", `Ref: ${res.reference}`);
}
}
return (
<View style={{ flex: 1, justifyContent: "center", padding: 20 }}>
<Button
title={isLoading ? "Processing…" : "Pay ₦5,000"}
onPress={pay}
disabled={isLoading}
/>
</View>
);
}
<SanwoProvider
provider={paystack}
publicKey="pk_test_xxxxxxxxxxxx"
debug={false}
timeout={120}
>
{children}
</SanwoProvider>
Prop Type Required Default Description
provider SanwoProvider Yes Imported provider
publicKey string Yes Your provider public key
debug boolean No false Log events to console
timeout number No 120 Checkout timeout in seconds

Internally, SanwoProvider renders a Modal containing a WebView. No native modules are required beyond react-native-webview.

Same API as the React web package.

const { checkout, isLoading, error, result, reset } = useSanwoCheckout();
Value Type Description
checkout (options: CheckoutOptions) => Promise<CheckoutResult> Start a checkout
isLoading boolean true while checkout is in progress
error Error | null Set if checkout threw
result CheckoutResult | null Last checkout result
reset () => void Clear error and result
Option Type Required Description
amount number Yes Amount in minor units
currency string Yes ISO 4217 currency code
customer { email: string } Yes Customer details
reference string No Your transaction reference
channels string[] No Allowed payment channels
metadata Record<string, unknown> No Arbitrary metadata
type CheckoutResult =
| { status: "successful"; reference: string; providerResponse: unknown }
| { status: "cancelled" }
| { status: "failed"; error: string }
| { status: "pending"; reference: string };

Low-level hook for direct access to provider config and event subscription.

const { provider, providerId, publicKey, debug, timeout, on, off } = useSanwo();
Value Type Description
provider SanwoProvider The active provider instance
providerId string Provider identifier string
publicKey string The public key in use
debug boolean Whether debug mode is on
timeout number Timeout in seconds
on (event, handler) => void Subscribe to an event
off (event, handler) => void Unsubscribe from an event
import { useSanwo } from "@sanwohq/react-native";
import { useEffect } from "react";
function PaymentTracker() {
const { on, off } = useSanwo();
useEffect(() => {
const handler = (data) => {
analytics.track("payment_success", { ref: data.reference });
};
on("success", handler);
return () => off("success", handler);
}, [on, off]);
return null;
}
import React from "react";
import { SafeAreaView, View, Text, Button, Alert, StyleSheet } from "react-native";
import { SanwoProvider, useSanwoCheckout } from "@sanwohq/react-native";
import { paystack } from "@sanwohq/paystack";
function CheckoutScreen() {
const { checkout, isLoading, result, reset } = useSanwoCheckout();
async function pay() {
const res = await checkout({
amount: 500000,
currency: "NGN",
customer: { email: "customer@example.com" },
reference: `order_${Date.now()}`,
});
switch (res.status) {
case "successful":
Alert.alert("Success", `Reference: ${res.reference}`);
break;
case "cancelled":
Alert.alert("Cancelled", "You closed the checkout.");
break;
case "failed":
Alert.alert("Failed", res.error);
break;
}
}
return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>My Store</Text>
<View style={styles.card}>
<Text>Premium Plan — ₦5,000</Text>
<Button
title={isLoading ? "Processing…" : "Pay Now"}
onPress={pay}
disabled={isLoading}
/>
</View>
{result && (
<Button title="Reset" onPress={reset} />
)}
</SafeAreaView>
);
}
export default function App() {
return (
<SanwoProvider provider={paystack} publicKey="pk_test_xxxxxxxxxxxx">
<CheckoutScreen />
</SanwoProvider>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 20 },
title: { fontSize: 24, fontWeight: "bold", marginBottom: 20 },
card: { padding: 20, backgroundColor: "#f5f5f5", borderRadius: 8, gap: 12 },
});

The React Native SDK renders the provider’s checkout page inside a react-native-webview WebView, wrapped in a React Native Modal. Communication between your app and the checkout happens via the WebView’s postMessage bridge. No additional native modules or linking steps are needed.