Handling the Callback
ជំពូកនេះមិនទាន់ត្រូវបានបកប្រែជាភាសាខ្មែរនៅឡើយទេ — សូមអានជាភាសាអង់គ្លេសខាងក្រោម។
Table of Contents
- What the callback is for
- A minimal callback handler
- Whitelisting your return_url
- Testing locally with ngrok
- Beginner Pitfalls
1. What the callback is for
After the customer completes (or cancels) payment, PayWay sends a POST
request to a return_url you configure — on your server, not your
browser. This is how you actually confirm the payment succeeded; never
trust the frontend alone.
Your return_url endpoint should:
- Accept
POSTwith a JSON body. - Read the
statusandtran_idfields. - Mark that order as paid in your own database.
For a beginner sandbox exercise, it's enough to log the callback body and print something like "Payment received for tran_id X." Production-grade verification — checking the callback is genuinely from PayWay, not spoofed — is its own lesson, covered in Part 6.
2. A minimal callback handler
router.post('/payment-callback', (req, res) => {
console.log('Received PayWay callback:', req.body);
// TODO: verify signature/authenticity of this callback before trusting it
// TODO: look up the order by tran_id and mark it paid/failed
res.sendStatus(200);
});
This is intentionally incomplete — it logs and acknowledges, nothing more.
Treat the two TODOs as the actual lesson here, not something to silently
"finish" without flagging that it needs verification against PayWay's
current docs first.
3. Whitelisting your return_url
Whitelist your return_url domain before testing callbacks. PayWay
validates return_url against a domain whitelist tied to your merchant
profile — error codes 6 ("Requested domain is not in whitelist") and 81
("The return URL is not in the whitelist"). If your domain isn't
whitelisted, PayWay silently never calls back — no error surfaces to
your app, which makes this easy to mistake for a bug in your own code.
Contact ABA PayWay's integration team with your domain (or your ngrok tunnel domain, for local testing) to get it whitelisted before testing callbacks.
Also note: a purchase response of code: "00" / "Success!" only means
the transaction request was accepted — it does not mean the customer
completed payment. The callback only fires once the customer actually
approves it (e.g. scanning the KHQR code and confirming in the ABA Mobile
app).
4. Testing locally with ngrok
PayWay's callback requires HTTPS, and it can't reach localhost directly,
so local testing needs a public HTTPS tunnel:
const RETURN_URL = 'https://your-tunnel-subdomain.ngrok-free.dev/payment-callback';
ngrok's free tier assigns a new random domain every time you restart the tunnel — which means re-whitelisting with PayWay's team every time, too. A paid ngrok static domain (or your own domain) avoids that churn.
5. Beginner Pitfalls
- A callback that never arrives, with no error anywhere, almost always means an un-whitelisted domain — not a bug in your handler. Check the whitelist before debugging your code.
- ngrok's free-tier domain changes on every restart. If callbacks that used to work stop arriving, check whether your tunnel domain changed and needs re-whitelisting.
- Logging the callback body is fine for a sandbox exercise, but shipping that as "done" skips signature verification and idempotency — both real gaps, not stylistic choices. See Part 6 for what's still missing.
ទិញកាហ្វេជូនខ្ញុំ
ចូលចិត្តមេរៀននេះមែនទេ? សូមពិចារណាទិញកាហ្វេជូនខ្ញុំមួយកែវ ដើម្បីគាំទ្រការបង្កើតមាតិកាឥតគិតថ្លៃបន្ថែមទៀត!