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:
- ellenőrizd az aláírást,
- mentsd el a nyers eseményt,
- tedd sorba a feladatot,
- 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.