Skip to main content

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

  1. Your backend creates a checkout session
  2. Customer is redirected to pay.zkp2p.xyz/checkout?session=...
  3. Customer completes payment on the hosted checkout page
  4. Customer is redirected back to your successUrl or cancelUrl

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

  1. Your page stays open in the original tab
  2. Checkout opens in a new browser tab
  3. Customer completes payment in the new tab
  4. On success/cancel, the new tab redirects to your successUrl/cancelUrl
  5. 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');
};
Demo App

Try this integration in the SDK Demo App - click "Open in New Tab" to see how it works.


Not Supported: Iframe Embedding

Not Currently Supported

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

  1. Full-page redirects - On completion, the checkout redirects to successUrl/cancelUrl via window.location.href, which would navigate the entire page out of your site if embedded
  2. No postMessage API - There's no parent-window communication to report checkout events
  3. Browser extension dependency - The PeerAuth extension communicates via window.postMessage, which may conflict with iframe sandboxing
  4. 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

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:

  • postMessage API for parent window communication
  • Embedded mode detection (?embed=true)
  • Event callbacks for payment completion
  • No full-page redirects in embedded mode