How do I secure payment notification callbacks from Haitian mobile-money providers?
poze 3 months ago395 gadeen
7
Both MonCash (alert URL) and our NatCash integration can call an endpoint on my server when a payment happens. Anyone could POST to that URL. How do I make sure a callback is genuine?
Dyagnostik IA
Se IA ki fè l. Se pa yon repons — kominote a anba a konfime oswa korije l. Toujou verifye anvan ou fye l.
poze 3 months ago
Fabienne Dorval 2.8k
1 Repons
3
✓✓ Repons yo aksepte
Treat every callback as an untrusted hint that something may have happened, never as proof.
The robust pattern: notify, then re-fetch.
app.post("/webhooks/:provider", async (req, res) => {
const provider = providers[req.params.provider.toUpperCase()];
if (!provider) return res.sendStatus(404);
// Extract only an identifier from the body…
const attemptId = extractAttemptId(provider.id, req.body);
if (attemptId) {
// …then ask the provider directly, server to server, what really happened.
await confirmAttempt(attemptId); // checks status + amount, idempotent
}
res.sendStatus(200); // acknowledge quickly; don't leak details
});
Because confirmAttempt verifies against the provider's API, a forged callback can at most trigger a harmless status check.
Add these when the provider supports them:
- Signature verification: if the provider signs callbacks (an HMAC header), verify it with a constant-time comparison before doing anything.
- Source IP allowlist, if the provider publishes stable addresses. It's a useful extra layer, never the only one.
- Rate-limit the endpoint. It shouldn't become a way to make your server hammer the provider's API.
- Respond fast and process asynchronously if confirmation is slow. Providers retry on timeouts, which is fine because your confirmation is idempotent.
- Log raw callbacks, with secrets and PINs redacted, for disputes and debugging.
Konekte pou di lòt moun si li te mache.
answered 3 months ago
Woodly Joseph 2.4k
Sign in and verify your email to post an answer.