Bir müşterinin tüm App Store iade geçmişini döndüren tek bir uç nokta var ve işte size verdiği şey
Apple'ın Get Refund History uç noktası, bir müşterinin tüm App Store iade geçmişini imzalı işlemler olarak döndürür. İşte her alan, revision belirtecinin sayfalamayı nasıl yaptığı, bunun neden uygulama başına değil müşteri başına olduğu ve kaçırdığınız bir iadenin size neye mal olduğu.

Önemli noktalar
- Get Refund History, bir müşterinin uygulamanızdaki iade edilmiş uygulama içi satın alımlarını imzalı işlemlerin bir listesi olarak döndüren bir App Store Server API uç noktasıdır; böylece bir bildirim size hiç ulaşmasa bile iadeleri mutabık kılabilir ve erişimi iptal edebilirsiniz.
- O müşteriye ait herhangi bir işlem kimliğiyle GET /inApps/v2/refund/lookup/{transactionId} çağrısı yaparsınız ve Apple, yalnızca sorduğunuz satın alım için değil, uygulamanızdaki her satın alım türü genelinde onun iadelerini döndürür.
- Yanıtın üç alanı vardır: en eski iade önce gelecek şekilde sıralanmış, sayfa başına en fazla 20 JWS işlemi içeren signedTransactions, ayrıca sayfalama için bir revision belirteci ve bir hasMore boole değeri.
- Son revision belirtecini saklayın. Bir sonraki sefer geri iletin, Apple yalnızca o noktadan daha yeni iadeleri döndürür; bu da tüm geçmişin dökümünü her çalıştırmada yalnızca yeni satırlardan oluşan kısa bir listeye dönüştürür.
- Çözümlenen her işlem, revocationDate ve revocationReason taşır. revocationReason değerinin 1 olması, müşterinin uygulamanızdaki gerçek veya algılanan bir soruna dayanarak iade aldığı anlamına gelir; 0 ise yanlışlıkla yapılan bir satın alım gibi başka bir neden anlamına gelir.
- Uç nokta uygulama başına değil, müşteri başına çalışır. Uygulamanızın tamamındaki her iadeyi listeleyen tek bir çağrı yoktur; bu yüzden bir işlem kimliğinden yola çıkarak hesap başına mutabakat yaparsınız ya da uygulama genelindeki görünüm için REFUND bildirim akışınızı okursunuz.
- Bunu kurmanın nedeni paradır. Hiç yakalayamadığınız bir iade, hesabı açık tutar ve App Store'un zaten telafi ettiği bir müşteri için işlem gücü, model API çağrıları, depolama ve ödemeler ödemeye devam edersiniz.
Apple, uygulamanız için bir müşterinin hesabında onayladığı her iadenin sorgulanabilir bir kaydını tutar ve tek bir çağrı bunu döndürür. Bu uç nokta, App Store Server API'nin bir parçası olan Get Refund History'dir ve o müşterinin tüm App Store iade geçmişini imzalı işlemlerin bir listesi olarak size verir. Bir işlem kimliği iletirsiniz, Apple'ın neyi iade ettiğini geri alırsınız ve hâlâ açık tuttuğunuz şeyle bunu mutabık kılarsınız.
İşte neden zahmete değer. Hiç görmediğiniz bir iade, ödemeye devam ettiğiniz bir iadedir. Para çoktan gitti, ama hesap açık kalıyor ve açık kaldığı her saat işlem gücü, model API çağrıları, depolama ve o müşteriye bağlı her ödeme için harcamaya devam edersiniz. İade bildirimleriniz bunu tam olduğu anda yakalamak içindir. Get Refund History, bunu yakalayamadıklarında devreye giren yedeğinizdir: bir kesintiden, bir webhook'u düşüren bir dağıtımdan ya da tüm tabloya tek bir çağrıda ihtiyaç duyduğunuz bir destek vakasından sonra.
App Store iade geçmişi uç noktasının döndürdüğü şey
App Store Server API'ye karşı GET /inApps/v2/refund/lookup/{transactionId} çağrısı yaparsınız; buna yaptığınız her diğer çağrıda kullandığınız aynı JWT ile imzalanır. Yoldaki işlem kimliği, o müşteriye ait herhangi bir işlem olabilir. Apple bunu bir filtre olarak değil bir kimlik olarak okur ve o müşterinin iade edilmiş satın alımlarını uygulamanızın tamamında döndürür: tüketilebilir, tüketilemez, otomatik yenilenen ve yenilenmeyen abonelikler, hepsi. Bu uç noktanın daha eski V1 sürümü tek bir yanıtta en fazla 50 iade döndürüyordu ve kullanımdan kaldırıldı. Mevcut sürüm sayfalama yapar; böylece uzun geçmişi olan müşterileri devasa bir yük olmadan idare edersiniz.
Yanıt üç alandan oluşur
| Field | İçerdiği şey |
|---|---|
| signedTransactions | Bu müşteri için en fazla 20 iade edilmiş işlem; her biri doğrulayıp çözümlediğiniz imzalı bir JWS. revocationDate'e göre en eski iade önce gelecek şekilde sıralanır. Boş bir dizi, müşterinin uygulamanızda hiç iadesi olmadığı anlamına gelir |
| revision | Bir sayfalama belirteci. Sonraki sayfayı almak için geri iletin ve bir dahaki sefere yalnızca yeni iadeleri çekmek için sonuncusunu saklayın |
| hasMore | Apple bu sayfanın döndürdüğünden daha fazla iade edilmiş işlem tuttuğunda doğrudur; bu yüzden revision ile tekrar çağrı yaparsınız |
İade edilmiş bir işlemin size söylediği şey
signedTransactions içindeki her giriş bir JWS'tir. Apple'ın sertifika zincirine karşı doğrulayın, çözümleyin ve iade alanları doldurulmuş sıradan bir işlem yükünüz olur. Burada önemli olanlar bunlardır.
| Field | Size söylediği şey |
|---|---|
| transactionId | İade edilmiş işlemin kimliği, kaydettiğiniz satın alıma geri bağlanan birleştirme anahtarınız |
| originalTransactionId | Zincirdeki ilk satın alımın kimliği, bir aboneliğin yenilemelerini birbirine nasıl bağladığınız |
| productId | İade edilen ürün; böylece doğru yetkilendirmeyi iptal edersiniz, başka hiçbir şeyi değil |
| revocationDate | Apple'ın işlemi iade ettiği UNIX zamanı, milisaniye cinsinden |
| revocationReason | Apple'ın neden iade ettiği. 1, uygulamanızla ilgili gerçek veya algılanan bir sorun anlamına gelir; 0, yanlışlıkla yapılan bir satın alım gibi başka bir neden anlamına gelir |
| price, currency | Tutar, milliunits cinsinden, ve ISO 4217 para birimi kodu; böylece iade edilen parayı toplayabilirsiniz |
| appAccountToken | Satın alımda eklediğiniz UUID, bir iadeyi kendi kullanıcınıza geri eşlemenin en temiz yolu |
Tüm listeyi tekrar tekrar okumayı revision belirteci ile bırakırsınız
Bu uç noktayı kullanmanın saf yolu, bir müşteriyi arayıp her seferinde her sayfayı dolaşmaktır. Bu işe yarar ve elli iadesi olan bir müşteride bu, zaten bildiğiniz elli satır artı yeni olan tek satırdır. revision belirteci, bu israfı ortadan kaldırmak için vardır. Her yanıt bir revision taşır. hasMore doğru olduğunda, sonraki sayfayı almak için onu geri iletirsiniz. Sona ulaştığınızda gördüğünüz son revision'ı saklarsınız.
Bu uç noktanın yapmayacağı şey
Üzerine inşa etmeden önce bırakmanız gereken bir beklenti var. Get Refund History uygulama başına değil, müşteri başına çalışır. Ondan uygulamanızın geçen hafta aldığı her iadeyi isteyemezsiniz. Tek bir soruyu yanıtlar: bu hesabın hangi iadeleri var; ve sormak için o hesaba ait bir işlem kimliğiyle gelmeniz gerekir. Geliştiriciler sürekli bu duvara toslar ve var olmayan bir uygulama geneli iade uç noktası aramaya gider.
Uygulama genelindeki görünüm başka bir yerde yaşar. App Store Server Notifications akışınız, Apple her birini onayladığı anda bir REFUND bildirimi gönderir ve Get Notification History o akışı bir tarih aralığında iade türlerine filtrelenmiş olarak yeniden oynatmanızı sağlar. Yani ayrım net. Bildirimler ve geçmişleri size uygulama geneli akışı verir. Get Refund History ise size tek bir hesabın yetkili listesini talep üzerine verir; bir destek masasında ya da bir kesintiden sonra istediğiniz de tam budur.

Kaçırılan bir iadenin size parasal maliyeti
Uç nokta tesisattır. Fatura ise boruyu döşemenizin nedenidir. O listedeki her iade zaten geri verilmiş paradır ve kontrolünüzde kalan tek değişken, artık ödeme yapmayan bir hesap için ne kadar süre harcamaya devam edeceğinizdir.
İade edilmiş bir hesaba hizmet vermek için ödemeye devam edersiniz
Satın alma bedeli, Apple iadeyi onayladığı anda gider. Çalışmaya devam eden şey, teslimatın maliyetidir. Kullanıcı başına gerçek iş yapan bir uygulama için bu; işlem gücü, model API çağrıları, depolama ve kullanımlarına bağlı her içerik üreticisi veya iş ortağı ödemesidir. Erişimini hiç kesmediğiniz iade edilmiş bir müşteri, cebinizden finanse ettiğiniz bir aboneliktir. Get Refund History ile mutabakat yapıp bulduğunuz şey üzerinde iptal etmek, bir bildirim kaçtığında o sayacı kapatma yolunuzdur.
İade nedeni 1, kılık değiştirmiş bir kusur raporudur
revocationReason'ı görmezden gelirseniz size iki kez maliyet çıkarır. İlk maliyet iadenin kendisidir. İkincisi ise aynı nedenden kaynaklanan her gelecekteki iadedir. Bir ürün sürekli revocationReason 1 ile, yani uygulamanızdaki gerçek veya algılanan bir sorunla geri geldiğinde, Apple size müşterilerin paralarını geri istemesine neyin yol açtığına dair etiketli bir örnek veriyor demektir. Bunu ürün bazında eğilim olarak izleyin, o zaman sızıntıyı iade iade ödemek yerine onarabilirsiniz.
Geç yakalamak yine de hiç yakalamamaktan iyidir
Bir ters ibraz banka nezdinde kesindir ve diğer mağazada artık geliştiricinin üstlendiği bir ücret taşır. Bir App Store iadesi bu değildir. Kapanmıştır, ama yetkilendirme, öğrendiğiniz anda iptal etmeniz için sizindir. Yani bu uç nokta üzerinden günler geç bulduğunuz bir iade bile bulmaya değer. Parayı geri alamazsınız, ama arkasında hâlâ çalışan harcamayı durdurabilirsiniz.
Bunun bildirimlerle ve Google ile nasıl bağdaştığı
Parçaları tek bir sistem olarak düşünün. REFUND bildirimi, Apple karar verdikçe sunucunuza gönderilen canlı sinyaldir. Get Refund History ise tek bir müşteri için talep tabanlı doğruluk kaynağıdır; gönderim başarısız olduğunda ya da bir insanın tüm hesabı önünde görmesi gerektiğinde yaptığınız çağrıdır. Google Play tarafında biçim, farklı adlarla aynı fikirdir: bir VoidedPurchaseNotification gerçek zamanlı olarak gönderilir ve Voided Purchases API çektiğiniz listedir. Her iki mağaza da size bir akış ve bir defter verir. Hata, yalnızca akışa güvenmektir, çünkü akışlar düşer.
Bunu RefundHalt yöntemiyle kurmak
Her parça yerine oturduğunda döngü küçüktür. Bir REFUND bildirimini tetikleyici olarak alın. Get Refund History ile mutabık kılın ki düşen bir webhook iade edilmiş bir hesabı asla açık bırakmasın. Her işlemi çözümleyin, appAccountToken veya transactionId üzerinden kullanıcınıza geri anahtarlayın, revocationReason'ı okuyun ki bir kusur iadesi yalnızca arşivlenmek yerine işaretlensin ve tüm hesabı değil, tam olarak o yetkilendirmeyi iptal edin. revision belirteciyle sayfalayın ki eskilerini değil yeni iadeleri okuyun.
İşte bu, RefundHalt'ın sizin için çalıştırdığı kısımdır. İade bildirimlerini dinler, yetkili listeye ihtiyacı olduğunda Get Refund History'ye geri çekilir, her imzalı işlemi doğrular, tam o satın alımı iptal eder ve revision'ı saklar ki her geçiş yalnızca değişeni okusun. Erişimin saniyeler içinde kesilmesini ve kime, ne için ve neden iade edildiğine dair temiz bir kaydı, yoklama ile JWS doğrulamasını kendiniz kurmadan elde edersiniz.
Sık sorulan sorular
- Yalnızca bir müşteriyi değil, uygulamamın tamamındaki her iadeyi nasıl görürüm?
- Get Refund History ile göremezsiniz, çünkü müşteri başına çalışır ve sorduğunuz hesaba ait bir işlem kimliğine ihtiyaç duyar. Uygulama genelindeki görünüm için App Store Server Notifications akışınızı kullanın; Apple her iadeyi onayladıkça bir REFUND bildirimi gönderir. Ve o akışı bir tarih aralığında iade türlerine filtrelenmiş olarak yeniden oynatmak için Get Notification History'yi kullanın.
- Get Refund History uç noktası kaç iade döndürür?
- Mevcut sürüm sayfa başına en fazla 20 iade edilmiş işlem döndürür, en eski iade önce gelecek şekilde sıralanır ve hasMore doğru olduğunda geri kalanını bir revision belirteciyle sayfalar. Kullanımdan kaldırılan V1 uç noktası tek bir yanıtta en fazla 50 döndürüyordu. Toplamda bir üst sınır yoktur; bu yüzden uzun geçmişi olan bir müşteri sadece daha fazla sayfaya yayılır.
- revision belirteci ne işe yarar?
- Sayfalamayı bu şekilde yaparsınız ve bir müşterinin tüm geçmişini her seferinde tekrar okumaktan bu şekilde kaçınırsınız. Her yanıt bir revision içerir. Sonraki sayfayı almak için onu geri iletirsiniz ve sonuncusunu saklarsınız ki bir sonraki aramanız yalnızca o noktadan daha yeni iadeleri döndürsün. Bu, zamanlanmış bir mutabakatı yeni satırlardan oluşan kısa bir listeyle sınırlı tutar.
- İade edilmiş bir işlemde revocationReason ne anlama gelir?
- Apple'ın işlemi neden iade ettiğidir. 1 değeri, müşterinin uygulamanızdaki gerçek veya algılanan bir sorun nedeniyle iade aldığı anlamına gelir; 0 ise yanlışlıkla yapılan bir satın alım gibi başka bir neden anlamına gelir. revocationDate, iadenin ne zaman gerçekleştiğini UNIX milisaniye cinsinden söyler. revocationReason'ı okumak, bir ürün kusurunu tek seferlik bir pişmanlık iadesinden ayırmanızı sağlar.
- REFUND bildirimlerini zaten işliyorsam yine de buna ihtiyacım var mı?
- Evet, bir yedek olarak. Bildirimler canlı sinyaldir, ama bir gönderim bir kesinti, kötü bir dağıtım ya da bir webhook değişikliği sırasında ulaşmayabilir ve kaçırılan bir iade, iade edilmiş bir hesabı açık ve size para kaybettirir halde bırakır. Get Refund History, mutabık kaldığınız talep tabanlı doğruluk kaynağıdır; böylece Apple'ın zaten iade ettiği hiçbir şey açık kalmaz.
Kaynaklar ve ek okumalar
- Apple Developer: Get Refund History (App Store Server API)
- Apple Developer: RefundHistoryResponse
- Apple Developer: JWSTransactionDecodedPayload (revocationDate, revocationReason)
- Apple Developer: Get Refund History V1 (deprecated)
- Apple Developer: App Store Server Notifications V2 notificationType (REFUND)
- Apple Developer: Support customers and handle refunds (WWDC21)
RefundHalt
App Store ve Google Play için geri ödeme otomatik pilotu
Okumaya devam edin
Uygulamanız uygulama içi bir iade talebi sayfası gösterebilir, işte müşteri gönder'e dokunduktan sonra Apple ne yapıyor
Apple'ın uygulama içi iade talebi, müşterinin uygulamanızdan çıkmadan, Apple'ın oluşturup incelediği bir sayfada iade istemesine olanak tanır. İşte beginRefundRequest'in döndürdükleri, sunucunuzda başlattığı CONSUMPTION_REQUEST ve 48 saat sayaçları ve bu düğmeyi yayınlamaya değip değmeyeceği.
Bir Google Play satın alması iade edildiğinde veya ters ibraz edildiğinde, bunu Voided Purchases API ile öğrenirsiniz
Google Play, bir satın alma iade edildiğinde veya ters ibraz edildiğinde onu sessizce geçersiz kılar. Voided Purchases API bu siparişlerin listesidir, böylece erişimi geri alabilirsiniz. İşte her alan, 30 günlük pencere, siparişleri gizleyen geri alma seçeneği ve maliyeti.