@keychain-pay/react
v1.2.0
Published
React hooks and components for Keychain Pay - Accept payments in React apps
Maintainers
Readme
@keychain-pay/react
Accept USDC payments in React with a single hook or drop-in button. Multi-currency support included.
Installation
npm install @keychain-pay/reactTwo Options
Option 1: Drop-in Button (Easiest)
import { KeychainCheckoutButton } from '@keychain-pay/react';
function Checkout() {
return (
<KeychainCheckoutButton
apiKey="sk_test_xxx"
amount={100000} // ₹1,000.00 in paise
currency="INR" // Supports: USD, INR, EUR, GBP, CAD, AUD, MXN, PHP
orderId="order_123"
onSuccess={(result) => {
console.log('Paid!', result.transactionId);
window.location.href = '/success';
}}
onError={(error) => console.error(error)}
onCancel={() => console.log('Cancelled')}
/>
);
}The button shows: "Pay ₹1,000.00 with Keychain" (formatted with correct locale).
Option 2: Hook (More Control)
For custom UI with secure session-based checkout.
Security First: Your API key never touches the frontend. The hook only needs a sessionId.
'use client';
import { useKeychainCheckout } from '@keychain-pay/react';
function CheckoutPage() {
const { open } = useKeychainCheckout();
const handlePay = async () => {
// Get sessionId from your backend
const res = await fetch('/api/create-checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 100000, // ₹1,000.00 in paise
currency: 'INR',
orderId: 'order_123'
}),
});
const { sessionId } = await res.json();
// Open checkout modal
open({
sessionId,
onSuccess: (result) => {
console.log('Paid!', result.transactionId);
window.location.href = '/success';
},
onCancel: () => console.log('Cancelled'),
onError: (error) => console.error(error.message),
});
};
return <button onClick={handlePay}>Pay ₹1,000.00</button>;
}Backend: Create Session
// app/api/create-checkout/route.ts (Next.js)
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
const { amount, currency, orderId } = await request.json();
const response = await fetch('https://api.trykeychain.com/api/v1/checkout/sessions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.KEYCHAIN_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount,
currency, // 'INR', 'USD', 'EUR', etc.
orderId,
returnUrl: `${process.env.NEXT_PUBLIC_BASE_URL}/success`,
}),
});
const { session } = await response.json();
return NextResponse.json({ sessionId: session.id });
}Multi-Currency Support
Supported Currencies
| Currency | Code | Symbol | Amount Unit | |----------|------|--------|-------------| | US Dollar | USD | $ | Cents (2500 = $25.00) | | Indian Rupee | INR | ₹ | Paise (100000 = ₹1,000.00) | | Euro | EUR | € | Cents (2500 = €25.00) | | British Pound | GBP | £ | Pence (2500 = £25.00) | | Canadian Dollar | CAD | C$ | Cents | | Australian Dollar | AUD | A$ | Cents | | Mexican Peso | MXN | $ | Centavos | | Philippine Peso | PHP | ₱ | Centavos |
Cross-Currency Payments
When merchant and customer currencies differ, the checkout shows both:
Primary: ₹1,000.00
Secondary: ≈ $12.00 USD at 1 USD = 83.50 INRExchange rates are locked at payment time - no surprises for either party.
KeychainCheckoutButton Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| apiKey | string | Yes | Your Keychain API key |
| amount | number | Yes | Amount in smallest unit (cents/paise) |
| orderId | string | Yes | Your order ID |
| currency | string | No | Currency code (default: 'usd') |
| metadata | object | No | Custom metadata |
| fullWidth | boolean | No | Make button full width |
| disabled | boolean | No | Disable the button |
| onSuccess | function | No | Called on successful payment |
| onError | function | No | Called on payment error |
| onCancel | function | No | Called when user cancels |
Hook API
useKeychainCheckout()
Returns { open, close } functions.
const { open, close } = useKeychainCheckout();
// Open checkout
open({
sessionId: 'cs_xxx',
onSuccess: (result) => { /* handle success */ },
onCancel: () => { /* handle cancel */ },
onError: (error) => { /* handle error */ },
});
// Programmatically close
close();Hook Options
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| sessionId | string | Yes | Session ID from your backend |
| onSuccess | function | No | Called when payment succeeds |
| onCancel | function | No | Called when user cancels |
| onError | function | No | Called on error |
| checkoutUrl | string | No | Custom checkout URL (for testing) |
PaymentResult Type
interface PaymentResult {
transactionId?: string;
subscriptionId?: string;
sessionId?: string;
reward?: {
amountCents: number;
};
// Multi-currency info
merchantCurrency?: string;
merchantAmountSmallestUnit?: number;
customerCurrency?: string;
customerAmountSmallestUnit?: number;
exchangeRate?: number;
}Modal Behavior
- Desktop: Centered modal (420px wide)
- Mobile: Bottom sheet (full width)
- Animations: Smooth open/close transitions
- Backdrop: Click outside to cancel
TypeScript Support
Full TypeScript definitions included:
import {
useKeychainCheckout,
KeychainCheckoutButton,
CheckoutOptions,
PaymentResult,
KeychainCheckoutButtonProps,
} from '@keychain-pay/react';Next.js Usage
Make sure you're in a client component:
'use client'; // Required for Next.js App Router
import { useKeychainCheckout } from '@keychain-pay/react';
// or
import { KeychainCheckoutButton } from '@keychain-pay/react';Test Mode
Use test API keys (sk_test_...) for development:
- No real money is transferred
- OTP code is always
123456 - Session IDs start with
cs_test_
Examples
INR Checkout (India)
<KeychainCheckoutButton
apiKey="sk_test_xxx"
amount={100000} // ₹1,000.00
currency="INR"
orderId="order_123"
onSuccess={(result) => router.push('/success')}
/>
// Button shows: "Pay ₹1,000.00 with Keychain"USD Checkout (US)
<KeychainCheckoutButton
apiKey="sk_test_xxx"
amount={2500} // $25.00
currency="USD"
orderId="order_456"
onSuccess={(result) => router.push('/success')}
/>
// Button shows: "Pay $25.00 with Keychain"EUR Checkout (Europe)
<KeychainCheckoutButton
apiKey="sk_test_xxx"
amount={5000} // €50.00
currency="EUR"
orderId="order_789"
onSuccess={(result) => router.push('/success')}
/>
// Button shows: "Pay 50,00 € with Keychain"Support
- Email: [email protected]
- Docs: developers.trykeychain.com
