Bir e-ticaret sitesinin checkout (ödeme) akışını tasarlayın. Stok tutarlılığını ve çift ödemeyi nasıl önlersiniz?

Cevap

Checkout'un iki kritik riski vardır: aynı ürünün stoktan fazla satılması (overselling) ve aynı siparişin iki kez ücretlendirilmesi. Çözümün özü: stok için atomik rezervasyon, ödeme için idempotency key ve ödeme sonucunun webhook ile doğrulanması.

Akış

  1. Sepet -> sipariş oluştur: orders kaydı pending_payment durumunda oluşturulur, fiyatlar sunucuda yeniden hesaplanır (client'ın gönderdiği fiyata asla güvenilmez).
  2. Stok rezervasyonu: stok atomik olarak düşülür ve rezervasyona süre verilir (ör. 15 dk).
  3. Ödeme: ödeme sağlayıcısında (Stripe, iyzico) payment intent oluşturulur, sipariş ID'sine bağlı bir idempotency key ile. 3D Secure gerekiyorsa kullanıcı yönlendirilir.
  4. Webhook: sağlayıcı payment.succeeded olayını gönderir; sipariş paid olur, rezervasyon kalıcılaşır, e-posta ve kargo süreçleri kuyruğa atılır.
  5. Süre aşımı: ödenmeyen siparişin rezervasyonu bir job ile serbest bırakılır.
-- Atomik stok düşme: aynı anda iki istek gelse de stok eksiye düşmez
UPDATE inventory SET available = available - $2
WHERE product_id = $1 AND available >= $2
RETURNING available;
-- 0 satır dönerse stok yetersiz

Çift ödemeyi önleme

  • Frontend: "Öde" butonu tıklanınca devre dışı bırakılır; ama bu tek başına yetmez.
  • Backend: her checkout denemesinin bir idempotency key'i olur; aynı key ile gelen ikinci istek yeni ödeme oluşturmaz, ilk sonucu döner.
  • Sağlayıcı: Stripe gibi API'ler Idempotency-Key başlığını destekler.
  • Webhook işleyicisi: olay ID'si işlenmiş olaylar tablosunda tutulur; aynı olay tekrar gelirse yok sayılır. Webhook imzası doğrulanır.

Neden webhook?

Kullanıcı ödeme sayfasından sonra tarayıcıyı kapatabilir veya redirect kaybolabilir. Siparişin "ödendi" durumuna geçişi client redirect'ine değil, sunucudan sunucuya gelen doğrulanmış olaya bağlanmalıdır. Redirect sonrası sayfa sadece durumu gösterir (gerekirse polling yapar).

Dağıtık tutarlılık

Sipariş, stok ve ödeme farklı servislerdeyse dağıtık transaction yerine Saga deseni kullanılır: her adımın telafi (compensation) işlemi vardır (ödeme başarısız -> stok iade). Olayların kaybolmaması için outbox pattern ile DB yazımı ve olay yayımlama aynı transaction'da yapılır.

  1. Dikey ve yatay ölçekleme arasındaki fark nedir?KolaySistem TasarımıFull Stack
  2. Hangi cache stratejilerini biliyorsunuz?OrtaSistem TasarımıFull Stack
  3. REST ile GraphQL arasındaki farklar nelerdir?OrtaSistem TasarımıFull Stack
  4. Bit.ly benzeri bir URL kısaltma servisi tasarlayın.ZorSistem TasarımıFull Stack
  5. Google Docs benzeri gerçek zamanlı ortak düzenleme yüksek seviyede nasıl tasarlanır?ZorSistem TasarımıFull Stack
  6. CDN nedir, nasıl çalışır ve hangi durumlarda kullanılır?KolaySistem TasarımıFull Stack

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle