Çoğu kişi çift tahsilatı ödeme sağlayıcısının ya da bankanın hatası sanır. Müşteri "iki kere çekildi" yazar, sen sağlayıcıya sorarsın, sağlayıcı "bizde tek işlem var" der ve konu çözümsüz kalır. Aslında çoğu vakada tahsilat gerçekten tektir; ikiye katlanan şey senin sistemindeki kayıt ve teslimatdır. Aynı bildirim iki kez düşer, sistemin iki kez işler, aynı siparişe iki kod gider ya da iki ayrı sipariş açılır. Faturayı da sen ödersin.
Bunun kökeni tek bir yanlış varsayımdır: "ödeme sağlayıcı bana bildirimi bir kez gönderir." Göndermez. Bildirim sistemleri tasarım gereği en az bir kez teslim garantisi verir; yani gerektiğinde tekrar dener. Senin tarafın bu tekrarları sindirecek şekilde kurulmadıysa, sağlığın yerinde bir ödeme altyapısı bile sana çift kayıt ürettirir. İyi bir e-pin satış scripti bu gerçeği baştan kabul eder ve her bildirimi "belki daha önce gördüm" şüphesiyle karşılar.
Çoğu bayi çift tahsilatı bankaya yazar — aslında akışın idempotent değil
Idempotent kelimesi kulağa akademik gelir ama anlamı basit: aynı isteği bir kez de yüz kez de uygulasan sonuç aynı kalır. Ödeme bildirimlerinde bunu sağlamazsan, ağın bir saniyelik gecikmesi bile sana ikinci bir teslimat yazdırır. Sağlayıcı cevabını zamanında alamadığı için tekrar gönderir, senin kodun aynı işlemi yeniden işler, stoktan ikinci kod düşer.
Klasik senaryo şudur: bildirimi aldın, siparişi güncelledin, tedarikçiden kodu çektin, müşteriye gönderdin ve tam cevabı dönerken bağlantı koptu. Sağlayıcı senden onay alamadı, otuz saniye sonra aynı bildirimi yine yolladı. Kodun bu ikinci bildirimi ilk kez görüyormuş gibi karşılıyorsa, aynı sipariş ikinci kez teslim edilir. Müşteri iki kod alır, sen bir kodun parasını alırsın. Zarar doğrudan stoğundan çıkar.
İmza doğrulama: gelen bildirimi neden asla olduğu gibi kabul edemezsin
Bildirim adresin internete açıktır. Adresi öğrenen herkes sana istek gönderebilir. Doğrulama yoksa, birisi "sipariş 12345 ödendi" içerikli bir paket yollar ve sistemin ona bedava e-pin teslim eder. Bu teorik bir risk değil; sahada en çok istismar edilen açıklardan biridir.
Doğru kurgu üç katmanlıdır. Birinci katman imza: sağlayıcı paketi paylaşılan gizli anahtarla imzalar, sen aynı anahtarla hesaplayıp karşılaştırırsın; karşılaştırmayı da sabit süreli yapman gerekir, basit eşitlik kontrolü zamanlama sızıntısına açıktır. İkinci katman kaynak doğrulama: sağlayıcı sabit IP aralığı yayınlıyorsa listeyi uygula. Üçüncü katman tazelik: paketin zaman damgasını kontrol et, belirlediğin pencereden eski bildirimi reddet, böylece yakalanmış bir paketin tekrar oynatılması işe yaramaz. Bu üçünü uygulamayan bir epin yazılım kurulumunu güvenli sayamazsın.
Aynı bildirim üç kez gelirse ne olur? Tekrar teslimat zinciri
Tekrarın nasıl zincirleme büyüdüğünü görmek için akışı tabloya dökelim. Soldaki kolon olayı, sağdakiler doğrulamasız ve doğrulamalı sistemin tepkisini gösteriyor.
| Olay | Korumasız sistem | Doğrulamalı sistem | Etki |
|---|---|---|---|
| İlk bildirim | Sipariş ödendi, kod teslim | Sipariş ödendi, kod teslim | Normal |
| Ağ kopması, cevap gitmedi | Kayıt yarım kalır | İşlem kimliği kaydedildi | Kritik an |
| İkinci bildirim | Yeniden teslim, ikinci kod | Daha önce görüldü, atlanır | Stok kaybı |
| Üçüncü bildirim | Üçüncü kod | Atlanır, 200 döner | Stok kaybı |
| Farklı tutarla bildirim | Sipariş tutarı ezilir | Reddedilir, kayda alınır | Dolandırıcılık |
| İade bildirimi | Durum değişmez | Sipariş iade, bakiye düzeltilir | Mutabakat |
| Bilinmeyen sipariş kimliği | Yeni kayıt açar | Reddedilir ve loglanır | Kirli veri |
Idempotency anahtarı nasıl kurulur: tablo, tekil indeks, kilit
Çözüm şaşırtıcı derecede basit ve tamamen veritabanı disiplinidir. Gelen her bildirim için sağlayıcının verdiği işlem kimliğini al, ayrı bir tabloya tekil indeksle yaz. Yazma başarılıysa bu bildirimi ilk kez görüyorsun, işle. Yazma tekillik ihlali veriyorsa daha önce görmüşsün, hiçbir şey yapmadan başarı cevabı dön.
Kritik nokta sıralamadır. Kaydı işlemin başında at, sonunda değil. Sonunda atarsan, iki bildirim aynı anda gelirse ikisi de kontrolü geçer. Tüm işi tek veritabanı işlemi içine al: bildirim kaydı, sipariş durumu, stok düşümü ve teslimat kaydı ya birlikte olur ya hiç olmaz. Teslimatın kendisi dış servise bağlıysa kuyruğa yaz ve kuyruk işini de aynı işlem kimliğiyle tekilleştir. Bir de satır kilidi kullan: siparişi güncellerken satırı kilitle, paralel gelen ikinci bildirim beklesin ve sırası geldiğinde "zaten ödendi" görüp geri dönsün. Bu davranışların hazır geldiği bir dijital ürün satış scripti seçmek, aynı mantığı sonradan elle örmekten kat kat ucuzdur.
Mükerrer teslimat vakalarının kök nedenleri
- Idempotency kaydı yok 45%
- İşlem ve kilit yönetimi hatası 25%
- İmza ve tazelik kontrolü eksik 20%
- Çelişen durum otoritesi 10%
Tutar ve para birimi doğrulama: 1 TL ile bin liralık e-pin
Bildirimi doğruladın, tekrarı engelledin; hâlâ bir açık var. Gelen paketteki tutarı olduğu gibi kabul ediyorsan, sipariş tutarını kendi kaydınla karşılaştırmıyorsun demektir. Saldırgan ya da hatalı bir akış, bin liralık siparişi bir liralık ödemeyle kapattırabilir.
Kural net: sipariş tutarı sunucu tarafında, katalog fiyatından hesaplanır ve bildirimde gelen tutarla kuruş kuruşuna eşleşmelidir. Para birimi de karşılaştırılır. Eşleşmezse sipariş kapatılmaz; "incelemede" durumuna alınır ve sana uyarı gider. Kısmi ödeme kabul ediyorsan bunu ayrı bir durum olarak modelle, asla "ödendi" ile karıştırma. Aynı hassasiyeti kupon ve bakiye kullanımında da göster: indirim sonrası beklenen tutarı sen hesapla, istemciden gelen sayıya güvenme. Bu tür sunucu tarafı doğrulamaların hazır olup olmadığını özellikler bölümünden mutlaka kontrol et.
Sağlayıcıya 200 cevabını yalnızca bildirimi kalıcı olarak kaydettikten sonra dön. Erken dönen bir onay, kaybolan ödeme demektir; geç dönen onay ise sadece bir tekrar denemesi.
Webhook mu dönüş sayfası mı? Otorite tek olmalı
Son ve en çok atlanan konu: sipariş durumunu kim belirliyor? Kullanıcı ödeme sonrası siteye geri döner, o dönüş sayfası da bir cevap taşır. Bazı kurulumlar hem dönüş sayfasına hem bildirime bakar ve ikisi de siparişi kapatmaya çalışır. Sonuç tahmin edilebilir: iki teslimat ya da çelişen durumlar.
Doğrusu şudur: otorite bildirimdir. Dönüş sayfası yalnızca kullanıcıya bilgi gösterir, veritabanında hiçbir para hareketi yaratmaz. Bildirim henüz düşmediyse kullanıcıya "ödemen doğrulanıyor" ekranı gösterilir ve sayfa arka planda durumu sorar. Sağlayıcı sorgu ucu sunuyorsa, uzun süre bildirim gelmeyen siparişler için zamanlanmış bir mutabakat işi kur: her saat bekleyen siparişleri sağlayıcıya sor, gerçeği oradan öğren. Aşağıdaki liste, canlıya almadan önce tek tek doğrulaman gereken maddeleri veriyor.
| Kontrol | Amaç | Durum |
|---|---|---|
| İmza sabit süreli karşılaştırmayla doğrulanıyor | Sahte bildirim engeli | Zorunlu |
| Zaman damgası penceresi uygulanıyor | Tekrar oynatma engeli | Zorunlu |
| İşlem kimliği tekil indeksle kaydediliyor | Mükerrer teslimat engeli | Zorunlu |
| Kayıt işlemin başında atılıyor | Eşzamanlı bildirim yarışı | Zorunlu |
| Sipariş satırı kilitleniyor | Paralel güncelleme koruması | Zorunlu |
| Tutar ve para birimi sunucuda karşılaştırılıyor | Eksik ödeme engeli | Zorunlu |
| Durum otoritesi yalnızca bildirim | Çelişki önleme | Zorunlu |
| Saatlik mutabakat işi çalışıyor | Kaybolan bildirim telafisi | Önerilir |
| Ham bildirim gövdesi log'da saklanıyor | İtiraz ve teşhis | Önerilir |
Bu korumaları sıfırdan yazmak zorunda değilsin
İmza doğrulama, idempotency kaydı, satır kilidi ve mutabakat işi hazır gelirse, çift tahsilat tartışması senin gündeminden tamamen çıkar.
Aynı bildirimin tekrar gelmesi bir hata mı?
Hayır, tasarım gereğidir. Bildirim sistemleri cevabı alamadığında tekrar dener. Senin işin tekrarı hata olarak görmek değil, ikinci kez işlem yapmadan başarı cevabı dönmektir.
Idempotency için hangi değeri anahtar yapmalıyım?
Sağlayıcının verdiği benzersiz işlem kimliğini kullan. Sipariş numarası tek başına yetmez, çünkü aynı siparişe ödeme, iade ve iptal gibi farklı bildirimler düşebilir. İdeali işlem kimliği ile olay tipinin birleşimidir.
İmza doğrulama yerine IP kısıtı yeterli olur mu?
Olmaz. IP listesi faydalı bir ek katmandır ama tek başına paketin içeriğinin bozulmadığını kanıtlamaz. İmza doğrulama her koşulda zorunludur.
Bildirim hiç gelmezse sipariş ne olacak?
Bekleyen siparişlere yaşam süresi ver ve zamanlanmış bir mutabakat işi kur. Bu iş sağlayıcıya durumu sorar, ödendiyse teslimatı tamamlar, ödenmediyse rezervi serbest bırakır.
Çift tahsilat ve mükerrer teslimat, şans işi değil mimari işidir; doğru üç kontrolü kurduğun gün konu kapanır. Bu kontrollerin sipariş ekranında, log kayıtlarında ve mutabakat raporunda nasıl göründüğünü incelemek istersen canlı demo üzerinden bak, ardından fiyat sayfasından işine uygun paketi değerlendir.

