Webhooks we wakalar
TL; DR
Gowy webhuk - gol çekilen (HMAC/mTLS), jemlenýän we kabul edijiden eksponensial backoff we de-duplikasiýa bilen at-least-once modeli boýunça getirilýän idempotent waka. Konwert ('event _ id', 'type', 'ts', 'version', 'attempt', 'signature'), wagt penjiresi (≤ 5 minut), jogap kodlary, retraýlar, DLQ we status-endpoint barada ylalaşyň.
1) Eltip bermegiň rollary we modeli
Iberiji (siz/üpjün ediji): wakany emele getirýär, gol çekýär, 2xx-a çenli eltmäge synanyşýar, 3xx/4xx/5xx-da retrait (aç-açan "kabul etmäň" -den başga), DLQ ýöredýär, API replay berýär.
Alyjy (hyzmatdaş/hyzmatyňyz): goly/wagtlaýyn penjiräni barlaýar, dedupy we idempotent işini edýär, dogry kod bilen jogap berýär ,/status we/ack replay 'event _ id' bilen üpjün edýär.
Kepillikler: at-least-once. Alyjy dublikatlary gaýtadan işlemegi we tertibi üýtgetmegi başarmalydyr.
2) Wakanyň konweri (envelope)
json
{
"event_id": "01HF7H9J9Q3E7DYT5Y6K3ZFD6M",
"type": "payout.processed",
"version": "2025-01-01",
"ts": "2025-11-03T12:34:56.789Z",
"attempt": 1,
"producer": "payments",
"tenant": "acme",
"data": {
"payout_id": "p_123",
"status": "processed",
"amount_minor": 10000,
"currency": "EUR"
}
}
Hökmany meýdanlar: 'event _ id', 'type', 'version', 'ts', 'attempt'.
Ewolýusiýanyň düzgünleri: meýdanlary goşýarys; Görnüşleri aýyrmak/üýtgetmek - diňe täze 'version' -dan.
3) Howpsuzlyk: gollar we baglanyşyk
3. 1 HMAC-gol (adaty)
Sözbaşylar:
X-Signature: v1=base64(hmac_sha256(<secret>, <canonical>))
X-Timestamp: 2025-11-03T12:34:56Z
X-Event-Id: 01HF7...
Kanoniki setir:
<timestamp>\n<method>\n<path>\n<sha256(body)>
Alyjy tarapyndan barlamak:
- abs(now − `X-Timestamp`) ≤ 300s
- 'X-Event-Id' öň işlenmedi
- 'X-Signature' gabat gelýär (wagt-howpsuz deňeşdirme bilen)
3. 2 Goşmaça. çäreler
mTLS ýokary duýgur webhook üçin.
IP/ASN allow-list.
DPoP (opsiýaly) sender-constrained üçin, eger webhuk ters çagyryşlary başlasa.
4) Idempotentlik we duplikasiýa
4. 1 Wakanyň idempotenti
Şol bir 'event _ id' bolan waka ýagdaýy täzeden üýtgetmeli däldir. Alyjy:- "event _ id" -ni TTL-de (KV/Redis/DB) dempotent adamda saklaýar ≥ 24-72 sagat;
- gaýtadan işlemek üçin gaýtadan işlemegiň netijesini (üstünlik/ýalňyşlyk, artefaktlar) saklaýar.
4. 2 Toparlaryň deňligi (yzyna çagyryşlar)
Eger webhuk müşderini API-ni çekmäge mejbur etse (mysal üçin, "payout tassykla"), şol REST çagyryşynda 'Idempotency-Key' -i ulanyň, netijäni hyzmatyň tarapynda saklaň (exactly-once outcome).
KV modeli (iň az):
key: idempotency:event:01HF7...
val: { status: "ok", processed_at: "...", handler_version: "..." }
TTL: 3d
5) Retraýlar we backoff
Maslahat berilýän grafik (jitter bilen eksponensial):- '5s, 15s, 30s, 1m, 2m, 5m, 10m, 30m, 1h, 3h, 6h, 12h, 24h' (N güne çenli gündelik)
- 2xx - üstünlik, retraýany bes ediň.
- '400/ 401/403/404/422' - eger gol/format ok bolsa, retraim däl (müşderi ýalňyşlygy).
- '429' - 'Retry-After' ýa-da backoff.
- 5xx/tor - retraim.
Iberijiniň sözbaşylary: 'User-Agent', 'X-Webhook-Producer', 'X-Attempt'.
6) Alyjynyň tarapynda gaýtadan işlemek
Pseudopypline:pseudo verify_signature()
if abs(now - X-Timestamp) > 300s: return 401
if seen(event_id):
return 200 // идемпотентный ответ
begin transaction if seen(event_id): commit; return 200 handle(data) // доменная логика mark_seen(event_id) // запись в KV/DB commit return 200
Geleşik ukyby: "seen" belligi şowsuzlyk ýüze çykanda iki gezek işlenmezlik üçin amalyň täsiri bilen (ýa-da netijäni düzedenden soň) atomiki görnüşde goýulmalydyr.
7) Tertip we snapshotlar kepillikleri
Tertip kepillendirilmeýär. 'ts' we 'seq '/' version' in 'data' domenlerini ulanyň.
Uzyn laglar/ýitgiler üçin - iberijiden/replay we alyjydan/resync goşuň (wagt penjiresi/ID boýunça snapshot we deltalary alyň).
8) Status, replay we DLQ
8. 1 Iberijiniň endpointleri
'POST/webhooks/replay' - 'event _ id' ýa-da wagt penjiresi boýunça.
'GET/webhooks/events/: id' - başlangyç bukjany we synanyşyklaryň taryhyny görkezmek.
DLQ: "öli" wakalar (retraýlaryň çäkleri gutardy) → aýratyn ammar, alertler.
8. 2 Alyjynyň endpointleri
`GET /webhooks/status/:event_id` — `seen=true/false`, `processed_at`, `handler_version`.
'POST/webhooks/ack' - DLQ-den (goşmaça) el bilen işlenilendigini tassyklamak.
9) Ýalňyşlyk şertnamalary (alyjynyň jogaby)
http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
Retry-After: 120
X-Trace-Id: 4e3f...
{
"error": "invalid_state",
"error_description": "payout not found",
"trace_id": "4e3f..."
}
Maslahatlar: elmydama anyk kody we mümkin bolsa 'Retry-After' -ni yzyna gaýtaryň. Howpsuzlyk jikme-jikliklerini yzyna gaýtarmaň.
10) Gözegçilik we SLO
Metrikler (iberiji):- delivery p50/p95, success rate, retry/waka, drop-rate DLQ, share 2xx/4xx/5xx, 2xx çenli gijikdirme penjiresi.
- verify fail rate (gol/wagt), dup-rate, latency handler p95, 5xx.
- Eltip bermek: ≥ 99. Wakalaryň 9% -i 2xx <3 c p95 alýar (ilkinji üstünlikli synanyşykdan soň).
- Kripto barlagy: goluň tassyklamasy ≤ 2-5 ms p95.
- Dap: 0 gaýtalanýan effekt (domen derejesinde exactly-once outcome).
11) Maglumatlaryň howpsuzlygy we gizlinlik
Webhuk bedeninde PAN/PII geçirmäň; tassyklanan API boýunça jikme-jiklikler üçin kesgitleýjileri we soňraky pull ulanyň.
Düwmelerdäki duýgur ýerleri gizläň; wakalary diňe TTL bilen iň az derejede saklaň.
DLQ we repli ammarlary şifrläň.
12) Wersiýalaşdyrmak we gabat gelmek
'version' wersiýasy (konwert) we ýolda: '/webhooks/v1/payments '.
Täze meýdanlar - goşmaça; öçürmek diňe "Sunset" döwründen soň.
Machine-readable changelog-daky üýtgeşmeleri resminamalaşdyryň (awtoprewkerler üçin).
13) Synag-hadysalar (UAT çek-sanawy)
- Şol bir 'event _ id' → bir effekt we '200' -ni dublikatlara gaýtadan ibermek.
- Gol: dogry açar, nädogry açar, köne açar (aýlaw), penjiräniň daşyndaky 'X-Timestamp'.
- Backoff: alyjy '429' -dan 'Retry-After' → dogry arakesme berýär.
- Sargyt: '... processed' wakalary '... created' → dogry gaýtadan işlemek/garaşmak.
- Alyjy we 'mark _ seen '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
- DLQ we el bilen replay → üstünlikli eltip bermek.
- Köpçülikleýin "tupan" (üpjün ediji paketleri iberýär) → ýitgisiz, çäklendirmeler möhüm däl.
14) Kiçi snippetler
Iberijiniň goly (psevdo):pseudo body = json(event)
canonical = ts + "\n" + "POST" + "\n" + path + "\n" + sha256(body)
sig = base64(hmac_sha256(secret, canonical))
headers = {"X-Timestamp": ts, "X-Event-Id": event.event_id, "X-Signature": "v1="+sig}
POST(url, body, headers)
Alyjynyň barlagy we atasy (psevdo):
pseudo assert abs(now - X-Timestamp) <= 300 assert timingSafeEqual(hmac(secret, canonical), sig)
if kv.exists("idemp:"+event_id): return 200
begin tx if kv.exists("idemp:"+event_id): commit; return 200 handle(event.data) // доменная логика kv.set("idemp:"+event_id, "ok", ttl=259200)
commit return 200
15) Ýygy-ýygydan ýalňyşlyklar
Dadup ýok → gaýtalanýan effektler (goşa refandlar/paýlamalar).
Taýmstampsiz/penjiresiz gol → replay gowşaklygy.
Bir HMAC-syry ähli hyzmatdaşlarda saklamak.
Netijäni düzetmezden ozal '200' jogaplary → kreş wagtynda wakalaryň ýitmegi.
Howpsuzlyk böleklerini jogaplara/ýazgylara "ýuwmak".
DLQ/repleýiň ýoklugy - hadysalar çözülip bilinmez.
16) Ornaşdyrmagyň şpargalkasy
Howpsuzlyk: HMAC v1 + 'X-Timestamp' + 'X-Event-Id', penjire ≤ 5 minut; mTLS/IP allow-list zerur.
Конверт: `event_id`, `type`, `version`, `ts`, `attempt`, `data`.
Eltip bermek: at-least-once, jitter bilen backoff, 'Retry-After', DLQ + replay API.
Idempotentlik: KV-kesh 24-72 sagat, täsiriň atomiki düzedilmegi + 'mark _ seen'.
Syn edilmegi: gowşuryş metrikleri, gollar, dublikatlar; trace _ id ".
Resminamalar: wersiýa, jogap kodlary, mysallar, UAT-çek-sanawy.
Jemleme
Durnukly webhuklar üç kitiň üstünde gurulýar: gol çekilen konwert, at-least-once eltip bermek we idempotent taýdan gaýtadan işlemek. Şertnamany resmileşdiriň, HMAC/mTLS-i we wagt penjiresini açyň, DLQ retraýalaryny we belliklerini durmuşa geçiriň, idempotent belliklerini saklaň we täsirleri atom bilen düzediň. Şonda wakalar toruň şowsuzlygy, ýüküň iň ýokary derejesi we ykbalyň seýrek "dublikatlary" bolanda-da ygtybarly bolup galýar.