npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-nomba-checkout-sdk

v2.1.5

Published

Nomba checkout sdk for react apps.

Downloads

722

Readme

🚀 React Nomba Checkout SDK

The react-nomba-checkout-sdk is a lightweight React SDK designed to simplify payment processing and checkout integration using Nomba's secure and reliable infrastructure.

Built with ❤️ by Israel Itua


🗺️ How It Works

Here's the full journey from signup to your first successful payment:

1. Create a Nomba business account at dashboard.nomba.com
        ↓
2. Go to Developer > API Keys > Test tab (sandbox) or Live tab (production)
        ↓
3. Copy your Client ID and Account ID
        ↓
4. Install the SDK and pass your credentials + environment
        ↓
5. Test your integration in sandbox mode
        ↓
6. Switch environment to 'live' and go to production

✅ Prerequisites

Before writing any code, you need a Nomba business account and your API credentials.

Step 1 — Create a Nomba Account

Sign up at dashboard.nomba.com. Complete your KYC verification to unlock full access.

Step 2 — Get Your API Credentials

  1. Log in to the Nomba dashboard
  2. In the left sidebar, click Developer
  3. Click API Keys
  4. Use the Test tab for sandbox credentials, Live tab for production

You will see three values:

| Dashboard Label | Description | Used as | |----------------|-------------|---------| | Client ID | Your public API key | clientId and order.customerId | | Account ID | Your Nomba account identifier | accountId and order.accountId | | Private Key | For backend/server use only | Not used in the SDK |

Note: The Client ID is your public key. The Private Key is for server-side use only — never expose it in your frontend code.


📦 Installation

You can install the SDK using npm or yarn:

npm install react-nomba-checkout-sdk
# or
yarn add react-nomba-checkout-sdk

⚡ Quick Start (React)

Here's how to integrate the SDK into your React project:

import { useState } from 'react';
import {
	useNombaCheckout,
	InitializeNombaCheckout,
} from 'react-nomba-checkout-sdk';
import './App.css';

// Initialize Nomba Checkout on app load
InitializeNombaCheckout();

function App() {
	const [isLoading, setIsLoading] = useState(false);

	const handleCheckout = async () => {
		setIsLoading(true);

		const res = await useNombaCheckout({
			accountId: 'your-account-id',
			clientId: 'your-client-id',
			order: {
				callbackUrl: 'sample-url',
				customerEmail: '[email protected]',
				amount: '10.00',
				currency: 'NGN',
				orderMetaData: {
					customMerchant: 'true',
				},
				splitRequest: {
					splitType: 'PERCENTAGE',
					splitList: [
						{
							accountId: 'your-account-id',
							value: '65.45',
						},
					],
				},
			},
			tokenizeCard: 'true',
			onCreateOrder: (orderReference) => {
				console.log('Function called after the order is created');
				console.log({ orderReference });
				setIsLoading(false);
			},
			onFailure: (err) => {
				console.log('Function called if error occurs while creating order.');
				console.log(err);
				setIsLoading(false);
			},
			onClose: () => {
				console.log('Function called when modal is closed.');
				setIsLoading(false);
			},
			onPaymentSuccess: (successResponse) => {
				console.log('Function called on payment success.');
				console.log({ successResponse });
			},
		});
	};

	return (
		<>
			<h1>Pay with Nomba</h1>
			<button onClick={handleCheckout}>
				{isLoading ? 'Please wait...' : 'Pay with Nomba Checkout'}
			</button>
		</>
	);
}

export default App;

🔥 Next.js Integration (App Router)

For Next.js 13+ with App Router, follow this setup to ensure proper client-side rendering:

Step 1: Create the Checkout Component

Create components/NombaCheckoutButton.tsx:

'use client';

import { useState, useEffect } from 'react';
import {
	useNombaCheckout,
	InitializeNombaCheckout,
} from 'react-nomba-checkout-sdk';

export default function NombaCheckoutButton() {
	const [isLoading, setIsLoading] = useState(false);
	const [isInitialized, setIsInitialized] = useState(false);

	useEffect(() => {
		InitializeNombaCheckout();
		setIsInitialized(true);
	}, []);

	const handleCheckout = async () => {
		if (!isInitialized) {
			console.log('SDK not initialized yet');
			return;
		}

		setIsLoading(true);

		const res = await useNombaCheckout({
			accountId: 'your-account-id',
			clientId: 'your-client-id',
			order: {
				callbackUrl: 'https://your-callback-url.com',
				customerEmail: '[email protected]',
				amount: '10.00',
				currency: 'NGN',
				orderMetaData: {
					customMerchant: 'true',
				},
				splitRequest: {
					splitType: 'PERCENTAGE',
					splitList: [
						{
							accountId: 'your-account-id',
							value: 65.45,
						},
					],
				},
				orderReference: 'your-order-reference',
				customerId: '',
				accountId: 'your-account-id',
			},
			tokenizeCard: true,
			onCreateOrder: (orderReference) => {
				console.log('Function called after the order is created');
				console.log({ orderReference });
				setIsLoading(false);
			},
			onFailure: (err) => {
				console.log('Function called if error occurs while creating order.');
				console.log(err);
				setIsLoading(false);
			},
			onClose: () => {
				console.log('Function called when modal is closed.');
				setIsLoading(false);
				return {};
			},
			onPaymentSuccess: (successResponse) => {
				console.log('Function called on payment success.');
				console.log({ successResponse });
				return {};
			},
		});
	};

	return (
		<>
			<h1>Pay with Nomba</h1>
			<button onClick={handleCheckout} disabled={!isInitialized}>
				{isLoading ? 'Please wait...' : 'Pay with Nomba Checkout'}
			</button>
		</>
	);
}

Step 2: Use Dynamic Import in Your Page

Create or update your app/page.tsx:

'use client';

import dynamic from 'next/dynamic';

// Dynamically import the component with SSR disabled
const NombaCheckoutButton = dynamic(
	() => import('@/components/NombaCheckoutButton'),
	{ ssr: false }
);

export default function Home() {
	return <NombaCheckoutButton />;
}

Step 3: Configure Layout (Optional)

Update your app/layout.tsx if needed:

import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import './globals.css';

const geistSans = Geist({
	variable: '--font-geist-sans',
	subsets: ['latin'],
});

const geistMono = Geist_Mono({
	variable: '--font-geist-mono',
	subsets: ['latin'],
});

export const metadata: Metadata = {
	title: 'Nomba Checkout Integration',
	description: 'Payment processing with Nomba',
};

export default function RootLayout({
	children,
}: Readonly<{
	children: React.ReactNode;
}>) {
	return (
		<html lang='en'>
			<body
				className={`${geistSans.variable} ${geistMono.variable} antialiased`}
				suppressHydrationWarning
			>
				{children}
			</body>
		</html>
	);
}

⚠️ Important Next.js Notes

  • Always use dynamic import with ssr: false - The SDK requires browser APIs and must be rendered client-side only
  • Initialize SDK in useEffect - Ensures proper initialization after component mounts
  • Use 'use client' directive - Required for components using browser-specific features
  • Check initialization state - Prevent checkout calls before SDK is ready

🔍 API Reference

InitializeNombaCheckout()

Initializes the SDK. Call once when your app loads (or in useEffect for Next.js).

InitializeNombaCheckout();

useNombaCheckout(options)

Launches the Nomba checkout modal.

Options

| Parameter | Type | Required | Description | | ------------------ | -------------- | -------- | -------------------------------------------------- | | accountId | string | Yes | Your Nomba account ID | | clientId | string | Yes | Your Nomba client ID (public key) | | environment | string | No | 'sandbox' for testing, 'live' for production (default: 'live') | | order | object | Yes | Order details (see below) | | tokenizeCard | boolean/string | No | Enable card tokenization | | onCreateOrder | function | No | Callback after order creation | | onFailure | function | No | Callback on error | | onClose | function | No | Callback when modal closes | | onPaymentSuccess | function | No | Callback on successful payment |

Order Object

| Field | Type | Required | Description | | ---------------- | ------ | -------- | --------------------------- | | callbackUrl | string | Yes | URL for payment callback | | customerEmail | string | Yes | Customer's email address | | amount | string | Yes | Payment amount | | currency | string | Yes | Currency code (e.g., 'NGN') | | orderReference | string | No | Your unique order reference | | customerId | string | No | Same value as your top-level clientId | | accountId | string | No | Same value as your top-level accountId | | orderMetaData | object | No | Additional metadata | | splitRequest | object | No | Payment split configuration | | allowedPaymentMethods | string[] | No | Restrict available payment methods (e.g., ['Transfer', 'Card']) |

Split Request Object

| Field | Type | Required | Description | | ----------- | ------ | -------- | ----------------------------- | | splitType | string | Yes | 'PERCENTAGE' or 'FLAT' | | splitList | array | Yes | Array of split configurations |

Split List Item

| Field | Type | Required | Description | | ----------- | ------------- | -------- | --------------------------- | | accountId | string | Yes | Account ID to receive split | | value | number/string | Yes | Split amount or percentage |

Allowed Payment Methods

By default, all payment methods are available to the customer. You can restrict which payment methods are shown in the checkout modal by passing the allowedPaymentMethods array inside the order object.

Available values:

| Value | Description | | ------------ | -------------------------- | | 'Transfer' | Bank transfer | | 'Card' | Debit/credit card | | 'USSD' | USSD payment | | 'QR' | QR code payment |

Example — Allow only bank transfer:

order: {
	callbackUrl: 'https://yoursite.com/callback',
	customerEmail: '[email protected]',
	amount: '5000.00',
	currency: 'NGN',
	allowedPaymentMethods: ['Transfer'],
}

Example — Allow transfer and card only:

order: {
	callbackUrl: 'https://yoursite.com/callback',
	customerEmail: '[email protected]',
	amount: '5000.00',
	currency: 'NGN',
	allowedPaymentMethods: ['Transfer', 'Card'],
}

Note: If allowedPaymentMethods is omitted or an empty array is passed, all payment methods will be available.


📝 Example with All Options

const res = await useNombaCheckout({
	accountId: 'acc_123456',
	clientId: 'client_123456',
	order: {
		callbackUrl: 'https://yoursite.com/payment/callback',
		customerEmail: '[email protected]',
		amount: '5000.00',
		currency: 'NGN',
		orderReference: 'ORDER-2024-001',
		customerId: 'CUST-001',
		accountId: 'acc_123456',
		orderMetaData: {
			customMerchant: 'true',
			productName: 'Premium Plan',
		},
		splitRequest: {
			splitType: 'PERCENTAGE',
			splitList: [
				{
					accountId: 'acc_partner_1',
					value: 20,
				},
				{
					accountId: 'acc_partner_2',
					value: 15,
				},
			],
		},
		allowedPaymentMethods: ['Transfer', 'Card'],
	},
	tokenizeCard: true,
	onCreateOrder: (orderReference) => {
		console.log('Order created:', orderReference);
	},
	onFailure: (error) => {
		console.error('Payment failed:', error);
	},
	onClose: () => {
		console.log('Checkout modal closed');
		return {};
	},
	onPaymentSuccess: (response) => {
		console.log('Payment successful:', response);
		return {};
	},
});

🧪 Testing in Sandbox

Before going live, always test your integration using sandbox credentials. The sandbox environment simulates real payments without processing actual money.

How to Enable Sandbox Mode

Pass environment: 'sandbox' to useNombaCheckout. Use your Test tab credentials from the dashboard.

await useNombaCheckout({
	accountId: 'your-test-account-id',   // from Developer > API Keys > Test tab
	clientId: 'your-test-client-id',     // from Developer > API Keys > Test tab (Client ID)
	environment: 'sandbox',              // 'sandbox' | 'live'
	order: {
		customerId: 'your-test-client-id', // same as clientId
		accountId: 'your-test-account-id', // same as accountId above
		callbackUrl: 'https://yoursite.com/callback',
		customerEmail: '[email protected]',
		amount: '100.00',
		currency: 'NGN',
	},
	onCreateOrder: (orderReference) => {
		console.log('Order created:', orderReference);
	},
	onPaymentSuccess: (response) => {
		console.log('Payment successful:', response);
		return {};
	},
	onFailure: (err) => {
		console.error('Payment failed:', err);
	},
	onClose: () => {
		console.log('Modal closed');
		return {};
	},
});

What Works in Sandbox

Card and Transfer can be tested end-to-end in sandbox today. Other payment methods (QR, USSD, Apple Pay, Google Pay, Installments, International Transfer) are coming soon to sandbox.

| Payment Method | Sandbox Status | Notes | | -------------- | -------------- | ----- | | Card (Nigerian) | ✅ Available | Use the test card numbers below | | Transfer | ✅ Available | Test virtual account auto-confirms — no real transfer needed | | QR, USSD, Apple Pay, Google Pay, Installments, International Transfer | 🔜 Coming soon | Available in production today; sandbox support on the way |

Tip: Restrict the checkout to the testable methods with allowedPaymentMethods: ['Card', 'Transfer'] while developing in sandbox.

Test Card Numbers

| Card number prefix | PIN required | Outcome | | ------------------ | ------------ | ------- | | 0000... / 1234... | No | Proceeds without PIN | | 5555... / 4444... | Yes | PIN step shown |

Testing a Transfer

  1. Select Transfer in the checkout sidebar.
  2. The sandbox generates a test virtual account (account number, bank, and amount).
  3. No real money or bank transfer is needed — the inbound transfer auto-confirms after a few seconds and the checkout moves to the success state.

Going Live

When you're ready for production:

  1. Switch to the Live tab in Developer > API Keys on the dashboard
  2. Copy your live Client ID and Account ID
  3. Change environment: 'sandbox' to environment: 'live'
  4. Replace your test credentials with live credentials
await useNombaCheckout({
	accountId: 'your-live-account-id',
	clientId: 'your-live-client-id',
	environment: 'live',              // changed from 'sandbox'
	order: { ... },
});

Important: Never use sandbox credentials in production or live credentials during testing. The SDK will log a console warning if it detects environment: 'sandbox' in a production build.


🔔 Webhooks — Confirming Payment on Your Server

Do not use onPaymentSuccess for order fulfillment. The frontend callback can be spoofed or missed (e.g. if the user closes the browser). Always confirm payment server-side via a webhook before marking an order as paid.

Step 1 — Set up your webhook endpoint (dashboard)

  1. Go to Settings → Developer → Webhook Setup
  2. Toggle Live / Test mode (top-right) to match your environment
  3. Click + Create Webhook
  4. Enter your Webhook URL (e.g. https://yourapp.com/webhooks/nomba)
  5. Optionally add a Signature Key — Nomba will sign each request with this; store it as a secret environment variable
  6. Select the events you want:
    • Payment success / Payment failed / Payment reversal
    • Payout success / Payout failed / Payout refund
    • Order success
  7. Save

Step 2 — Receive and verify the webhook

// Express (Node.js)
import crypto from 'crypto';
import express from 'express';

const app = express();

function verifyNombaSignature(rawBody: string, header: string, secret: string): boolean {
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}

app.post('/webhooks/nomba', express.raw({ type: 'application/json' }), async (req, res) => {
  const sig = req.headers['x-nomba-signature'] as string;

  if (!verifyNombaSignature(req.body.toString(), sig, process.env.NOMBA_WEBHOOK_SECRET!)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(req.body.toString());

  if (event.type === 'payment.success') {
    await fulfillOrder(event.data.orderReference); // your fulfillment logic
  }

  res.json({ received: true });
});

🛠️ Troubleshooting

Next.js Hydration Errors

  • Ensure you're using dynamic import with ssr: false
  • Add suppressHydrationWarning to your body tag in layout.tsx

SDK Not Initialized

  • In Next.js, initialize the SDK in useEffect
  • Check that the button is disabled until isInitialized is true

Modal Not Opening

  • Verify that InitializeNombaCheckout() was called before useNombaCheckout()
  • Check browser console for errors

👤 Current Maintainer

Kelechi Uma
Frontend Engineer
GitHub


👥 Contributors

  • Israel Itua - Original Author - GitHub
  • Kelechi Uma - Contributor & Current Maintainer - GitHub

📄 License

MIT


🤝 Contributing

Contributions, issues, and feature requests are welcome!