AddonHive
HU

Hogyan működnek a CMS webhookjai, és miért jobbak a pollingnál

Amikor egy integrációnak tudnia kell az új rendelésről, két út van: körkörösen kérdezgetni az API-t, vagy üzenetet kapni, amikor történik valami. A CMS mindkettőt tudja, de csak az egyik fenntartható.

Ez a szöveg fejlesztőknek szól. Ha kész megoldást keres, kezdje inkább a Notify oldalon.

Miért ne polling

A rendeléslista percenkénti letöltése arra a kérdésre költi a kéréskeretet, amelyre a válasz szinte mindig az, hogy „semmi új”. Egy webáruháznál ez elmegy. Kétszáz webáruháznál ez percenként kétszáz felesleges hívás — és amikor a rendelés tényleg megérkezik, rosszabb esetben egy perc a csúszása.

A webhook megfordítja az irányt: a platform hívja Önt.

Regisztráció

POST /api/webhooks, data tömbbel, amelyben minden elemnek van event és url mezője. Egyszerre legfeljebb 50 webhook regisztrálható, az URL pedig legfeljebb 2000 karakter lehet.

Fontos korlát: eseményenként egy URL. Ugyanannak az eseménynek a második regisztrálása 422 Webhook already exists for this event hibával végződik, tehát a regisztrációnak már az Ön oldalán idempotensnek kell lennie — előbb GET /api/webhooks, aztán csak a hiányzót pótolni.

Néhány esemény kizárja egymást. Az order:update nem regisztrálható az order:cancel mellé, a customer:update pedig a customer:disableOrders vagy a customer:enableOrders mellé; a kombináció 409-et ad vissza.

Mi érkezik

Az értesítés rövid JSON:

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

Az eventInstance az entitás azonosítója — rendeléskód, termék-GUID, tömeges eseménynél lista. Az entitás törzse nincs benne az értesítésben. A sendPayload: "full" paraméter létezik, de csak a payload supported jelölésű eseményekre, és a jelenlegi OpenAPI-ban egyetlen ilyen esemény sincs. A rendelés részleteit tehát mindig külön hívással kell beolvasni.

Aláírás

Minden értesítés hordozhatja az aláírás-fejlécet — hash_hmac('sha1', rawBody, signatureKey) hexadecimális alakban. A kulcsot a POST /api/webhooks/renew-signature-key adja, bővítményenként × webáruházanként érvényes, és minden hívás újat generál.

A bökkenő: amíg ezt a végpontot meg nem hívja, az értesítéseknek nincs aláírásuk. Hívja meg rögtön a telepítés után, a kulcsot pedig tárolja titkosítva. Az aláírást a kérés nyers törzsén ellenőrizze, ne azon, ami a JSON parserből kijön — az objektum bármilyen újraszerializálása elrontja.

Az aláíratlan értesítést utasítsa el. Fail closed, ne fail open.

Négy másodperc

Az értesítésre 4 másodpercen belül 200-zal kell válaszolni. Ha ez nem sikerül, a CMS 15 percenként újrapróbálja, legfeljebb háromszor, majd az értesítést inactive jelöléssel látja el — vagyis visszavonhatatlanul elveszett. A hétnapos előzmény a GET /api/webhooks/notifications végponton nézhető meg.

Ebből egyetlen lehetséges handler-felépítés következik:

  1. ellenőrizd az aláírást,
  2. mentsd el a nyers eseményt,
  3. tedd sorba a feladatot,
  4. adj vissza 200-at.

Semmi több. Semmilyen CMS API-hívás, semmilyen üzenetösszeállítás, semmilyen Slackre küldés — mindez a workerbe tartozik. A cél 500 ms alatt, nem az, hogy „beleférünk négy másodpercbe”.

Idempotencia

A CMS nem küld kézbesítési azonosítót. Amikor tehát az értesítés másodszor is megérkezik — és újrapróbálkozásnál megérkezik —, semmi nem árulja el, hogy ugyanarról van szó. A kulcsot magának kell összeraknia abból, ami az üzenetben van:

(bővítmény, eshopId, event, eventCreated, eventInstance)

Ez az ötös újrapróbálkozásokon át stabil. Tárolja egyedi indexszel, a második írást pedig csendben dobja el.

Rate limit

Az API leaky bucketet használ: 200 csepp méret, másodpercenként 10 elfolyás, azaz percenként 600 kérés, bővítményenként × webáruházanként számolva. Ugyanannak a webáruháznak egy másik bővítménye saját bucketet kap, tehát nem versenyeznek egymással.

Az X-RateLimit-Bucket-Filling: 130/200 fejléc mindig jön, a Retry-After csak tele bucketnél — és az HTTP-date GMT-ben, nem másodpercek száma. Aki számként próbálja értelmezni, NaN-t kap, és üresben kezdi pörgetni a kéréseket.

Összefoglalva

A CMS webhookjai egyenesek, de négy helyen szokott eltörni az integráció: hiányzó aláírókulcs, hosszú handler, hiányzó idempotencia és rosszul értelmezett Retry-After. Ha ez a négy rendben van, a többi már csak az üzenet összeállítása.

Pontosan ezt oldja meg a monorepónk közös CMS kitje, és erre épül a Notify.

← Összes cikk

További cikkek