Odosielanie webhookov
Odchádzajúci endpoint tvorí URL adresa príjemcu, ktorú vám dá zákazník, typy udalostí, ktoré odoberá, a tajný kľúč, ktorým príjemca overuje:
use RoundlyConsulting\Webhooks\DataTransferObjects\OutboundEndpointOptions;
use RoundlyConsulting\Webhooks\Facades\Webhooks;
// $url — the receiver address your customer typed into your settings page
$created = Webhooks::for($team)->outbound()->create(
$url,
events: ['invoice.*', 'customer.created'], // exact, prefix.*, or *
name: 'ERP',
headers: ['X-Tenant' => 'acme'], // custom headers (validated)
options: new OutboundEndpointOptions(rateLimitPerMinute: 30, description: 'ledger sync'),
);
$created->secret; // whsec_… — hand it to the receiver onceURL adresu posúdi ochrana pred SSRF (pozrite Bezpečnosť odosielania) a uloží sa šifrovane — môže obsahovať token; url_host zostáva čitateľný pre výpisy a resources zobrazia URL ako scheme://host[:port]/…. Odmietnutá alebo nepreložiteľná URL vyhodí DestinationBlockedException.
Odbery
events je zoznam 1–100 položiek: * pre všetky typy, presný typ ako invoice.paid alebo prefix + .* — invoice.* zodpovedá invoice.paid aj invoice.line.added, no nie samotnému invoice. Typy zodpovedajú ^[a-z0-9_]+(\.[a-z0-9_]+)*$, najviac 100 znakov. $endpoint->subscribesTo('invoice.paid') vám odpovie na tú istú otázku vo vašom kóde.
Vlastné hlavičky
| Pravidlo | Význam |
|---|---|
| Názvy | Tokeny podľa RFC 9110; bez CR, LF a NUL; najviac 20 hlavičiek a 8 KB; uložené šifrovane. |
| Nikdy nenastaviteľné | content-length, content-type, transfer-encoding, connection, te, upgrade, cookie, content-digest, keep-alive, expect, trailer, proxy-*, webhook-*, signature* |
| Len ak je povolené | host a authorization cez outbound.headers.allowed_overrides — host len pri vypnutej ochrane pred SSRF: ochrana vždy posiela overeného hostiteľa, takže hlavička Host sa pri nej odmietne, nie potichu nahradí. |
| Pri každom pokuse | Pravidlá sa uplatnia znova: hlavička, ktorej výnimku ste zo zoznamu odstránili, sa vynechá, nikdy neodošle. |
| Presmerovania | Vlastné hlavičky idú len na prvý origin; iný origin dostane len podpisové hlavičky. |
send a broadcast
Webhooks::send($endpoint, 'invoice.paid', ['invoice' => 42]); // array, Arrayable or JsonSerializable
Webhooks::send($endpoint, 'invoice.paid', $payload, id: 'invoice-42-paid'); // idempotent: a repeat returns the first delivery
Webhooks::for($team)->broadcast('invoice.paid', $payload); // every enabled, subscribed endpoint of $team
Webhooks::broadcast('system.maintenance', $payload); // owner-less endpoints only
$team->broadcastWebhook('invoice.paid', $payload); // the HasWebhooks trait
Webhooks::outbound()->ping($endpoint); // a webhook.ping test event- Idempotentné odoslanie — id: je vaše (id udalosti, invoice-42-paid). webhook-id sa odvodí z endpointu a id a opakovanie s rovnakým id vráti doručenie zaradené prvýkrát a nič nové nezaradí — pre listener, ktorý sa môže spustiť dvakrát. Platí prvé telo.
- send() na vypnutý endpoint alebo endpoint bez odberu vyhodí EndpointNotAcceptingException (reason(): disabled alebo not_subscribed); broadcast() ich preskočí.
- Typy udalostí sa overujú (InvalidEventTypeException); ak outbound.event_types nie je prázdne, povolené sú len uvedené.
- Doručenie sa vloží a jeho prvý pokus sa odošle až po potvrdení aktuálnej transakcie: transakcia vrátená späť neodošle nič.
Obálka
Telo sa zostaví raz — {"type", "timestamp" (RFC 3339 UTC), "data"}, alebo obsah tak, ako je, pri vypnutom outbound.envelope — ako JSON s nezakódovanými lomkami a unicode, uloží sa šifrovane a pri každom pokuse je bajt po bajte rovnaké. Nad outbound.max_payload_bytes (256 KB) vyhodí PayloadTooLargeException.
{"type":"invoice.paid","timestamp":"2026-11-08T12:00:00Z","data":{"invoice":42}}Udalosti, ktoré sa odošlú samy
Pridajte BroadcastsAsWebhook na vlastnú udalosť a jej vyvolanie ju odošle ako broadcast — cez manažér, takže ju Webhooks::fake() zaznamená:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use RoundlyConsulting\Webhooks\Contracts\BroadcastsAsWebhook;
final class InvoicePaid implements BroadcastsAsWebhook
{
use Dispatchable;
public function __construct(public Invoice $invoice) {}
public function webhookType(): string { return 'invoice.paid'; }
public function webhookPayload(): array { return ['invoice' => $this->invoice->id]; }
public function webhookOwner(): ?Model { return $this->invoice->team; } // null: app-level endpoints
}
InvoicePaid::dispatch($invoice); // or event(new InvoicePaid($invoice))Ping
Testovacie tlačidlo pre vašich zákazníkov. ping() odošle webhook.ping bez ohľadu na odbery endpointu a na to, či ho outbound.event_types obsahuje — inak ide o bežné doručenie: podpísané, opakované, zaznamenané. Vypnutý endpoint vyhodí EndpointNotAcceptingException. Z konzoly: webhooks:ping {endpoint}.
Webhooks::outbound()->ping($endpoint);
// {"type":"webhook.ping","timestamp":"…","data":{"ping":true}}Prejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.