Accept Payments
Accept payments with NadaPay Checkout by creating sessions on Pay click and verifying payment server-side.
Accept Payments
Create a checkout session when the customer clicks Pay, open NadaPay Checkout, and verify the payment before fulfilment.
Time to complete: 15 minutes
Prerequisites
Create a backend endpoint that can create checkout sessions with your NadaPay secret key, and load the Checkout JavaScript SDK on your payment page.
How it works
Your frontend never creates a checkout session directly. When the customer clicks Pay, your frontend asks your backend to create a session, then opens Checkout with the returned np_reference_id.
Customer clicks Pay
↓
Frontend calls your backend
↓
Backend calls POST /checkout/sessions
↓
Frontend opens NadaPay Checkout
↓
Customer pays
↓
Backend verifies the session
↓
Order is fulfilledStep 1 - Load and initialize Checkout
Load the Checkout SDK and call NadaPay.init() once when the page loads.
<script src="https://js.nadapay.io/v1/inline.js" async></script>
<script>
window.addEventListener('load', function () {
NadaPay.init({
key: 'npk_test_xxxxxxxxxxxx',
environment: 'sandbox',
checkoutType: 'CUSTOM',
currency: 'USD',
onSuccess: function (result) {
fetch('/api/orders/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ reference: result.reference })
});
},
onFailure: function (result) {
console.log('Payment failed:', result.reason, result.message);
},
onClose: function () {
console.log('Checkout closed');
}
});
});
</script>Use npk_test_ public keys in sandbox and npk_live_ public keys in production. Public keys are safe in browser code; secret keys are not.
Step 2 - Create the session on Pay click
Call your backend from the button click handler. Wait for the backend to return np_reference_id, then call NadaPay.open().
<button id="pay-button">Pay $245.00</button>
<p id="status"></p>
<script>
document.getElementById('pay-button').addEventListener('click', async function () {
const response = await fetch('/api/checkout/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ orderId: 'ORD-4821' })
});
if (!response.ok) {
document.getElementById('status').textContent = 'Could not start checkout.';
return;
}
const session = await response.json();
NadaPay.open({
amount: session.amount,
ref: session.np_reference_id,
metadata: {
order_id: 'ORD-4821'
}
});
});
</script>Save np_reference_id. You will verify it after the customer completes payment.
Step 3 - Create the NadaPay checkout session on your backend
Your backend calls NadaPay with your secret key. The authoritative amount comes from this backend session, not the frontend display amount.
app.post('/api/checkout/session', async function (req, res) {
const { orderId } = req.body;
const order = await getOrder(orderId);
const response = await fetch('https://core.nadapay.io/v1/checkout/sessions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-NadaPay-Secret-Key': process.env.NADAPAY_SECRET_KEY
},
body: JSON.stringify({
merchant_id: 'your_merchant_id',
amount_cents: order.amountCents,
currency: 'USD',
metadata: {
order_id: order.id,
customer_email: order.customerEmail
}
})
});
if (!response.ok) {
return res.status(502).json({ message: 'Unable to create checkout session' });
}
const session = await response.json();
res.json({
np_reference_id: session.np_reference_id,
amount: order.amount
});
});{
"np_reference_id": "NP-P-CHECKOUT-4821-K9XZ",
"amount": 245.00
}Save np_reference_id; pass it to NadaPay.open() as ref.
Step 4 - Verify the payment before fulfilment
When onSuccess fires, verify the reference on your backend before shipping goods, unlocking content, or provisioning access.
app.post('/api/orders/verify', async function (req, res) {
const { reference } = req.body;
const response = await fetch(
`https://core.nadapay.io/v1/checkout/sessions/${reference}`,
{
headers: {
'X-NadaPay-Secret-Key': process.env.NADAPAY_SECRET_KEY
}
}
);
if (!response.ok) {
return res.status(502).json({ message: 'Unable to verify payment' });
}
const session = await response.json();
if (session.status !== 'PAID') {
return res.status(400).json({ message: 'Payment is not complete' });
}
await fulfillOrder(session.metadata.order_id);
res.json({ status: 'fulfilled' });
});{
"status": "fulfilled"
}Fulfil the order only after your backend confirms the session status is PAID.
What success looks like
- Checkout opens only after your backend creates a session
- your frontend passes
np_reference_idtoNadaPay.open() - your backend verifies the reference before fulfilment
- your production frontend uses an
npk_live_public key - your secret key never appears in browser code
Troubleshooting
Checkout does not open
Confirm NadaPay.init() ran before NadaPay.open() and that NadaPay.open() is called from a direct user interaction, such as a button click.
The amount looks wrong
Use USD consistently. Send $245.00 to the session API as 24500 cents and pass 245.00 to the frontend display amount.
Payment succeeds in the browser but the order is not fulfilled
Check your backend verification endpoint. The order should only be fulfilled after GET /checkout/sessions/{reference} confirms the session status is PAID.
What's next
| Next step | Why |
|---|---|
| Collection Overview | Understand when to use Checkout versus deposit instructions. |
| Get Deposit Instructions | Retrieve inbound funding instructions for account transfers. |
| Handle Webhooks | Receive payment and transaction updates asynchronously. |
Updated 13 days ago