Integration Options
This guide explains the available integration methods for ZKP2P Pay and their trade-offs.
Supported: Full-Page Redirect
The primary integration method is a full-page redirect to the hosted checkout page. This is similar to Stripe Checkout.
import { createCheckoutSession } from '@zkp2p-pay/sdk';
const response = await createCheckoutSession(params, opts);
// Redirect the customer to checkout
window.location.href = response.checkoutUrl;
How It Works
- Your backend creates a checkout session
- Customer is redirected to
pay.zkp2p.xyz/checkout?session=... - Customer completes payment on the hosted checkout page
- Customer is redirected back to your
successUrlorcancelUrl
Benefits
- Zero frontend code required - Just redirect to the URL
- Always up-to-date - Automatically gets new features and payment platforms
- PCI/security compliant - Payment handling is fully hosted
- Browser extension integration - Works seamlessly with PeerAuth extension
Redirect Methods
// Option 1: Full-page redirect (recommended)
window.location.href = response.checkoutUrl;
// Option 2: Use SDK helper
import { redirectToCheckout } from '@zkp2p-pay/sdk';
redirectToCheckout(session.id, sessionToken, opts);
Supported: New Tab Checkout
If you want to keep your page visible while the customer completes checkout, open the checkout in a new tab:
// Open checkout in new tab - keeps your page in the background
window.open(response.checkoutUrl, '_blank');
How It Works
- Your page stays open in the original tab
- Checkout opens in a new browser tab
- Customer completes payment in the new tab
- On success/cancel, the new tab redirects to your
successUrl/cancelUrl - Customer can return to your original tab
Benefits
- Original page preserved - Customer doesn't lose their place
- Cart state maintained - No need to restore form data after redirect
- Less disruptive UX - Customer can switch between tabs
Example
const response = await createCheckoutSession({
merchantId: 'merchant_123',
amountUsdc: '50.00',
destinationChainId: 8453,
recipientAddress: '0xYourWallet',
// These URLs open in the new tab after checkout
successUrl: 'https://yoursite.com/payment/success',
cancelUrl: 'https://yoursite.com/payment/cancelled',
}, opts);
// Open in new tab when user clicks checkout button
document.getElementById('checkout-btn').onclick = () => {
window.open(response.checkoutUrl, '_blank');
};
Try this integration in the SDK Demo App - click "Open in New Tab" to see how it works.
Not Supported: Iframe Embedding
Opening the checkout in an iframe or modal on the same page is not currently supported.
The checkout page is designed as a full-screen application and cannot be embedded in an iframe for the following reasons:
Technical Limitations
- Full-page redirects - On completion, the checkout redirects to
successUrl/cancelUrlviawindow.location.href, which would navigate the entire page out of your site if embedded - No postMessage API - There's no parent-window communication to report checkout events
- Browser extension dependency - The PeerAuth extension communicates via
window.postMessage, which may conflict with iframe sandboxing - Viewport assumptions - The UI is designed for full-screen display
Why Redirect Works Better
For fiat-to-crypto payments with ZK proofs:
- Users need to interact with the PeerAuth browser extension
- The extension captures payment platform data from the user's browser
- This works best in a full browser context, not inside an iframe with restrictions
Recommended Integration Pattern
For the best user experience, use redirects with proper success/cancel handling:
// 1. Create session on your backend
const response = await createCheckoutSession({
merchantId: 'merchant_123',
amountUsdc: '50.00',
destinationChainId: 8453,
recipientAddress: '0xYourWallet',
successUrl: 'https://yoursite.com/payment/success?session_id={SESSION_ID}',
cancelUrl: 'https://yoursite.com/payment/cancelled',
}, opts);
// 2. Store session ID in your database for tracking
await db.orders.update({
where: { id: orderId },
data: { checkoutSessionId: response.session.id }
});
// 3. Redirect customer
window.location.href = response.checkoutUrl;
Handling Success/Cancel
When the customer returns to your site:
// On your success page
const sessionId = new URLSearchParams(window.location.search).get('session_id');
// Verify payment status via webhook or API
// Don't trust the redirect alone - always verify server-side
Future: Embedded Checkout
Embedded checkout (iframe/modal) may be supported in a future release. If this is a priority for your integration, please reach out to the ZKP2P team.
Features that would be included:
postMessageAPI for parent window communication- Embedded mode detection (
?embed=true) - Event callbacks for payment completion
- No full-page redirects in embedded mode