Skip to content

Webhooks & IPN / APN

HayBTech utilise un système de notifications en temps réel appelé Webhooks, souvent désigné sous les termes IPN (Instant Payment Notification) ou APN (Automated Payment Notification) par les passerelles locales.

  • IPN : Notification instantanée envoyée dès que le paiement est confirmé (ex: payment.success).
  • APN : Notifications automatiques pour les changements d'état secondaires ou les cycles de vie (ex: payment.expired).

La livraison est signée (HMAC-SHA256), idempotente par événement, retentée avec backoff, et le secret peut être roté sans coupure.

Événements

ÉvénementQuand
payment.successLe connecteur confirme le paiement
payment.failedLe connecteur refuse, retourne une erreur ou expire
payment.cancelledLe payeur a annulé
payment.expiredExpiration de la fenêtre de complétion
payment.pending(optionnel, désactivé par défaut)

Vous choisissez les événements auxquels vous abonner par endpoint (Dashboard -> Webhooks).

Configuration

Dashboard -> Développeurs -> Webhooks -> Add endpoint

  • URL : doit être HTTPS.
  • Événements : sous-ensemble de la liste ci-dessus.
  • Secret : généré aléatoirement. À conserver côté serveur.

Auto-suspension après un nombre d'échecs consécutifs (seuil interne).

Signature

Chaque requête porte le header :

X-HayB-Signature: t=<unix>,v1=<hex_hmac_sha256>

Pendant une rotation de secret, deux signatures peuvent coexister :

X-HayB-Signature: t=<unix>,v1=<hmac_secret_courant>,v2=<hmac_secret_suivant>

Vérification

  1. Parser le timestamp t et la signature v1 (et éventuellement v2).
  2. Vérifier que t est récent (dans la fenêtre de tolérance applicable).
  3. Recalculer expected = HMAC-SHA256(t + "." + raw_body, secret).
  4. Comparer en temps constant (hash_equals en PHP, crypto.timingSafeEqual en Node).
  5. Si une v2 est présente, accepter si v1 OU v2 matche.
php
$header = $_SERVER['HTTP_X_HAYB_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
$secrets = [getenv('HAYB_WEBHOOK_SECRET'), getenv('HAYB_WEBHOOK_SECRET_NEXT')];

if (! preg_match('/t=(\d+)/', $header, $tm)) throw new RuntimeException('bad sig');
$ts = (int) $tm[1];
if (abs(time() - $ts) > 300) throw new RuntimeException('expired');

$ok = false;
foreach (['v1', 'v2'] as $i => $version) {
    if (! preg_match("/{$version}=([a-f0-9]{64})/", $header, $vm)) continue;
    $secret = $secrets[$i] ?? null;
    if ($secret === null || $secret === '') continue;
    if (hash_equals(hash_hmac('sha256', "{$ts}.{$body}", $secret), $vm[1])) {
        $ok = true; break;
    }
}
if (! $ok) throw new RuntimeException('invalid');

Tolérance

L'exemple ci-dessus utilise 300 secondes, qui est un plafond raisonnable. La fenêtre HayBTech est plus courte en production ; une valeur de 300s côté marchand est donc sûre.

Headers complémentaires

HeaderSens
X-HayB-EventType d'événement (payment.success, ...)
X-HayB-DeliveryIdentifiant de livraison unique utile pour les logs
User-AgentHayBTech-Webhook/1.0

Idempotency côté votre serveur

Le même événement peut arriver plusieurs fois (retry après timeout, replay sur incident). Stockez l'event_id (champ data.id du payload) et ignorez les doublons.

sql
CREATE UNIQUE INDEX uq_inbound_event ON your_webhook_log(event_id);

Retry et livraison

  • Plusieurs tentatives, backoff exponentiel sur plusieurs jours.
  • 2xx = succès, HayBTech arrête.
  • 3xx = considéré comme échec (votre endpoint doit répondre 2xx directement).
  • 4xx, 5xx, timeout = échec, retry programmé.
  • Après un nombre d'échecs consécutifs, l'endpoint est auto-suspendu et un email vous est envoyé.

Vous pouvez relancer manuellement depuis Dashboard -> Webhook logs -> Resend.

Rotation de secret zero-downtime

  1. Dashboard -> Webhooks -> Rotate secret. HayBTech affiche le nouveau secret (à copier maintenant, jamais réaffiché).
  2. Pendant la fenêtre de rotation, chaque payload peut être signé avec les deux secrets.
  3. Mettez à jour votre vérificateur pour accepter v1 OU v2.
  4. Cliquez Promote : le nouveau secret devient le secret courant, l'ancien est invalidé.

Tester un webhook

Vous pouvez déclencher un événement de test signé avec votre secret réel de deux façons :

  • Dashboard : Développeurs -> Webhooks -> Test.
  • API : Appelez POST /v1/webhooks/test. Cette commande déclenche un événement payment.test vers tous vos endpoints actifs.

Si vous ratez un webhook

  1. Endpoint pull : POST /v1/payments/{id}/verify force HayBTech à interroger le connecteur et à ré-émettre l'événement si la transition s'est produite.
  2. Réconciliation automatique interne qui rattrape les transactions bloquées : vous n'avez généralement rien à faire.

Documentation de l'API de paiement HayBTech.