Haki internetowe i impreza iempotencja
TL; DR
Dobrym hakiem jest podpisany (HMAC/mTLS), podsumowane i idempotentne zdarzenie dostarczane na co najmniej raz model z wykładniczym backoff i deduplication w odbiorcy. Uzgodnić kopertę ('event _ id',' type ',' ts', 'version', 'try', 'signature'), okno czasowe (≤ 5 minut), kody odpowiedzi, przekaźniki, DLQ i punkt końcowy statusu.
1) Role i model dostawy
Nadawca (Ty/dostawca): generuje zdarzenie, znaki, próbuje dostarczyć do 2xx, retrait na 3xx/4xx/5xx (z wyjątkiem wyraźnego „nie akceptuj”), prowadzi DLQ, daje powtórkę API.
Odbiorca (partner/twój serwis): sprawdza okno podpisu/czasu, przetwarza dedup i idempotentne, odpowiada prawidłowym kodem, zapewnia/status i/ack powtórzenie za pomocą 'event _ id'.
Gwarancje: przynajmniej raz. Odbiorca musi mieć możliwość obsługi duplikatów i ponownego zamawiania.
2) Koperta wydarzenia
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"
}
}
Wymagane pola to 'event _ id',' type ',' version ',' ts', 'try'.
Zasady ewolucji: dodawanie pól; usunąć/zmienić typy - tylko z nową „wersją”.
3) Bezpieczeństwo: podpisy i wiążące
3. 1 podpis HMAC (domyślnie zalecany)
Tytuły:
X-Signature: v1=base64(hmac_sha256(<secret>, <canonical>))
X-Timestamp: 2025-11-03T12:34:56Z
X-Event-Id: 01HF7...
Ciąg kanoniczny:
<timestamp>\n<method>\n<path>\n<sha256(body)>
Sprawdź u odbiorcy:
- abs (obecnie − „X-Timestamp”) ≤ 300s
- "X-Event-Id nie przetworzone wcześniej (dedup)
- "X-Signature 'matches (porównanie bezpieczne w czasie)
3. 2 Add. środki
mTLS dla bardzo wrażliwych haków webowych.
Lista zezwoleń IP/ASN.
DPoP (opcjonalnie) dla nadawcy ograniczonego, jeśli hak internetowy zainicjuje wywołanie zwrotów zwrotnych.
4) Idempotencja i deduplikacja
4. 1 Przypadek idempotencji
Zdarzenie z tym samym 'event _ id' nie powinno ponownie zmieniać stanu. Odbiorca:- zdarzenie _ id' w pamięci podręcznej (KV/Redis/DB) magazynów na TTL ≥ 24-72 godziny;
- zapisuje wynik przetwarzania (sukces/błąd, artefakty) w celu powrotu.
4. 2 Dowództwo idempotencja (zwrotne)
Jeśli hak webhook zmusza klienta do pobrania API (na przykład „potwierdzenie wypłaty”), użyj 'Idempotency-Key' na wywołaniu REST, zapisz wynik po stronie usługi (dokładnie raz wynik).
Model KV (minimum):
key: idempotency:event:01HF7...
val: { status: "ok", processed_at: "...", handler_version: "..." }
TTL: 3d
5) Retrai i backoff
Zalecana działka (wykładnicza z jitterem):- „5s, 15s, 30s, 1m, 2m, 5m, 10m, 30m, 1h, 3h, 6h, 12h, 24h” (następnie codziennie do N dni)
- 2xx - sukces, przerwa.
- '400/ 401/403/404/422' - nie podlega zmianie, jeśli podpis/format jest w porządku (błąd klienta).
- "429" - retrayim przez "Retry-After 'or backoff.
- 5xx/network - retrayim.
Nagłówki nadawcy: 'User-Agent', 'X-Webhook-Producer', 'X-Attempt'.
6) Przetwarzanie po stronie odbiornika
Pseudo-rurociąg: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
Transakcyjność: Etykieta „widziana” musi być ustawiona atomowo z efektem operacji (lub po ustaleniu wyniku), aby uniknąć podwójnego przetwarzania na awarii.
7) Gwarancje zamówienia i migawki
Zamówienie nie jest gwarantowane. Użyj 'ts' i domeny' seq '/' version 'w' data 'w celu zweryfikowania znaczenia.
Dla długich opóźnień/strat - dodaj/powtórz w nadawcy i/resync w odbiorniku (pobierz migawki i delty w oknie czasu/identyfikatora).
8) Status, powtórka i DLQ
8. 1 Punkty końcowe nadawcy
'POST/webhooks/replay' - przez 'event _ id' list lub przez okno czasowe.
'GET/webhooks/events/: id' - pokaż pakiet źródłowy i historię prób.
DLQ: „martwe” zdarzenia (limit retray został wyczerpany) → oddzielne przechowywanie, wpisy.
8. 2 Punkty końcowe odbiorcy
'GET/ webhooks/status/:event_id' -' seen = true/false ',' processed _ at ',' handler _ version '.
'POST/webhooks/ack' - (opcjonalnie) potwierdzenie ręcznego przetwarzania z DLQ.
9) Umowy o błąd (odpowiedź odbiorcy)
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..."
}
Zalecenia: zawsze zwracać jasny kod i, jeśli to możliwe, „Retry-After”. Nie zwracaj szczegółowych danych zabezpieczających.
10) Monitorowanie i SLO
Mierniki (nadawca):- dostawa p50/p95, wskaźnik sukcesu, retray/event, drop-rate DLQ, share 2xx/4xx/5xx, delay window up to 2xx.
- zweryfikować wskaźnik awarii (podpis/czas), dup-rate, latency handler p95, 5xx.
- Dostawa: ≥ 99. 9% zdarzeń otrzymuje 2xx <3 c p95 (po pierwszej udanej próbie).
- Weryfikacja kryptograficzna: walidacja podpisu ≤ 2-5 ms p95.
- Dedup: 0 powtarzających się efektów (dokładnie raz wynik na poziomie domeny).
11) Bezpieczeństwo danych i prywatność
Nie nadawać PAN/PII w korpusie haka; użyć identyfikatorów, a następnie pociągnąć za szczegóły na autoryzowanym API.
Pola wrażliwe na maski w dziennikach; przechowywać ciała zdarzeń do minimum, z TTL.
Szyfruj sklepy DLQ i powtórz.
12) Wersioning i kompatybilność
Wersja w 'wersji' (koperta) i w tranzycie: '/webhooks/v1/payments '.
Nowe pola są opcjonalne; usunięcie - tylko po okresie 'Zachód słońca'.
Dokumentacja zmian w changelogu do odczytu maszynowego (do automatycznych kontroli).
13) Przypadki badań (lista kontrolna UAT)
- Ponowne dostarczenie tego samego 'event _ id' → jeden efekt i' 200 'do duplikatów.
- Podpis: poprawny klucz, nieprawidłowy klucz, stary klucz (obrót), „X-Timestamp” poza oknem.
- Backoff: Odbiorca daje '429' z 'Retry-After' → poprawna pauza.
- Porządek: Wydarzenia "... przetworzone „przyjść przed”... created '→ prawidłowe przetwarzanie/czekanie.
- Awaria bazy danych w odbiorniku pomiędzy efektem a 'mark _ seen' → atomowość/powtarzanie.
- DLQ i manual replay → udana dostawa.
- Masowa „burza” (dostawca wysyła pakiety) → bez strat, limity nie stłumić krytyczne.
14) Mini snajpery
Podpis nadawcy (pseudo):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)
Sprawdzenie i miejsce przeznaczenia (pseudo):
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) Częste błędy
Brak deduplikacji → powtarzające się efekty (podwójne odroczenia/wypłaty).
Podpis bez znacznika czasu/okna → powtórzyć lukę.
Przechowywanie jednej tajemnicy HMAC na wszystkich partnerów.
Odpowiedzi „200” ustalając wynik → utrata zdarzeń awaryjnych.
„Zmywanie” danych zabezpieczających do odpowiedzi/dzienników.
Brak DLQ/replay - incydenty są nierozstrzygnięte.
16) Realizacja arkusz oszustwa
Bezpieczeństwo: HMAC v1 + 'X-Timestamp' + 'X-Event-Id', okno ≤ 5 minut; mTLS/IP zezwala na listę zgodnie z wymaganiami.
Конвера: 'event _ id',' type ',' version ',' ts', 'attempt', 'data'.
Dostawa: przynajmniej raz, backoff z jitterem, 'Retry-After', DLQ + replay API.
Idempotencja: KV-cache 24-72 h, utrwalenie atomowe efektu + 'mark _ seen'.
Obserwowalność: dostawa, podpis, duplikat mierników; trace _ id.
Dokumentacja: wersja, kody odpowiedzi, przykłady, lista kontrolna UAT.
Wznów streszczenie
Trwałe haki są zbudowane na trzech wielorybach: podpisanej kopercie, co najmniej raz dostawy i idempotent przetwarzania. Sformalizować kontrakt, włączyć HMAC/mTLS i okno czasu, wdrożyć retrai + DLQ i powtórzyć, przechowywać etykiety idempotent i uchwycić efekty atomowo. Wtedy wydarzenia pozostają niezawodne nawet przy awariach sieci, szczytach obciążenia i rzadkich „duplikatach losu”.