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

يمكن لـ Apple عكس عملية استرداد سبق أن وافقت عليها، والاسترداد المعكوس الذي يتجاهله خادمك يحجب عميلًا قد دفع

عندما يعكس App Store عملية استرداد سبق أن وافق عليها، فإنه يتوقع من خادمك أن يعيد الوصول الذي ألغيته. إليك كيف تعمل إشعارات الاسترداد، ورفض الاسترداد، والاسترداد المعكوس على App Store و Google Play، وما تكلفة كل منها عندما تتجاهله.

قفل متوهج على هاتف بجانب كشف حساب بنكي ومفتاح بعيد المنال، يمثّل استردادًا معكوسًا يحجب عميلًا قد دفع

أهم الخلاصات

  • يرسل App Store إشعار REFUND_REVERSED عندما يعكس عملية استرداد سبق أن وافق عليها لأن العميل اعترض عليها، وتعليمات Apple صريحة: إذا كان تطبيقك قد ألغى محتوى أو خدمات، فيلزم إعادتها.
  • يعني إشعار REFUND أن App Store قد استرد المعاملة بالفعل، لذا ينبغي لخادمك إلغاء الاستحقاق. ويعني إشعار REFUND_DECLINED أن Apple قد رفضت الطلب، ويحتفظ العميل بكلٍّ من وصوله والرسوم المفروضة عليه.
  • إذا ألغيت الوصول عند الاسترداد لكنك لم تعالج العكس أبدًا، فإن العميل الذي تُعاد إليه الرسوم يبقى محجوبًا. هذه تذكرة دعم، ومراجعة بنجمة واحدة، وعلى Google Play إحباط قد يتحول إلى ردّ مبالغ (chargeback) يكلّفك المال الآن.
  • يخبرك revocationReason من Apple بسبب حدوث الاسترداد: القيمة value 1 تعني أن Apple استردت بسبب مشكلة فعلية أو متصوَّرة داخل تطبيقك، والقيمة value 0 تعني سببًا آخر مثل عملية شراء عرضية.
  • لا يملك Google Play إشعار عكس. فهو يرسل VoidedPurchaseNotification عند إبطال عملية شراء، ويرسل PendingRefundReviewNotification منفصلًا لردود المبالغ، وتُسوّي الباقي عبر نموذج السحب (pull) في Voided Purchases API.
  • يمنحك Google Play 24 ساعة للرد على PendingRefundReviewNotification باستدعاء orders.reviewrefund، ويسجّل استدعاءك الأول فقط. اعتبارًا من 3 أغسطس 2026، يكلّف ردُّ المبلغ الخاسر المطوّرَ السعرَ ناقصًا رسوم خدمة Google زائدًا رسوم البنك.
  • عالِج إشعارات استرداد App Store بطريقة مُتكافئة (idempotent). فالتسليمات المكرَّرة أمر طبيعي، لذا اربط كل إلغاء وإعادة بمعرّف المعاملة id واجعل الإشعار المتكرر بلا أثر (no-op).

الاسترداد ليس دائمًا الكلمة الأخيرة. يمكن لـ App Store أن يعكس عملية استرداد سبق أن وافق عليها، بعد أن يعترض العميل، وعندما يصل ذلك الاسترداد المعكوس إلى خادمك فإنه يحمل تعليمة واحدة: أعِد الوصول. تربط معظم الفرق إشعار REFUND البسيط، وتقطع الوصول عن العميل، وتتوقف عند ذلك. ولا تبني أبدًا النصف الآخر. لذا عندما يصل العكس، لا يعمل شيء، ويبقى عميل يدفع من جديد محجوبًا عمّا اشتراه. إليك كيف تعمل المجموعة الكاملة من إشعارات الاسترداد على App Store و Google Play، وما تكلفة كل منها عندما تتجاهله.

يرسل App Store ثلاثة إشعارات استرداد، لا واحدًا

تُبنى معظم معالجة الاسترداد لحدث واحد: عاد المال، اقطع الوصول عن العميل. لكن تدفق App Store Server Notifications V2 يحمل في الواقع ثلاث نتائج استرداد منفصلة، وهي تطلب ثلاثة أشياء مختلفة. اثنتان منها تغيّران ما يمكن للعميل الوصول إليه. وواحدة تلغي الأولى. إليك المجموعة الكاملة، بكلمات Apple نفسها.

الإشعارماذا يعنيماذا يفعل خادمك
CONSUMPTION_REQUESTطلب العميل استردادًا وتريد Apple بيانات الاستهلاكأرسل payload الاستهلاك خلال 12 ساعة
REFUNDاسترد App Store المعاملةألغِ استحقاق تلك المعاملة
REFUND_DECLINEDرفض App Store طلب الاستردادلا شيء؛ يحتفظ العميل بالوصول والرسوم
REFUND_REVERSEDعكس App Store استردادًا كان قد وافق عليهأعِد المحتوى أو الخدمة التي ألغيتها

REFUND، الإشعار الذي تعالجه كل فريق

عندما يعالج App Store عملية استرداد، فإنه يرسل إشعار REFUND إلى الـ URL الذي تُهيّئه، وتعريف Apple واضح: إنه 'يشير إلى أن App Store استرد بنجاح معاملةً عن In-App Purchase استهلاكي، أو In-App Purchase غير استهلاكي، أو اشتراك تلقائي التجديد، أو اشتراك غير متجدد.' تخزّن المعاملة المستردة، وتلغي كل ما اشترته، وتطلب منك Apple أن تُعلم العميل بما تغيّر عبر رسائل سياقية داخل التطبيق. هذا هو الإشعار الذي يربطه الجميع أولًا، وغالبًا الوحيد.

REFUND_DECLINED، الإشعار الذي لا يتطلب منك شيئًا

يعني REFUND_DECLINED تمامًا ما يقوله: 'رفض App Store طلب استرداد.' طلب العميل، قالت Apple لا، وتبقى المعاملة قائمة. لا شيء بشأن وصول العميل يتغير، لذا لا يفعل منطق الاستحقاق لديك شيئًا هنا. قيمة هذا الإشعار في مسك الدفاتر. فهو يُغلق حلقة طلب استرداد ربما أجبت عنه بـ CONSUMPTION_REQUEST، ويؤكّد أن العميل ما زال يملك ما دفع مقابله. عامِله كسجل، لا كإجراء.

REFUND_REVERSED، الإشعار الذي يباغت الفرق

هذا هو الإشعار الذي لا تعالجه معظم خطوط أنابيب الاسترداد أبدًا. تعريف Apple لا لبس فيه: REFUND_REVERSED 'يشير إلى أن App Store عكس استردادًا سبق منحه بسبب نزاع أثاره العميل. إذا كان تطبيقك قد ألغى محتوى أو خدمات نتيجة الاسترداد ذي الصلة، فيلزم إعادتها.' اقرأ ذلك مرتين. منحت Apple العميل استردادًا، وألغيت أنت الوصول، ثم قررت Apple أن الاسترداد لا ينبغي أن يبقى وسحبته. الرسوم فعّالة من جديد. دفع العميل، وإذا كان خادمك لا يعرف سوى الإلغاء، فإنه يبقى محجوبًا. الاسترداد المعكوس هو حدث الاسترداد الوحيد الذي يعيد الوصول، وهو الذي لا يبني له أحد تقريبًا.

ما الذي يكلّفك إياه الاسترداد المعكوس فعلًا

العكس الفائت ليس خطأ تقريب. تتبّع المال في كلا الاتجاهين، لأن الخطأ في أيٍّ من النصفين له ثمن.

افـتِ العكس، وتُبقِ عميلًا يدفع محجوبًا. أعادت Apple فرض الرسوم، فصار العميل خاسرًا لماله من جديد، وتطبيقك يحرمه ما اشتراه. التكلفة الفورية هي وقت الدعم واسترداد حسن نية قد تصدره الآن بنفسك، هذه المرة دون عمولة متجر تعود لتخفّفه. أما التكلفة الأبطأ فهي المراجعة وفقدان العملاء، وعلى Google Play فإن إحباط الحجب ذاته هو بالضبط ما يتحول إلى ردّ مبلغ.

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

  • تكلفة الدعم: شخص يرد على تذكرة عن وصول أزالته شيفرتك أنت ولم تُعِده أبدًا.
  • استردادات حسن النية: إعادة المال لعميل حجبته خطأً، دون عمولة متجر تُعاد على بادرة يدوية.
  • إنفاق مهدور: حوسبة، واستدعاءات API، وتخزين يستهلكها حساب مسترد لم تقطعه أبدًا.
  • خطر ردّ المبلغ: على Google Play، يمكن لعميل يشعر بأنه دُفع عليه مرتين أن يعترض، وردّ نزاع خاسر يقع عليك الآن.

الاسترداد المعكوس والاسترداد البسيط هما تدفق webhook نفسه يشير في اتجاهين متعاكسين. عالِج أحدهما وتخطَّ الآخر، فتدفع الثمن عند الطرفين.

يد تسحب إيصالًا ورقيًا عائدةً به عبر المكتب، يمثّل استردادًا معكوسًا يُبطل استرداد App Store الذي سبق أن تصرّف خادمك بناءً عليه

لماذا تعكس Apple عملية استرداد، وكيف تقرأ revocationReason

العكس ليس عشوائيًا. تربطه Apple بـ 'نزاع أثاره العميل'، أي أن العميل يطعن في قرار الاسترداد لاحقًا. عندما مُنح الاسترداد أول مرة، حملت المعاملة revocationDate و revocationReason، وذلك السبب جدير بالقراءة قبل أن يتصرف أي شيء لاحق بناءً عليه.

  • revocationReason 1: استرد App Store 'بسبب مشكلة فعلية أو متصوَّرة داخل تطبيقك.' هذه إشارة عن منتجك، لا عن هذا العميل وحده.
  • revocationReason 0: استرد App Store 'لأسباب أخرى، مثل عملية شراء عرضية.' دون أي إشارة مرفقة عن جودة التطبيق.

عندما يصل REFUND_REVERSED لتلك المعاملة، يجري إلغاء العكس. ينبغي لمنطق الإعادة لديك أن يبحث عن معرّف المعاملة الأصلي id، ويؤكد أنك ألغيتها، ويعيد الاستحقاق تمامًا كما كان.

لا يرسل Google Play عكسًا، لذا تُسوّي بدلًا من ذلك

نموذج Google Play مختلف، والفرق مهم إذا كنت تُشغّل المتجرين عبر معالج webhook واحد. لا يوجد مكافئ لدى Google لـ REFUND_REVERSED. تقسّم إشعارات مطوّري Google الفورية أحداث الاسترداد إلى رسالتين، وتُعالَج العكوس بالتسوية، لا بدفعة (push).

إشعار الشراء المُبطَل

عند إبطال عملية شراء على Google Play، يتلقى خادمك VoidedPurchaseNotification. يذكر purchaseToken و orderId، و productType من نوع subscription أو one-time، و refundType إما إبطال كامل أو استرداد جزئي قائم على الكمية في عمليات الشراء متعددة الكميات. تقول Google إن تلك البيانات كافية للعثور على الشراء الصحيح وضبط الاستحقاق. ولأي شيء أكثر، تحيلك إلى Voided Purchases API، نموذج سحب (pull) يسرد الطلبات المُبطَلة ضمن نطاق طابع زمني تستعلم عنه.

مراجعة ردّ المبلغ، وساعتها ذات الـ 24 ساعة

تأتي ردود المبالغ عبر رسالة مختلفة، PendingRefundReviewNotification. عندما يعترض عميل على رسوم لدى بنكه، يرسل Google Play هذا الإشعار ويبدأ ساعة. لديك 24 ساعة لاستدعاء orders.reviewrefund بتفضيل استرداد وأي دليل استخدام، كي تتمكن Google من الطعن في ردّ مبلغ غير مشروع نيابةً عنك. تسجّل Google استدعاءك الأول وتتجاهل الباقي. هذا هو نظير Google لـ CONSUMPTION_REQUEST من Apple، النافذة الوحيدة التي يُحتسَب فيها جانبك من النزاع.

ولأنه لا توجد دفعة عكس، فإن ردّ مبلغ تطعن فيه Google وتربحه لا يصل كحدث إعادة مرتّب. تُسوّيه مقابل Voided Purchases API وسجلّاتك الخاصة. الدرس هو نفسه على App Store: الطلب المُبطَل ليس دائمًا نهائيًا، وحالة الاستحقاق لديك يجب أن تكون قادرة على التحرك للخلف، لا للأمام فقط.

حدث الاستردادApp StoreGoogle Play
مُنح الاستردادإشعار REFUNDVoidedPurchaseNotification
رُفض الاستردادإشعار REFUND_DECLINEDلا رسالة منفصلة
عُكس الاستردادإشعار REFUND_REVERSEDلا دفعة؛ سوِّ عبر Voided Purchases API
نافذة دليل النزاعCONSUMPTION_REQUEST، 12 ساعةPendingRefundReviewNotification، 24 ساعة
مَن يمكنه إصدار الاستردادApple فقطGoogle، أو أنت من تبويب Orders

كيف تعالج كل إشعار استرداد دون أن تحجب أحدًا

لست بحاجة إلى خطوط أنابيب منفصلة لكل متجر. أنت بحاجة إلى معالج يمكنه تحريك الاستحقاق في كلا الاتجاهين ويعامل كل رسالة على أنها ربما مكرَّرة.

  • ابنِ الإعادة، لا الإلغاء فقط. لكل مسار يزيل الوصول عند REFUND، اكتب عكسه الذي يعيده عند REFUND_REVERSED، مربوطًا بمعرّف المعاملة id نفسه.
  • اجعله متكافئًا (idempotent). يمكن لكلا المتجرين تسليم الإشعار نفسه أكثر من مرة، لذا اربط كل إلغاء وإعادة بمعرّف المعاملة أو الطلب id واجعل التكرار بلا أثر (no-op).
  • اقرأ السبب قبل أن تتصرف. استخدم revocationReason للتمييز بين استرداد يتعلق بجودة التطبيق وآخر عرضي، ووجّه ما يتعلق بجودة التطبيق إلى من يملك جودة المنتج.
  • أجب عن نوافذ الأدلة في الوقت المناسب. أرسل بيانات استهلاك Apple خلال 12 ساعة من CONSUMPTION_REQUEST، واستدعِ orders.reviewrefund خلال 24 ساعة من PendingRefundReviewNotification.
  • خزّن كل حدث. احتفظ بـ REFUND_DECLINED والإشعارات الخام، كي يتسنى مطابقة عكسٍ يصل لاحقًا بالاسترداد الذي يُبطله.

لا شيء من هذا يغيّر ما إذا كان الاسترداد يحدث. بل يغيّر ما إذا كان العميل على الجانب الآخر من استرداد معكوس سيلاحظ يومًا أن خادمك أخطأ.

الأسئلة الشائعة

ما هو إشعار REFUND_REVERSED على App Store؟
هو إخبار App Store لخادمك بأنه عكس استردادًا سبق أن منحه، لأن العميل اعترض عليه. تعليمات Apple صريحة: إذا كان تطبيقك قد ألغى محتوى أو خدمات نتيجة ذلك الاسترداد، فيلزم إعادتها. الرسوم فعّالة من جديد، لذا ينبغي أن يستعيد العميل وصوله.
ماذا ينبغي أن أفعل عندما أتلقى إشعار REFUND_DECLINED؟
لا شيء بشأن وصول العميل. يعني REFUND_DECLINED أن App Store رفض طلب الاسترداد، فتبقى المعاملة قائمة ويحتفظ العميل بما دفع مقابله. عامِله كسجل يُغلق طلب الاسترداد، غالبًا طلبًا أجبت عنه بـ CONSUMPTION_REQUEST.
هل يرسل Google Play إشعارًا عند عكس استرداد أو ردّ مبلغ؟
لا. لا يملك Google Play مكافئًا لـ REFUND_REVERSED من Apple. فهو يرسل VoidedPurchaseNotification عند إبطال عملية شراء و PendingRefundReviewNotification لردود المبالغ، لكن ردّ مبلغ مطعون فيه تربحه Google لا يُدفع إليك عائدًا. تُسوّيه باستخدام Voided Purchases API وسجلّاتك الخاصة.
كم من الوقت لديّ للرد على ردّ مبلغ في Google Play؟
24 ساعة. عندما يرسل Google Play إشعار PendingRefundReviewNotification، لديك 24 ساعة لاستدعاء orders.reviewrefund بتفضيل استرداد ودليل استخدام. تسجّل Google استدعاءك الأول فقط. اعتبارًا من 3 أغسطس 2026، يكلّف ردُّ المبلغ الخاسر المطوّرَ السعرَ ناقصًا رسوم خدمة Google زائدًا رسوم البنك.
ماذا يخبرني revocationReason على معاملة App Store مستردة؟
يخبرك لماذا استردت Apple. القيمة value 1 تعني أن Apple استردت بسبب مشكلة فعلية أو متصوَّرة داخل تطبيقك، وهي إشارة عن المنتج. والقيمة value 0 تعني سببًا آخر، مثل عملية شراء عرضية. قراءته تتيح لك فصل الاستردادات التي تشير إلى خلل (bug) عن الاستردادات الاعتيادية.

المصادر وقراءات إضافية

RefundHalt

الطيار الآلي للاستردادات في App Store وGoogle Play

تابع القراءة

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

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