FlowAlp

Vérifier la signature des webhooks

July 30, 2026

Vérifiez l'authenticité des webhooks FlowAlp Pay : contrôle de signature HMAC-SHA256 en PHP, schéma ApiSignature et test via SignatureCheck.

Un endpoint webhook est une porte d'entrée dans votre système de commandes : chaque événement entrant doit prouver qu'il vient réellement de FlowAlp Pay. Deux mécanismes se complètent : l'en-tête de signature du webhook lui-même et la validation côté serveur via la Merchant API.

Fonctionnement de la signature webhook

Chaque webhook porte l'en-tête HTTP X-Webhook-Signature. Sa valeur est un HMAC-SHA256 calculé sur le corps brut de la requête avec votre clé de signature, encodé en hexadécimal minuscule. Trois détails comptent :

  • Données signées : le corps brut et non modifié de la requête — ne resérialisez jamais le JSON parsé avant le hachage.
  • Encodage de la clé : la clé de signature s'utilise comme simple chaîne UTF-8 ; elle n'est pas décodée depuis Base64.
  • Encodage de la signature : le résultat est en hex minuscule — pas en Base64.

La clé de signature appartient à votre configuration webhook dans le dashboard sur https://pay.flowalp.com. Si vos réglages webhook n'affichent pas de clé de signature pour votre compte, ne devinez ni noms d'en-têtes ni clés : appuyez-vous sur la validation côté API décrite ci-dessous et confirmez la disponibilité de la signature pour votre compte auprès du support FlowAlp avant la mise en production.

Vérifier et rejeter en PHPPHP
<?php
// Reject any webhook whose signature does not match
$rawBody    = file_get_contents('php://input');
$received   = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$signingKey = getenv('FLOWALP_WEBHOOK_SIGNING_KEY');

// Lowercase hex HMAC-SHA256 of the raw body; the key is a plain UTF-8 string
$expected = hash_hmac('sha256', $rawBody, $signingKey);

if (!hash_equals($expected, $received)) {
    http_response_code(401); // non-2xx: the delivery counts as failed
    exit('invalid signature');
}

http_response_code(200);
// Queue the event for asynchronous, idempotent processing

Utilisez hash_equals() (ou la comparaison à temps constant de votre langage) contre les attaques par timing, et répondez aux livraisons non signées ou invalides par un statut non-2xx comme 401 — sans jamais les traiter.

Ne pas confondre avec ApiSignature

La Merchant API connaît un second HMAC, indépendant : le mode d'authentification ApiSignature pour les requêtes API sortantes. Distinguez bien les deux :

AspectSignature webhookApiSignature
Ce qui est signéCorps POST brut du webhook entrantParamètres de requête triés alphabétiquement et URL-encodés (tous sauf instance)
CléClé de signature des webhooksVotre API Secret
EncodageHexadécimal minusculeBase64
TransportEn-tête X-Webhook-Signature, entrantParamètre ApiSignature, sortant
Helper ApiSignaturePHP
<?php
function flowalpApiSignature(array $params, string $apiSecret): string
{
    ksort($params);
    $query = http_build_query($params, '', '&');
    return base64_encode(hash_hmac('sha256', $query, $apiSecret, true));
}

Les règles exactes d'encodage des paramètres pour ApiSignature sont documentées dans Authentification de la Merchant API.

Valider les identifiants avec SignatureCheck

La ressource SignatureCheck vérifie le nom d'instance, l'API Secret et — en mode signature — votre implémentation HMAC, sans rien créer. Appelez-la lors du setup et depuis vos health checks :

GEThttps://api.pay.flowalp.com/v1.16/SignatureCheck/v1.14 · v1.15 · v1.16
SignatureCheck avec le SDK PHPPHP
<?php
use FlowAlpPay\FlowAlpPay;
use FlowAlpPay\Models\Request\SignatureCheck;

$client = new FlowAlpPay(
    getenv('FLOWALP_TENANT'),
    getenv('FLOWALP_API_SECRET'),
    FlowAlpPay::DEFAULT_COMMUNICATION_HANDLER,
    'pay.flowalp.com',
    '1.16'
);

try {
    $client->getOne(new SignatureCheck());
    // Credentials are valid
} catch (\FlowAlpPay\FlowAlpPayException $e) {
    // Wrong instance name or API secret
}

Détails et réponses d'erreur sur la page de référence SignatureCheck ; la configuration du client est traitée dans le guide du SDK PHP.

Défense en profondeur

  • Rejetez les webhooks non signés ou invalides avec une réponse non-2xx et alertez en cas d'échecs répétés.
  • Traitez les événements vérifiés de façon idempotente — déduplication sur ID de transaction plus statut.
  • Pour les changements d'état à enjeu financier, récupérez en plus la transaction via l'API avant d'exécuter.
  • Conservez le résultat de la vérification à côté du payload brut pour les audits.

Étape suivante : repassez en revue les payloads webhook que votre handler doit gérer, puis suivez la checklist de mise en production.