Ö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.
Kısa cevap
Tek cümleyle: imza “bu gerçekten sağlayıcı mı”yı, idempotency “bu işi daha önce yaptım mı”yı sorar. İkincisinin genel hâlini, yani aynı isteği güvenle tekrar etmenin API tarafındaki kurallarını idempotency yazısında anlatmıştım; burada aynı fikrin webhook üzerindeki uygulaması var.
Neden
-
İmza ile tekillik farklı şeyleri garanti eder. Geçerli imzalı bir bildirim beş kez gelebilir; imza onun sahiciliğini söyler, kaçıncı kez geldiğini değil.
-
Bir-kez garantisini uygulama mantığı veremez. İki istek aynı anda gelirse “önce kontrol et, sonra yaz” mantığı ikisini de geçirir. Tekilliği ancak veritabanının kendi kısıtı verir.
-
Yavaş yanıt yeni tekrarlar üretir. Sağlayıcı timeout yerse aynı bildirimi yeniden gönderir; senkron çalışan bir handler kendi sorununu büyütür.
Ne yapmalı
-
İmzayı RAW body üzerinde doğrula. HMAC imzasını, parse etmeden önce ham gövde üzerinde, constant-time karşılaştırmayla kontrol et. JSON’ı decode edip yeniden encode edersen imza bozulur.
-
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.
-
Önce hızlı 200 dön, işi kuyruğa al. İmzayı doğrula, kaydı al, hızlıca
200dön ve asıl işi kuyruğa it; worker aynı key üzerinde idempotent kalsın. Kuyruk tarafının operasyonel detayı Laravel queue ve Supervisor yazısında. -
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.
-
Sıralamayı ve replay penceresini gözet. “Refund” bildirimi “charge”dan önce gelebilir; out-of-order durumları handle et.
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.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.