Ödeme webhook'u aynı bildirimi tekrar gönderiyor; idempotency'i nasıl kurarım?
Soru
Üçüncü parti bir ödeme sağlayıcısından webhook alıyorum. Sağlayıcı ağ kesintileri nedeniyle aynı başarılı ödeme bildirimini birden çok kez (retries) gönderebiliyor. Sistemim mükerrer işlem (double-spending) yapmasın diye webhook endpoint'inde nasıl bir mimari kurmalıyım? İstekleri imzalama (HMAC) ve DB seviyesinde idempotency key takibi nasıl olmalı?
Cevap
Kısa cevap: Bunlar iki ayrı mesele — kimlik doğrulama (HMAC) ve mükerrerliği önleme (idempotency). İkisini karıştırma, ikisini de ayrı çöz.
Tek cümleyle: imza “bu gerçekten sağlayıcı mı”yı, idempotency “bu işi daha önce yaptım mı”yı sorar. Mimarini bu ayrım üzerine kur:
- İmzayı RAW body üzerinde doğrula. Sağlayıcının HMAC imzasını, parse etmeden önce ham gövde üzerinde, constant-time karşılaştırmayla kontrol et; tutmuyorsa hiçbir şeye güvenme, reddet. JSON’ı decode edip yeniden encode edersen imza bozulur — body’ye dokunmadan doğrula.
- Idempotency’i DB’ye yaptır. Provider’ın event id’sini (ya da hash’ini) UNIQUE constraint’li bir tabloda sakla; bir transaction içinde check-or-insert yap. Bir-kez garantisini uygulama mantığı değil, veritabanı verir — aynı id ikinci kez gelirse insert zaten patlar.
- Önce hızlı 200 dön, işi kuyruğa al. Webhook handler’ında ödeme yan etkilerini senkron çalıştırma; imzayı doğrula, kaydı al, hızlıca
200dön ve asıl işi kuyruğa it. Worker aynı key üzerinde idempotent kalsın. Sağlayıcı timeout yiyip tekrar denemesin diye yanıt hızlı olmalı. - Her katmanda iki-kez-çağrılmaya dayanıklı ol. Handler da, worker da, yan etki de aynı bildirimle iki kez çağrılınca tek bir net sonuç üretmeli. “Bir kere gelir” varsayımını hiçbir yere koyma.
- Sıralamayı ve replay penceresini gözet. “Refund” bildirimi “charge”dan önce gelebilir; out-of-order durumları handle et. Provider’ın replay/retry penceresini de bil ki eski bir bildirimi yeni sanıp tekrar işlemeyesin.
Sonuç: Ben olsam akışı imza doğrula → hızlı 200 → işi kuyruğa al diye kurar, idempotency’i event_id üzerindeki UNIQUE constraint + transaction’lı check-or-insert ile DB’ye yaptırırdım. HMAC’i ham body’de constant-time karşılaştır. Double-spending’i app kodu değil, veritabanının tekillik garantisi durdurur. Kuyruk tarafının operasyonel detayını hub yazısında bulursun.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.