AddonHive
CZ

Jak fungují webhooky v CMS e-shopu a proč jsou lepší než polling

Když integrace potřebuje vědět o nové objednávce, jsou dvě cesty: ptát se API dokola, nebo si nechat poslat zprávu, když se něco stane. CMS umí obojí, ale udržitelné je jen jedno.

Tenhle text je pro vývojáře. Pokud hledáte hotové řešení, začněte radši na stránce Notify.

Proč ne polling

Stahovat seznam objednávek každou minutu znamená spotřebovat limit požadavků na otázku, na kterou je odpověď skoro vždycky „nic nového”. U jednoho e-shopu to projde. U dvou set e-shopů je to dvě stě zbytečných volání za minutu — a ve chvíli, kdy objednávka opravdu přijde, máte v horším případě minutu zpoždění.

Webhook otočí směr: platforma zavolá vás.

Registrace

POST /api/webhooks s polem data, kde každá položka má event a url. Najednou lze zaregistrovat nejvýše 50 webhooků a URL smí mít nejvýše 2000 znaků.

Důležité omezení: jedna URL na jednu událost. Pokus zaregistrovat tutéž událost podruhé skončí chybou 422 Webhook already exists for this event, takže registrace musí být idempotentní už u vás — nejdřív GET /api/webhooks, pak doplnit jen to, co chybí.

Některé události se navzájem vylučují. order:update nelze registrovat spolu s order:cancel a customer:update spolu s customer:disableOrders nebo customer:enableOrders; kombinace vrátí 409.

Co přijde

Notifikace je krátký JSON:

{
  "eshopId": 222651,
  "event": "order:create",
  "eventCreated": "2019-01-08T15:13:39+0100",
  "eventInstance": "2018000057"
}

eventInstance je identifikátor entity — kód objednávky, GUID produktu, u hromadných událostí seznam. Tělo entity v notifikaci není. Parametr sendPayload: "full" existuje, ale platí jen pro události označené jako payload supported, a v aktuálním OpenAPI taková událost není ani jedna. Detail objednávky si tedy vždycky dočtete samostatným voláním.

Podpis

Každá notifikace může nést podpisovou hlavičku — hash_hmac('sha1', rawBody, signatureKey) v hexadecimálním tvaru. Klíč získáte přes POST /api/webhooks/renew-signature-key, platí per doplněk × e-shop a každé zavolání vygeneruje nový.

Háček: dokud tenhle endpoint nezavoláte, notifikace podpis nemají. Volejte ho tedy hned po instalaci a klíč si uložte šifrovaně. A ověřujte podpis nad surovým tělem požadavku, ne nad tím, co vypadne z JSON parseru — jakékoli přeskládání objektu podpis rozbije.

Nepodepsanou notifikaci odmítněte. Fail closed, ne fail open.

Čtyři sekundy

Na notifikaci je třeba odpovědět 200 do 4 sekund. Pokud se to nestihne, CMS to zkusí znovu každých 15 minut, nejvýše třikrát, a pak notifikaci označí jako inactive — čili je nenávratně pryč. Sedmidenní historii si prohlédnete přes GET /api/webhooks/notifications.

Z toho plyne jediná možná architektura handleru:

  1. ověř podpis,
  2. ulož surovou událost,
  3. zařaď úlohu do fronty,
  4. vrať 200.

Nic víc. Žádné volání API vašeho CMS, žádné skládání zprávy, žádné odesílání do Slacku — to všechno patří do workeru. Cíl pod 500 ms, ne „vejdeme se do čtyř sekund”.

Idempotence

CMS neposílá žádné delivery ID. Když tedy notifikace dorazí podruhé — a při opakování dorazí — nemáte podle čeho poznat, že jde o tutéž. Klíč si musíte poskládat sami z toho, co ve zprávě je:

(doplněk, eshopId, event, eventCreated, eventInstance)

Tahle pětice je stabilní napříč opakováními. Uložte ji s unikátním indexem a druhý zápis potichu zahoďte.

Rate limit

API má leaky bucket velikosti 200 kapek s odtokem 10 za sekundu, tedy 600 požadavků za minutu, počítáno per doplněk × e-shop. Jiný doplněk téhož e-shopu má vlastní bucket, takže si navzájem nekonkurujete.

Hlavička X-RateLimit-Bucket-Filling: 130/200 chodí vždycky, Retry-After jen při plném bucketu — a je to HTTP-date v GMT, ne počet sekund. Kdo ho parsuje jako číslo, dostane NaN a začne točit requesty naprázdno.

Shrnutí

Webhooky v CMS jsou přímočaré, ale mají čtyři místa, kde se integrace láme: chybějící podpisový klíč, dlouhý handler, chybějící idempotence a špatně parsovaný Retry-After. Když tyhle čtyři věci sedí, zbytek je už jen skládání zprávy.

Přesně tohle řeší sdílený CMS kit v našem monorepu a stojí na tom Notify.

← Všechny články

Další články