وب سایت ها و idemotency رویداد
TL ؛ دکتر متخصص
یک webhook خوب یک رویداد امضا شده (HMAC/mTLS)، خلاصه شده و idempotent است که در یک مدل حداقل یک بار با عقب ماندگی نمایی و deduplication در گیرنده تحویل داده می شود. توافق بر روی یک پاکت نامه («event _ id»، «type»، «ts»، «version»، «attempt»، «signature»)، پنجره زمانی (≤5 دقیقه)، کدهای پاسخ، retrays، DLQ و نقطه پایانی وضعیت.
1) نقش و مدل تحویل
فرستنده (شما/ارائه دهنده): تولید یک رویداد، نشانه ها، تلاش می کند تا ارائه تا 2xx، retrait در 3xx/4xx/5xx (به جز صریح «قبول نمی کند»)، منجر DLQ، API پخش را می دهد.
گیرنده (شریک/سرویس شما): پنجره امضا/زمان را بررسی می کند، پردازش dedup و idemotent را انجام می دهد، با کد صحیح پاسخ می دهد ،/وضعیت و/ack را با «event _ id» پخش می کند.
گارانتی: حداقل یک بار گیرنده باید قادر به تکرار و تنظیم مجدد باشد.
2) پاکت از رویداد
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», «type», «version», «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 (در حال حاضر − 'X-Timestamp') ≤ 300 ثانیه
- 'X-Event-Id' قبل از پردازش (dedup) پردازش نشده است
- تطابق «X-Signature» (مقایسه ایمن در زمان)
3. 2 اضافه کردن اقدامات
mTLS برای وب سایت های بسیار حساس.
IP/ASN اجازه لیست.
DPoP (اختیاری) برای فرستنده محدود اگر webhook شروع callbacks.
4) Idempotency و deduplication
4. 1 توانمندی رویداد
رویدادی با همان «event _ id» نباید دوباره حالت را تغییر دهد. دریافت کننده:- event _ id 'in the idempotent cache (KV/Redis/DB) on TTL ≥ 24-72 ساعت;
- موجب صرفه جویی در نتیجه پردازش (موفقیت/خطا، مصنوعات) برای بازگشت مجدد.
4. 2 idempotency فرمان (مخاطبین)
اگر webhook مشتری را مجبور کند API را بیرون بکشد (به عنوان مثال، «تأیید پرداخت»)، از «Idempotency-Key» در تماس REST استفاده کنید، نتیجه را در سمت سرویس ذخیره کنید (نتیجه دقیقاً یک بار).
مدل KV (حداقل):
key: idempotency:event:01HF7...
val: { status: "ok", processed_at: "...", handler_version: "..." }
TTL: 3d
5) Retray و عقب نشینی
طرح توصیه شده (نمایی با لرزش):- '5s، 15s، 30s، 1m، 2m، 5m، 10m، 30m، 1h، 3h، 6h، 12h، 24h' (سپس روزانه تا N روز)
- 2xx - موفقیت, توقف retrays.
- '400/ 401/403/404/422' - اگر امضا/فرمت خوب باشد (خطای مشتری) قابل پرداخت نیست.
- '429' - retrayim توسط 'Retry-After' or برگشت.
- 5xx/شبکه - retrayim.
هدرهای فرستنده: «User-Agent»، «X-Webhook-Producer»، «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
Transactionality: برچسب «دیده شده» باید با اثر عملیات (یا پس از تثبیت نتیجه) به صورت اتمی تنظیم شود تا از پردازش دوگانه در شکست جلوگیری شود.
7) تضمین سفارش و عکس های فوری
نظم تضمین شده نیست. از «ts» و «seq »/« version» در «data» برای تأیید ارتباط استفاده کنید.
برای تاخیرهای طولانی/تلفات - اضافه کردن/پخش در فرستنده و/resync در گیرنده (دریافت عکس فوری و دلتاها در پنجره زمان/شناسه).
8) وضعیت، پخش و DLQ
8. 1 نقاط پایانی فرستنده
'POST/webhooks/replay' - توسط لیست 'event _ id' یا توسط پنجره زمان.
'GET/webhooks/events/: id' - بسته منبع و تاریخچه تلاش ها را نشان می دهد.
DLQ: رویدادهای «مرده» (حد مجاز خسته شده است) → ذخیره سازی جداگانه، هشدار.
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..."
}
توصیه ها: همیشه یک کد روشن را بازگردانید و در صورت امکان دوباره امتحان کنید. جزئیات امنیتی را گزارش ندهید.
10) نظارت و SLO
معیارها (فرستنده):- تحویل p50/p95، میزان موفقیت، retray/event، drop-rate DLQ، سهم 2xx/4xx/5xx، پنجره تاخیر تا 2xx.
- تأیید نرخ شکست (امضا/زمان)، dup-rate، latency handler p95، 5xx.
- تحویل: ≥ 99. 9٪ از رویدادها 2xx <3 c p95 (پس از اولین تلاش موفقیت آمیز) دریافت می کنند.
- تأیید رمزنگاری: اعتبار امضا ≤ 2-5 ms p95.
- Dedup: 0 اثرات تکراری (دقیقا یک بار نتیجه در سطح دامنه).
11) امنیت داده ها و حریم خصوصی
هنوز PAN/PII در بدن از webhook انتقال نیست ؛ از شناسه ها استفاده کنید و سپس جزئیات را در برابر یک API مجاز بکشید.
زمینه های حساس ماسک در سیاهههای مربوط ؛ رویدادهای فروشگاه تنها به حداقل، با TTL.
ذخیره و پخش DLQ را رمزگذاری کنید.
12) نسخه و سازگاری
نسخه در 'نسخه' (پاکت) و در حمل و نقل: '/webhooks/v1/payments '.
زمینه های جدید اختیاری هستند ؛ حذف - تنها پس از دوره «غروب».
مستند تغییرات در changelog ماشین قابل خواندن (برای خودکار چک).
13) موارد آزمون (چک لیست UAT)
- دوباره ارائه همان «event _ id» → یک اثر و «200» به تکراری.
- امضا: کلید صحیح، کلید نادرست، کلید قدیمی (چرخش)، «X-Timestamp» خارج از پنجره.
- برگشت: گیرنده می دهد '429' با 'سعی-پس از' → مکث درست است.
- سفارش: رویدادها... پردازش شده قبل از... ایجاد شده → پردازش صحیح/انتظار.
- خرابی پایگاه داده در گیرنده بین اثر و 'mark _ seen' → اتمی بودن/تکرار.
- DLQ و پخش دستی → تحویل موفق.
- توده «طوفان» (ارائه دهنده بسته می فرستد) → بدون از دست دادن، محدودیت انجام بحرانی خفه نیست.
14) قطعه های کوچک
امضای فرستنده) شبه (: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) خطاهای مکرر
Signature without timestamp/window → آسیب پذیری بازپخش
بدون deduplication → اثرات تکرار (refands دو/پرداخت).
ذخیره یک راز HMAC در همه شرکا.
پاسخ '200' قبل از تثبیت نتیجه → از دست دادن حوادث سقوط.
جزئیات امنیتی «شستشو» را به پاسخ/سیاهههای مربوط.
عدم وجود DLQ/پخش - حوادث غیر قابل حل است.
16) ورق تقلب پیاده سازی
امنیت: HMAC v1 + 'X-Timestamp' + 'X-Event-Id'، پنجره ≤ 5 دقیقه ؛ mTLS/IP اجازه لیست به عنوان مورد نیاز است.
Конверт: 'event _ id', 'type', 'version', 'ts', 'attempt', 'data'.
تحویل: حداقل یک بار، عقب نشینی با jitter، 'Retry-After'، DLQ + پخش API.
Idempotency: KV-cache 24-72 h، تثبیت اتمی اثر + 'mark _ seen'.
قابلیت مشاهده: تحویل، امضا، معیارهای تکراری ؛ ردیابی _ شناسه
مستندات: نسخه، کدهای پاسخ، نمونه ها، چک لیست UAT.
خلاصه رزومه
Webhooks مداوم بر روی سه نهنگ ساخته شده است: یک پاکت امضا شده، حداقل یک بار تحویل و پردازش idempotent. قرارداد را رسمی کنید، HMAC/mTLS و پنجره زمان را فعال کنید، retray + DLQ را اجرا کنید و پخش کنید، برچسب های idempotent را ذخیره کنید و جلوه های اتمی را ضبط کنید. سپس رویدادها حتی با خرابی شبکه، قله های بار و «تکرار سرنوشت» نادر قابل اعتماد باقی می مانند.