كل المقالات
Deep diveمدة القراءة 8 دقائق

عندما يُسترَد مبلغ عملية شراء على Google Play أو يحدث ردّ مبالغ، تكون Voided Purchases API هي الطريقة التي تعرف بها ذلك

يُبطِل Google Play عملية الشراء بهدوء عند استرداد مبلغها أو حدوث ردّ مبالغ. إن Voided Purchases API هي قائمة تلك الطلبات، حتى تتمكن من إلغاء الوصول. إليك كل حقل، ونافذة الثلاثين يومًا، وخيار الإلغاء الذي يُخفي الطلبات، وما يكلفه ذلك.

هاتف ذكي بجانب دفتر حسابات ورقي، وقفل نحاسي مغلق، وعملة معدنية تنزلق مبتعدة، تجسّد 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معرّف الطلب الذي يحدّد بشكل فريد عملية شراء لمرة واحدة، أو عملية شراء اشتراك، أو تجديد اشتراك واحد. هذا هو مفتاح الربط لديك
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عملية شراء غير مقصودة، غالبًا جهاز مشترك
5Fraudصنّف Google المعاملة على أنها احتيالية
6Friendly_fraudردّ مبالغ يعترض فيه حامل البطاقة الشرعي على معاملة أجراها بنفسه
7Chargebackعكس بنك العميل الدفعة. نهائي لدى البنك، وتُحتسب عليك الآن
8Unacknowledged_purchaseاسترد Google تلقائيًا مبلغ عملية شراء لم يؤكّدها تطبيقك قط

نافذة الثلاثين يومًا هي الفخ الذي يُفرغ قائمتك

لا تستطيع Voided Purchases API أن تُظهر إلا عمليات الشراء المُبطَلة خلال الثلاثين يومًا الماضية. يكون معامل startTime افتراضيًا الوقت الحالي ناقص 30 يومًا، ولا يمكن ضبطه على أقدم من ذلك. ويكون endTime افتراضيًا الآن. فالـ endpoint إذًا نافذة متحركة مدتها شهر، لا أرشيف.

النتيجة قاطعة. إذا تعطلت مهمة الاستعلام لديك ولم يلاحظ أحد لمدة خمسة أسابيع، فإن حالات الإبطال من الأسبوع الأول قد تقادمت وخرجت من الـ API. لا يوجد اتصال يعيدها. لن تُلغي تلك الطلبات، ولن تعرف حتى أنها وُجدت ما لم تلتقطها بطريقة أخرى ما. إن الـ API شبكة أمان بها ثقب بحجم أسوأ انقطاع خدمة لديك.

خيار الإلغاء يقرّر ما إذا كان الطلب سيظهر أصلًا

هذا هو السبب الأكثر شيوعًا الذي يجعل فريقًا يُبلّغ عن أن الـ API معطّلة. لا تُعاد إلا الطلبات المُلغاة. إن عمليات الاسترداد التي يبدأها المستخدم، والإلغاءات، وردود المبالغ، وعمليات الاسترداد التي يبدأها Google تُلغى دائمًا، لذا تظهر دائمًا. أما الاسترداد الذي يبدأه المطوّر فمختلف. عندما تسترد مبلغ طلب بنفسك، عبر Play Console أو Orders API، تختار ما إذا كنت ستلغيه أيضًا. استرد دون إلغاء، فيُسوّى الطلب مع العميل لكنه لا يظهر أبدًا في Voided Purchases API.

القاعدة التي تتبع ذلك بسيطة. إذا كان قصدك سحب الوصول، فاسترد المبلغ مع تفعيل خيار الإلغاء. وإلا فقد أعدت المال وتركت الباب مفتوحًا، ومهمة الإلغاء لديك، مهما أُحسِن كتابتها، ليس لديها ما تتصرف بشأنه.

كيف تستعلم عنها دون تجاوز الحصة

الـ endpoint محدود المعدل، والحدود منخفضة بما يكفي لأن تصطدم بها حلقة ساذجة. لديك 6,000 استعلام في اليوم، تُحتسب بتوقيت المحيط الهادئ، وما لا يزيد على 30 استعلامًا في أي فترة مدتها 30 ثانية. هذه الميزانية جيدة للاستعلام بالنوافذ ومعادية لتصاميم الطلب الواحد لكل طلب شراء.

نوافذ الاستعلام ورمز المتابعة

يكون maxResults افتراضيًا 1,000، وهو أيضًا الحد الأقصى. عندما تحوي نافذة أكثر من صفحة واحدة من حالات الإبطال، تحمل الاستجابة كائن tokenPagination مع nextPageToken. أعد تمرير ذلك الرمز في الاتصال التالي لتجتاز الصفحات. اضبط startTime و endTime لتحديد النافذة التي تهمّك، وتصفّح الصفحات حتى ينفد الرمز، ثم تقدّم بالنافذة. يُبقيك هذا النمط داخل حدّ الاندفاع لمدة 30 ثانية والحدّ اليومي معًا.

Real-time developer notifications تسدّ الفجوة

لا يزال الاستعلام يوميًا يترك ما يصل إلى يوم من العمى، وتعاقب نافذة الثلاثين يومًا الفجوات الطويلة. تزيل Real-time developer notifications هذا التأخر. ينشر Google إشعار VoidedPurchaseNotification إلى موضوع Cloud Pub/Sub تملكه أنت في اللحظة التي تُبطَل فيها عملية الشراء، ويستهلكه نظامك الخلفي خلال ثوانٍ. الرسالة صغيرة.

حقل RTDNماذا يحمل
purchaseTokenالرمز من عملية الشراء الأصلية
orderIdمعرّف الطلب للمعاملة المُبطَلة، جديد لكل تجديد اشتراك
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 حتى يُعالَج ردّ المبالغ بطريقة مختلفة عن استرداد الندم. استعلِم وفق جدول محكم بما يكفي لئلا تعضّك نافذة الثلاثين يومًا أبدًا، واسترد المبلغ مع تفعيل خيار الإلغاء كلما كان قصدك قطع الوصول.

هذا هو الجزء الذي يشغّله 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

تابع القراءة

طلب الاسترداد التالي في طريقه إليك بالفعل.

أعد RefundHalt في الوقت الذي تستغرقه لقراءة رسالة دعم أخرى عن استرداد لم تتمكن من الاعتراض عليه.