Teknik

Aynı Siparişi İki Kez Teslim Etmenin Asıl Sebebi Sunucun Değil: Idempotency Anahtarını Yanlış Ürettiğin İçin Her Ay Sessizce Stok Kaybediyorsun

Çift teslimatın kaynağı sunucu değil, kötü üretilmiş idempotency anahtarıdır. E-pin scripti tarafında doğru anahtar üretimini adım adım öğren.

Aynı Siparişi İki Kez Teslim Etmenin Asıl Sebebi Sunucun Değil: Idempotency Anahtarını Yanlış Ürettiğin İçin Her Ay Sessizce Stok Kaybediyorsun

Çoğu satıcı çift teslimat sorununu bir sunucu arızası sanır. Hosting firmasını arar, PHP sürümünü yükseltir, önbelleği temizler; sonra aynı olay bir hafta sonra yine tekrarlar. Çünkü sorun hiçbir zaman sunucuda değildi. Sorun, aynı ödeme bildiriminin iki kez gelmesi halinde sistemin bunu "yeni bir sipariş" olarak okumasıydı. Yani eksik olan şey donanım değil, kimlik. Her siparişin kendine ait, tekrarlandığında aynı kalan bir parmak izi yoksa, ikinci bildirim senin için taze bir müşteri gibi görünür ve kasadan ikinci kod çıkar.

Bu parmak izinin adı idempotency anahtarı. Kulağa akademik geliyor ama pratikte tek bir işi var: "Bu isteği daha önce işledim mi?" sorusunu milisaniyeler içinde kesin biçimde yanıtlamak. İyi kurulmuş bir e-pin scripti bu anahtarı sipariş doğmadan önce üretir, ödeme sağlayıcısına taşır, geri dönen her bildirimde aynı anahtarı arar. Kötü kurulmuş bir sistem ise anahtarı hiç üretmez ya da tam olarak tekrarlanmayacak biçimde üretir; ki bu ikincisi birinciden daha tehlikelidir, çünkü sana koruma varmış hissi verir.

%18Ödeme bildirimlerinin tekrar gönderilme oranı (ağ/timeout kaynaklı)
3,4 snOrtalama çift tıklama aralığı: klasik çift sipariş penceresi
%0Doğru anahtarla çift teslimat oranı (aynı trafik altında)
7 alanSağlam bir anahtarın beslendiği tipik girdi sayısı

Anahtarı kim üretir: tarayıcı mı, sunucu mu?

Burada verilen ilk karar, sonraki her şeyi belirler. Anahtarı tarayıcıda üretirsen, kullanıcının sekmeyi yenilemesi ya da JavaScript'in yeniden yüklenmesi yeni bir anahtar doğurur; koruma buharlaşır. Anahtarı yalnızca sunucuda üretirsen, ağ kopmasında kullanıcı tekrar denediğinde sunucu yine yeni bir anahtar üretir ve aynı delik açılır. Doğru yaklaşım ikili: anahtar sunucuda üretilir, oturuma bağlanır ve forma gömülür. Böylece tarayıcı aynı sayfayı kaç kez gönderse de taşıdığı anahtar aynıdır; sunucu ise anahtarın gerçekten kendi ürettiği bir değer olduğunu doğrulayabilir. Dijital ürün satış scripti tarafında bu, sepet oluşturulurken yazılan tek bir satırdır ama çift teslimat riskinin yarısını o satır kapatır.

Rastgele mi, türetilmiş mi? İkisi aynı şey değil

Rastgele anahtar (UUIDv4 gibi) üretmek kolaydır ve çakışma riski pratikte sıfırdır. Ama rastgele anahtarın bir zaafı var: aynı kullanıcı aynı sepeti iki farklı sekmede açarsa iki farklı rastgele anahtar doğar ve sistem ikisini de meşru sayar. Türetilmiş anahtar ise sipariş içeriğinden hesaplanır: kullanıcı kimliği, ürün kimliği, adet, tutar, para birimi ve kısa bir zaman penceresi birleştirilip özetlenir. Aynı içerik aynı pencerede tekrar gelirse aynı anahtar çıkar, yani ikinci sekme de aynı kapıya çarpar. Olgun bir e-pin satış yazılımı genelde ikisini birlikte kullanır: kullanıcı akışında türetilmiş anahtar, sağlayıcı bildiriminde ise sağlayıcının kendi işlem kimliğiyle eşlenen rastgele anahtar.

StratejiNasıl üretilirÇift sekmeyi durdurur muTekrar gelen bildirimi durdurur muRisk
UUIDv4 (saf rastgele)Sunucuda tek seferlik üretimHayırEvetÇoklu sekmede boşluk
Türetilmiş özetSHA-256(kullanıcı+ürün+adet+tutar+pencere)EvetEvetPencere çok uzunsa gerçek 2. alım bloklanır
Sağlayıcı işlem kimliğiÖdeme tarafından gelen benzersiz referansHayırEvetÖdeme öncesi aşamayı korumaz
Artan sayaçVeritabanı auto-incrementHayırHayırTahmin edilebilir, tekrarda yeni değer
Hibrit (önerilen)Türetilmiş anahtar + sağlayıcı referansı eşlemesiEvetEvetKurulum biraz daha uzun

Anahtarı neyden besleyeceksin: girdi listesini yanlış seçmek

Türetilmiş anahtarın kalitesi, içine koyduğun alanların kalitesidir. İçine oturum kimliği koyarsan kullanıcı çıkış yapıp girdiğinde koruma kırılır. İçine tam zaman damgası koyarsan her saniye yeni anahtar doğar ve hiçbir şeyi korumazsın. İçine kupon kodunu koymazsan indirimli ve indirimsiz aynı sepet farklı tutarda iki sipariş üretebilir. Sağlıklı girdi kümesi şöyle görünür: kullanıcı kimliği, ürün kimliği, varyant, adet, kuruş cinsinden tutar, para birimi ve 90-180 saniyelik yuvarlanmış zaman kovası. Zaman kovasını yuvarlaman şart: floor(unix/120) gibi bir ifade, iki dakika içindeki tekrar denemelerini aynı kovada tutar, üçüncü dakikada gerçekten yeni bir alım yapmak isteyen müşteriyi ise serbest bırakır.

Çift teslimat olaylarının kök nedeni dağılımı

  • Tekrar gelen ödeme bildirimi 45%
  • Kullanıcının çift gönderimi 25%
  • Elle yapılan yönetici işlemi 20%
  • Kuyruk/iş tekrarı 10%

Anahtarı nereye yazacaksın: tabloyu kilitlemezsen anahtar işe yaramaz

Anahtarı ürettin, peki nerede tutuyorsun? Eğer "önce var mı diye bakıyorum, yoksa yazıyorum" diyorsan koruma yalnızca yavaş trafiğe dayanır. İki istek aynı milisaniyede geldiğinde ikisi de "yok" cevabını alır ve ikisi de yazar. Doğrusu, kararı uygulamaya değil veritabanına verdirmektir: anahtar kolonuna UNIQUE indeks koy ve yazmayı dene. İkinci yazma hata döndürürse bu bir arıza değil, koruma çalıştı demektir; o isteği reddetmek yerine ilk siparişin sonucunu döndürürsün. Müşteri iki kez tıkladığını fark etmez, sen de iki kod harcamazsın. Epin yazılım katmanında bu davranışa "yanıt tekrarı" denir ve iyi bir uygulamanın ayırt edici işaretidir.

Anahtarın ömrü ne kadar olmalı?

Sonsuza kadar saklanan anahtar, bir yıl sonra aynı ürünü yeniden almak isteyen müşteriyi bloklar. Bir dakika sonra silinen anahtar ise geciken bildirimi kaçırır. Pratikte iki katmanlı bir ömür işe yarar: türetilmiş anahtar zaman kovasıyla birlikte kendiliğinden eskir, sağlayıcı referansına bağlı kayıt ise en az 30 gün saklanır; çünkü ödeme sağlayıcıları iade ve itiraz bildirimlerini günler sonra tekrar gönderebilir. Kayıtta yalnızca anahtarı değil, o anahtarla üretilen sonucun özetini de tut: hangi sipariş açıldı, hangi kod teslim edildi, hangi tutar tahsil edildi. Böylece tekrar gelen istek karşısında sıfırdan iş yapmak zorunda kalmazsın.

Test etmediğin koruma, koruma değildir

Idempotency en sinsi konulardan biridir, çünkü doğru çalıştığında hiçbir şey olmaz. Bu yüzden onu görünür kılmak gerekir. Aynı gövdeyi aynı anahtarla üst üste on kez gönderen küçük bir betik yaz; sonunda tek sipariş ve tek teslimat görmelisin. Ardından anahtarı değiştirip aynı gövdeyi gönder; bu kez iki sipariş görmen normaldir. Son olarak ödeme bildirimini elle iki kez tetikle. Bu üç testi geçen bir e-pin satış scripti, gerçek yükte de ayakta kalır. Loglara da anahtarı yaz; bir gün "bu müşteriye iki kod mu gitti" tartışması yaşarsan tek arama ile bitirirsin.

KontrolBeklenen durumSıklıkDurum
Anahtar sunucuda üretiliyorSepet açılışında, oturuma bağlıBir kez kurulumZorunlu
UNIQUE indeks mevcutidempotency_key kolonundaBir kez kurulumZorunlu
Tutar kuruş cinsindenOndalık yuvarlama farkı yokHer sürümdeZorunlu
Zaman kovası yuvarlanmış90-180 sn aralığıAyda bir gözden geçirÖnerilir
Yanıt tekrarı çalışıyorAynı anahtar aynı sonucu döndürürHer sürümdeZorunlu
Bildirim kaydı 30 günİade/itiraz için saklanıyorÜç ayda birÖnerilir
Yükleme testi yapıldı10 eşzamanlı istek, 1 teslimatHer büyük güncellemeZorunlu
Küçük ayar, büyük fark

Anahtarı üretirken tutarı kuruş cinsinden tam sayı olarak kullan. 149,90 gibi ondalıklı bir değer farklı katmanlarda farklı yuvarlanır ve aynı sipariş için iki ayrı anahtar doğurur; korumanın en sessiz kaçağı tam olarak budur.

Hazır bir altyapıda bu iş nasıl duruyor?

Bütün bunları kendi kodunda kurmak mümkün, ama her ödeme sağlayıcısı için ayrı eşleme, her ürün tipi için ayrı pencere ve her yönetici işlemi için ayrı koruma yazmak zaman alır. Pinova'nın sipariş katmanı bu işi kurulumla birlikte hazır getirir: sepet açılışında türetilmiş anahtar, ödeme dönüşünde sağlayıcı referansı eşlemesi, veritabanı seviyesinde tekillik ve tekrar gelen isteğe aynı yanıtı döndüren bir akış. Sen dijital ürün satış yazılımı tarafında ürün ve fiyat yönetmeye odaklanırken çift teslimat tartışması gündeminden düşer. Modüllerin ayrıntısını özellikler bölümünde, paket farklarını ise fiyat tablosunda görebilirsin.

Çift teslimatı bir kez kapat, bir daha açma

Pinova'nın sipariş ve teslimat katmanı idempotency korumasını kurulumdan itibaren açık getirir. Kendi kodunu kurcalamadan aynı güvenliği al.

Idempotency anahtarını müşteri görebilir mi, sorun olur mu?

Görebilir, sorun olmaz. Anahtar bir sır değil, bir kimliktir. Yine de tahmin edilemez olması iyidir; böylece kimse başkasının siparişinin sonucunu kendi anahtarıyla çekmeye çalışmaz. Sunucu tarafında anahtarı her zaman kullanıcı kimliğiyle birlikte doğrula.

Zaman penceresi kaç saniye olmalı?

90-180 saniye çoğu satıcı için doğru aralıktır. Bu süre, çift tıklama ve tekrar gelen bildirimleri yakalar ama gerçekten ikinci bir kod almak isteyen müşteriyi engellemez. Toptan satış yapıyorsan pencereyi kısalt, tek adetlik ürünlerde uzat.

Anahtar varsa ayrıca kilit gerekir mi?

Evet. Anahtar "bu istek daha önce geldi mi" sorusunu yanıtlar; kilit ise aynı anda gelen iki isteğin aynı stok satırına dokunmasını engeller. İkisi birbirinin yerine geçmez, birlikte çalışırlar.

Mevcut sistemime sonradan ekleyebilir miyim?

Ekleyebilirsin. Kolon ve UNIQUE indeks ile başla, sonra sepet açılışına üretimi, en sonda bildirim tarafına eşlemeyi bağla. Geçiş sırasında anahtarı boş gelen eski siparişleri ayrı ele almayı unutma.

Idempotency, müşterinin hiç fark etmediği ama senin kasanda doğrudan görünen bir disiplindir. Bir kez doğru kurduğunda "acaba iki kod mu gitti" sorusunu bir daha sormazsın. Bu korumanın gerçek bir panelde nasıl göründüğünü, sipariş kaydında anahtarın nerede durduğunu ve tekrar gelen bildirimin nasıl sessizce yutulduğunu görmek istersen canlı demo üzerinden kendi test siparişini açıp aynı isteği iki kez göndermeyi dene; tek teslimat gördüğünde neyi kazandığını anlayacaksın.

Daha Fazlasını Keşfedin

Dijital ürün satışı ve otomasyon üzerine güncel rehberlere göz atın.

Tüm Yazıları Gör →
Bu yazıyı paylaşın
Bu yazıyı beğendiniz mi?
Teşekkürler!
← Tüm yazılar