Skip to main content

Collect payments with Xendit

XENDIT sends the payer to a Xendit-hosted payment page. There the payer picks a local method: GCash or Maya in the Philippines, QRIS, e-wallets or bank transfer in Indonesia, PromptPay in Thailand, FPX online banking in Malaysia, e-wallets in Vietnam, or a card. Which methods appear is up to you: Xendit shows every method you have activated on your account. Centipid Billing creates a Xendit payment session, sends the payer to its payment link, and confirms the result on a webhook that is re-checked against Xendit before anything is credited. The money goes into your own Xendit account. Centipid Billing never holds it. You open the account with Xendit yourself and paste its keys here. Offered in the country catalog for the five countries where Xendit opens accounts: the Philippines, Indonesia, Thailand, Malaysia and Vietnam.

Before you start

  1. Open a Xendit account owned by the ISP and finish verification, so it can take live payments.
  2. Activate the payment methods you want payers to see, under Payment methods in the Xendit dashboard.
  3. Check your billing currency. Xendit bills each country in one currency: PHP in the Philippines, IDR in Indonesia, THB in Thailand, MYR in Malaysia and VND in Vietnam. Your Centipid Billing account must be in that currency, or every payment is refused before it reaches Xendit.
  4. Plan the walled garden: the payer’s browser must reach Xendit’s payment page, so a Hotspot subscriber who is not yet online cannot pay unless Xendit is reachable before login. Centipid Billing adds Xendit’s hosts to your routers’ walled garden when Xendit is your connected gateway.
An e-wallet or online-banking payment can hand the payer over to the provider’s own website (GCash, Maya, a Malaysian bank’s FPX page). That website is not Xendit’s, so it cannot be added to the walled garden in advance. A Hotspot payer who is not yet online may be stopped there. QR methods (QRIS, PromptPay, QR Ph) are paid in the payer’s banking app over mobile data and are not affected. Subscribers paying from PPPoE or from the customer portal are already online and are not affected either.

Configure the gateway

1

Open Settings → Payments → Xendit

Select Xendit from the payment marketplace.
2

Enter the secret API key

In Xendit, open Settings → Developers → API keys and create a secret key with write access to Money-in. It starts with xnd_production_ on a live account and xnd_development_ in test mode. The public key is not needed and is refused.
3

Add the webhook in Xendit

Copy the Webhook URL shown under Callback URLs on the Xendit settings page. In Xendit, open Settings → Developers → Webhooks and paste it into Payment Session – Completed. Leave the legacy Payment Link (invoice) webhook alone: Centipid Billing does not use it.
4

Enter the webhook verification token

On the same Webhooks page, reveal the verification token and paste it into Webhook verification token.
5

Run a controlled test payment

Pay a small amount from the captive portal on a device that is not logged in, and confirm the payment reaches the ledger and the subscriber connects.

Credentials

Both fields gate the switch. Test mode and live mode have separate keys and separate verification tokens.

Callback URLs

The payer’s browser returns to https://<your-host>/api/xendit/return after paying. Centipid Billing sends that address with every payment, always over HTTPS because Xendit refuses anything else, so there is nothing to register for it.
Xendit sends the verification token in the x-callback-token header of every webhook. A wrong or missing token means every webhook is rejected with HTTP 400. Payers who wait for the return page are still connected, but a payer who closes the tab before it loads is charged and left disconnected until someone reconciles by hand.

What the payer must provide

Whatever the chosen method asks for: an e-wallet approval, a QR scan in a banking app, an online-banking login or card details.
Amounts are sent in the main currency unit, not cents: ₱50 is sent as 50. Rupiah and dong are sent as whole numbers; pesos, baht and ringgit keep two decimals.

How a payment completes

1

Create the payment session

Centipid Billing creates a Xendit payment session for the amount, tagged with our own reference, and writes a pending row against that reference.
2

Payment

The payer pays on Xendit’s page and is sent back to the return page. A payer who chose a method paid later, such as an Indonesian virtual account or an Alfamart code, is told the payment is being confirmed and not to pay again.
3

Confirmation

Xendit posts the payment_session.completed webhook. The token is checked, then the session Centipid Billing created for this payment is read back from the Xendit API. Only a session that is COMPLETED records a payment and applies the package. The return page runs the same check. A repeated webhook updates the same payment rather than crediting it twice.
Webhooks for sessions that other software created on the same Xendit account are acknowledged and ignored, and so are expired sessions.
A Xendit account has one Payment Session – Completed webhook URL. Two ISPs can share one Xendit account without a payment ever being credited to the wrong one, but only the ISP whose URL is registered receives webhooks. The other connects payers only when they reach the return page, so a payer who closes the tab first stays disconnected until someone reconciles by hand. Give each ISP its own Xendit account.
If Xendit’s API cannot be reached when a webhook arrives, Centipid Billing answers with HTTP 503 so Xendit sends the webhook again later.

Troubleshooting

For every gateway’s fields in one place, see the credential reference.