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

जब Google Play की कोई खरीद रिफंड या चार्जबैक होती है, तो Voided Purchases API ही वह जरिया है जिससे आपको पता चलता है

जब कोई खरीद रिफंड या चार्जबैक होती है, तो Google Play उसे चुपचाप रद्द कर देता है। Voided Purchases API उन्हीं ऑर्डरों की सूची है, ताकि आप एक्सेस वापस ले सकें। यहाँ हर फ़ील्ड, 30 दिन की विंडो, वह रिवोक विकल्प जो ऑर्डर छिपा देता है, और इसकी लागत बताई गई है।

एक स्मार्टफ़ोन के बगल में एक कागज़ी बहीखाता, एक बंद पीतल का ताला, और सरककर दूर जाता एक सिक्का, जो Google Play Voided Purchases API को दर्शाते हैं जो रिफंड और चार्जबैक हुए ऑर्डरों की रिपोर्ट देता है

मुख्य बातें

  • Voided Purchases API, यानी purchases.voidedpurchases.list विधि, वे ऑर्डर लौटाती है जिन्हें Google Play ने रद्द, रिफंड या चार्जबैक किया, ताकि आप एक ऐसी रिवोकेशन प्रणाली बना सकें जो उस चीज़ का एक्सेस काट दे जो ग्राहक के पास अब नहीं है।
  • केवल रिवोक किए गए ऑर्डर ही दिखते हैं। रिवोक विकल्प के बिना डेवलपर द्वारा जारी किया गया रिफंड इस API के लिए अदृश्य होता है, इसलिए यदि आप एक्सेस वापस लेना चाहते हैं, तो आपको रिवोक चालू रखकर रिफंड करना होगा।
  • विंडो 30 दिन की है। startTime को 30 दिन पहले से पुराना नहीं रखा जा सकता, इसलिए एक महीने से ज़्यादा बंद रहने वाला सर्वर उन रद्द किए गए ऑर्डरों को हमेशा के लिए खो देता है। एक तय समय पर पोल करें।
  • voidedSource आपको बताता है कि ऑर्डर किसने रद्द किया: 0 यूज़र है, 1 डेवलपर है, 2 Google है। voidedReason आपको कारण बताता है, 0 Other से लेकर 7 Chargeback और 8 Unacknowledged_purchase तक।
  • Real-time developer notifications उसी क्षण एक VoidedPurchaseNotification भेजती हैं जब कोई खरीद रद्द होती है, पर इसे एक संकेत मानें। रिवोक करने से पहले आधिकारिक सूची के लिए Voided Purchases API को कॉल करें।
  • सब्सक्रिप्शन रिन्युअल की पहचान orderId से करें, purchaseToken से नहीं। एक purchaseToken किसी सब्सक्रिप्शन के हर रिन्युअल को कवर करता है, इसलिए अकेला टोकन दो रिन्युअल में फ़र्क नहीं बता सकता।
  • कोटा प्रतिदिन 6,000 क्वेरी और किसी भी 30-सेकंड विंडो में 30 क्वेरी है, इसलिए कंटिन्यूएशन टोकन से नतीजों के पन्ने पलटें और समय-विंडो के हिसाब से क्वेरी करें, हर ऑर्डर पर एक कॉल कभी न करें।

Google Play पर रिफंड आपके दरवाज़े पर दस्तक नहीं देता। पैसा चला जाता है, ग्राहक ऐप खुला रखता है, और जब तक आप खुद जाकर न देखें, आपकी तरफ़ कुछ नहीं बदलता। Voided Purchases API वही जगह है जहाँ आप जाकर देखते हैं। यह आपको उन ऑर्डरों की एक सूची देती है जो रद्द, रिफंड या चार्जबैक हुए, ताकि आप उस चीज़ का एक्सेस वापस ले सकें जिसके लिए ग्राहक अब भुगतान नहीं कर रहा। इस पर एक निर्धारित जॉब लगाएँ, सूची पढ़ें, एनटाइटलमेंट काट दें। बस यही पूरा चक्र है।

एक पेच है जिसमें ज़्यादातर टीमें फँसती हैं, और वह कोड में नहीं है। यहाँ केवल वे ऑर्डर दिखते हैं जो रिवोक किए गए थे। अगर आप Play Console में किसी खरीद को रिफंड करते हैं और रिवोक विकल्प पर निशान नहीं लगाते, तो वह ऑर्डर कभी इस API तक नहीं पहुँचता, और आपकी जॉब साफ़-सुथरी चलती रहती है जबकि एक रिफंड पाया ग्राहक वह सब कुछ रखे रहता है जो आपने बेचा था। यह पोस्ट इस API को फ़ील्ड दर फ़ील्ड, इसे सीमित करने वाले आँकड़ों, और जहाँ से पैसा रिसता है जब आप इसे छोड़ देते हैं, समझाती है।

Voided Purchases API असल में क्या लौटाती है

यह API एक ही सवाल का जवाब देती है: इस ऐप के कौन-से ऑर्डर हाल ही में रद्द हुए। एक वॉइड तीन नतीजों को कवर करता है जो सभी ग्राहक के पैसे वापस पाने पर ख़त्म होते हैं। एक रद्दीकरण, एक रिफंड, या एक चार्जबैक। यह एक-बार वाले इन-ऐप उत्पादों और सब्सक्रिप्शनों पर लागू होता है, और आप एक ही पैरामीटर से दायरा चुनते हैं। type को 0 पर रखें और आपको केवल रद्द किए गए इन-ऐप उत्पाद खरीद मिलते हैं, जो डिफ़ॉल्ट है। इसे 1 पर रखें और आपको रद्द किए गए इन-ऐप खरीद और रद्द किए गए सब्सक्रिप्शन खरीद एक साथ मिलते हैं।

सूची में हर प्रविष्टि एक रद्द की गई खरीद ऑब्जेक्ट है। फ़ील्ड कम हैं और उनमें से हर एक मायने रखता है।

एक रद्द की गई खरीद पर फ़ील्ड

फ़ील्डयह क्या रखता है
orderIdवह ऑर्डर id जो किसी एक-बार वाली खरीद, सब्सक्रिप्शन खरीद, या किसी एकल सब्सक्रिप्शन रिन्युअल की विशिष्ट पहचान करता है। यही आपकी जॉइन कुंजी है
purchaseTokenवह टोकन जो एक-बार वाली खरीद या एक सब्सक्रिप्शन की पहचान करता है। यह रिन्युअल में फ़र्क नहीं करता, इसलिए उनके लिए orderId का इस्तेमाल करें
purchaseTimeMillisखरीद कब हुई, युग से मिलीसेकंड में
voidedTimeMillisखरीद कब रद्द, रिफंड या चार्जबैक हुई, युग से मिलीसेकंड में
voidedSourceवॉइड किसने शुरू किया: 0 यूज़र, 1 डेवलपर, 2 Google
voidedReasonखरीद क्यों रद्द हुई, 0 से 8 तक का एक पूर्णांक
voidedQuantityमात्रा-आधारित आंशिक रिफंड से रद्द की गई मात्रा, केवल तभी लौटाई जाती है जब includeQuantityBasedPartialRefund true हो

कार्रवाई करने से पहले voidedReason पढ़ें

voidedReason वह फ़ील्ड है जो एक कच्ची सूची को एक फ़ैसले में बदल देता है। खरीदार के पछतावे का रिफंड और बैंक का चार्जबैक दोनों एक ही सूची में आते हैं, पर वे एक ही घटना नहीं हैं, और अगस्त की क़ीमतें उनमें से एक को महँगा बना देती हैं। यहाँ पूरा सेट है।

voidedReasonलेबलयह आपके लिए क्या मायने रखता है
0Otherकोई श्रेणी नहीं सौंपी गई। रिवोक करें और आगे बढ़ें
1Remorseखरीदार ने अपना मन बदल लिया। एक सामान्य रिफंड
2Not_receivedग्राहक कहता है कि उसे उत्पाद कभी नहीं मिला। अपनी डिलीवरी जाँचना उचित है
3Defectiveउत्पाद ने काम नहीं किया। एक गुणवत्ता संकेत, इसे लॉग करें
4Accidental_purchaseएक अनचाही खरीद, अक्सर एक साझा डिवाइस
5FraudGoogle ने लेनदेन को धोखाधड़ी के रूप में चिह्नित किया
6Friendly_fraudएक चार्जबैक जहाँ वैध कार्डधारक अपनी ही की गई एक खरीद पर विवाद करता है
7Chargebackग्राहक के बैंक ने भुगतान पलट दिया। बैंक के स्तर पर अंतिम, और अब आप पर बिल किया गया
8Unacknowledged_purchaseGoogle ने एक ऐसी खरीद अपने आप रिफंड कर दी जिसे आपके ऐप ने कभी स्वीकार नहीं किया

30 दिन की विंडो वह जाल है जो आपकी सूची खाली कर देता है

Voided Purchases API केवल पिछले 30 दिनों की रद्द की गई खरीद ही दिखा सकती है। startTime पैरामीटर डिफ़ॉल्ट रूप से मौजूदा समय घटा 30 दिन होता है, और इसे उससे पुराना नहीं रखा जा सकता। endTime डिफ़ॉल्ट रूप से अभी होता है। तो यह endpoint एक चलती हुई एक-महीने की विंडो है, कोई संग्रह नहीं।

नतीजा साफ़ है। अगर आपकी पोलिंग जॉब टूट जाती है और पाँच हफ़्तों तक किसी का ध्यान नहीं जाता, तो पहले हफ़्ते के वॉइड API में पुराने होकर हट चुके होते हैं। कोई कॉल उन्हें वापस नहीं लाती। आप उन ऑर्डरों को रिवोक नहीं करेंगे, और आपको यह भी पता नहीं चलेगा कि वे मौजूद थे, जब तक कि आपने उन्हें किसी और तरीके से कैप्चर न किया हो। यह API एक ऐसी सुरक्षा-जाली है जिसमें एक छेद है जिसका आकार आपकी सबसे बुरी बंदी जितना है।

रिवोक विकल्प तय करता है कि कोई ऑर्डर दिखेगा भी या नहीं

यह सबसे आम वजह है जिसके चलते कोई टीम इस API को ख़राब बताती है। केवल रिवोक किए गए ऑर्डर ही लौटाए जाते हैं। यूज़र द्वारा शुरू किए गए रिफंड, रद्दीकरण, चार्जबैक, और Google द्वारा शुरू किए गए रिफंड हमेशा रिवोक होते हैं, इसलिए वे हमेशा दिखते हैं। डेवलपर द्वारा शुरू किया गया रिफंड अलग है। जब आप खुद Play Console या Orders API के ज़रिए किसी ऑर्डर को रिफंड करते हैं, तो आप चुनते हैं कि उसे रिवोक भी करना है या नहीं। रिवोक किए बिना रिफंड करें, और ऑर्डर ग्राहक के साथ निपट जाता है पर कभी Voided Purchases API में नहीं आता।

जो नियम इससे बनता है वह सरल है। अगर आपका इरादा एक्सेस वापस लेना है, तो रिवोक विकल्प चालू रखकर रिफंड करें। वरना आपने पैसा वापस दे दिया और दरवाज़ा खुला छोड़ दिया, और आपकी रिवोकेशन जॉब, चाहे कितनी भी अच्छी लिखी हो, के पास काम करने को कुछ नहीं है।

कोटा से टकराए बिना इसे कैसे पोल करें

यह endpoint रेट-लिमिटेड है, और सीमाएँ इतनी कम हैं कि एक भोला-भाला लूप इनसे टकरा जाएगा। आपको प्रतिदिन 6,000 क्वेरी मिलती हैं, जो पैसिफ़िक टाइम में गिनी जाती हैं, और किसी भी 30-सेकंड अवधि में 30 से ज़्यादा क्वेरी नहीं। यह बजट विंडो-आधारित पोलिंग के लिए ठीक है और हर ऑर्डर पर एक अनुरोध वाली डिज़ाइनों के लिए प्रतिकूल है।

क्वेरी विंडो और कंटिन्यूएशन टोकन

maxResults डिफ़ॉल्ट रूप से 1,000 होता है, जो अधिकतम सीमा भी है। जब एक विंडो में वॉइड का एक से ज़्यादा पन्ना होता है, तो प्रतिक्रिया एक nextPageToken वाला tokenPagination ऑब्जेक्ट लाती है। अगली कॉल पर उस टोकन को वापस भेजें ताकि पन्ने चले जा सकें। जिस विंडो की आपको परवाह है उसे सीमित करने के लिए startTime और endTime सेट करें, टोकन ख़त्म होने तक पन्ने पलटें, फिर विंडो आगे बढ़ाएँ। यह तरीका आपको 30-सेकंड बर्स्ट सीमा और दैनिक सीमा, दोनों के भीतर रखता है।

Real-time developer notifications खाई को पाट देती हैं

रोज़ पोल करना फिर भी एक दिन तक की अंधता छोड़ देता है, और 30 दिन की विंडो लंबे अंतरालों को दंडित करती है। Real-time developer notifications इस देरी को हटा देती हैं। जिस क्षण कोई खरीद रद्द होती है, Google एक VoidedPurchaseNotification को आपके अपने एक Cloud Pub/Sub टॉपिक पर प्रकाशित करता है, और आपका बैकएंड इसे कुछ सेकंडों में उपभोग कर लेता है। संदेश छोटा है।

RTDN फ़ील्डयह क्या रखता है
purchaseTokenमूल खरीद का टोकन
orderIdरद्द किए गए लेनदेन का ऑर्डर id, हर सब्सक्रिप्शन रिन्युअल पर एक नया
productType1 एक सब्सक्रिप्शन के लिए, 2 एक-बार वाली खरीद के लिए
refundType1 पूर्ण रिफंड के लिए, 2 मात्रा-आधारित आंशिक रिफंड के लिए
एक हाथ एक स्मार्टफ़ोन के बगल में रसीदों के ढेर पर एक पीतल का ताला बंद कर रहा है, जो Google Play की किसी खरीद के रद्द होने के बाद एक्सेस वापस लेने को दर्शाता है

यह आपको पैसे में क्या पड़ता है

यह API नलसाज़ी है, पर इसे जोड़ने की वजह एक बिल है। उस सूची में हर वॉइड एक असली आँकड़े से मेल खाता है, और उनमें से दो और महँगे होते जा रहे हैं।

चार्जबैक का बिल 3 अगस्त 2026 से आप पर आ पड़ता है

3 अगस्त 2026 से, Google एक चार्जबैक की लागत डेवलपर पर डाल देता है। आप खरीद क़ीमत खोते हैं और उसके ऊपर बैंक का चार्जबैक शुल्क भी भरते हैं। voidedReason का 7 होना अब केवल एक खोई हुई बिक्री नहीं रहा, यह एक ऐसी मद है जिसके साथ एक शुल्क जुड़ा है। आप एक चार्जबैक को पलट नहीं सकते, यह बैंक के स्तर पर अंतिम है, पर आप उसके बाद रक्तस्राव रोक सकते हैं। वॉइड को जल्दी पकड़ना आपको एनटाइटलमेंट रिवोक करने देता है और, जो कुछ भी आप अब भी दे रहे हैं उसके लिए, एक ऐसे ग्राहक पर ख़र्च करना बंद करने देता है जिसे रिफंड मिला और फिर उसने पलट दिया।

आप एक रिफंड पाए ग्राहक की सेवा के लिए भुगतान करते रहते हैं

जिस क्षण एक वॉइड दिखता है, खरीद क़ीमत चली जाती है। जो अब भी आपके नियंत्रण में है वह है देते रहने की लागत। हर घंटे जब एक रिफंड पाया एनटाइटलमेंट जीवित रहता है, आप उन चीज़ों के लिए भुगतान करते रहते हैं जिन्हें ग्राहक अब वित्त नहीं देता: कंप्यूट, मॉडल API कॉल, स्टोरेज, और उसके उपयोग से जुड़ा कोई भी क्रिएटर या पार्टनर भुगतान। इस API से चलने वाली एक रिवोकेशन प्रणाली ही वह तरीका है जिससे आप उस मीटर को बंद करते हैं। इसे छोड़ दें, और आप उन लोगों के लिए उत्पाद को वित्त देते हैं जिन्हें स्टोर पहले ही भरपाई कर चुका है।

फ़्रेंडली फ़्रॉड एक ऐसा पैटर्न है जिसका रुझान देखना उचित है

voidedReason का 5 या 6 होना कोई एक-बार की बात नहीं। धोखाधड़ी और फ़्रेंडली फ़्रॉड खाते के हिसाब से, डिवाइस के हिसाब से, और कभी-कभी प्रोमोशन के हिसाब से गुच्छे में आते हैं। यह API हर वॉइड पर आपको voidedSource और voidedReason देती है, जो हर पलटाव को एक अलग-थलग लागत मानने के बजाय खाते के हिसाब से दुरुपयोग का रुझान देखने के लिए काफ़ी है। दो बार चार्जबैक करने वाला एक ग्राहक आपको कुछ ऐसा बता रहा है जो पहला रिफंड नहीं बता पाया।

इसे RefundHalt के तरीके से जोड़ना

एक बार जब आप सारे टुकड़े थाम लेते हैं तो यह मॉडल छोटा है। VoidedPurchaseNotification को रीयल टाइम में सुनें ताकि कोई भी चीज़ पूरे दिन इंतज़ार न करे। सच्चाई के स्रोत के रूप में Voided Purchases API को कॉल करें, orderId पर कुंजीबद्ध ताकि सब्सक्रिप्शन रिन्युअल कभी न उलझें। voidedSource और voidedReason पढ़ें ताकि एक चार्जबैक को एक पछतावे के रिफंड से अलग तरीके से संभाला जाए। एक इतने कसे हुए तय समय पर पोल करें कि 30 दिन की विंडो कभी न काटे, और जब भी आपका इरादा एक्सेस काटना हो, रिवोक विकल्प चालू रखकर रिफंड करें।

यह वह हिस्सा है जो RefundHalt आपके लिए चलाता है। यह रीयल-टाइम नोटिफ़िकेशन उपभोग करता है, हर वॉइड का API से मिलान करता है, पूरे उत्पाद के बजाय ठीक उसी ऑर्डर को रिवोक करता है, और एक बैंक चार्जबैक को एक सामान्य रिफंड से अलग करता है ताकि महँगे वाले चिह्नित हों, दबे नहीं। आपको सेकंडों में एक्सेस रिवोक मिलता है और एक रिकॉर्ड कि किसने क्या और क्यों रद्द किया, बिना खुद एक Pub/Sub पाइपलाइन और एक पोलिंग जॉब खड़ी किए।

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

मेरे रिफंड किए गए ऑर्डर Voided Purchases API में क्यों नहीं दिख रहे?
क्योंकि केवल रिवोक किए गए ऑर्डर ही लौटाए जाते हैं। यूज़र रिफंड, रद्दीकरण, चार्जबैक, और Google द्वारा शुरू किए गए रिफंड हमेशा रिवोक होते हैं और हमेशा दिखते हैं। डेवलपर द्वारा शुरू किया गया रिफंड केवल तभी दिखता है जब आपने रिवोक विकल्प भी चुना हो। अगर आपने किसी ऑर्डर को रिवोक किए बिना रिफंड किया, तो ऑर्डर निपट गया पर इस API के लिए अदृश्य है, इसलिए जब भी आपका इरादा एक्सेस वापस लेना हो, रिवोक चालू रखकर रिफंड करें।
Voided Purchases API कितना पीछे तक जाती है?
तीस दिन। startTime पैरामीटर डिफ़ॉल्ट रूप से मौजूदा समय घटा 30 दिन होता है और इसे उससे पुराना नहीं रखा जा सकता, इसलिए यह endpoint एक संग्रह के बजाय एक चलती हुई एक-महीने की विंडो है। एक वॉइड किया गया ऑर्डर जो 30 दिन से पुराना हो जाता है वह API से चला जाता है और उसे वापस पाने का कोई तरीका नहीं, यही वजह है कि आप एक तय समय पर पोल करते हैं और उसे रीयल-टाइम नोटिफ़िकेशन से सहारा देते हैं।
एक्सेस रिवोक करने के लिए मुझे Real-time developer notifications का इस्तेमाल करना चाहिए या Voided Purchases API का?
दोनों का इस्तेमाल करें। VoidedPurchaseNotification कुछ सेकंडों में आ जाती है और आपको देखने को कहती है, पर Google का अपना मार्गदर्शन इसे एक संकेत मानने का है, सच्चाई का स्रोत नहीं। मौजूदा स्थिति की पुष्टि के लिए Voided Purchases API को कॉल करें, फिर रिवोक करें। नोटिफ़िकेशन देरी हटा देती है, और API आपको काम करने के लिए आधिकारिक voidedSource और voidedReason देती है।
मैं API में एक चार्जबैक को एक सामान्य रिफंड से कैसे पहचानूँ?
voidedReason फ़ील्ड पढ़ें। 7 का मान एक चार्जबैक है, यानी ग्राहक के बैंक ने भुगतान पलट दिया, और 6 फ़्रेंडली फ़्रॉड है। 1 का मान एक पछतावे का रिफंड है। यह मायने रखता है क्योंकि 3 अगस्त 2026 से Google चार्जबैक की खरीद क़ीमत और बैंक शुल्क डेवलपर पर डालता है, इसलिए voidedReason का 7 होना आपको एक सादे रिफंड से ज़्यादा पड़ता है।
क्या Voided Purchases API सब्सक्रिप्शन को कवर करती है?
हाँ। type पैरामीटर को 1 पर सेट करें ताकि रद्द किए गए इन-ऐप खरीद और रद्द किए गए सब्सक्रिप्शन खरीद दोनों मिलें। डिफ़ॉल्ट, type 0, केवल इन-ऐप उत्पाद खरीद लौटाता है। सब्सक्रिप्शन के लिए, ठीक उस रद्द की गई अवधि की पहचान orderId से करें, क्योंकि एक purchaseToken हर रिन्युअल को कवर करता है और हर रिन्युअल लेनदेन के लिए एक नया orderId बनता है।

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

RefundHalt

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

आगे पढ़ें

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

Apple के फैसला लेने के बाद तीन App Store रिफंड नोटिफिकेशन आते हैं, और REFUND_REVERSED बिक्री वापस दे देता है

Apple App Store Server Notifications V2 के जरिए चार रिफंड संदेश भेजता है, और ज्यादातर ऐप्स केवल दो को संभालते हैं। REFUND आपको एक्सेस रद्द करने को कहता है, REFUND_DECLINED का मतलब है बिक्री रखें, और REFUND_REVERSED बिक्री वापस सौंप देता है और आपसे जो लिया था उसे बहाल करने को कहता है। यहाँ बताया गया है कि हर एक के लिए क्या जरूरी है।

गहन विश्लेषणपढ़ने में 7 मिनट

अब हर Apple रिफंड अनुरोध एक कारण के साथ आता है, और उसे पढ़ने का तरीका consumptionRequestReason है

WWDC24 के बाद से, हर Apple CONSUMPTION_REQUEST एक consumptionRequestReason ले जाता है, यानी रिफंड चाहने के लिए ग्राहक का खुद बताया गया कारण। इसके पाँच मान हैं, UNINTENDED_PURCHASE से LEGAL तक, और हर एक को आपकी 12 घंटे की विंडो के भीतर आपके भेजे जाने वाले जवाब को बदलना चाहिए। यहाँ बताया गया है कि हर एक को कैसे पढ़ें।

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

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