paynotify-react
v1.4.0
Published
Official React Components for PayNotify
Readme
[!NOTE] To all developers and AI Agents integrating this SDK: This README contains the complete, step-by-step workflow required to perfectly implement the PayNotify checkout system. Follow this guide precisely to ensure a robust, enterprise-grade integration.
⚡ Core Features
- Built-in "Securing Gateway" UI: Native support for pre-checkout loading states via the
isInitializingprop. No need to build custom loading spinners or overlays! - Premium HD QR Codes: Generates stunning 1200x1440 high-definition QR codes with modern gradients, typography, and rounded corners for maximum user trust.
- Intelligent Status Polling: Implements anti-DDoS exponential backoff and Tab Visibility APIs to poll the PayNotify engine efficiently.
- Zero-Friction Modal:
<PayNotifyModal />automatically handles z-index, screen centering, mobile bottom-sheet styling, and cancellation logic.
📦 1. Installation
Install the package alongside its peer dependency react-qr-code:
# npm
npm install paynotify-react react-qr-code
# yarn
yarn add paynotify-react react-qr-code[!IMPORTANT] Backend Requirement: This SDK operates strictly on the frontend. Order creation (
orderId,amount) MUST happen on your secure backend using thePayNotifyclass frompaynotify-node. You cannot generate authenticorderIds on the frontend.
🚀 2. The Implementation Workflow
To perfectly implement this SDK, you must follow a two-step flow:
- Initialize: Show the beautiful SDK loading state while you call your backend to create the order.
- Checkout: Pass the returned
orderIdandamountto the SDK to render the QR code.
Step-by-Step Code Example
Here is the flawless, production-ready implementation:
import React, { useState } from 'react';
import { PayNotifyModal } from 'paynotify-react';
import axios from 'axios';
export default function CheckoutPage() {
const [checkoutState, setCheckoutState] = useState<'idle' | 'initializing' | 'checkout' | 'success'>('idle');
const [orderData, setOrderData] = useState<{ orderId?: string, amount?: number } | null>(null);
const startPayment = async () => {
// 1. Instantly show the SDK's "Securing Gateway" loading state
setCheckoutState('initializing');
try {
// 2. Call your secure backend to create the PayNotify order
const response = await axios.post('/api/create-order', { productId: 'pro-plan' });
// 3. Save the returned orderId and precise amount
setOrderData({
orderId: response.data.orderId,
amount: response.data.amount // Exact penny-drop amount (e.g. 49.04)
});
// 4. Switch to checkout mode to display the QR Code
setCheckoutState('checkout');
} catch (error) {
console.error("Failed to initialize checkout:", error);
setCheckoutState('idle'); // Fallback if API fails
}
};
const handleSuccess = () => {
// Payment verified! Show success UI.
setCheckoutState('success');
};
const handleCancel = () => {
// User clicked the 'X' button or overlay
setCheckoutState('idle');
setOrderData(null);
};
if (checkoutState === 'success') {
return <h1>Payment Successful! Welcome to Pro.</h1>;
}
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50 p-4">
{/* Trigger Button */}
{checkoutState === 'idle' && (
<button onClick={startPayment} className="bg-blue-600 text-white px-6 py-3 rounded-lg">
Buy Pro Plan
</button>
)}
{/* PayNotify Modal (Handles BOTH Loading & Checkout states) */}
{(checkoutState === 'initializing' || checkoutState === 'checkout') && (
<PayNotifyModal
isOpen={true}
isInitializing={checkoutState === 'initializing'} // Enables the "Securing Gateway" UI
onClose={handleCancel}
orderId={orderData?.orderId}
amount={orderData?.amount}
upiId="your-merchant-vpa@upi" // e.g. nallamotusurya331@upi
merchantName="Acme SaaS Premium"
description="Lifetime Access to Pro Features"
features={['Instant Access', 'Zero Hidden Fees', '256-bit SSL']}
image="https://your-domain.com/product-thumbnail.png"
themeColor="#4f46e5"
onSuccess={handleSuccess}
/>
)}
</div>
);
}📖 3. API Reference for <PayNotifyModal />
| Prop | Type | Required | Description |
|---|---|---|---|
| isOpen | boolean | Yes | Controls the visibility of the modal portal. |
| isInitializing | boolean | No | If true, overrides the checkout view and renders the beautiful "Securing Gateway" animated loader. Use this while fetching order details. |
| orderId | string | Yes (if not initializing) | Unique identifier generated by your backend via PayNotify Engine. |
| amount | number | Yes (if not initializing) | Exact decimal amount to charge (e.g., 49.04). Critical for verification matching. |
| upiId | string | Yes (if not initializing) | The merchant's UPI VPA (e.g., business@sbi). |
| merchantName | string | No | Display name of the business/platform. |
| onSuccess | () => void | No | Callback executed when polling confirms the payment is VERIFIED. |
| onClose | () => void | Yes | Callback executed when the user clicks the close (X) button. Use this to unmount the modal. |
| description | string | No | Short description of the product or subscription. |
| features | string[] | No | List of highlighted badges (e.g., ["30 Days Access", "Secure"]). |
| image | string | No | URL to product thumbnail image to display in the UI. |
| themeColor | string | No | Hex color code for brand accenting. Defaults to #4f46e5. |
🛡️ 4. Security Best Practices for AI Agents
[!WARNING] Client-Side vs. Server-Side State Never fulfill a digital product solely based on the
onSuccesscallback of this React component. The frontend callback is for UI routing only (e.g., showing a "Success" message). Your actual database updates (e.g., unlocking premium content or adding credits) MUST occur in your backend webhook handler securely.
Quick Architecture Mental Model
- Frontend: User clicks "Buy" -> Frontend sets
isInitializing=true-> Calls Backend. - Backend: Calls PayNotify API -> Gets
orderIdand exactamount-> Saves to DB asPENDING-> Returns to Frontend. - Frontend: Sets
isInitializing=false, passesorderIdandamountto Modal -> Modal shows QR Code and polls for status. - User: Scans QR and pays.
- Backend Webhook: Receives
VERIFIEDping from PayNotify -> Updates DB toVERIFIED-> Unlocks features. - Frontend Polling: Detects
VERIFIED-> TriggersonSuccess-> Shows Success UI.
