---
title: "Prijímanie webhookov — Webhooks for Laravel | Roundly"
description: "Prichádzajúce endpointy, spracovanie v pevnom poradí a jeho stavové kódy, ochrana pred opakovaním a idempotencia a vlastná trasa."
url: https://roundly-consulting.com/sk/open-source/navody/webhooks-for-laravel/prijimanie
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Webhooks for Laravel](https://roundly-consulting.com/sk/open-source/navody/webhooks-for-laravel.md)

# Prijímanie webhookov

Jeden endpoint na odosielateľa. Adresou je kľúč v URL — 32 náhodných alfanumerických znakov, približne 190 bitov; tajný kľúč sa zobrazí len raz. Vygenerujte ho alebo doslovne importujte ten, ktorý vám dal odosielateľ:

```php
use RoundlyConsulting\Webhooks\DataTransferObjects\InboundEndpointOptions;
use RoundlyConsulting\Webhooks\Facades\Webhooks;

$created = Webhooks::for($team)->inbound()->create(handler: 'billing');   // owned by $team
$created = Webhooks::inbound()->create(handler: 'billing');               // owner-less
$created = Webhooks::inbound()->create(
    handler: 'github', scheme: 'github', name: 'GitHub',
    secret: $theSecretGitHubShowedYou,                                   // imported verbatim
    options: new InboundEndpointOptions(rateLimitPerMinute: 120, maxPayloadBytes: 1_048_576,
        contentTypes: ['application/json'], toleranceSeconds: 60),
);

$created->endpoint;   // InboundEndpoint
$created->url;        // route('webhooks.inbound', key) — or inbound.route.url_base + '/' + key
$created->secret;     // whsec_… (generated) — never readable again
```

Neznámy alias handlera vyhodí UnknownHandlerException, neznáma schéma UnknownSchemeException a vlastník, ktorého kľúč nezodpovedá webhooks.key\_type, vyhodí InvalidWebhooksConfigurationException ešte predtým, ako sa čokoľvek zapíše. Voľby sa kontrolujú voči limitom v časti Správa endpointov.

## Spracovanie — pevné poradie, rozhoduje prvé zlyhanie

POST {prefix}/{key} (predvolene /webhooks/{key}, názov trasy webhooks.inbound) prejde tieto kroky. Žiadne odmietnutie neuloží doručenie ani nič nezaradí do frontu:

| # | Kontrola | Odpoveď | Udalosť |
| --- | --- | --- | --- |
| 1 | Kľúč má 32 alfanumerických znakov | `404 not_found` | — |
| 2 | Vyhľadanie endpointu — neznámy, mäkko zmazaný alebo vypnutý | Rovnaké telo 404 | Len vypnutý: WebhookRejected(endpoint\_disabled) |
| 3 | Strážca odmietnutí na endpoint a IP (60 za minútu, počítajú sa len odmietnutia v krokoch 4–7) | `429 rate_limited + Retry-After` | Raz za okno |
| 4 | Veľkosť — Content-Length nad limitom alebo telo čítané do limitu + 1 bajt | `413 payload_too_large` | `WebhookRejected` |
| 5 | Typ obsahu (parametre sa ignorujú) | `415 unsupported_content_type` | `WebhookRejected` |
| 5b | Limit overených doručení na endpoint (600 za minútu) — kontroluje sa tu, započíta sa až po overení podpisu | `429 + Retry-After` | Raz za okno |
| 6 | Podpis a časová pečiatka — schéma endpointu | `401 missing_signature · invalid_signature · missing_timestamp · invalid_timestamp · stale_timestamp · missing_id · key_not_bound · unknown_scheme · replayed` | `WebhookRejected` |
| 7 | Dekódovanie JSON — len polia, hĺbka ≤ 64, veľké čísla ako reťazce; skalár na najvyššej úrovni sa odmietne | `400 invalid_payload` | `WebhookRejected` |
| 8 | Opakovanie a idempotencia | Duplicita → 200 (alebo 409 conflict); rovnaké id, iné telo → 409 idempotency\_key\_reused; práve sa spracúva → 409 in\_progress + Retry-After: 1; bez id → 400 missing\_id | Opätovne použité alebo chýbajúce id: WebhookRejected |
| 9 | Sanitizácia → uloženie (+ zaznamenanie nonce RFC 9421 v jednej transakcii) → zaradenie ProcessInboundDelivery | 202 accepted; zlyhaný sanitizér → 500 sanitizer\_failed | WebhookReceived sa vyvolá na workeri |

- Veľkosť a typ obsahu sa kontrolujú pred podpisom: neoverený volajúci nedokáže prinútiť aplikáciu počítať MAC nad megabajtmi. Limit doručení sa kontroluje tiež pred ním, započíta sa však len overené doručenie.
- Strážca odmietnutí a limit doručení sú samostatné počítadlá — chybné podpisy cudzieho z inej IP nikdy neminú rozpočet skutočného odosielateľa, pokiaľ $request->ip() vracia adresu klienta (nastavte dôveryhodné proxy).
- Neznáme kľúče nevyvolajú udalosť, takže cudzí nemôže zahlcovať vaše listenery; odmietnutie pre limit sa vyvolá raz za okno limitéra; duplicita nevyvolá nič.
- Odmietnutia sú application/problem+json (RFC 9457) s preloženým nadpisom — bez interných detailov a bez názvov tried.

```json
// 202 — stored and queued
{"status": "accepted", "id": "01JCDEF0000000000000000000"}

// 200 — a duplicate (inbound.on_duplicate = accept)
{"status": "duplicate"}

// any refusal — application/problem+json (RFC 9457), no internals, no class names
{"title": "…", "status": 401, "code": "invalid_signature"}
```

## Ochrana pred opakovaním a idempotencia

- Kľúčom je id doručenia zo schémy (pri predvolenej schéme podpísané webhook-id), inak hlavička Idempotency-Key (v úvodzovkách alebo samostatný token, kým je zapnuté inbound.accept\_idempotency\_header), inak 400. Kľúč dlhší ako 255 bajtov alebo s netlačiteľnými znakmi sa zmení na sha256:<hex>.
- Deduplikácia beží cez úložisko idempotencie Sentinelu, oddelene pre každý endpoint, s odtlačkom SHA-256 tela a pamäťou inbound.dedupe\_ttl (7 dní): prvá požiadavka sa uloží a zaradí, opakovanie je duplicita, rovnaký kľúč s iným telom je idempotency\_key\_reused.
- Podpísané id má prednosť: podvrhnutý Idempotency-Key nedokáže rozdeliť jednu podpísanú správu na dve.
- Nepodpísané id (hlavička doručenia v štýle GitHubu, samostatný Idempotency-Key) majú druhého strážcu podľa odtlačku tela, takže rovnaké telo pod novým id je duplicita. Pri formáte bez podpísanej časovej pečiatky tento strážca kontroluje aj uložené doručenia — rovnaké telo zostáva duplicitou, kým existuje riadok prvého doručenia (payloads.delivery\_retention\_days), nielen počas okna deduplikácie.
- Poistkou je unikátny index nad (endpoint\_id, idempotency\_key): doručenie, ktorého id úložisko zabudlo, je stále jedno doručenie.
- Ak úložisko zlyhá až po uložení a zaradení doručenia, úspech odosielateľa sa nezmení na chybu — požiadavka aj tak odpovie 202.
- Doručenie uložené počas výpadku frontu zaradí jeho najbližšia duplicita a pravidelný beh po inbound.requeue\_after (60 s).

Nonce v RFC 9421 používajú odložené API Sentinelu: krok s podpisom overí, že nonce ešte nebol použitý, a krok s uložením ho zaznamená v tej istej databázovej transakcii, ktorá zapisuje doručenie — pred odpoveďou 202 a pred zaradením jobu handlera. Požiadavka odmietnutá cestou — 400, 500 sanitizer\_failed, chyba databázy — nechá nonce voľný, takže nezmenené opätovné odoslanie sa posúdi nanovo; z dvoch súbežných kópií sa uloží presne jedna. Úložisko nonce v Sentineli musí implementovať InspectsNonces (jeho úložiská database a cache to robia). Pozrite [odložené nonce v Sentineli](https://roundly-consulting.com/sk/open-source/navody/sentinel-for-laravel/podpisy-http.md) a [idempotenciu](https://roundly-consulting.com/sk/open-source/navody/sentinel-for-laravel/idempotencia.md).

## Overenie bez spracovania

Pre vlastný postup spustí verify() len schému endpointu — bez kontroly veľkosti, bez deduplikácie, nič sa neuloží (nonce RFC 9421 sa zaznamená hneď):

```php
use RoundlyConsulting\Webhooks\Exceptions\WebhookSignatureException;

try {
    $verified = Webhooks::inbound()->verify($endpoint, $request);   // the scheme only — nothing stored
    $verified->deliveryId;   // also: timestamp, eventType, idIsSigned, slot
} catch (WebhookSignatureException $e) {
    $e->reason();            // RejectionReason, e.g. RejectionReason::StaleTimestamp
}
```

## Vlastná trasa

Trasu balíka vypnite cez WEBHOOKS\_INBOUND\_ROUTE=off a pripojte ju, kam potrebujete. Route::webhooks() pripojí POST {prefix}/{key} s názvom webhooks.inbound (URL adresy endpointov sa podľa nej riadia) a pre daný prefix vypne TrimStrings a ConvertEmptyStringsToNull — spracovanie si surové telo overí a dekóduje samo. Nikdy ju nedávajte do skupiny middleware web: odosielateľ nemá session ani CSRF token.

```php
// WEBHOOKS_INBOUND_ROUTE=off, then in routes/web.php or routes/api.php:
Route::webhooks('hooks', middleware: ['throttle:120,1']);
```

Trasa vlastného návrhu volá spracovanie priamo — potom zaregistrujte obe výnimky pre middleware sami:

```php
Route::post('/hooks/{key}', fn (Request $request, string $key) => Webhooks::inbound()->receive($key, $request));
TrimStrings::skipWhen(fn (Request $r) => $r->is('hooks/*'));
ConvertEmptyStringsToNull::skipWhen(fn (Request $r) => $r->is('hooks/*'));
```

Nastavte webhooks.inbound.route.url\_base (WEBHOOKS\_INBOUND\_URL), aby ->url ukazovalo adresu, ktorú odosielatelia naozaj používajú, napríklad za proxy.

## 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 kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## 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.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/webhooks-for-laravel.md)
