React SDK
React components and hooks for integrating ZevPay Checkout. Wraps the Inline Checkout SDK with idiomatic React APIs.
Installation
npm install @zevpay/react @zevpay/inlineRequires React 18 or later.
Quick start
Button component
The simplest way to add checkout — renders a button that opens the payment modal on click:
import { ZevPayButton } from '@zevpay/react';
function CheckoutPage() {
return (
<ZevPayButton
apiKey="pk_test_your_public_key"
email="customer@example.com"
amount={500000} // ₦5,000 in kobo
onSuccess={(reference) => {
console.log('Payment successful:', reference);
// Verify payment on your server
}}
>
Pay ₦5,000
</ZevPayButton>
);
}Hook
For custom UI — call openCheckout() from any event handler:
import { useZevPayCheckout } from '@zevpay/react';
function CheckoutPage() {
const { openCheckout } = useZevPayCheckout({
apiKey: 'pk_test_your_public_key',
onSuccess: (reference) => {
console.log('Paid:', reference);
},
onClose: () => {
console.log('Modal closed');
},
});
return (
<button onClick={() => openCheckout({
email: 'customer@example.com',
amount: 500000,
reference: 'ORDER-123',
firstName: 'John',
lastName: 'Doe',
})}>
Pay ₦5,000
</button>
);
}Provider (shared API key)
Wrap your app in <ZevPayProvider> to avoid repeating apiKey on every component:
import { ZevPayProvider, ZevPayButton } from '@zevpay/react';
function App() {
return (
<ZevPayProvider apiKey="pk_test_your_public_key">
<StorePage />
</ZevPayProvider>
);
}
function StorePage() {
// No apiKey needed — inherited from provider
return (
<ZevPayButton email="customer@example.com" amount={500000}>
Pay ₦5,000
</ZevPayButton>
);
}<ZevPayButton />
A button that opens ZevPay Checkout on click.
Props
| Prop | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes* | Your public API key (pk_live_* or pk_test_*) |
email | string | Yes | Customer email address |
amount | number | Yes | Amount in kobo (₦1 = 100 kobo) |
currency | string | No | Currency code. Default: "NGN" |
reference | string | No | Your unique transaction reference |
firstName | string | No | Customer first name |
lastName | string | No | Customer last name |
metadata | object | No | Custom metadata attached to the transaction |
paymentMethods | "all" | string[] | No | Payment methods to show |
onSuccess | (reference: string) => void | No | Called when payment is confirmed |
onClose | () => void | No | Called when the modal closes |
onError | (error: Error) => void | No | Called on error |
onFailure | (error?: Error) => void | No | Called when payment fails |
onExpired | () => void | No | Called when session expires |
onInitialize | () => void | No | Called when session initializes |
children | ReactNode | No | Button content. Default: "Pay Now" |
className | string | No | CSS class name for the button |
disabled | boolean | No | Whether the button is disabled |
*Required unless <ZevPayProvider> is used.
Examples
// Minimal
<ZevPayButton
apiKey="pk_test_xxx"
email="customer@example.com"
amount={500000}
onSuccess={(ref) => verifyPayment(ref)}
>
Pay
</ZevPayButton>
// With all options
<ZevPayButton
apiKey="pk_test_xxx"
email="customer@example.com"
amount={500000}
currency="NGN"
reference="ORDER-123"
firstName="John"
lastName="Doe"
metadata={{ orderId: '123' }}
paymentMethods={['bank', 'payid']}
className="btn btn-primary"
onSuccess={(ref) => verifyPayment(ref)}
onClose={() => console.log('closed')}
onError={(err) => console.error(err)}
>
Pay ₦5,000
</ZevPayButton>useZevPayCheckout(config)
Hook for imperative checkout control.
Config
Shared options that persist across calls:
| Option | Type | Description |
|---|---|---|
apiKey | string | Public API key (or use <ZevPayProvider>) |
currency | string | Currency code |
paymentMethods | "all" | string[] | Payment methods to enable |
onSuccess | function | Success callback |
onClose | function | Close callback |
onError | function | Error callback |
onFailure | function | Failure callback |
onExpired | function | Expiry callback |
onInitialize | function | Init callback |
Return value
| Property | Type | Description |
|---|---|---|
openCheckout | (params) => void | Opens the checkout modal |
openCheckout params
Per-call parameters:
| Param | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Customer email |
amount | number | Yes | Amount in kobo |
reference | string | No | Transaction reference |
firstName | string | No | Customer first name |
lastName | string | No | Customer last name |
metadata | object | No | Custom metadata |
Example
function DonationPage() {
const [email, setEmail] = useState('');
const [amount, setAmount] = useState(0);
const { openCheckout } = useZevPayCheckout({
apiKey: 'pk_test_xxx',
onSuccess: (reference) => {
fetch('/api/verify', {
method: 'POST',
body: JSON.stringify({ reference }),
});
},
});
return (
<form onSubmit={(e) => {
e.preventDefault();
openCheckout({ email, amount: amount * 100 });
}}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Your email"
/>
<input
type="number"
value={amount}
onChange={(e) => setAmount(Number(e.target.value))}
placeholder="Amount in Naira"
/>
<button type="submit">Donate</button>
</form>
);
}<ZevPayProvider>
Context provider for sharing configuration across components.
| Prop | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | Shared public API key |
children | ReactNode | Yes | Child components |
Both <ZevPayButton> and useZevPayCheckout() will inherit the API key from the nearest provider. A direct apiKey prop/config always takes priority over the provider.
Payment methods
// All methods (default)
<ZevPayButton paymentMethods="all" ... />
// Specific methods
<ZevPayButton paymentMethods={['bank', 'payid']} ... />
// Bank transfer only
<ZevPayButton paymentMethods={['bank']} ... />| Method | Value | Status |
|---|---|---|
| Bank Transfer | "bank" | Available |
| ZevPay ID | "payid" | Available |
| Card | "card" | Coming soon |
Verify payments
Always verify server-side
Never trust the client-side onSuccess callback alone. Always verify the payment on your server.
// Server-side (Node.js)
import ZevPay from '@zevpay/node';
const zevpay = new ZevPay('sk_live_xxx');
const result = await zevpay.checkout.verify(sessionId);
if (result.status === 'completed') {
// Payment confirmed — fulfill the order
}TypeScript
All types are exported:
import type {
ZevPayCheckoutOptions,
ZevPayButtonProps,
UseZevPayConfig,
OpenCheckoutParams,
UseZevPayReturn,
PaymentMethodOption,
} from '@zevpay/react';Error types from the inline SDK are also re-exported:
import { CheckoutError } from '@zevpay/react';Resources
- API Reference — Full endpoint documentation
- Inline Checkout SDK — Underlying checkout SDK
- Webhook Events — All event types
- npm — Package registry