FedCheckout
AccueilDocumentationTableau de bord

Démarrer

Vue d'ensembleMode test

Intégrer

Référence de l'APIWebhooksMoyens de paiement

Référence

Codes d'erreurJournal des versions

Webhooks

La redirection du navigateur n'est qu'un confort d'affichage. La vérité, c'est le webhook signé — ou une lecture serveur du paiement.

Ne débloque jamais une commande parce qu'une adresse contient « success ». Une redirection se fabrique ; une signature HMAC, non.

Ce que tu reçois

POST /webhooks/fedcheckout HTTP/1.1
FedCheckout-Event-Id: evt_9F3K…
FedCheckout-Event-Type: payment_intent.succeeded
FedCheckout-Timestamp: 1789964330
FedCheckout-Signature: 4b1f…
Content-Type: application/json

{
  "id": "evt_9F3K…",
  "type": "payment_intent.succeeded",
  "mode": "live",
  "created_at": "2026-09-21T04:38:50Z",
  "data": {
    "id": "fpay_pi_8K2M…",
    "object": "payment_intent",
    "status": "succeeded",
    "amount": "500.000000",
    "currency": "GDS",
    "external_reference": "ORD-7781",
    "payment_method": "gds_wallet"
  }
}

La chaîne signée

La signature est un HMAC-SHA256 calculé sur "{timestamp}.{corps brut}", avec le secret de cette destination. Le corps brut : pas un objet re-sérialisé. Deux JSON équivalents n'ont pas le même texte, donc pas la même signature.

  • FedCheckout-Event-Ididentifiant de l'événement, stable entre deux envois
  • FedCheckout-Event-Typele type, par exemple payment_intent.succeeded
  • FedCheckout-Timestampsecondes Unix, à inclure dans le calcul
  • FedCheckout-SignatureHMAC-SHA256 en hexadécimal

Trois règles qui évitent les ennuis

  1. RÈGLE 1

    Compare à temps constant

    timingSafeEqual, hash_equals, compare_digest — jamais ===.

  2. RÈGLE 2

    Refuse les vieux envois

    Au-delà de cinq minutes d'écart entre le timestamp et l'heure de réception, rejette : c'est ce qui bloque le rejeu.

  3. RÈGLE 3

    Traite une seule fois

    Le même Event-Id peut arriver deux fois. Enregistre-le et ignore les doublons.

Événements émis

  • payment_intent.created
  • payment_intent.processing
  • payment_intent.succeeded
  • payment_intent.failed
  • payment_intent.cancelled
  • payment_intent.expired
  • refund.created
  • refund.succeeded
  • refund.failed

Réessais et lettre morte

Réponds 2xx dès que tu as enregistré l'événement — le traitement peut venir après. En cas d'échec, FedCheckout réessaie avec un recul croissant, puis range la livraison en lettre morte. Tu peux la renvoyer depuis la console, dans « Journaux d'API ».

Vérifier la signature

import { createHmac, timingSafeEqual } from "node:crypto";

// Le corps BRUT, pas un objet re-sérialisé : deux JSON équivalents
// n'ont pas le même texte, donc pas la même signature.
export function verifier(corpsBrut, entetes, secret) {
  const ts  = entetes["fedcheckout-timestamp"];
  const sig = entetes["fedcheckout-signature"];
  if (!ts || !sig) return false;

  // Rejeu : on refuse au-delà de cinq minutes d'écart.
  if (Math.abs(Date.now() - Number(ts) * 1000) > 300000) return false;

  const attendue = createHmac("sha256", secret)
    .update(`${ts}.${corpsBrut}`)
    .digest("hex");

  const a = Buffer.from(attendue), b = Buffer.from(sig);
  return a.length === b.length && timingSafeEqual(a, b);
}
FedCheckout — une infrastructure de paiement de Fed Digital, Gonaïves, Haïti.
DocumentationConditionsConfidentialitéRemboursementsFedTopUp