Bir ödeme sisteminde en tehlikeli bug’lardan biri uygulamanın çökmesi değildir.
Ödeme başarılı olduğu halde uygulamanın başarılı olup olmadığını bilmemesidir.
Kullanıcı “Öde” butonuna bastı.
Backend bankaya isteği gönderdi.
Banka parayı çekti.
Tam o anda network bağlantısı koptu.
Backend response alamadı.
Şimdi ne yapacağız?
Tekrar göndermek mantıklı görünür. Fakat ilk işlem başarılıysa müşteriden ikinci kez para çekme riski doğar.
İşte idempotency burada devreye girer.
Aynı niyet, aynı sonuç
Idempotent bir ödeme endpoint’i aynı mantıksal işlemi tekrar aldığında yeni bir ödeme oluşturmak yerine önceki işlemin sonucunu döndürmelidir.
Stripe’ın API tasarımı da bu yaklaşımı kullanıyor. Aynı idempotency key ile tekrar edilen işlemlerde ilk çağrının sonucunun tekrar döndürülmesi, bağlantı problemlerinde request’in güvenle yeniden denenebilmesini sağlıyor.
Örneğin:
POST /api/payments
Idempotency-Key: 78be9f63-...
{
"paymentIntentId": "PI-2026-000184"
}
Backend’de anahtar ve request fingerprint saklanabilir:
idempotency_key
request_hash
payment_id
status
response
created_at
Aynı key yeniden geldiğinde yeni banka işlemi başlatılmaz.
Tutarı URL’den almak iyi bir ödeme tasarımı değildir
Şöyle bir akış düşünün:
/pay?student=123&amount=12750
Kullanıcının browser’dan değiştirebildiği bir değer ödeme sisteminin source of truth’u olamaz.
Daha sağlıklı tasarım şudur:
Ana uygulama server-to-server iletişimle bir payment intent oluşturur.
POST /payment-intents
Ödeme sistemi:
{
"paymentIntent": "PI_X8A2...",
"expiresAt": "...",
"redirectToken": "..."
}
üretir.
Kullanıcı browser üzerinden yalnızca opaque token ile yönlendirilir.
/pay/PI_X8A2...?token=...
Gerçek tutar payment sisteminin kendi güvenilir storage’ından okunur.
Client hiçbir zaman ödeme tutarının otoritesi değildir.
Callback de aynı derecede önemlidir
Ödeme tamamlandıktan sonra kullanıcı browser’ının başarı sayfasına gelmesini transaction sonucu olarak kabul etmek doğru değildir.
Browser kapanabilir.
İnternet kesilebilir.
Kullanıcı redirect olmadan sekmeyi kapatabilir.
Gerçek settlement bilgisi banka/provider tarafından server-to-server callback veya webhook ile doğrulanmalıdır.
Webhook’un kendisi de duplicate gelebileceğinden callback consumer’ı idempotent olmalıdır.
Bu nedenle ödeme sistemlerinde idempotency sadece API tasarımı değildir.
Uçtan uca bir ilkedir.
AWS’nin güvenli retry tasarımı hakkındaki dokümantasyonu da aynı noktaya dikkat çekiyor: retry işleminin güvenli olabilmesi için çağrının yan etkilerinin tekrar oluşmaması gerekir.
Ödeme sistemlerinin güvenilirliği “isteği gönderdim” noktasında başlamaz.
Asıl soru şudur:
Aynı işlem üç farklı sebeple üç kez gelirse sistem hâlâ doğru sonucu üretir mi?