Skip to main content

Examples

E-commerce Checkout (Backend)

import express from 'express';
import { createCheckout } from '@zkp2p/pay-sdk';

const app = express();
app.use(express.json());

const zkpayConfig = {
apiBaseUrl: process.env.ZKPAY_API_URL!,
checkoutBaseUrl: process.env.ZKPAY_CHECKOUT_URL!,
apiKey: process.env.ZKPAY_API_KEY!,
};

app.post('/api/checkout', async (req, res) => {
const { orderId, amount, customerId } = req.body;

try {
const checkout = await createCheckout(
{
requestedUsdcAmount: Number(amount).toFixed(2),
destinationChainId: 8453,
destinationToken: 'USDC',
destinationAddress: process.env.WALLET_ADDRESS,
successUrl: `${process.env.APP_URL}/order/${orderId}/success`,
cancelUrl: `${process.env.APP_URL}/cart`,
notes: { orderId, customerId },
},
zkpayConfig,
);

res.json({
checkoutOrderId: checkout.order.id,
checkoutUrl: checkout.checkoutUrl,
});
} catch {
res.status(500).json({ error: 'Failed to create order' });
}
});

Frontend Redirect

function CheckoutButton({ orderId, amount, customerId }) {
const handleCheckout = async () => {
const response = await fetch('/api/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ orderId, amount, customerId }),
});

const { checkoutUrl } = await response.json();
window.location.href = checkoutUrl;
};

return <button onClick={handleCheckout}>Pay</button>;
}

Onramp Into User Wallet

const checkout = await createCheckout(
{
requestedUsdcAmount: '100.00',
destinationChainId: 8453,
destinationToken: 'USDC',
destinationAddress: userWalletAddress,
successUrl: `${process.env.APP_URL}/onramp/success`,
cancelUrl: `${process.env.APP_URL}/onramp`,
notes: {
type: 'onramp',
userWallet: userWalletAddress,
},
},
zkpayConfig,
);

Webhook Handler

import express from 'express';
import crypto from 'crypto';
import type { WebhookPayload } from '@zkp2p/pay-shared';

const app = express();

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

const expectedSignature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET!)
.update(`${timestamp}.${payload}`)
.digest('hex');

if (signature !== expectedSignature) {
return res.status(401).send('Invalid signature');
}

const event = JSON.parse(payload) as WebhookPayload;
res.status(200).send('OK');

switch (event.type) {
case 'ORDER_FULFILLED':
await db.orders.update({
where: { checkoutOrderId: event.data.order?.id },
data: { status: 'paid' },
});
break;
case 'PAYMENT_SETTLED':
// Optional: record settlement telemetry, but do not mark order as paid here.
break;
case 'PAYMENT_FAILED':
case 'PAYMENT_EXPIRED':
await db.orders.update({
where: { checkoutOrderId: event.data.order?.id },
data: { status: 'failed' },
});
break;
}
});