Aller au contenu principal

Webhooks

CajouPay envoie un POST JSON à l'adresse de votre serveur à chaque changement de statut d'un paiement ou d'un retrait. Ajoutez cette adresse dans Développeurs (une par environnement) et copiez son secret whsec_…. Supprimer arrête aussitôt les envois vers une adresse, relances en attente comprises ; les envois passés restent dans le journal.

Événements​

TypeQuand
payment.request_sentla demande est partie vers la banque du client
payment.accepted_deferredle client a accepté et paiera à la livraison
payment.succeededle paiement est reçu
payment.declinedle client a refusé
payment.expireddélai dépassé
payment.canceledvous avez annulé le paiement
payment.failederreur technique côté banque
payment.duplicate_refundedun paiement en double a été remboursé au client
payout.paid, payout.failedun retrait est versé, ou a échoué
{
"id": "evt_3Fz9Qm2LkP",
"object": "event",
"type": "payment.succeeded",
"created_at": "2026-10-11T17:42:08Z",
"livemode": false,
"data": { "object": { "id": "pay_8Kq2xVt41N", "status": "succeeded", "amount": 32500, "…": "…" } }
}

data.object est le paiement (ou le retrait) complet, tel que l'API le renvoie.

Vérifier la signature​

Chaque envoi porte l'en-tête CajouPay-Signature: t=<horodatage>,v1=<signature>, où la signature est le HMAC-SHA256, en hexadécimal, de <horodatage>.<corps brut> avec votre secret. Refusez (400) une signature fausse ou un horodatage à plus de 5 minutes de l'heure courante. Calculez la signature sur le corps brut, avant tout décodage JSON.

$payload = file_get_contents('php://input');
try {
$event = \CajouPay\Webhook::constructEvent(
$payload,
$_SERVER['HTTP_CAJOUPAY_SIGNATURE'] ?? null,
getenv('CAJOUPAY_WEBHOOK_SECRET'),
);
} catch (\CajouPay\Exception\SignatureVerificationException $e) {
http_response_code(400);
exit;
}

Répondre​

Répondez un code 2xx en moins de 10 secondes, puis traitez l'événement. Sans réponse 2xx, CajouPay renvoie l'événement après 1 min, 5 min, 30 min, 2 h puis 12 h (six envois en tout). Les redirections ne sont pas suivies.

Traiter sans surprise​

  • Une seule fois : le même événement peut arriver plusieurs fois. Retenez les id déjà traités, ou rendez l'action sans effet la seconde fois (une commande déjà payée le reste).
  • Dans le désordre : l'ordre d'arrivée n'est pas garanti. Fiez-vous au status de data.object, et ne revenez jamais en arrière depuis un statut final.
  • Vérifiez le montant avant de livrer : data.object.amount doit être celui de votre commande.
  • En cas de doute, relisez le paiement : GET /v1/payments/{id}.

En production, l'adresse doit être en https et joignable depuis Internet.