Salta ai contenuti
getnextpdf.com

Enterprise edizione

Webhook

NextPDF Enterprise recapita gli eventi di job a endpoint webhook per-tenant tramite HTTP POST, firma ogni payload con una firma HMAC-SHA256, ritenta con backoff esponenziale e instrada i recapiti definitivamente falliti a una coda dead-letter per l’ispezione e il replay. Questa pagina descrive il comportamento webhook osservabile e il contratto pubblico.

Questa capacità è inclusa in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di livello Enterprise. Un deployment privo di tale entitlement non carica le classi della capacità. Confronta le edizioni e ottieni una licenza.

La superficie webhook è una capacità Enterprise di base, disponibile una volta installato il pacchetto Enterprise; non esiste un flag per-funzionalità separato.

Un tenant registra un URL di callback, un secret di firma e un elenco facoltativo di tipi di evento. Un elenco di eventi vuoto significa «iscriversi a tutti gli eventi». Le registrazioni hanno un ambito strettamente per-tenant: un tenant può vedere e gestire solo le proprie registrazioni, e la registrazione sotto un tenant non corrispondente viene rifiutata. L’annullamento della registrazione disattiva la registrazione anziché eliminarla, così che la storia sia preservata; solo le registrazioni attive ricevono dispatch.

Quando un evento di job viene dispatchato per un tenant, ogni registrazione attiva iscritta al tipo di evento riceve un recapito. Il payload è un documento JSON standardizzato — un identificatore univoco del recapito, l’identificatore del job, il tipo di evento, i dati dell’evento, un timestamp RFC 3339 e l’identificatore del tenant. Il recapito è un HTTP POST che trasporta il corpo JSON e quattro header: una firma HMAC-SHA256, un timestamp in secondi unix, l’identificatore del recapito e il tipo di evento. La firma è calcolata sulla base string canonica {timestamp}.{body} con il secret della registrazione, così che l’header timestamp sia legato crittograficamente al corpo. Il ricevitore ricalcola l’HMAC sulla stessa base string e rifiuta i recapiti il cui timestamp cade fuori da una finestra di freschezza accettabile, il che limita il replay.

Il recapito usa il backoff esponenziale. Una risposta 2xx è successo. Una risposta 4xx diversa da 429 è trattata come un rifiuto permanente e non viene ritentata. Altri fallimenti — 5xx, 429 o un errore di connessione — vengono ritentati fino al numero di tentativi della policy con un ritardo che raddoppia, con un tetto a un massimo. Quando tutti i tentativi sono esauriti, il recapito è registrato in una coda dead-letter in memoria con il payload originale, il conteggio dei tentativi, l’ultimo errore e l’ultimo status HTTP; una voce dead-letter può essere contrassegnata come rigiocata. Sono incluse due retry policy — una default (5 tentativi, base 1s, tetto 5min) e una aggressive (10 tentativi, base 2s, tetto 10min).

Il recapito è trattato come una superficie operativa, non come una chiamata fire-and-forget. I fallimenti sono classificati per intento. Un 4xx diverso da 429 è un genuino rifiuto del ricevitore, quindi si ferma subito. Un 5xx, un 429 o un errore di connessione è transitorio, quindi si guadagna un retry limitato con backoff. I recapiti che esauriscono ogni tentativo non vengono mai scartati in silenzio; finiscono in una coda dead-letter ispezionabile che può essere rigiocata. La firma lega un timestamp nella sua base string, e ogni destinazione supera un gate di egress, così che autenticità e resistenza al replay valgano per costruzione per ogni tenant.

Contesto di progettazione: Operating NextPDF in production.

Terminal window
composer require nextpdf/enterprise:^3

I punti di integrazione supportati sono il webhook manager (register, unregister, activeRegistrations, dispatch), il value object della registrazione (subscribesTo, deactivate), il payload (fromJobEvent, toJson, toArray, sign, signedTimestamp), il motore di recapito (deliver, deadLetters, clearDeadLetters), la retry policy (delayForAttempt, shouldRetry, default, aggressive) e la voce dead-letter (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

Verifica lato ricevitore:

$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
}
  • Un elenco di eventi vuoto iscrive a tutti. Una registrazione senza tipi di evento riceve ogni evento; passare un elenco esplicito per limitarne l’ambito.
  • L’isolamento del tenant è applicato. La registrazione con un tenant ID diverso dal tenant del contesto viene rifiutata; il dispatch itera solo le registrazioni attive del tenant chiamante.
  • 4xx (eccetto 429) è terminale. Un 4xx diverso da 429 non viene ritentato — è trattato come un rifiuto permanente del ricevitore e va alla coda dead-letter.
  • L’annullamento della registrazione è soft. L’annullamento della registrazione disattiva; il record persiste ed è escluso dal dispatch.
  • La coda dead-letter è in memoria. È per l’ispezione e il replay entro la durata del processo; persistere le voci da sé se è necessario un replay durevole tra i riavvii.

Il costo del dispatch è proporzionale al numero di registrazioni attive per il tenant iscritte all’evento. Ogni recapito è un HMAC-SHA256 sulla base string firmata più il round trip HTTP; i retry aggiungono ritardi di backoff esponenziale limitati. La firma è O(dimensione del payload).

Ogni payload è autenticato con una firma HMAC-SHA256 con chiave il secret della registrazione e inviato nell’header X-NextPDF-Signature come sha256=<hex>. La firma copre la base string {timestamp}.{body}, e il timestamp viaggia nell’header X-NextPDF-Timestamp; i ricevitori verificano con un confronto a tempo costante e rifiutano i recapiti fuori da una finestra di freschezza per limitare il replay. Gli URL di destinazione superano un gate di egress centrale prima di ogni invio: è richiesto HTTPS, e gli host che risolvono a indirizzi privati, loopback, link-local o di cloud-metadata sono rifiutati senza una richiesta e instradati alla coda dead-letter. Il secret di firma è per-registrazione; trattarlo come una credenziale. La firma autentica l’integrità e l’origine del payload; non è uno strato di cifratura — non inserire secret nei dati dell’evento che il ricevitore non dovrebbe vedere.

  • L’autenticazione del payload usa HMAC con SHA-256, il codice di autenticazione del messaggio con hash a chiave di FIPS PUB 198-1; OWASP ASVS 5.0 elenca HMAC-SHA-256 tra i suoi algoritmi di autenticazione del messaggio approvati.
  • I timestamp del payload sono stringhe data-ora RFC 3339. Nota: RFC 3339 non è stato recuperato dal corpus RAG per questa pagina; il formato è dichiarato nel codice (RFC 3339 esteso) e contrassegnato come dichiarato nel codice anziché verificato tramite RAG.
  • Le registrazioni hanno un ambito strettamente per-tenant; la registrazione sotto un tenant non corrispondente è rifiutata e l’annullamento della registrazione è una disattivazione soft che preserva la storia.
  • Un elenco di eventi vuoto iscrive a tutti gli eventi; solo le registrazioni attive iscritte al tipo di evento ricevono un dispatch.
  • Ogni recapito è un HTTP POST con il corpo JSON più un header di firma HMAC-SHA256 (sulla base string {timestamp}.{body}), un header timestamp in secondi unix, l’identificatore del recapito e il tipo di evento.
  • Un 2xx è successo; un 4xx diverso da 429 è un rifiuto permanente (nessun retry); 5xx, 429 o un errore di connessione viene ritentato fino al numero di tentativi della policy con backoff a raddoppio limitato.
  • I tentativi esauriti registrano il recapito in una coda dead-letter in memoria (payload, conteggio dei tentativi, ultimo errore, ultimo status); una voce dead-letter può essere contrassegnata come rigiocata.

Questa pagina documenta solo il comportamento osservabile dall’esterno e la superficie API pubblica supportata. Percorsi di namespace interni, classi helper, tabelle di meccanismi, nomi di file di runbook e prefissi di ticket sono fuori ambito.

NextPDF Core (Apache-2.0) non ha alcuna superficie di registrazione o recapito di webhook — nessuna; questa capacità non ha equivalente a livello Core.

NextPDF Pro non ha alcuna superficie di registrazione o recapito di webhook — nessuna; questa capacità non ha equivalente a livello Pro. Il webhook manager, la registrazione, il payload, il motore di recapito e la retry policy sono inclusi esclusivamente nel pacchetto nextpdf/enterprise.

La retry policy, lo schema di backoff e la gestione dead-letter sono descritti a livello di comportamento. La coda dead-letter è in memoria per l’ispezione e il replay entro la durata del processo; la persistenza durevole tra riavvii e qualsiasi dettaglio interno di recapito sono fuori ambito per la superficie pubblica.

L’operatore possiede gli endpoint di callback, i secret di firma per-registrazione (trattati come credenziali), la persistenza durevole delle voci dead-letter se è richiesto il replay tra riavvii e la postura HTTPS degli URL ricevitori. NextPDF Enterprise firma e recapita ma non persiste esso stesso registrazioni o dead letter oltre la durata del processo.

Nessuna restrizione di controllo delle esportazioni si applica alla superficie webhook. La firma HMAC autentica l’integrità e l’origine del payload; non è uno strato di cifratura — gli operatori non devono inserire secret nei dati dell’evento che il ricevitore non dovrebbe vedere. Questa documentazione non è un parere legale; consultare i propri consulenti legali e di conformità.