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.

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

Sign in and verify your email to post an answer.