Webhooks და idempotence
TL; DR
კარგი ვებჰუკი არის ხელმოწერილი (HMAC/mTLS), შეაჯამებელი და იდემპოტენტური მოვლენა, რომელიც მოცემულია at-least-once მოდელის მიხედვით ექსპონენციალური backoff- ით და მიმღების შუამდგომლობით. შეთანხმდით კონვერტზე ('event _ id', 'ტიპი', 'ts', 'version', 'attempt', 'signature'), დროის ფანჯარა (5 წუთი), პასუხების კოდი, მიმოწერა, DLQ და სტატუს-ენდოინტი.
1) როლები და მიწოდების მოდელი
გამგზავნი (თქვენ/პროვაიდერი): აყალიბებს მოვლენას, ხელს აწერს ხელს, ცდილობს 2xx- მდე მიიტანოს, 3xx/4xx/5xx (გარდა აშკარა „არ მიიღოთ“), ხელმძღვანელობს DLQ- ს, აძლევს replay API- ს.
მიმღები (პარტნიორი/თქვენი სერვისი): ამოწმებს ხელმოწერას/დროებით ფანჯარას, აკეთებს დედაპლატს და იდემპოტენტურ დამუშავებას, აკმაყოფილებს სწორ კოდს, უზრუნველყოფს/status და/ack replay 'event _ id'.
გარანტიები: at-least-once. მიმღებმა უნდა შეძლოს დუბლიკატების დამუშავება და შეკვეთის შეცვლა.
2) მოვლენის კონვერტი (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"
}
}
სავალდებულო ველები: 'event _ id', 'ტიპი', 'ვერსია', 'ts', 'attempt'.
ევოლუციის წესები: დაამატეთ ველები; ტიპის მოცილება/შეცვლა - მხოლოდ ახალი 'ვერსიით ".
3) უსაფრთხოება: ხელმოწერები და კავშირი
3. 1 HMAC ხელმოწერა (სტანდარტულად რეკომენდებულია)
სათაურები:
X-Signature: v1=base64(hmac_sha256(<secret>, <canonical>))
X-Timestamp: 2025-11-03T12:34:56Z
X-Event-Id: 01HF7...
კანონიკური სტრიქონი:
<timestamp>\n<method>\n<path>\n<sha256(body)>
მიმღების შემოწმება:
- abs(now − `X-Timestamp`) ≤ 300s
- 'X-Event-Id' ადრე არ დამუშავებულა (დედაპაპი)
- 'X-Signature' ემთხვევა (დროის უსაფრთხო შედარებას)
3. 2 დოპი. ზომები
mTLS უაღრესად მგრძნობიარე ვებჰუკებისთვის.
IP/ASN allow-list.
DPOP (სურვილისამებრ) sender-constrained- ისთვის, თუ ვებჰუკი იწყებს საპირისპირო გამოწვევებს.
4) Idempotence და deduplication
4. 1 მოვლენის იდემპოტენტურობა
იგივე მოვლენა _ id 'არ უნდა შეიცვალოს მდგომარეობა. მიმღები:- ინახავს 'event _ id' idempotent კეშში (KV/Redis/BD) TTL- ზე 24-72 საათის განმავლობაში;
- ინარჩუნებს დამუშავების შედეგს (წარმატება/შეცდომა, არტეფაქტები) ხელახლა დაბრუნებისთვის.
4. 2 გუნდების იდემპოტენტურობა (საპირისპირო ზარები)
თუ ვებჰუკი აიძულებს კლიენტს API- ს გადაადგილება (მაგალითად, "დაადასტუროს პაიოტი"), გამოიყენეთ 'Idempotency-Key "ამ REST ზარზე, შეინახეთ შედეგი სამსახურის მხარეს (exactly-once outcome).
KV მოდელი (მინიმალური):
key: idempotency:event:01HF7...
val: { status: "ok", processed_at: "...", handler_version: "..." }
TTL: 3d
5) Retrai და backoff
რეკომენდებული გრაფიკი (ექსპონენციალური ჯიტერთან):- '5s, 15s, 30s, 1m, 2 მ, 5 მ, 10 მ, 30 მ, 1h, 3h, 6h, 12h, 24h' (ყოველდღიურად N დღემდე)
- 2xx - წარმატება, შეჩერება.
- '400/401/403/404/422' - არა, თუ ხელმოწერა/ფორმა ok (კლიენტის შეცდომა).
- '429' - Retry-After 'ან backoff.
- 5xx/ქსელის - retraim.
გამგზავნის სათაურები: 'User-Agent', 'X-Webhook-Producter', 'X-Attempt'.
6) მიმღების მხარეს დამუშავება
ფსევდოპაილინი: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
გარიგება: ეტიკეტი „თესლი“ უნდა განთავსდეს ატომურად ოპერაციის ეფექტით (ან შედეგის დაფიქსირების შემდეგ), რათა თავიდან იქნას აცილებული ორმაგი დამუშავება.
7) წესრიგისა და სნაიპშოტის გარანტიები
ბრძანება გარანტირებული არ არის. გამოიყენეთ 'ts' და დომენი 'seq '/' version' in 'data' შესაბამისობის შესამოწმებლად.
გრძელი ლაგებისთვის/დანაკარგებისთვის - დაამატეთ/replay გამგზავნისთვის და/resync- ში მიმღები (მიიღეთ snapshot და დელტა დროის ფანჯრის გასწვრივ/ID).
8) სტატუსი, replay და DLQ
8. 1 Endpoints გამგზავნი
'POST/webhooks/replay' - 'event _ id' ჩამონათვალის მიხედვით ან დროის ფანჯრის მიხედვით.
'GET/webhooks/events/: id' - აჩვენეთ ორიგინალური პაკეტი და მცდელობების ისტორია.
DLQ: „მკვდარი“ მოვლენები (ამოწურულია retray- ის ლიმიტი) - ცალკეული საცავი, ალერტები.
8. 2 მიმღების ენდოინტი
`GET /webhooks/status/:event_id` — `seen=true/false`, `processed_at`, `handler_version`.
'POST/webhooks/ack' - (სურვილისამებრ) სახელმძღვანელო დამუშავების დადასტურება DLQ- დან.
9) შეცდომის კონტრაქტები (მიმღების პასუხი)
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..."
}
რეკომენდაციები: ყოველთვის დაუბრუნეთ მკაფიო კოდი და, თუ შესაძლებელია, 'Retry-After'. ნუ დააბრუნებთ უსაფრთხოების დეტალებს.
10) მონიტორინგი და SLO
მეტრიკი (გამგზავნი):- delivery p50/p95, success rate, retrai/ღონისძიება, drop-rate DLQ, shar2xx/4xx/5xx, შეფერხების ფანჯარა 2xx- მდე.
- verify fail rate (ხელმოწერა/დრო), dup-rate, latency handler p95, 5xx.
- ადგილზე მიტანა: 99 ევრო. მოვლენების 9% იღებს 2xx <3 c p95 (პირველი წარმატებული მცდელობის შემდეგ).
- კრიპტოვალუტა: ხელმოწერის ნამდვილობა - 2-5 ms p95.
- Deadup: 0 განმეორებითი ეფექტები (exactly-once outcome დომენის დონეზე).
11) მონაცემთა უსაფრთხოება და კონფიდენციალურობა
ნუ გადაიტანთ PAN/PII ვებჰუკის სხეულში; გამოიყენეთ იდენტიფიკატორები და შემდგომი pull დეტალები უფლებამოსილი API- ით.
შენიღბეთ მგრძნობიარე ველები ლოგებში; შეინახეთ მოვლენების სხეულები მხოლოდ მინიმუმამდე, TTL- ით.
დაშიფრეთ DLQ და rapley საცავები.
12) ვერსიები და თავსებადობა
ვერსია 'ვერსიაში "(კონვერტი) და გზაზე: '/webhooks/v1/payments'.
ახალი ველები არჩევითია; მოცილება - მხოლოდ „Sunset“ პერიოდის შემდეგ.
შეადგინეთ ცვლილებები მანქანაში რეგულარული ჩანგელოგში (მანქანის შეკეთებისთვის).
13) ტესტის შემთხვევები (UAT ჩეკების სია)
- იგივე 'ღონისძიების _ id' ხელახალი მიწოდება არის ერთი ეფექტი და '200' დუბლიკატებზე.
- ხელმოწერა: სწორი გასაღები, არასწორი გასაღები, ძველი გასაღები (როტაცია), 'X-Timestamp' ფანჯრის გარეთ.
- Backoff: მიმღები იძლევა '429' s 'Retry-After' - ს სწორ პაუზას.
- შეკვეთა: მოვლენები '... პროგრესირებადი' ადრე მოდის '... created' - სწორი დამუშავება/მოლოდინი.
- მიმღები ვერ ახერხებს BD- ს ეფექტსა და 'mark _ seen' - ს შორის.
- DLQ და სახელმძღვანელო replay - წარმატებული მიწოდება.
- მასობრივი „ქარიშხალი“ (პროვაიდერი მართავს პაკეტს) - დანაკარგის გარეშე, ლიმიტები კრიტიკულად არ გამოხატავს.
14) მინი snippets
გამგზავნის ხელმოწერა (ფსევდო):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)
მიმღების შემოწმება და დედობა (ფსევდო):
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) ხშირი შეცდომები
არ არსებობს ბაბუა, განმეორებითი ეფექტები (ორმაგი რეფანდი/პეიაუტი).
ხელმოწერა ტაიმსტამპის/ფანჯრის გარეშე - დაუცველობა.
ერთი HMAC საიდუმლოების შენახვა ყველა პარტნიორზე.
შედეგის დაფიქსირებამდე '200' პასუხები არის მოვლენების დაკარგვა კრეშით.
უსაფრთხოების დეტალების „გათხრა“ პასუხებში/ლოგოებში.
DLQ/reple- ის არარსებობა - ინციდენტები გადაუჭრელია.
16) დანერგვა
უსაფრთხოება: HMAC v1 + 'X-Timestamp' + 'X-Event-Id', ფანჯარა 5 წუთი; MTLS/IP ალოუ-სია საჭიროებისამებრ.
Конверт: `event_id`, `type`, `version`, `ts`, `attempt`, `data`.
ადგილზე მიტანა: at-least-once, backoff ერთად ჯიტერი, 'Retry-After', DLQ + replay API.
Idempotence: KV-cash 24-72 საათი, ეფექტის ატომური ფიქსაცია + 'mark _ seen'.
დაკვირვება: მიტანის მეტრიკა, ხელმოწერები, დუბლიკატები; ტრეკი _ id '.
დოკუმენტაცია: ვერსია, პასუხის კოდი, მაგალითები, UAT ჩეკების სია.
რეზიუმე
მუდმივი ვებჰუკები აგებულია სამ ვეშაპზე: ხელმოწერილი კონვერტი, at-least-once მიწოდება და იდემპოტენტური დამუშავება. გააფორმეთ კონტრაქტი, ჩართეთ HMAC/mTLS და დროის ფანჯარა, განახორციელეთ retrais + DLQ და raples, შეინახეთ idempotent ეტიკეტები და დააფიქსირეთ ატომური ეფექტები. შემდეგ მოვლენები საიმედოდ რჩება ქსელის წარუმატებლობის, დატვირთვის მწვერვალებისა და იშვიათი „ბედის დუბლიკატების“ დროსაც.