This is the core endpoint for hosted checkout. Merchants POST their signed orders, and you return a URL to your payment page.
Flow
- Merchant creates and signs an order
- Merchant POSTs order to your
/orders/checkout
- You verify the signature and create a checkout session
- You return a
redirect_url to your payment page
- Merchant redirects their customer to your page
- Customer completes payment on your hosted UI
- You send signed proof to merchant’s
/transfer/webhook
- You redirect customer back to merchant’s
completed URL
Implementation
app.post('/orders/checkout', verifyAuth, async (req, res) => {
const { order, signature, urls } = req.body;
const merchantOcid = parseInt(req.headers['x-oc-id']);
// 1. Verify merchant is registered
const merchant = await db.getMerchant(merchantOcid);
if (!merchant) {
return res.status(401).json({
error: { code: 'MERCHANT_NOT_REGISTERED', message: 'Unknown merchant' }
});
}
// 2. Verify order signature
const publicKey = merchant.publicKey;
const canonical = JSON.stringify(order, Object.keys(order).sort());
if (!secp256k1_verify(publicKey, signature, SHA256(canonical))) {
return res.status(400).json({
error: { code: 'INVALID_SIGNATURE', message: 'Order signature invalid' }
});
}
// 3. Validate order
if (order.expiresAt && order.expiresAt < Date.now() / 1000) {
return res.status(400).json({
error: { code: 'ORDER_EXPIRED', message: 'Order has expired' }
});
}
// 4. Check we can settle with merchant
if (!order.accepts.includes(YOUR_OCID)) {
return res.status(400).json({
error: { code: 'SETTLEMENT_NOT_SUPPORTED', message: 'Merchant does not accept this gateway' }
});
}
// 5. Create checkout session
const session = await db.createSession({
id: generateSessionId(),
merchantOcid,
order,
signature,
urls,
status: 'pending',
createdAt: Date.now()
});
// 6. Return redirect URL
res.json({
redirect_url: `https://pay.yourgateway.com/checkout/${session.id}`
});
});
Validation Checklist
Before accepting an order:
Hosted Payment Page
On your payment page (/checkout/{sessionId}):
- Retrieve the session and order
- Display order details (items, amount, merchant name)
- Present payment options (cards, wallets, bank transfer)
- Process payment using your internal systems
- On success, call merchant’s webhook and redirect to
urls.completed
- On failure/cancel, redirect to
urls.cancelled
Always verify the session hasn’t expired and hasn’t already been paid before processing payment.