App Store & Play Store Development

Her App Store satın alımının bir appAccountToken'a ihtiyacı vardır, yoksa iade savunmanızın dayanacağı hiçbir şey kalmaz

Bir müşteri iade talep ettiğinde Apple, o kişiyi hiçbir zaman adıyla belirtmeyen bir CONSUMPTION_REQUEST gönderir. appAccountToken, bir satın alımı kullanıcınıza bağlayan UUID'dir. Onu ayarlarsanız gerçek verilerle yanıt verebilirsiniz; atlarsanız sadece tahmin yürütürsünüz.

5 min read
Her App Store satın alımının bir appAccountToken'a ihtiyacı vardır, yoksa iade savunmanızın dayanacağı hiçbir şey kalmaz

Apple'ın bir iadeyi kanıtla gerekçelendirmeniz için size tanıdığı süre yalnızca on iki saattir. Önünüzdeki işlem, adını veremeyeceğiniz bir müşteriye aitse bu sayaç hiçbir işe yaramaz. appAccountToken, bu adı sağlayan UUID'dir ve yalnızca satın alma gerçekleşirken eklenebilir.

Bildirimin ulaştığını hayal edin. Apple, bu alıcının üründen gerçekte ne kadar tükettiğini, ne kadar süredir müşteriniz olduğunu, toplamda ne harcadığını öğrenmek ister. Makul sorular ve veritabanınız tüm cevapları barındırıyor. Sorun şu ki önünüzdeki veri yükü size yalnızca bir originalTransactionId ve bir ürün tanımlayıcısı sunuyor; ikisi de kullanıcı tablonuzdaki hiçbir şeyle eşleşmiyor. Elinizde üzerinde isim olmayan bir fatura var, ihtiyacınız olan cevaplar ise isimlere göre dosyalanmış durumda.

Bu uyumsuzluğun bir çözümü var ve bu çözümün bir son tarihi var. appAccountToken, sisteminizin oluşturduğu, satın alma sırasında StoreKit'e verdiği ve ardından Apple'ın ortaya çıkan işleme damgaladığı bir UUID'dir. O andan itibaren Apple'ın size o satın alım hakkında söylediği her şey önceden kimliklendirilmiş olarak gelir. Ancak bu anı kaçırırsanız söz konusu satış kalıcı olarak anonim kalır. Aşağıda: bu alanın ne olduğu, nasıl ekleneceği, uygulamanızın hiç görmediği satın almaları geriye dönük kurtaran uç nokta (endpoint) ve anonim bir iadenin işletmenizden gerçekte ne götürdüğünün hesabı yer alıyor.

Önemli çıkarımlar

  • Bir App Store satın alımına bir UUID ekleyin; oluşturulan işlem doğrudan kayıtlarınızdaki belirli bir kullanıcıya işaret eder. Apple bu değeri işlemde tutar ve işlem her ortaya çıktığında onu size geri verir.

  • Apple'ın denetlediği tek şey formattır ve format UUID'dir. Ona bir veritabanı kimliği, bir e-posta adresi veya birbirine yapıştırdığınız bir karakter dizisi verin; StoreKit hiç şikayet etmeden bunu atar ve appAccountToken'ın olması gereken yerde size nil verir.

  • StoreKit 2 bunu tek bir satın alma seçeneği olarak sunar: Product.PurchaseOption.appAccountToken(_:); bu seçenek, sisteminizin önceden oluşturup o hesaba kaydettiği bir UUID ile beslenir.

  • Onu ilk satın almaya ekleyin; Apple aynı değeri abonelik zinciri boyunca her yenilemede, her yeniden denenen faturalandırma girişiminde ve her yükseltmede yayar.

  • 2025'ten itibaren, Set App Account Token uç noktası sunucunuza, uygulama içi akışın hiç görmediği satın almaları -bunlar arasında offer code kullanımları ve promosyonlu satın almalar da var- etiketleme imkanı verir.

  • Apple'ın CONSUMPTION_REQUEST'i yanıtlanabilir hale yalnızca bu token sayesinde gelir. Token olmadan, 12 saatlik pencere içinde tüketimini ayrıntılandırmanız beklenen müşteriyle iadeyi birbirine bağlayamazsınız.

  • Kimliği belirlenemeyen bir iade, savunulamayan bir iadedir. Kanıtını elinizde tuttuğunuz satışlarda para geri gider ve bu satışları gerçekleştirmek için zaten harcanmış işlem gücü, API çağrıları ve ödemeler de onunla birlikte gider.

Bu alan gerçekte ne işe yarar

Apple bu değeri anlamsız olarak ele alır ve asıl mesele de budur. Satın alma sırasında StoreKit'e verdiğiniz her UUID, işleme yazılır ve süresiz olarak saklanır; yorumlanmaya, neyi ifade ettiğinin doğrulanmaya veya herhangi bir şeye karşılık gelip gelmediğinin kontrol edilmeye çalışılmaz. Apple'ın kendi tanımı buna "işlemi kendi servisinizdeki kullanıcı hesabıyla ilişkilendiren UUID" der. Yorumlama tamamen sizin alanınızdır. Apple sadece değeri taşır ve talep üzerine size geri verir.

Bu alanı yararlı kılan şey, nerede geri verildiğidir. Sunucu bildirimleri bunu imzalı işlemin içinde taşır. App Store Server API'den Get Transaction Info isteyin, orada da karşınıza çıkar. Orijinal satın alma bu değeri taşıdığı sürece, abonelik zincirindeki her sonraki yenileme de onu yeniden üretir. Başka bir deyişle, değeri bir kez ekleyin, o müşteri size ödeme yapmaya devam ettiği sürece tekrar tekrar ortaya çıkmaya devam eder.

UUID dışında bir şey geçirin, hiç uyarı vermeden kaybolur

Geliştiriciler genellikle bu kuralı ihlal ederek keşfeder. Makul görünen bir şey geçirilir -dahili bir hesap kimliği, bir e-posta adresi, birbirine birleştirilmiş birkaç alan- ve StoreKit hiçbir itirazda bulunmaz. Ne istisna, ne uyarı, ne de başarısız bir satın alma olur. İşlem, appAccountToken nil durumda otururken geri döner ve var olduğunu sandığınız bağlantı hiçbir zaman kurulmamıştır. Apple'ın geliştirici forumlarında bu tam kafa karışıklığı sürekli olarak görülür, genellikle "appAccountToken is missing in the transaction payload" şeklinde ifade edilir ve açıklama neredeyse her zaman format gereksinimini karşılamayan bir değerdir.

Bu gereksinim dardır: StoreKit 2 yalnızca bir RFC 4122 UUID'sini kabul eder, başka hiçbir şeyi değil. Dolayısıyla güvenli yöntem, UUID'yi sunucunuzda oluşturmak, hesaba karşı kalıcı olarak saklamak ve başka hiçbir türde değerin satın alma çağrısına ulaşamamasını sağlamaktır.

Bunu tehlikeli kılan şey sessizliktir. Hatalı biçimlendirilmiş bir değer size ne bir hataya ne de başarısız bir satışa mal olur; yalnızca her şey normal şekilde ilerlerken sessizce atılan bağlantının kendisine mal olur. Değeri StoreKit'e ulaşmadan önce UUID formatına karşı kontrol etmek bir satır tutar ve bu başarısızlık modunun tamamını ortadan kaldırır.

Satın alma sırasında tokeni ekleme

Uygulamanın tamamı tek bir satın alma seçeneğinden ibarettir. UUID'yi kayıt sırasında veya bir müşteri ilk kez satın alma ekranına geldiğinde sunucu tarafında oluşturun, hesap kaydına yazın, ardından her satın aldıklarında aynı değeri sağlayın.

Seçeneğin imzası Product.PurchaseOption.appAccountToken(_ token: UUID) şeklindedir ve çağrının kendisi try await product.purchase(options: [.appAccountToken(token)]) şeklinde görünür. Tamamlanan işlem size hangi yoldan ulaşırsa ulaşsın -ister kendiniz App Store Server API'ye karşı doğrulayın ister bir sunucu bildirimi olarak alın- o UUID işlemin içinde taşınır ve bu da müşteri kimliklendirmeyi tek bir indeksli aramaya indirger.

Müşteri başına bir token, sonsuza dek yeniden kullanılır

Cazip bir hata, her işlem için yeni bir token oluşturmaktır. Bunu yapmak faydayı sessizce ortadan kaldırır. Apple, orijinal satın almadaki hangi token varsa onu yenilemelerde, yeniden denenen faturalandırma girişimlerinde ve o zincirdeki yükseltmelerde yeniden üretir; bu da hesap başına kalıcı bir UUID'nin müşterinin tüm ödeme geçmişini bağlı tutmasını sağlar. Değeri döndürürseniz her satın alma kendi başına bir ada dönüşür. Burada önemli olan özellik kararlılıktır, bu yüzden hesap oluşturulduğunda bir UUID seçin ve bir daha asla değiştirmeyin.

Uygulamanızın hiç dokunmadığı satın almaları kurtaran uç nokta

Daha önce iki satın alma yolu bunu tamamen etkisiz hale getiriyordu. Bir offer code kullanmak uygulamanızda değil, App Store'da gerçekleşir. Bir mağaza listesinden promosyonlu bir uygulama içi satın alma yapmak da öyle. Hiçbir yol satın alma kodunuzu çalıştırmaz; bu da bir tokenin sağlanabileceği bir an olmadığı anlamına gelir ve bu işlemler kalıcı olarak anonim kalırdı.

Bu kısıtlama, WWDC 2025'te Set App Account Token uç noktasıyla sona erdi. Sunucunuz, gövdede UUID taşıyarak App Store Server API'ye karşı PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken isteği gönderir ve Apple bunu işleme yazar. Kapsam her ürün türünü -offer code kullanımları ve promosyonlu satın almalar dahil olmak üzere- içerir ve bu şekilde gönderilen bir değer, işlemin önceden taşıdığı her hangi bir tokeni değiştirir. Dolayısıyla kimliklendirme, uygulamanızın hiç dahil olmadığı satın almalarda bile tamamen sunucu tarafında, sonradan gerçekleştirebileceğiniz bir işlem haline gelmiştir.

Tokeni nereye ekleyeceğiniz, satın almanın nasıl gerçekleştiğine bağlıdır:

  • Sıradan bir uygulama içi satın alma için, satın alma anında Product.PurchaseOption.appAccountToken(UUID) aracılığıyla StoreKit satın alma seçeneğinde ayarlayın.

  • Bir offer code kullanımı için, bunu sunucunuzdan Set App Account Token uç noktasıyla ayarlayın; çünkü bağlanacak hiçbir uygulama içi nokta yoktur ve sonradan eklemeniz gerekir.

  • App Store'dan promosyonlu bir uygulama içi satın alma için de aynı şekilde Set App Account Token uç noktasıyla ayarlayın, çünkü işlem uygulamanızın dışında gerçekleşir.

  • Bir abonelik yenilemesi için hiçbir şey yapmanız gerekmez. Token, orijinal satın almadan otomatik olarak devralınır.

Kopuk bir bağlantı gelirinize ne yapar

Burada söz konusu olan şey düzenli kayıt tutma değildir. Mesele şudur: Apple, bir iade sırasında geliştiricilere bir CONSUMPTION_REQUEST olarak iletilen tam olarak tek bir soru sorar ve bu soruyu yanıtlamak, hangi müşterinizden bahsedildiğini bilmeyi gerektirir.

Tüketilebilir ürünler ve yenilenmeyen abonelikler için yapılan iade talepleri bu bildirimi tetikler ve on iki saat içinde yanıt vermenin yolu Send Consumption Information'dır. Apple, tek bir kişiyle ilgili ayrıntılar bekler: ürünün ne kadarının tüketildiği, hesap kıdemi, yaşam boyu harcama, teslimat durumu. Token, talebin içinde bir alan olarak görünür, ancak daha önemli rolü yapısaldır, çünkü bu bildirimi kendi veritabanınızdaki bir satıra dönüştürebilecek tek şeydir. Tokeni çıkarın, kullanım takibiniz ne kadar titiz olursa olsun talep yanıtlanamaz hale gelir.

Boş yanıt vermenin bedeli

Bir iade kimliği belirlenmemiş şekilde geldiğinde geriye iki seçenek kalır ve ikisi de iyi değildir. Boş bir tüketim yanıtı gönderin, Apple bunu minimal kullanım olarak okur; bu da yoğun kullanıcılar dahil olmak üzere kararı onaya doğru ağırlıklandırır. Bunun yerine bir tahmin uydurun, bu sefer de bir platform sahibine kurgu rapor etmiş olursunuz. Hangi yolu izlerseniz izleyin, kanıtlayabileceğiniz satışlar, onları karşılamak için zaten ödeme yaptıktan sonra yine de iade edilir.

Asıl acıtan kısım teslimat maliyetidir, çünkü bu satış fiyatıyla hiçbir ilgisi yoktur. Bir üretim sırasında tüketilen model API çağrıları, üretilen görseller, render edilip dışa aktarılan bir video, alt tarafta serbest bırakılan bir içerik üreticisi ödemesi: bu paraların hepsi teslimat anında hesaplarınızdan çıkmıştır ve müşteriye iade yapmak onu geri çağırmaya hiçbir şekilde yaramaz. Şimdi sorunu ölçeklendirin. Kimliği belirsiz tek bir müşteri tekrar tekrar talepte bulunur. Alışkanlık haline getirmiş iade talep edenler, özellikle kendilerini tanımlayamayan işletmeleri hedef alır. Atlanan token, bu noktada küçük bir ihmal olmaktan çıkıp açık bir musluk gibi işlemeye başlar.

Apple'ın sorusu bir müşterinin gerçek tüketimiyle ilgilidir ve yanıtlamak, o müşterinin kim olduğunu bilmeyi gerektirir. Token olmadan, kanıtlayabileceğiniz satışları ve bunları teslim etmek için zaten harcanmış işlem gücü ile API masraflarını kaybedersiniz.

Android aynı oyunu farklı bir etiket altında oynar

setObfuscatedAccountId, Google Play'de bu görevi üstlenir; bir hesap tanımlayıcısını satın almaya bağlayarak orders.reviewrefund üzerinden yapılan chargeback incelemesinin inceleyecek gerçek bir kişiye sahip olmasını sağlar. Uygulamalar önemli ölçüde farklılaşır, ancak altta yatan disiplin değişmeden aktarılır: kimlik işlem sırasında bağlanır, yoksa anlaşmazlık daha sonra varsayılan olarak kaybedilir. Apple'ın bu disipline karşılık gelen versiyonu appAccountToken'dır ve bu da bir UUID'de ısrar eder.

Her satın almayı kimliklendirilmiş tutan üç uygulama

  • Hesap başına bir UUID oluşturun ve kalıcı hale getirin. Kayıt sırasında veya ilk satın almada oluşturulan, kaydına yazılan ve satın aldıkları her şeyde yeniden kullanılan, müşteri başına kalıcı tek bir token.

  • Değeri teslim etmeden önce kontrol edin. Satın alma kodunuzun içinde gerçekten bir UUID olduğunu doğrulayın; böylece hatalı biçimlendirilmiş bir tanımlayıcı işlemde sessizce nil bir tokene dönüşemez.

  • Uygulama dışında satın alınan her şeyi geriye dönük doldurun. Bir offer code kullanımı veya token taşımayan promosyonlu bir satın alma için bir sunucu bildirimi geldiğinde Set App Account Token uç noktasına başvurun ve doğru tokeni ekleyin.

Üçünü de benimseyin, kimliklendirme artık olaydan sonra denediğiniz bir şey olmaktan çıkar. Apple size verdiğinde her işlemin -iade talepleri dahil olmak üzere- zaten sahip olduğu bir özellik haline gelir.

Refund Sensor doğrudan bu varsayım üzerine inşa edilmiştir. Her işlemden ve sunucu bildiriminden appAccountToken'ı çıkarır, bunu o hesap için zaten kaydedilmiş tüketim verileriyle eşleştirir ve on iki saatlik pencerenin rahatlıkla içinde, o alıcıyı gerçekten tanımlayan rakamları kullanarak Apple'ın talebine bir yanıt sunarız. Adını koyabildiğiniz bir iade, tartışabileceğiniz bir iadedir ki tartışılmaya değer tek tür iade de budur.

Bu kuralların belgelendiği yerler

Sık sorulan sorular

Sahibi sizin sisteminiz olan, StoreKit'in yalnızca kaydettiği bir UUID'dir. Satın alma sırasında siz sağlarsınız, Apple bunu ortaya çıkan işleme yazar ve o andan itibaren bu satın alımın göründüğü her yerde yeniden karşınıza çıkar: işlem bilgisinde, onunla ilgili her sunucu bildiriminde ve aynı zincirdeki her yenilemede. Pratikteki etkisi, Apple'ın size daha sonra söylediği her şeyin -iade talebi dahil- kendi veritabanınızdaki doğru satıra işaret edilebilmesidir.

Hemen hemen kesinlikle format sorunudur. StoreKit 2'nin kabul ettiği standart RFC 4122'dir ve bu testi geçemeyen bir değer hiçbir hata verilmeden atılır; satın alma sanki hiçbir sorun yokmuş gibi tamamlanırken geriye nil kalır. Dahili kayıt kimlikleri, e-posta adresleri ve birbirine eklenmiş karakter dizileri bu şekilde başarısız olur. Diğer olasılık, uygulamanızın satın almayı hiç işlememiş olmasıdır; genellikle suçlu bir offer code (teklif kodu) kullanımıdır, yani bir token sağlamak için kodunuz hiç çalışmamıştır.

2025'ten itibaren, evet. Apple, tam da bu durum için App Store Server API'ye Set App Account Token özelliğini ekledi. Gövdede UUID sağlanarak /inApps/v1/transactions/{originalTransactionId}/appAccountToken adresine yapılan bir PUT isteği, zaten var olan bir işleme bir token yazar veya orada zaten bulunan bir tokeni değiştirir. Her ürün türü bu özellikten yararlanabilir ve özellik, özellikle uygulamanızın hiç işlemediği satın almalar -offer code'lar ve promosyonlu satın almalar- göz önünde bulundurularak tasarlandı.

Evet, istisnasız. UUID'nin sizin tarafınızda neyi işaret ettiği tamamen sizin işinizdir ve Apple bunu asla incelemez, ancak değerin kendisi UUID formatını karşılamak zorundadır. Bu şartı karşılamazsa StoreKit onu tutmayı reddeder ve işlemde nil kalır.

İadeler bir CONSUMPTION_REQUEST tetikler ve Apple, on iki saat içinde o belirli alıcının ürünü nasıl kullandığını açıklayan bir yanıt bekler. Böyle bir yanıt üretmek, bildirimdeki işlemi gerçekten sorgulayabileceğiniz bir müşteri kaydına dönüştürmek demektir ki tokenin işlevi tam olarak budur. Token ayrıca talebin içinde bir alan olarak da yer alır. Token olmadan yanıtınız ya boş ya da uydurma olur ve boş bir yanıt genellikle iadenin onaylanmasıyla sonuçlanır.

#appaccounttoken#storekit#refunds#in-app purchases#ios
Refund SensorRefund Sensor TeamRefund defense for App Store and Google Play developers