सभी लेख
Deep diveपढ़ने में 8 मिनट

StoreKit 2 में रिफंड की पहचान transaction की एक ही property पर टिकी है, और वह है revocationDate

जब Apple आपके किसी ग्राहक को रिफंड देता है, तो वह रिफंड आपके सर्वर जॉब के चलने से पहले ही, transaction के revocationDate में आपकी app के भीतर मौजूद होता है. यहाँ बताया गया है कि StoreKit 2 में रिफंड की पहचान डिवाइस पर कहाँ दिखती है, revocationDate और revocationReason आपको क्या बताते हैं, और क्यों क्लाइंट गति के लिए है और सर्वर सच्चाई के लिए.

एक अंधेरे डेवलपर डेस्क पर एक यांत्रिक घड़ी के पास चमकता हुआ स्मार्टफोन, जो दर्शाता है कि StoreKit 2 में रिफंड की पहचान app के भीतर कैसे उभरती है

मुख्य बातें

  • StoreKit 2 में एक रिफंड किया गया purchase अपने Transaction पर एक non-nil revocationDate रखता है, इसलिए आपकी app अपने सर्वर को कॉल किए बिना, खुद ही रिफंड की पहचान कर सकती है.
  • revocationDate तब सेट होता है जब App Store किसी transaction को रिफंड करता है या जब कोई ग्राहक Family Sharing के जरिए उसे खो देता है, इसलिए एक non-nil तारीख हमेशा रिफंड नहीं होती.
  • revocationReason आपको बताता है कि क्यों: developerIssue का मतलब है कि ग्राहक ने आपकी app में किसी समस्या का हवाला दिया, और other बाकी हर रिफंड कारण को कवर करता है.
  • Transaction.currentEntitlements पहले से ही रिफंड किए गए और रद्द किए गए purchases को बाहर रखता है, इसलिए access के लिए सबसे साफ क्लाइंट-साइड गेट बस यह है कि क्या कोई product अब भी वहाँ दिखता है.
  • Transaction.updates उस रिफंड को तभी पहुँचाता है जो आपकी app बंद रहते हुए हुआ था, अगर आप launch पर सुनना शुरू करते हैं, इसलिए एक गायब Task का मतलब एक छूटा हुआ रिफंड है.
  • क्लाइंट-साइड पहचान तभी चलती है जब app खुली हो, यही वजह है कि App Store Server Notifications V2 का REFUND वह भरोसेमंद संकेत बना रहता है जो आपको एक रिफंड किए गए उपयोगकर्ता की सेवा में पैसा खर्च करने से रोकता है.
  • एक रिफंड को पलटा जा सकता है, और जब ऐसा होता है, तो revocation फील्ड transaction से हटा दिए जाते हैं और आपसे उस access को बहाल करने की अपेक्षा की जाती है जिसे आपने काटा था.

अधिकांश apps किसी Apple रिफंड के बारे में अपने सर्वर से, एक App Store Server Notification के जरिए जानती हैं, और कभी ध्यान नहीं देतीं कि वही रिफंड पहले से ही app के भीतर मौजूद है. यह transaction पर, revocationDate नामक एक property में होता है, और इसे पढ़ना आपकी app को एक रिफंड किए गए ग्राहक का access अगली बार जब वे इसे खोलें तभी काटने देता है, न कि किसी बैकएंड जॉब की प्रतीक्षा करने देता है. StoreKit 2 में रिफंड की पहचान एक क्लाइंट-साइड संकेत है जिसे अधिकांश टीमें छोड़ देती हैं. यहाँ ठीक-ठीक बताया गया है कि एक रिफंड डिवाइस पर कहाँ उभरता है, वह आपको क्या बताता है, क्या नहीं बताता, और क्यों यह आपके सर्वर notifications के स्थान पर नहीं बल्कि उनके साथ होना चाहिए.

StoreKit 2 के भीतर एक रिफंड कहाँ दिखता है

StoreKit 2 आपको transactions को हस्ताक्षरित मानों के रूप में सौंपता है, और एक रिफंड transaction को हटाता नहीं है. यह उसे चिह्नित करता है. Transaction पर दो properties यह चिह्न रखती हैं, और दोनों एक स्वस्थ purchase के पूरे जीवन भर nil रहती हैं. जब उनमें से एक non-nil हो जाती है, तो App Store ने purchase वापस ले लिया है.

revocationDate वह फील्ड है जो पलटता है

revocationDate एक वैकल्पिक Date है. Apple का अपना विवरण सटीक है: यह वह तारीख है जब App Store ने transaction को रिफंड किया या उसे Family Sharing से रद्द किया. एक ऐसे purchase के लिए जो अब भी अच्छा है, यह nil है. जिस पल एक रिफंड संसाधित होता है, यह उस रिफंड का समय-चिह्न रखता है. वही एक जाँच, क्या revocationDate non-nil है, यही पूरी क्लाइंट-साइड रिफंड पहचान है. बाकी सब कुछ उसके ऊपर रखी बारीकियाँ हैं.

revocationReason आपको बताता है कि Apple ने इसे क्यों खींचा

revocationReason तारीख के बगल में बैठता है और कारण समझाता है. StoreKit इसे दो मान देता है जो रिफंड के लिए मायने रखते हैं. developerIssue का मतलब है कि ग्राहक ने Apple को बताया कि रिफंड आपकी app में किसी वास्तविक या कथित समस्या के कारण था. other बाकी हर कारण को कवर करता है. एक तीसरा मान, upgradedToBundle, कोई रिफंड नहीं है; यह एक ऐसे transaction को चिह्नित करता है जिसे App Store ने इसलिए रद्द किया क्योंकि ग्राहक एक subscription bundle में चला गया. कार्य करने से पहले कारण पढ़ें, क्योंकि developerIssue वही है जिसे गिनना सार्थक है: उनका एक समूह आपके अपने product का यह बताना है कि वह कहाँ टूटा.

PropertyTypeएक non-nil मान का क्या मतलब है
revocationDateDate?App Store ने इस transaction को रिफंड किया, या इस तारीख को Family Sharing के जरिए रद्द किया
revocationReason है developerIssuereasonग्राहक ने आपकी app में किसी वास्तविक या कथित समस्या का हवाला दिया
revocationReason है otherreasonरिफंड किसी अन्य कारण से हुआ जिसे Apple विस्तार से नहीं बताता
revocationReason है upgradedToBundlereasonकोई रिफंड नहीं; transaction इसलिए रद्द हुआ क्योंकि ग्राहक एक subscription bundle में गया

currentEntitlements पहले ही एक रिफंड किए गए purchase को हटा देता है

आपको हमेशा revocation फील्ड खुद पढ़ने की जरूरत नहीं होती. Transaction.currentEntitlements उन purchases का क्रम है जिनका ग्राहक अभी भी अधिकारी है, और Apple इसे इस तरह बनाता है कि उन्हें छोड़ दे जिन्हें आपको सम्मान नहीं देना चाहिए. एक product जिसे App Store ने रिफंड या रद्द कर दिया है, इसमें नहीं दिखता. न ही समाप्त हो चुके subscriptions दिखते हैं, या consumables, जो खत्म होते ही चले जाते हैं.

यह currentEntitlements को access के लिए सबसे साफ गेट बनाता है. इससे पूछें कि ग्राहक के पास क्या है, बिल्कुल वही दें, और एक रिफंड आपके लिए entitlement हटा देता है, बिना एक भी revocationDate जाँच के. revocation फील्ड तब के लिए हैं जब आप विवरण चाहते हैं, तारीख और कारण, घटना को लॉग करने या उस पर प्रतिक्रिया देने के लिए. entitlement सूची इस सीधे सवाल के लिए है कि रोशनी जलाए रखनी है या नहीं.

व्यवहार में StoreKit 2 रिफंड पहचान, launch से और app के चलते हुए

आपकी app डिवाइस पर एक रिफंड को दो पलों में पकड़ सकती है, और उन्हें अलग कोड चाहिए. एक तब है जब app खुली हो और एक रिफंड लाइव या किसी अन्य डिवाइस पर होता है. दूसरा launch पर है, उस सब को पकड़ना जो आपके बंद रहते हुए बदला. दूसरे को चूकें और आपकी StoreKit 2 रिफंड पहचान में ठीक वहाँ एक छेद है जहाँ अधिकांश रिफंड गिरते हैं, क्योंकि ग्राहक जब रिफंड माँगते हैं तब शायद ही कभी आपकी app खुली होती है.

launch पर सुनना शुरू करें वरना आप वे रिफंड चूक जाएँगे जो बंद रहते हुए हुए

Transaction.updates वह async क्रम है जो एक transaction उत्सर्जित करता है जब भी सिस्टम आपकी app के बाहर या किसी अन्य डिवाइस पर एक बनाता या अपडेट करता है, एक रिफंड सहित. Apple का निर्देश स्पष्ट है: एक Task शुरू करें जो इसे तब पुनरावृत्त करे जैसे ही आपकी app launch हो, वरना आप उन transactions को चूक सकते हैं जो यह startup पर केवल एक बार पहुँचाता है. रात भर में आया एक रिफंड updates के जरिए अगली बार जब app खुले तब आता है, पर तभी अगर उसे पाने के लिए पहले से एक listener चल रहा हो. कोई listener नहीं, कोई event नहीं, और रिफंड तब तक अदृश्य रहता है जब तक कुछ और उसका मिलान न कर दे.

एक ही डिवाइस पर किया गया purchase updates से नहीं आता

एक जाल उन लोगों को पकड़ता है जो हाथ से रिफंड जाँचते हैं. एक ही डिवाइस पर किया गया एक सामान्य purchase updates से नहीं आता; StoreKit उसे सीधे purchase कॉल के परिणाम से लौटाता है. updates उन बाहरी बदलावों के लिए है: रिफंड, Ask to Buy अनुमोदन, offer-code रिडेम्पशन, और कहीं और किए गए purchases. इसलिए अपने रिफंड हैंडलिंग को updates और currentEntitlements के इर्द-गिर्द बनाएँ, न कि purchase प्रवाह के इर्द-गिर्द, क्योंकि रिफंड कभी उस रास्ते से वापस नहीं आएगा जिससे बिक्री गई थी.

एक अंधेरी सतह पर एक मुड़ी हुई कागज की रसीद जिस पर एक धुंधली लाल मुहर दबी हुई है, जो एक रिफंड किए गए transaction का प्रतीक है जिसे StoreKit 2 एक revocation date से चिह्नित करता है

क्लाइंट-साइड पहचान आपके लिए क्या नहीं कर सकती

डिवाइस पर रिफंड पढ़ना तेज है और मुफ्त है, पर इसकी एक सीमा है, और यह दिखावा करना कि नहीं है, राजस्व के रिसने का तरीका है. डिवाइस केवल वही जानता है जो StoreKit ने उसे बताया है, और StoreKit केवल तभी बोलता है जब आपकी app चल रही हो. एक ग्राहक जिसे रिफंड मिलता है और जो फिर कभी आपकी app नहीं खोलता, वह एक ऐसा ग्राहक है जिसे आपकी क्लाइंट-साइड जाँच कभी नहीं देखती.

एक revocationDate हमेशा रिफंड नहीं होता

वही फील्ड Family Sharing के लिए भी पलटता है. जब एक ग्राहक किसी साझा purchase का access खो देता है, क्योंकि आयोजक ने उन्हें हटा दिया या साझाकरण समाप्त हो गया, तो उस transaction को भी एक revocationDate मिलता है. इसलिए एक non-nil तारीख का मतलब है कि ग्राहक के पास अब यह purchase नहीं है, जो ठीक वही है जो आपको access नियंत्रण के लिए चाहिए, पर इसका हमेशा यह मतलब नहीं कि पैसा वापस गया. अगर आप राजस्व के लिए रिफंड गिन रहे हैं, तो संख्या पर भरोसा करने से पहले Family Sharing रद्दीकरणों को असली रिफंड से अलग करें.

एक रिफंड को पलटा जा सकता है

एक रिफंड हमेशा अंतिम नहीं होता. Apple एक को पलट सकता है, और जब वह ऐसा करता है, तो revocation फील्ड transaction से हटा दिए जाते हैं और purchase फिर से वैध हो जाता है. अगर आपने रिफंड पर access काटा, तो आपसे पलटाव पर उसे बहाल करने की अपेक्षा की जाती है. डिवाइस पर यह एक साफ transaction के साथ एक और updates event के रूप में दिखता है; आपके सर्वर पर यह एक अलग REFUND_REVERSED notification है. केवल रिफंड को संभालें और आप एक भुगतान करने वाले ग्राहक को बिना access और एक चालू रसीद के साथ फँसा छोड़ देंगे.

एक देर से किया गया रद्दीकरण असल में कितना महँगा पड़ता है

एक रिफंड शायद ही कभी केवल बिक्री मूल्य का आपके खाते से जाना होता है. जब तक यह साफ होता है, आप आमतौर पर उस purchase की सेवा में पहले ही असली पैसा खर्च कर चुके होते हैं, और वह खर्च वापस नहीं आता. उत्पन्न की गई images GPU मिनट खर्च करती हैं. chat उत्तर model API कॉल खर्च करते हैं जिनके लिए आपसे प्रति token बिल लिया गया. uploads storage खर्च करते हैं जिसे रखने के लिए आप अब भी भुगतान कर रहे हैं. अगर purchase ने किसी creator को भुगतान वित्तपोषित किया, तो वह पैसा पहले ही बाहर जा चुका है. इनमें से कुछ भी रिफंड के साथ नहीं पलटता.

क्लाइंट-साइड पहचान उस एक हिस्से पर खिड़की को छोटा करती है जिसे आप अब भी नियंत्रित कर सकते हैं, जो है भविष्य का खर्च. जितनी जल्दी आप जानते हैं कि एक purchase रिफंड हो गया, उतनी जल्दी आप उसकी सेवा रोकते हैं. पर डिवाइस केवल तभी बताता है जब app खुली हो, इसलिए एक रिफंड किया गया उपयोगकर्ता जो कभी वापस नहीं आता, वह आपके द्वारा दिए गए किसी भी सर्वर-साइड access को बनाए रखता है, जो चुपचाप हर बार आपको खर्च कराता है जब कोई बैकग्राउंड जॉब या एक sync किया गया डिवाइस उनकी ओर से कार्य करता है. क्लाइंट रद्दीकरण को तेज बनाता है. यह उसे सुनिश्चित नहीं बनाता.

गति के लिए क्लाइंट और सच्चाई के लिए सर्वर का उपयोग करें

साफ डिज़ाइन दोनों संकेतों का उपयोग उसके लिए करता है जिसमें हर एक अच्छा है. डिवाइस पर, Transaction.updates और currentEntitlements आपको एक तत्काल, स्थानीय प्रतिक्रिया देते हैं जिस पल एक रिफंड किया गया ग्राहक app खोलता है, UI के लिए और एक round trip के बिना entitlement बदलाव पूरे करने के लिए अच्छा. सर्वर पर, App Store Server Notifications V2 एक REFUND संदेश भेजते हैं जो चाहे app फिर कभी खुले या न खुले पहुँचता है, जो एकमात्र संकेत है जो भरोसेमंद ढंग से आपके बैकएंड को एक रिफंड किए गए खाते पर खर्च करने से रोकता है.

Signalयह कहाँ रहता हैकब चलता हैइस पर भरोसा करें
revocationDate एक transaction परDevice, StoreKit 2आपकी app transaction पढ़ती हैआपको बताएँ कि एक विशेष purchase रिफंड या रद्द हुआ
Transaction.updatesDevice, StoreKit 2app के चलते हुए एक रिफंड आता है, या launch पर अगर आप सुनेंएक मौजूद ग्राहक के लिए तुरंत प्रतिक्रिया दें
currentEntitlementsDevice, StoreKit 2आप जाँचते हैं कि ग्राहक के पास अभी क्या हैखुद रिफंड ट्रैक किए बिना access को गेट करें
REFUND notificationआपका सर्वर, App Store Server Notifications V2Apple रिफंड संसाधित करता है, app खुली हो या न होएक ऐसे ग्राहक पर सर्वर-साइड खर्च रोकें जो कभी नहीं लौटता

फोन थामे हुए ग्राहक के लिए डिवाइस संकेतों को जोड़ें, और उसके लिए सर्वर notification को जो नहीं थामे. रिफंड जानबूझकर दोनों जगहों पर दिखता है. उनमें से केवल एक को पढ़ना ही वह तरीका है जिससे एक रिफंड किया गया खाता बिक्री के पहले ही जा चुकने के बाद आपको खर्च कराता रहता है.

अक्सर पूछे जाने वाले सवाल

मैं StoreKit 2 में एक रिफंड कैसे पहचानूँ?
transaction का revocationDate जाँचें. यह एक वैध purchase के लिए nil होता है और एक बार App Store के transaction रिफंड करने पर एक तारीख रखता है, इसलिए एक non-nil revocationDate वह संकेत है कि एक purchase रिफंड या रद्द हुआ.
revocationDate और revocationReason में क्या अंतर है?
revocationDate वह है जब App Store ने purchase वापस लिया, और revocationReason यह है कि क्यों. कारण developerIssue होता है जब ग्राहक ने आपकी app में किसी समस्या का हवाला दिया और other बाकी किसी भी चीज़ के लिए.
क्या एक रिफंड किया गया purchase अब भी currentEntitlements में दिखता है?
नहीं. Transaction.currentEntitlements उन purchases को बाहर रखता है जिन्हें App Store ने रिफंड या रद्द किया है, इसलिए एक रिफंड किया गया product खुद ही ग्राहक के entitlements से बाहर हो जाता है, जो इसे access के लिए एक सुरक्षित गेट बनाता है.
क्या StoreKit मेरी app को उस रिफंड के बारे में बताएगा जो app बंद रहते हुए हुआ?
केवल तभी अगर आप launch से सुनें. Transaction.updates उन बदलावों को startup पर एक बार पहुँचाता है, इसलिए आपको एक Task शुरू करना होगा जो इसे तब पुनरावृत्त करे जैसे ही आपकी app launch हो वरना रिफंड तब तक छूट जाता है जब तक कुछ और उसका मिलान न कर दे.
क्या क्लाइंट-साइड रिफंड पहचान अपने आप में पर्याप्त है?
नहीं. डिवाइस केवल तभी एक रिफंड के बारे में जानता है जब आपकी app चल रही हो, इसलिए एक ग्राहक जो app फिर कभी नहीं खोलता उसके लिए अदृश्य है. App Store Server Notifications V2 का REFUND वह संकेत है जो चाहे जो हो आप तक पहुँचता है.
क्या एक revocationDate हमेशा यह मतलब है कि ग्राहक को रिफंड मिला?
नहीं. revocationDate तब भी सेट होता है जब एक ग्राहक Family Sharing के जरिए एक purchase खो देता है, इसलिए एक non-nil तारीख का मतलब है कि उनके पास अब वह purchase नहीं है पर हमेशा यह नहीं कि पैसा वापस किया गया.

स्रोत और आगे की जानकारी

RefundHalt

App Store और Google Play के लिए refund ऑटोपायलट

आगे पढ़ें

Playbookपढ़ने में 7 मिनट

App Store और Google Play की हर रिफंड विंडो एक उलटी गिनती है, और यहाँ बताया गया है कि हर एक आपको कितने घंटे देती है

App Store और Google Play का हर रिफंड एक घड़ी शुरू कर देता है, और उनमें से ज़्यादातर आपके बिना ही चलती हैं। Apple की सबसे छोटी रिफंड विंडो 12 घंटे की है, Google की चार्जबैक विंडो 24 घंटे की है, और 3 अगस्त 2026 से एक छूटी हुई चार्जबैक विंडो सिर्फ़ एक खोई बिक्री नहीं, बल्कि एक बिल है। यहाँ हर वह समयसीमा दी गई है जो आपके खाते को छूती है।

Deep diveपढ़ने में 7 मिनट

रद्द की गई खरीद की सूचना आपके Google Play सर्वर को उसी क्षण एक्सेस रद्द करने देती है जब रिफंड आता है

Google Play किसी खरीद के रिफंड होने, चार्जबैक होने या रद्द होने के तुरंत बाद आपके सर्वर को रद्द की गई खरीद की सूचना भेज सकता है। इसमें एक purchaseToken, orderId, productType और refundType होता है, और इसका एक ही मतलब है, एक्सेस रद्द करो। यहाँ बताया गया है कि इसे कैसे पढ़ें और कैसे जोड़ें।

अगला refund अनुरोध पहले ही रास्ते में है.

RefundHalt को उतने समय में सेटअप करें, जितने में आप उस refund के बारे में एक और सपोर्ट ईमेल पढ़ते हैं जिस पर आपत्ति नहीं कर पाए.