Apple'ın iade akışıyla daha önce çalıştıysanız, dokümantasyonda bahsedilen 12 saatlik yanıt süresini muhtemelen görmüşsünüzdür. Ancak dokümantasyon, buna gerçekte nasıl yanıt vereceğinizi her zaman açıkça belirtmez.
CONSUMPTION_REQUEST bir bildirimdir; yanıt ise kendine ait bir anahtarı olan ve 2021'den bu yana gövdesi iki kez değişen farklı bir API'ye yapılan çağrıdır. Bir süre önce bildirimin kendisinin neler içerdiğini ele almıştık. Bu yazı ise ondan sonraki aşamayı, yani buna gerçekten yanıt vermeniz gereken kısmı ele alıyor.
Önemli Noktalar
Tek bir PUT isteğiyle App Store Server API'sine gönderilir. Mekanizmanın tamamı bu kadar.
Her istek, uygulama içi satın alma anahtarınızdan oluşturulan bir JWT ile imzalanır; 60 dakikadan eski token'lar reddedilir.
v2 gövdesinde beş alan vardır, bunlardan üçü zorunludur.
Apple yalnızca 202 yanıtı verir, başka bir şey vermez. İade kararı daha sonra, ayrı bir bildirim olarak gelir.
Bildirimin ulaştığı andan itibaren on iki saatiniz vardır ve bu süre içinde yeniden gönderim yapabilirsiniz.
Apple Tüketim Talebi (Consumption Request) Nedir?
Apple tüketim talebi, tüm teknik jargonun altında aslında bir sorudur. Bir müşteri Apple'dan parasını geri istemiştir ve Apple bu kişiye yanıt vermeden önce sizin sunucunuza dönüp şunu sorar: bu kişi ödediği şeyi aldı mı ve kullandı mı?
Apple, söylediklerinizi bu müşterinin ne sıklıkla iade talep ettiği gibi zaten bildiği bilgilerle birleştirir ve kararı kendisi verir.
İnsanlar bu son kısmı sürekli yanlış anlıyor. Siz hiçbir şeyi onaylamaz veya reddetmezsiniz; sadece gerçekleri aktarırsınız.
Apple'ın gönderdiği CONSUMPTION_REQUEST, App Store Connect'e girdiğiniz sunucu URL'sine, sürüm 2 sunucu bildirimi olarak ulaşır.
2021'de yalnızca tüketilebilir ürünler (consumables) için tetikleniyordu. 2024'te abonelikler eklendi ve Aralık 2025'te Apple, dokümantasyonuna göre tüketilemeyen ürünler ve yenilenmeyen abonelikler dahil olmak üzere tüm ürün türlerini kapsayan uç noktanın (endpoint) 2. sürümünü yayınladı. Bildirim referans sayfası hâlâ sadece ilk iki türü listeliyor; ben daha yeni sayfaya güvenip dördü için de geliştirme yapardım.
İsimlendirme konusundayken şunu da ekleyeyim: insanlar Apple refund API diye bir şey arıyor ama ayrı bir şey olarak böyle bir şey yok. Bu çağrı, App Store Server API'sinin bir parçasıdır.
Göndermeden Önce İhtiyacınız Olanlar
Bu dört şeyden üçü aceleye getirilemez, bu yüzden bunu ilk isteğinizden önce okuyun, sonra değil.
Birincisi bir anahtar, daha spesifik olarak App Store Connect'te Users and Access bölümünde oluşturulan bir uygulama içi satın alma anahtarı. Apple size bir .p8 dosyasını tam olarak bir kez verir; ayrıca anahtarın key ID'sine ve issuer ID'nize de ihtiyacınız olacak.
İkincisi, bir transaction ID'den (Apple'ın size verdiği) veritabanınızdaki bir kişiye (sizin ihtiyacınız olana) ulaşmanın bir yolu. Bunun temiz yolu, satın alma anında ayarlanan ve sonrasında o işlemle ilgili her bildirimde geri gelen appAccountToken'dır.
Bu terim size yabancıysa, önce appAccountToken'ın iade savunması için neden önemli olduğunu okuyun, çünkü bu eşleştirme olmadan bu yazının devamı sadece teorik kalır.
Üçüncüsü ve sabahın 2'sinde çözülemeyecek olan şey: onay (consent).
Apple'ın dokümantasyonu, müşteri bu verinin paylaşılmasına onay vermemişse hiç yanıt vermemeniz gerektiğini açıkça belirtiyor. Ayrıca daha hukuki bir dille, geçerli onay sayılan şeyin faaliyet gösterdiğiniz yere bağlı olduğunu ve bu konuda size tavsiye veremeyeceklerini söylüyorlar.
Şartlarınızda yer alan bir opt-in ifadesi genelde izlenen yoldur ve talep ortaya çıkmadan önce mevcut olması gerekir.
Dördüncüsü ise transaction ID'nin kendisidir; bunu yalnızca bildirim geldiğinde ve Apple'ın imzasını kontrol ettiğinizde elde edersiniz.
Tüketim Bilgisi Adım Adım Nasıl Gönderilir
send consumption information apple diye arama yapan çoğu kişi, alanları listeleyip ardından oldukça aniden kesilen Apple'ın referans sayfasına ulaşır. İşte pratikte izlenmesi gereken sıra.
Önce bildirimin gerçek olduğunu kontrol ederek başlayın. signedPayload bir JWS'dir; Apple'ın App Store Server Library'si bunu doğrular ve transactionId ile appAccountToken dahil, çözümlenmiş işlemi geri verir.
Satın almayı kendi tarafınızda bulun. Aradığınız bilgiler şunlar: teslim ettik mi, yaklaşık ne kadarı kullanıldı, önceden bir örnek veya deneme gördüler mi ve Apple'ın ne yapmasını tercih ederiz.
Şimdi token sırası. Header: alg ES256, kid sizin key ID'niz, typ JWT'dir. Payload: iss issuer ID'niz, iat şu anki zaman, exp en fazla 60 dakika sonrası, aud appstoreconnect-v1 sabit dizesi ve bid ise bundle ID'nizdir. Apple'ın JSON Web Token oluşturma kılavuzu tam yapıyı gösterir, ancak kütüphane bunu sizin için oluşturur.
PUT isteğini gönderin. Üretim URL'si https://api.storekit.apple.com/inApps/v2/transactions/consumption/{transactionId}, Authorization başlığında Bearer token olarak JWT ile ve aşağıdaki gibi bir gövdeyle:
{
"customerConsented": true,
"deliveryStatus": "DELIVERED",
"consumptionPercentage": 94000,
"sampleContentProvided": false,
"refundPreference": "DECLINE"
}
Apple 202 Accepted yanıtı verir ve alacağınız tek şey budur. Zamanı, gövdeyi ve transaction ID'yi kaydedin, çünkü bir ay sonra biri bu konuda Apple'a ne söylediğimizi soracaktır.
Sonra beklersiniz. Karar, bir REFUND veya REFUND_DECLINED bildirimi olarak gelir. REFUND ise, içeriği veya yetkiyi (entitlement) aynı gün geri alın.
Yani Apple'ın gerçekten kullanacağı tüketim bilgisini nasıl gönderebileceğinizi merak ediyorsanız, işte bu kadar: tek bir istek, beş alan, süre içinde.
Apple ayrıca o 12 saat içinde güncellenmiş bir gövde göndermenize de izin verir, yani ilk çağrı eksik bilgiyle gittiyse, bir ikincisini gönderin.
Alan adlarının size söylemediği birkaç şey var. consumptionPercentage milliunit cinsindendir ve bu çoğu kişiyi yanıltır: 94000, %94 anlamına gelir, 100000 ise tamamı demektir ve deliveryStatus DELIVERED dışında bir şeyse 0 olmak zorundadır.
Teslim edilmemiş (undelivered) seçenekleri UNDELIVERED_QUALITY_ISSUE, UNDELIVERED_WRONG_ITEM, UNDELIVERED_SERVER_OUTAGE ve UNDELIVERED_OTHER'dır.
refundPreference isteğe bağlıdır ve GRANT_FULL, GRANT_PRORATED veya DECLINE değerlerini alır; otomatik yenilenen bir abonelikte GRANT_PRORATED için yüzdeyi boş bırakın, Apple bunu kalan süreye göre kendisi hesaplar.
İlgili Send Consumption Information referansında eksiksiz hata listesi bulunur.
Yanıt Kodları Ne Anlama Gelir?
İyi olan tek bir yanıt var: 202. Diğer her şey, Apple'ın genellikle isim vererek size neyi yanlış yaptığınızı söylemesidir.
400 serisi en kullanışlı olanlardır, çünkü gövde hatanın adını verir.
ConsumptionPercentageOutOfRangeError hemen her zaman birinin 94000 yerine 94 göndermesi anlamına gelir.
UndeliveredConsumptionPercentageNonZeroError, ürünün hiç ulaşmadığını söylediğiniz ama sonra kısmen kullanıldığını iddia ettiğiniz anlamına gelir.
InvalidCustomerConsentedError zaten kendini açıklıyor.
401, token sorunudur: yanlış anahtar, bir saatten fazla uzaklıkta bir son geçerlilik tarihi, eşleşmeyen bir bundle ID veya iat'ı gelecekte gösterecek kadar kaymış bir sunucu saati.
404, transaction ID'nin bulunamadığı anlamına gelir ve benim ilk sorum her zaman bir sandbox işleminin üretim URL'sine gidip gitmediğidir (veya tersi).
429, hız sınırıdır (üretimde uygulama başına saniyede 50 istek, sandbox'ta bunun onda biri); yeniden denemeden önce Retry-After başlığını okuyun.
500, Apple'ın tarafındaki bir sorundur; daha sonra yeniden deneyin.
Sandbox'ta Nasıl Test Edilir
Bunu test etmek göründüğünden daha kolaydır, ancak bir incelik var.
App Store Connect'e bir sandbox sunucu URL'si girin, bir sandbox Apple Account ile oturum açın, bir şey satın alın, ardından uygulamanızın iade sayfasını (beginRefundRequest) açıp bir talep gönderin.
Apple'ın iade talepleri için test kılavuzu, test ortamının nasıl davrandığını açıklar: herhangi bir neden seçin, iade otomatik olarak onaylanır; Other seçip DECLINE yazarsanız reddedilir; orantılı bir iade için GRANT_PRORATED yazın.
İncelik şu kurallarda: sandbox, sunucunuzun gönderdiğine değil, sayfaya yazdığınıza göre karar verir, yani verilerinizin Apple'ı herhangi bir şeye ikna edip etmediğini size söyleyemez.
Test edebildiği şey ise alt yapıdır (plumbing): bildirim ulaşır, api.storekit-sandbox.apple.com'a yaptığınız PUT isteği 202 döner ve REFUND veya REFUND_DECLINED ortaya çıktığında işlenir.
Ayrıca sandbox iade e-postaları göndermez, bu yüzden birini beklemeyin.
Apple İade Otomasyonu: Bunu Elle Yapmayı Ne Zaman Bırakmalısınız
Elle yapıldığında bu iş, birinin günün her saatinde bir uyarı beklemesi, bir sorgu çalıştırması ve 12 saatlik süre dolmadan beş alanı göndermesi demektir.
Ayda bir avuç Apple iade talebi için bu sorun değildir. Ama kimsenin kontrol etmediği ilk uzun hafta sonunda durum oldukça farklıdır.
Apple iade taleplerini otomatikleştirmek için yukarıdaki her şeyi alıp ortadaki insan unsurunu kaldırırsınız: bildirim gelir, kurallarınız teslimat ve kullanım verilerini bir gövdeye dönüştürür, çağrı dakikalar içinde gönderilir, karar vakaya karşı kaydedilir ve bir REFUND bir iptali (revoke) tetikler.
Bunu kurmak büyük bir proje değildir; asıl sessizce maliyet çıkaran kısım, sonrasında Apple'ın değişikliklerine (örneğin V1'den v2'ye geçiş) ayak uydurmaktır.
Bunu kendiniz yapmak istemiyorsanız, bunun için oluşturulmuş hizmetleri Apple iade yönetim araçları karşılaştırmamızda ele aldık; Refund Sensor'ün nereye uyduğu ve nereye uymadığı da dahil.
Bu konu her gündeme geldiğinde itiraz ettiğim bir şey var: Apple iade otomasyonu, kararı kimin verdiğini değil, ne kadar güvenilir yanıt verdiğinizi değiştirir. Bu API'de hiçbir şey geliştiriciye son sözü vermez.
Sonuç
Çağrının kendisi küçüktür: imzalı bir token, bir PUT isteği, beş alan, kaydedilecek bir 202.
Bunu başarılı veya başarısız kılan şey başka bir yerde olur: şartlarınızda zaten yer alan onay, her satın almada bir appAccountToken, saniyeler içinde erişebileceğiniz kullanım kayıtları ve bildirim geldiğinde sabahın 3'ünde uyanan bir mekanizma.
Bunları yoluna koyduğunuzda bu iş bir koşuşturmaca olmaktan çıkar ve sunucunuzun kendiliğinden yaptığı bir şey haline gelir.
Sık sorulan sorular
Bu, bir CONSUMPTION_REQUEST'e yanıt vermek için kullanılan bir App Store Server API uç noktasıdır. Tüketim bilgilerini içeren bir PUT isteği gönderirsiniz ve Apple 202 Accepted döner.
CONSUMPTION_REQUEST'in ulaşmasından itibaren 12 saatiniz vardır. Apple, bu aynı 12 saatlik süre içinde güncellenmiş bir gövdenin gönderilmesine izin verir.
Evet. Apple, 12 saatlik süre içinde güncellenmiş bir gövde göndermenize izin verir. Bu, ilk gönderim eksik olduğunda faydalıdır.
Hayır. 202 Accepted yalnızca Apple'ın bilginizi aldığı anlamına gelir. Sonuç daha sonra bir REFUND veya REFUND_DECLINED bildirimi olarak gelir.
Evet. Tüketim bilgisi gönderirken customerConsented alanı zorunludur. Müşteri onay vermemişse, Apple'ın dokümantasyonu yanıt vermemeniz gerektiğini belirtir.



