Aller au contenu
getnextpdf.com

Enterprise édition

Webhook

NextPDF Enterprise livre les événements de tâche vers des points de terminaison webhook par locataire en HTTP POST, signe chaque charge utile avec une signature HMAC-SHA256, réessaie avec un backoff exponentiel et route les livraisons définitivement échouées vers une file de rebut (dead-letter) pour inspection et rejeu. Cette page décrit le comportement observable du webhook et le contrat public.

Cette capacité est livrée dans NextPDF Enterprise (nextpdf/enterprise) et s’active avec une enveloppe de licence de palier Enterprise. Un déploiement sans ce droit ne charge pas les classes de la capacité. Comparer les éditions et obtenir une licence.

La surface webhook est une capacité de base Enterprise, disponible dès que le paquet Enterprise est installé ; il n’y a aucun indicateur distinct par fonctionnalité.

Un locataire enregistre une URL de rappel, un secret de signature et une liste facultative de types d’événements. Une liste d’événements vide signifie « abonné à tous les événements ». Les enregistrements sont strictement à portée de locataire : un locataire ne peut voir et gérer que ses propres enregistrements, et un enregistrement sous un locataire non concordant est rejeté. La désinscription désactive l’enregistrement plutôt que de le supprimer, de sorte que l’historique est préservé ; seuls les enregistrements actifs reçoivent des distributions.

Lorsqu’un événement de tâche est distribué pour un locataire, chaque enregistrement actif abonné au type d’événement reçoit une livraison. La charge utile est un document JSON standardisé — un identifiant de livraison unique, l’identifiant de tâche, le type d’événement, les données d’événement, un horodatage RFC 3339 et l’identifiant de locataire. La livraison est une requête HTTP POST portant le corps JSON et quatre en-têtes : une signature HMAC-SHA256, un horodatage en secondes unix, l’identifiant de livraison et le type d’événement. La signature est calculée sur la chaîne de base canonique {timestamp}.{body} avec le secret de l’enregistrement, de sorte que l’en-tête d’horodatage est cryptographiquement lié au corps. Le récepteur recalcule le HMAC sur la même chaîne de base et rejette les livraisons dont l’horodatage tombe en dehors d’une fenêtre de fraîcheur acceptable, ce qui borne le rejeu.

La livraison utilise un backoff exponentiel. Une réponse 2xx est un succès. Une réponse 4xx autre que 429 est traitée comme un rejet permanent et n’est pas réessayée. Les autres échecs — 5xx, 429 ou une erreur de connexion — sont réessayés jusqu’au nombre de tentatives de la politique avec un délai qui double, plafonné à un maximum. Lorsque toutes les tentatives sont épuisées, la livraison est enregistrée dans une file de rebut en mémoire avec la charge utile d’origine, le nombre de tentatives, la dernière erreur et le dernier statut HTTP ; une entrée de rebut peut être marquée comme rejouée. Deux politiques de nouvelles tentatives sont livrées — une default (5 tentatives, base de 1 s, plafond de 5 min) et une aggressive (10 tentatives, base de 2 s, plafond de 10 min).

La livraison est traitée comme une surface opérationnelle, pas comme un appel « tire et oublie ». Les échecs sont classés par intention. Un 4xx autre que 429 est un véritable rejet du récepteur, il s’arrête donc immédiatement. Un 5xx, un 429 ou une erreur de connexion est transitoire, il obtient donc une nouvelle tentative plafonnée avec backoff. Les livraisons qui épuisent toutes les tentatives ne sont jamais abandonnées en silence ; elles atterrissent dans une file de rebut inspectable qui peut être rejouée. La signature lie un horodatage dans sa chaîne de base, et chaque destination franchit une barrière de sortie (egress), de sorte que l’authenticité et la résistance au rejeu tiennent par construction pour chaque locataire.

Contexte de conception : Exploiter NextPDF en production.

Fenêtre de terminal
composer require nextpdf/enterprise:^3

Les points d’intégration pris en charge sont le gestionnaire de webhooks (register, unregister, activeRegistrations, dispatch), l’objet-valeur d’enregistrement (subscribesTo, deactivate), la charge utile (fromJobEvent, toJson, toArray, sign, signedTimestamp), le moteur de livraison (deliver, deadLetters, clearDeadLetters), la politique de nouvelles tentatives (delayForAttempt, shouldRetry, default, aggressive) et l’entrée de rebut (markReplayed).

use NextPDF\Enterprise\Webhook\WebhookManager;
use NextPDF\Enterprise\Webhook\WebhookRegistration;
$manager->register($tenant, new WebhookRegistration(
id: $id,
tenantId: $tenant->tenantId,
url: 'https://customer.example.com/hooks/nextpdf',
events: [], // empty = subscribe to all event types
secret: $signingSecret,
));
$delivered = $manager->dispatch($tenant, $jobEvent); // count of successes

Vérification côté récepteur :

$ts = (int) $request->header('X-NextPDF-Timestamp');
if (abs(time() - $ts) > 300) {
return new Response(401); // stale timestamp: reject to bound replay
}
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $rawBody, $sharedSecret);
if (! hash_equals($expected, $request->header('X-NextPDF-Signature'))) {
return new Response(401);
}
use NextPDF\Enterprise\Webhook\WebhookDelivery;
use NextPDF\Enterprise\Webhook\WebhookRetryPolicy;
$delivery = new WebhookDelivery(
$httpClient, $requestFactory, $streamFactory,
retryPolicy: WebhookRetryPolicy::aggressive(), // 10 attempts, 2s base, 10min cap
logger: $logger,
);
$manager = new WebhookManager($delivery, $logger);
$manager->dispatch($tenant, $jobEvent);
foreach ($delivery->deadLetters() as $dead) {
$this->scheduleReplay($dead); // inspect last error + last HTTP status
}
  • Une liste d’événements vide s’abonne à tout. Un enregistrement sans types d’événements reçoit tous les événements ; passe une liste explicite pour le restreindre.
  • L’isolation des locataires est appliquée. S’enregistrer avec un ID de locataire qui diffère du locataire du contexte est rejeté ; la distribution n’itère que sur les enregistrements actifs du locataire appelant.
  • 4xx (sauf 429) est terminal. Un 4xx autre que 429 n’est pas réessayé — il est traité comme un rejet permanent par le récepteur et va en file de rebut.
  • La désinscription est douce. La désinscription désactive ; l’enregistrement persiste et est exclu de la distribution.
  • La file de rebut est en mémoire. Elle sert à l’inspection et au rejeu dans la durée de vie du processus ; persiste toi-même les entrées si tu as besoin d’un rejeu durable à travers les redémarrages.

Le coût de distribution est proportionnel au nombre d’enregistrements actifs du locataire qui s’abonnent à l’événement. Chaque livraison est un HMAC-SHA256 sur la chaîne de base signée plus l’aller-retour HTTP ; les nouvelles tentatives ajoutent des délais de backoff exponentiel bornés. La signature est en O(taille de charge utile).

Chaque charge utile est authentifiée avec une signature HMAC-SHA256 ayant pour clé le secret de l’enregistrement et envoyée dans l’en-tête X-NextPDF-Signature sous la forme sha256=<hex>. La signature couvre la chaîne de base {timestamp}.{body}, et l’horodatage voyage dans l’en-tête X-NextPDF-Timestamp ; les récepteurs vérifient avec une comparaison en temps constant et rejettent les livraisons hors d’une fenêtre de fraîcheur pour borner le rejeu. Les URL de destination franchissent une barrière de sortie (egress) centrale avant chaque envoi : HTTPS est requis, et les hôtes qui se résolvent en adresses privées, de bouclage (loopback), locales au lien (link-local) ou de métadonnées cloud sont refusés sans requête et routés vers la file de rebut. Le secret de signature est par enregistrement ; traite-le comme un identifiant. La signature authentifie l’intégrité et l’origine de la charge utile ; ce n’est pas une couche de chiffrement — ne place pas de secrets dans les données d’événement que le récepteur ne devrait pas voir.

  • L’authentification de la charge utile utilise HMAC avec SHA-256, le code d’authentification de message à clé de hachage de FIPS PUB 198-1 ; OWASP ASVS 5.0 répertorie HMAC-SHA-256 parmi ses algorithmes d’authentification de message approuvés.
  • Les horodatages de charge utile sont des chaînes date-heure RFC 3339. Note : RFC 3339 n’a pas été récupéré du corpus RAG pour cette page ; le format est déclaré dans le code (RFC 3339 étendu) et marqué « déclaré dans le code » plutôt que « vérifié par RAG ».
  • Les enregistrements sont strictement à portée de locataire ; un enregistrement sous un locataire non concordant est rejeté et la désinscription est une désactivation douce qui préserve l’historique.
  • Une liste d’événements vide s’abonne à tous les événements ; seuls les enregistrements actifs abonnés au type d’événement reçoivent une distribution.
  • Chaque livraison est une requête HTTP POST avec le corps JSON plus un en-tête de signature HMAC-SHA256 (sur la chaîne de base {timestamp}.{body}), un en-tête d’horodatage en secondes unix, l’identifiant de livraison et le type d’événement.
  • Un 2xx est un succès ; un 4xx autre que 429 est un rejet permanent (pas de nouvelle tentative) ; 5xx, 429 ou une erreur de connexion est réessayé jusqu’au nombre de tentatives de la politique avec un backoff à doublement plafonné.
  • Les tentatives épuisées enregistrent la livraison dans une file de rebut en mémoire (charge utile, nombre de tentatives, dernière erreur, dernier statut) ; une entrée de rebut peut être marquée comme rejouée.

Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins d’espace de noms internes, les classes utilitaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de ticket sont hors périmètre.

NextPDF Core (Apache-2.0) n’a aucune surface d’enregistrement ou de livraison de webhook — aucune ; cette capacité n’a aucun équivalent au palier Core.

NextPDF Pro n’a aucune surface d’enregistrement ou de livraison de webhook — aucune ; cette capacité n’a aucun équivalent au palier Pro. Le gestionnaire de webhooks, l’enregistrement, la charge utile, le moteur de livraison et la politique de nouvelles tentatives sont livrés uniquement dans le paquet nextpdf/enterprise.

La politique de nouvelles tentatives, le calendrier de backoff et la gestion de la file de rebut sont décrits au niveau du comportement. La file de rebut est en mémoire pour l’inspection et le rejeu dans la durée de vie du processus ; la persistance durable à travers les redémarrages et tout détail interne de livraison sont hors du périmètre de la surface publique.

L’opérateur possède les points de terminaison de rappel, les secrets de signature par enregistrement (traités comme des identifiants), la persistance durable des entrées de rebut si un rejeu à travers les redémarrages est requis, et la posture HTTPS des URL de récepteur. NextPDF Enterprise signe et livre mais ne persiste pas lui-même les enregistrements ni les rebuts au-delà de la durée de vie du processus.

Aucune restriction de contrôle des exportations ne s’applique à la surface webhook. La signature HMAC authentifie l’intégrité et l’origine de la charge utile ; ce n’est pas une couche de chiffrement — les opérateurs ne doivent pas placer de secrets dans les données d’événement que le récepteur ne devrait pas voir. Cette documentation n’est pas un avis juridique ; consulte tes propres conseillers conformité et juridiques.