Wocart

Webhooks des transporteurs

Les transporteurs poussent les mises à jour de livraison vers CodFlow. Le serveur vérifie la signature, stocke les événements dans une boîte de réception, répond immédiatement au transporteur et traite les événements après la réponse. Votre intégration lit l'état d'expédition résultant via l'API.

Pour recevoir les événements de votre propre boutique sur votre serveur, lisez plutôt Webhooks.

Les webhooks entrants existent pour Yalidine et ZR Express. NOEST et EcoTrack n'envoient pas de webhooks ; leurs expéditions sont synchronisées toutes les cinq minutes par une tâche cron et à la demande via les endpoints de synchronisation des expéditions.

Endpoints

TransporteurEndpointForme d'envoiSignature
YalidinePOST /webhooks/yalidineUn lot d'événements d'un même typeHMAC-SHA256 dans x-yalidine-signature
YalidineGET /webhooks/yalidineChallenge CRCRenvoie crc_token en texte brut
ZR ExpressPOST /webhooks/zr_expressUn événement Svix par requêteSvix HMAC-SHA256

Les chemins sont les URL que détiennent les transporteurs. Ne les placez pas derrière une authentification : les transporteurs ne peuvent pas envoyer votre clé API. La signature est l'authentification.

Fonctionnement de la réception

  1. Transporteur vers CodFlow

    Le transporteur envoie un POST signé à /webhooks/yalidine ou /webhooks/zr_express.

  2. Vérifier et découper

    CodFlow vérifie la signature avec le secret de la société et découpe l'enveloppe du transporteur en événements individuels.

  3. Stocker dans la boîte de réception

    Chaque événement est stocké dans webhook_events, indexé par son identifiant d'événement fournisseur.

  4. Répondre au transporteur

    CodFlow renvoie 200 {"received":true} sans attendre le traitement.

  5. Traiter après la réponse

    Quelques secondes plus tard, la file d'événements réveille le drain, qui applique les jalons d'expédition de chaque événement et enregistre leurs Business Events. La tâche planifiée toutes les cinq minutes exécute le même drain : un événement manqué par un réveil perdu est tout de même traité.

Le transporteur reçoit son 200 dès que les événements sont stockés. Les échecs de traitement ne font pas échouer le webhook ; le drain les réessaie selon le calendrier de la boîte de réception. Yalidine exige une réponse sous 10 secondes et réessaie une livraison échouée sept fois sur 40 heures, d'où l'importance de cette séparation.

Configurer un webhook

Les deux flux commencent sur la page d'identifiants de la société de livraison dans le tableau de bord.

Yalidine

  1. Ouvrez la page d'identifiants de la société et copiez l'URL de réception depuis la carte de configuration du webhook.
  2. Dans le Webhooks Dashboard de Yalidine, créez un endpoint avec cette URL.
  3. Abonnez-vous aux types d'événements dont vous avez besoin. Yalidine valide l'URL avec le challenge CRC.
  4. Copiez le secret de signature depuis Yalidine dans la carte et enregistrez-le. Stockez la même valeur dans votre gestionnaire de secrets.

ZR Express

  1. Ouvrez la page d'identifiants de la société et choisissez Register webhook.
  2. Le serveur enregistre l'endpoint auprès de ZR Express et récupère le secret de signature pour vous.
  3. La carte affiche l'endpoint comme enregistré. Utilisez Unregister pour le supprimer.

Envoyez un événement de test depuis le transporteur et confirmez que la société de livraison le reçoit.

Un webhook a besoin de son secret. Une livraison qu'aucun secret de société ne vérifie est refusée avec 401 et jamais stockée : ce qu'un transporteur rapporte devient un événement métier dont les systèmes des marchands et les clients peuvent être informés, il faut donc prouver qu'il vient du transporteur. Si ZR Express ne donne pas son secret de signature, l'enregistrement est annulé et rien n'est conservé ; enregistrez à nouveau.

Vérification de la signature

Yalidine

Yalidine signe le corps brut de la requête avec HMAC-SHA256 en utilisant le secret de webhook de la société. La signature arrive dans x-yalidine-signature (ou x_yalidine_signature). Le serveur accepte les représentations hexadécimales minuscules, hexadécimales majuscules et base64, et compare en temps constant.

Le challenge GET est distinct : lorsque Yalidine envoie les paramètres de requête subscribe et crc_token, le serveur renvoie le jeton en texte brut. Cela permet à Yalidine de vérifier l'URL avant d'envoyer des événements.

ZR Express

ZR Express utilise Svix. Le contenu signé est :

Code
{svix-id}.{svix-timestamp}.{rawBody}

La signature arrive dans svix-signature, et le serveur accepte n'importe quelle entrée v1,<base64> séparée par des espaces. Un svix-id, svix-timestamp ou svix-signature manquant est rejeté.

Idempotence et ordre

  • Yalidine regroupe plusieurs événements dans une requête. Chaque événement possède son propre event_id, qui sert de clé dans la boîte de réception.
  • ZR Express envoie un événement par requête. svix-id est la clé de la boîte de réception.
  • Les livraisons en double sont ignorées par la boîte de réception, donc une nouvelle tentative du transporteur ne peut pas appliquer deux fois le même événement.
  • Les événements peuvent arriver dans le désordre. Le serveur applique les jalons d'expédition selon l'horodatage de l'événement, pas selon l'ordre d'arrivée.

Développement local

Les transporteurs ont besoin d'une URL HTTPS publique. Exposez votre Worker local avec un tunnel de confiance, puis configurez cette origine chez le transporteur. Pour Yalidine, créez l'endpoint à <tunnel-origin>/webhooks/yalidine et enregistrez son secret dans la carte webhook de la société. Pour ZR Express, envoyez l'origine du tunnel comme X-Worker-URL lors de l'enregistrement, afin que l'endpoint créé pointe vers le tunnel au lieu de localhost.

Le récepteur local reste http://localhost:8787/webhooks/yalidine ou /webhooks/zr_express, ce qui vous permet de rejouer une charge utile signée avec curl pendant le développement :

TerminalCode
curl -X POST http://localhost:8787/webhooks/yalidine \ -H "Content-Type: application/json" \ -H "x-yalidine-signature: <hex hmac of the raw body>" \ --data-binary @event.json

Voir aussi