AddonHive
SK

Ako fungujú webhooky v CMS e-shope a prečo sú lepšie ako polling

Keď integrácia potrebuje vedieť o novej objednávke, sú dve cesty: pýtať sa API dokola, alebo si nechať poslať správu, keď sa niečo stane. CMS vie oboje, ale len jedno z toho je udržateľné.

Tento text je pre vývojárov. Ak hľadáte hotové riešenie, začnite radšej na stránke Notify.

Prečo nie polling

Sťahovať zoznam objednávok každú minútu znamená spotrebovať limit požiadaviek na otázku, na ktorú je odpoveď takmer vždy „nič nové”. Pri jednom e-shope to prejde. Pri dvesto e-shopoch to je dvesto zbytočných volaní za minútu — a v čase, keď objednávka naozaj príde, máte v horšom prípade minútu oneskorenia.

Webhook otočí smer: platforma zavolá vás.

Registrácia

POST /api/webhooks s poľom data, kde každá položka má event a url. Naraz sa dá zaregistrovať najviac 50 webhookov a URL smie mať najviac 2000 znakov.

Dôležité obmedzenie: jedna URL na jeden event. Pokus zaregistrovať ten istý event druhýkrát skončí chybou 422 Webhook already exists for this event, takže registrácia musí byť idempotentná už u vás — najskôr GET /api/webhooks, potom dopĺňať len to, čo chýba.

Niektoré eventy sa navzájom vylučujú. order:update sa nedá registrovať spolu s order:cancel a customer:update spolu s customer:disableOrders alebo customer:enableOrders; kombinácia vráti 409.

Čo príde

Notifikácia je krátky 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, pri hromadných udalostiach zoznam. Telo entity v notifikácii nie je. Parameter sendPayload: "full" existuje, ale platí len pre eventy označené ako payload supported, a v aktuálnom OpenAPI taký event nie je ani jeden. Detail objednávky si teda vždy dočítate samostatným volaním.

Podpis

Každá notifikácia môže niesť podpisovú hlavičku — hash_hmac('sha1', rawBody, signatureKey) v hexadecimálnom tvare. Kľúč získate cez POST /api/webhooks/renew-signature-key, platí per doplnok × e-shop a každé zavolanie vygeneruje nový.

Háčik: kým tento endpoint nezavoláte, notifikácie podpis nemajú. Volajte ho teda hneď po inštalácii a kľúč si uložte šifrovane. A overujte podpis nad surovým telom požiadavky, nie nad tým, čo vypadne z JSON parsera — akékoľvek preskladanie objektu podpis rozbije.

Nepodpísanú notifikáciu odmietnite. Fail closed, nie fail open.

Štyri sekundy

Na notifikáciu treba odpovedať 200 do 4 sekúnd. Ak sa to nestihne, CMS to skúsi znova každých 15 minút, najviac trikrát, a potom notifikáciu označí ako inactive — čiže je nenávratne preč. Sedemdňovú históriu si viete pozrieť cez GET /api/webhooks/notifications.

Z toho vyplýva jediná možná architektúra handlera:

  1. over podpis,
  2. ulož surovú udalosť,
  3. zaraď úlohu do fronty,
  4. vráť 200.

Nič viac. Žiadne volanie API vášho CMS, žiadne skladanie správy, žiadne odosielanie do Slacku — to všetko patrí do workera. Cieľ pod 500 ms, nie „zmestíme sa do štyroch sekúnd”.

Idempotencia

CMS neposiela žiadne delivery ID. Keď teda notifikácia dorazí druhýkrát — a pri opakovaní dorazí — nemáte podľa čoho poznať, že ide o tú istú. Kľúč si musíte poskladať sami z toho, čo v správe je:

(doplnok, eshopId, event, eventCreated, eventInstance)

Táto pätica je stabilná naprieč opakovaniami. Uložte ju s unikátnym indexom a druhý zápis potichu zahoďte.

Rate limit

API má leaky bucket veľkosti 200 kvapiek s odtokom 10 za sekundu, teda 600 požiadaviek za minútu, počítané per doplnok × e-shop. Iný doplnok toho istého e-shopu má vlastný bucket, takže si navzájom nekonkurujete.

Hlavička X-RateLimit-Bucket-Filling: 130/200 chodí vždy, Retry-After len pri plnom buckete — a je to HTTP-date v GMT, nie počet sekúnd. Kto ho parsuje ako číslo, dostane NaN a začne točiť requesty naprázdno.

Zhrnutie

Webhooky v CMS sú priamočiare, ale majú štyri miesta, kde sa integrácia láme: chýbajúci podpisový kľúč, dlhý handler, chýbajúca idempotencia a zle parsovaný Retry-After. Keď tieto štyri veci sedia, zvyšok je už len skladanie správy.

Presne toto rieši zdieľaný CMS kit v našom monorepe a stojí na tom Notify.

← Všetky články

Ďalšie články