İçeriğe geç
getnextpdf.com

Enterprise sürüm

Webhook — Derin referans

NextPDF\Enterprise\Webhook ad alanı, iş olayları için kiracı kapsamlı webhook teslimi sunar. Genel yüzey altı simgeden oluşur: WebhookManager, WebhookRegistration, WebhookPayload, WebhookDelivery, WebhookRetryPolicy ve DeadLetterEntry. Yönetici, uç noktaları kiracı başına kaydeder ve iş olaylarını abone olan kayıtlara gönderir. Teslim motoru, HMAC-SHA256 ile imzalanmış bir JSON yükünü POST eder, her hedefi Core SSRF çıkış geçidine karşı doğrular, üstel geri çekilme ile yeniden dener ve kalıcı başarısızlıkları bellek içi bir ölü-mektup kuyruğuna kaydeder. 3.1.0 itibarıyla imza, X-NextPDF-Timestamp başlığını MAC temel dizesine bağlar; böylece alıcılar tazeliği ve bütünlüğü birlikte doğrular. İş akışı düzeyindeki kılavuz için Webhook sayfasına bakın.

Bu yetenek NextPDF Enterprise (nextpdf/enterprise) içinde sunulur ve Enterprise katmanlı bir lisans zarfıyla etkinleşir. Bu yetkiye sahip olmayan bir dağıtım, yeteneğin sınıflarını yüklemez. Sürümleri karşılaştırın ve lisans alın.

Webhook yüzeyi, Enterprise paketi kurulduğunda kullanılabilen temel bir Enterprise yeteneğidir; özellik başına ayrı bir bayrak yoktur. NextPDF Core (Apache-2.0) ve NextPDF Pro hiçbir webhook kaydı veya teslim yüzeyine sahip değildir; yönetici, kayıt, yük, teslim motoru, yeniden deneme politikası ve ölü-mektup girişi yalnızca nextpdf/enterprise içinde sunulur.

SimgeParametrelerVarsayılan davranışDöndürürFırlatır veya şununla başarısız olurNotlar
WebhookManager::__constructWebhookDelivery $delivery, ?LoggerInterface $logger = nullBoş bir bellek içi kayıt dizini olan bir yönetici oluştururYeni WebhookManagerFırlatmazKayıtlar kiracı başına dizinlenir
WebhookManager::registerTenantContext $tenant, WebhookRegistration $registrationKaydı, çağıran kiracının dizinine eklervoidKayıt kiracısı bağlam kiracısıyla eşleşmediğinde InvalidArgumentExceptionKiracılar arası kayıt, depolamadan önce reddedilir
WebhookManager::unregisterTenantContext $tenant, string $registrationIdEşleşen kaydı devre dışı bırakılmış bir kopyayla değiştirirboolFırlatmaz; kimlik bulunmadığında false döndürürYumuşak devre dışı bırakma; geçmiş korunur
WebhookManager::activeRegistrationsTenantContext $tenantKiracının kayıtlarını etkin olanlara filtrelerlist<WebhookRegistration>FırlatmazYalnızca çağıran kiracının kayıtları görünür
WebhookManager::dispatchTenantContext $tenant, JobEvent $eventOlayı, olay türüne abone olan her etkin kayda teslim ederint (başarılı teslimler)Olay verisi JSON ile kodlanamadığında JsonException yayar; teslim başarısızlıkları fırlatmazHer kayıt teslimi için yeni bir 32 haneli onaltılık teslim kimliği üretilir
WebhookRegistration::__constructstring $id, string $tenantId, string $url, array $events, string $secret, bool $active = true, ?string $description = nullVerilen değerleri olduğu gibi saklarYeni WebhookRegistrationBildirilmiş @throws yok; strict_types altında uyumsuz argüman türlerinde PHP TypeError fırlatırfinal readonly; boş $events tümüne-abone-ol anlamına gelir
WebhookRegistration::subscribesToJobEventType $eventType$events boş olduğunda veya türü içerdiğinde trueboolFırlatmazKatı özdeşlik karşılaştırması
WebhookRegistration::deactivateEtkin olmayan bir kopya döndürürselfFırlatmazOrijinal örnek değişmez
WebhookPayload::fromJobEventJobEvent $event, string $tenantId, string $deliveryIdİş kimliğini, olay türünü, veriyi ve zaman damgasını olaydan kopyalarselfFırlatmazdispatch tarafından kullanılan statik fabrika
WebhookPayload::toJsonAltı alanlı gövdeyi kaçışsız eğik çizgilerle serileştirirnon-empty-stringOlay verisi JSON ile kodlanamadığında JsonExceptionJSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES
WebhookPayload::toArrayGövdeyi ilişkisel bir dizi olarak döndürürarray<string, mixed>FırlatmazZaman damgası RFC 3339 genişletilmiş olarak biçimlendirilir
WebhookPayload::signedTimestampSıfıra veya daha büyüğe sabitlenmiş Unix saniye cinsinden olay zamanıint<0, max>FırlatmazX-NextPDF-Timestamp olarak yayılır ve MAC’e bağlanır
WebhookPayload::signstring $secret{signedTimestamp}.{jsonBody} temel dizesi üzerinde HMAC-SHA256non-empty-string (onaltılık)Gövde kodlanamadığında toJson() yoluyla JsonExceptionZaman damgası başlığını gövdeye kriptografik olarak bağlar
WebhookDelivery::__constructClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, WebhookRetryPolicy $retryPolicy = new WebhookRetryPolicy(), ?LoggerInterface $logger = nullBoş bir ölü-mektup kuyruğuna sahip PSR-18/PSR-17 teslim motoruYeni WebhookDeliveryFırlatmazVarsayılan politika: 5 deneme, 1 sn temel, 300 sn sınır
WebhookDelivery::deliverWebhookRegistration $registration, WebhookPayload $payloadİmzalı yükü, deneme başına SSRF çıkış doğrulaması ve üstel geri çekilme ile POST ederboolGövde kodlanamadığında ilk denemeden önce JsonException; aksi hâlde fırlatmaz — false, yükün ölü-mektup kuyruğuna yönlendirildiği anlamına gelirYalnızca 2xx yanıtında true
WebhookDelivery::deadLettersKaydedilen tüm girişleri döndürürlist<DeadLetterEntry>FırlatmazBellek içi, süreç kapsamlı
WebhookDelivery::clearDeadLettersÖlü-mektup kuyruğunu boşaltırvoidFırlatmazGeri alınamaz; yeniden oynatma gerekiyorsa önce girişleri dışa aktarın
WebhookRetryPolicy::__constructint $maxRetries = 5, int $baseDelaySeconds = 1, int $maxDelaySeconds = 300Politika değerlerini saklarYeni WebhookRetryPolicyBildirilmiş @throws yok; parametreler positive-int olarak belgelenmiştir$maxRetries, toplam deneme sayısını sayar
WebhookRetryPolicy::delayForAttemptint $attemptmaxDelaySeconds değerinde sınırlanmış baseDelaySeconds × 2^(attempt − 1)positive-intFırlatmazDeneme numaraları 1 tabanlıdır
WebhookRetryPolicy::shouldRetryint $currentAttemptGeçerli deneme maksimumun altındayken trueboolFırlatmazSon denemeden sonra bekleme atlanır
WebhookRetryPolicy::default5 deneme, 1 sn temel, 300 sn sınırselfFırlatmazStatik fabrika; üretim varsayılanı
WebhookRetryPolicy::aggressive10 deneme, 2 sn temel, 600 sn sınırselfFırlatmazKritik uç noktalar için statik fabrika
DeadLetterEntry::__constructstring $id, string $registrationId, WebhookPayload $payload, int $attempts, string $lastError, ?int $lastHttpStatus, DateTimeImmutable $failedAt, bool $replayed = falseBaşarısızlık kaydını olduğu gibi saklarYeni DeadLetterEntryBildirilmiş @throws yok; strict_types altında TypeErrorfinal readonly; null $lastHttpStatus taşıma başarısızlığı anlamına gelir
DeadLetterEntry::markReplayedreplayed = true olan bir kopya döndürürselfFırlatmazAynı kimlik; orijinal giriş değişmez
public function __construct(
private readonly WebhookDelivery $delivery,
private readonly ?LoggerInterface $logger = null,
) {}
public function register(TenantContext $tenant, WebhookRegistration $registration): void
public function unregister(TenantContext $tenant, string $registrationId): bool
public function activeRegistrations(TenantContext $tenant): array
public function dispatch(TenantContext $tenant, JobEvent $event): int
public function __construct(
public string $id,
public string $tenantId,
public string $url,
public array $events,
public string $secret,
public bool $active = true,
public ?string $description = null,
) {}
public function subscribesTo(JobEventType $eventType): bool
public function deactivate(): self
public static function fromJobEvent(
JobEvent $event,
string $tenantId,
string $deliveryId,
): self
public function toJson(): string
public function toArray(): array
public function signedTimestamp(): int
public function sign(string $secret): string
public function __construct(
private readonly ClientInterface $httpClient,
private readonly RequestFactoryInterface $requestFactory,
private readonly StreamFactoryInterface $streamFactory,
private readonly WebhookRetryPolicy $retryPolicy = new WebhookRetryPolicy(),
private readonly ?LoggerInterface $logger = null,
) {}
public function deliver(WebhookRegistration $registration, WebhookPayload $payload): bool
public function deadLetters(): array
public function clearDeadLetters(): void
public function __construct(
public int $maxRetries = 5,
public int $baseDelaySeconds = 1,
public int $maxDelaySeconds = 300,
) {}
public function delayForAttempt(int $attempt): int
public function shouldRetry(int $currentAttempt): bool
public static function default(): self
public static function aggressive(): self
public function __construct(
public string $id,
public string $registrationId,
public WebhookPayload $payload,
public int $attempts,
public string $lastError,
public ?int $lastHttpStatus,
public DateTimeImmutable $failedAt,
public bool $replayed = false,
) {}
public function markReplayed(): self
  • Kayıtlar kiracı başına dizinlenir. register(), kiracı tanımlayıcısı çağıran bağlamla eşleşmeyen bir kaydı reddeder. unregister() yumuşak bir devre dışı bırakmadır: kayıt, etkin olmayan bir kopyayla değiştirilir; böylece geçmiş korunurken gelecekteki gönderimlerden çıkarılır.
  • dispatch(), yalnızca gönderilen olay türüne abone olan çağıran kiracının etkin kayıtlarında yinelenir. Boş bir abone-olunan-olay listesi, tümüne-abone-ol anlamına gelir. Dönüş değeri, başarılı teslimleri sayar.
  • Her teslim, bir JSON gövdesi ve beş başlığa sahip bir HTTP POST’tur: Content-Type: application/json, X-NextPDF-Signature (sha256=<hex>), X-NextPDF-Timestamp (unix saniye), X-NextPDF-Delivery-Id ve X-NextPDF-Event.
  • JSON gövde alanları delivery_id, job_id, event_type, data, timestamp (RFC 3339 genişletilmiş) ve tenant_id olup kaçışsız eğik çizgilerle serileştirilir. Olay türü değerleri nextpdf/core içindeki JobEventType’tan gelir: progress, completed, failed, cancelled.
  • İmza şeması (3.1.0’da değişti, kırıcı). HMAC-SHA256 temel dizesi, kayıt gizli anahtarıyla anahtarlanmış {signedTimestamp}.{jsonBody} olup yalnızca gövde değildir. X-NextPDF-Timestamp değeri, MAC’in zaman damgası bileşenidir; böylece kurcalanmış veya yeniden oynatılmış bir zaman damgası başlığı imzayı geçersiz kılar.
  • Alıcı doğrulaması: X-NextPDF-Timestamp başlığı T’yi okuyun; T kabul edilebilir bir tazelik penceresinin (örneğin 300 sn) dışındaysa reddedin; ham alınan baytlar üzerinde hash_hmac('sha256', T . '.' . rawBody, secret)’i yeniden hesaplayın; sha256= önekini çıkardıktan sonra başlık değeriyle sabit zamanda karşılaştırın.
  • Gövde, imza ve teslim kimliği, teslim başına bir kez hesaplanır ve yeniden deneme denemeleri boyunca sabit kalır.
  • SSRF çıkış geçidi. Her denemeden önce hedef URL, Core UrlValidator::validateExternalUrl() geçidinden geçer: yalnızca HTTPS şeması; loopback, özel, ayrılmış, taşıyıcı düzeyli NAT, bulut meta verisi ve IPv4 gömülü IPv6 geçiş aralıkları engellenir; ana makine adları DNS ile çözümlenir (A ve AAAA) ve çözümlenemeyen ana makineler başarısız-kapalı olarak reddedilir. Engellenen bir URL asla gönderilmez: deneme döngüsü iptal edilir ve yük, Blocked SSRF destination: son hatası ve null HTTP durumuyla doğrudan ölü-mektup kuyruğuna yönlendirilir.
  • Deneme başına sonuç sınıflandırması: 2xx başarıdır ve hemen döner; 429 dışındaki bir 4xx nihaidir ve doğrudan ölü-mektuba gider; diğer her sonuç — 3xx, 429, 5xx veya bir taşıma istisnası — politikanın toplam deneme sayısına kadar yeniden denenebilir.
  • Geri çekilme üsteldir: bir sonraki denemeden önceki bekleme, maxDelaySeconds değerinde sınırlanmış baseDelaySeconds × 2^(attempt − 1)’dir. Son denemeden sonra bekleme atlanır.
  • Hiçbir deneme başarılı olmadığında, bir DeadLetterEntry şunları kaydeder: benzersiz bir kimlik, kayıt kimliği, orijinal yük, deneme sayısı (politika maksimumuna sabitlenmiş), son hata mesajı, son HTTP durumu (taşıma başarısızlığında veya SSRF engellemesinde null) ve başarısızlık zaman damgası.
  • Ölü-mektup kuyruğu bellek içidir ve süreç ömrüyle kapsamlıdır. markReplayed(), işaretlenmiş bir kopya üretir; yeniden göndermez ve kuyruk orijinal girişi korur.
  • Boş olay listesi. Kayıt her olay türünü alır. Alıcı tüm olayları görmemeliyse listeyi açıkça kapsamlandırın.
  • Nihai 4xx’e karşı taşıma başarısızlığı. Bir 4xx reddi, doldurulmuş bir lastHttpStatus kaydeder; bir bağlantı başarısızlığı null kaydeder. Alıcı reddini taşıma başarısızlığından ayırmak için null’ı kullanın.
  • SSRF ile engellenen hedef. Bir HTTP, özel, loopback veya meta veri adresini işaret eden bir kayıt, ilk denemede Blocked SSRF destination: hatası ve null durumla ölü-mektuba düşer. Hiçbir giden istek yapılmaz. URL’yi düzeltin ve yeniden kaydedin.
  • Yükseltmeden sonra eski alıcılar. 3.1.0 öncesi yalnızca-gövde HMAC’ini hâlâ doğrulayan bir alıcı, 3.1.0 teslimlerine karşı başarısız-kapalı olur. Alıcıyı {timestamp}.{body} temel dizesine geçirin ve X-NextPDF-Timestamp’ı tüketin.
  • Kodlanamayan olay verisi. toJson() ve sign(), herhangi bir deneme yapılmadan önce deliver() ve dispatch() dışına yayılan JsonException fırlatır.
  • Eşzamanlı engelleme. deliver(), denemeler arasında satır içinde uyur. Kümülatif geri çekilme, varsayılan politikada 15 sn’ye ve aggressive politikada yaklaşık 17 dakikaya ulaşır. Alıcı gecikmesi güvenilmezse bir kuyruk çalışanından gönderin.
  • Deneme sayısı sabitlemesi. Dahilî döngü sayacı tükenmede onun ötesine ilerlese de, kaydedilen deneme sayısı asla politika maksimumunu aşmaz.
  • Kuyruk büyümesi ve kalıcılık. Ölü-mektup kuyruğu süreç içinde sınırsız büyür ve yeniden başlatmada kaybolur. Kalıcı yeniden oynatma gerektiğinde, clearDeadLetters() çağrılmadan önce girişleri deadLetters() yoluyla dışa aktarın ve haricî olarak kalıcılaştırın.
  • Yeniden oynatma operatör güdümlüdür. Yeniden teslim, deliver()’ı girişin yüküyle yeniden çağırmak anlamına gelir; markReplayed() yalnızca bu olguyu bir kopyada kaydeder.
  • DNS yeniden bağlama kalıntısı. URL her denemede yeniden doğrulanır; bu, yeniden bağlama penceresini daraltır ama kapatmaz: PSR-18 soyutlaması bağlantıyı doğrulanmış IP’ye sabitleyemez. Bu kalıntının önem taşıdığı yerlerde ağ katmanı çıkış denetimleri ekleyin.
  • Gizli anahtar işleme. Kayıt gizli anahtarı bir kimlik bilgisidir. HMAC yalnızca bütünlüğü ve kökeni doğrular — gizlilik değildir. Alıcının görmemesi gereken veriyi olay yüküne koymayın.

Yük imzalama, PHP’nin hash_hmac()’i aracılığıyla HMAC-SHA256’dır; bu nedenle ana makine kripto sağlayıcısına dayanır. FIPS kısıtlamalı bir derlemede, onaylanmamış bir ilkel, düşürmek yerine kriptografik sınırda başarısız olur. Webhook katmanı, kendine ait hiçbir kriptografik politika eklemez.

  • Yük kimlik doğrulaması, SHA-256 ile örneklenmiş, FIPS PUB 198-1 §1’in anahtarlı-karma mesaj kimlik doğrulama kodu olan HMAC’i uygular.
  • Yeniden oynatma koruması, OWASP Cheat Sheet Series webhook güvenliği yönergesini izler: olay zaman damgası özel bir başlıkta taşınır ve imza hesaplamasına tohumlanır; böylece kurcalanmış bir zaman damgası doğrulamada başarısız olur.
  • Gövde zaman damgaları, RFC 3339 genişletilmiş tarih-saat biçimini kullanır. Kodda bildirilmiş: RFC 3339 bu sayfa için RAG bütüncesinden alınmamıştır.
  • Bunlar, ürün kaynağına ve alıntılanan hükümlere dayanan yetenek beyanlarıdır. NextPDF, bu yüzey için hiçbir uygunluk veya sertifikasyon iddiasında bulunmaz.
  • Tüm sınıflar strict_types=1 bildirir ve final’dir; WebhookRegistration, WebhookPayload, WebhookRetryPolicy ve DeadLetterEntry, yükseltilmiş genel özelliklere sahip final readonly’dir.
  • Modül, 2.2.0 olan bir @since açıklaması taşır; zaman damgasına bağlı imza şeması, 3.1.0’da belgelenmiş bir kırıcı değişikliktir.
  • Teslim motoru, PSR-18/PSR-17 soyutlamalarını alır; böylece sahte bir HTTP istemcisi, tam gönderme, yeniden deneme ve ölü-mektup yolunu çevrimdışı çalıştırır. Günlükleyici varsayılan olarak null’dur; üretimde bir PSR-3 günlükleyici enjekte edin, yoksa başarısızlıklar yalnızca dönüş değerleri aracılığıyla ortaya çıkar.
  • Alıcı uygulamaları, imza karşılaştırması için hash_equals() kullanmalı ve X-NextPDF-Timestamp üzerinde bir tazelik penceresi uygulamalıdır.
  • Önerilen sınır testleri: kiracı uyumsuz kayıt, boş-olay-listesi dağıtımı, nihai 4xx, yeniden deneme tükenmesi, SSRF ile engellenen URL, sabit bir vektöre karşı zaman damgası kurcalanmış imza reddi ve ölü-mektup deneme sayısı sabitlemesi.

Bu sayfa yalnızca dışarıdan gözlemlenebilir davranışı ve desteklenen genel API yüzeyini belgeler. Dahilî ad alanı yolları, yardımcı sınıflar, mekanizma tabloları, runbook dosya adları ve bilet önekleri kapsam dışıdır.