Webhooks & Callbacks
Que vous utilisiez l'API de Paiement (avec redirection ou en direct sans redirection) ou l'API de Retrait (Décaissement), les transactions Mobile Money sont asynchrones. Pour être notifié instantanément du succès ou de l'échec d'une transaction, vous devez configurer et écouter nos Webhooks.
Événements d'Encaissement (Paiements)
transaction.successDéclenché dès qu'un client valide son paiement (qu'il vienne d'une redirection Checkout Session ou d'une requête API Directe sans redirection). C'est le signal pour vous de valider la commande.
transaction.failedDéclenché si le paiement échoue (fonds insuffisants, annulation par le client sur son téléphone, ou délai d'attente dépassé).
Événements de Décaissement (Retraits API)
payout.successDéclenché lorsque votre requête de retrait via l'API (Décaissement B2C) est traitée et que les fonds sont effectivement arrivés sur le numéro de destination.
payout.failedDéclenché si l'envoi des fonds au destinataire a échoué (numéro erroné, plafond atteint sur le compte de destination). Le montant est alors automatiquement re-crédité sur votre solde DolaPay.
Sécuriser vos endpoints (Vérification HMAC)
Comme votre URL de Webhook sera publiquement accessible sur Internet, vous devez vous assurer que seules les requêtes provenant de DolaPay sont traitées. Pour cela, nous signons chaque webhook envoyé avec un système HMAC SHA-256.
Où trouver ma clé secrète de Webhook ?
La clé de signature des Webhooks est différente de votre clé d'API secrète. Vous pouvez la trouver dans votre Tableau de bord > Développeurs > Webhooks.
Structure du Header de Signature
L'en-tête HTTP x-dolapay-signature contient le timestamp de l'événement et la signature calculée, séparés par une virgule.
import crypto from "crypto";
import express from "express";
const app = express();
const WEBHOOK_SECRET = process.env.DOLAPAY_WEBHOOK_SECRET;
app.post("/webhooks/dolapay", express.raw({ type: "application/json" }), (req, res) => {
const signatureHeader = req.headers["x-dolapay-signature"];
const payload = req.body.toString();
// 1. Extraire le timestamp et la signature du header
const parts = signatureHeader.split(',');
const timestamp = parts.find((p: string) => p.startsWith('t=')).split('=')[1];
const signature = parts.find((p: string) => p.startsWith('v1=')).split('=')[1];
// 2. Recréer la chaîne à signer : "timestamp.payload"
const signedPayload = `${timestamp}.${payload}`;
// 3. Calculer le HMAC SHA-256 avec votre Webhook Secret
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(signedPayload)
.digest('hex');
// 4. Comparer les signatures de manière sécurisée
if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {
const event = JSON.parse(payload);
// Traiter les événements d'encaissement (Paiement)
if (event.type === "transaction.success") {
console.log("Paiement validé :", event.data.id);
// Valider la commande du client...
}
// Traiter les événements de décaissement (Retrait API)
if (event.type === "payout.success") {
console.log("Retrait API effectué avec succès :", event.data.id);
// Mettre à jour le statut du retrait côté serveur...
}
// Il est très important de répondre avec un 200 OK rapidement
res.status(200).send("Webhook reçu");
} else {
res.status(401).send("Signature invalide");
}
});Politique de Retry
Si votre serveur ne répond pas avec un statut HTTP 200 OK ou s'il est indisponible, DolaPay tentera de renvoyer le webhook plusieurs fois avec un back-off exponentiel pour garantir la livraison.
