كل المقالات
دليل عمليمدة القراءة 9 دقائق

إشعارات الاسترداد الفائتة قد تُفقدك الطلبات الوحيدة التي يحق لك الاعتراض عليها، والمتجران كلاهما يتيحان استعادتها إن بحثت في الوقت المناسب

عندما يفوت خادمك إشعار استرداد، يُغلق مسارا الاسترداد اللذان يطلبان أدلتك دون مشاركتك. إليك كيف تعيد Apple وGoogle Play محاولة الإرسال، وإلى أي مدى زمني يمكنك استعادة إشعارات الاسترداد الفائتة، وأين توجد الثغرات في الاستعادة.

رف خوادم ليلًا تضيء فيه لمبة تحذير كهرمانية واحدة بين لمبات خضراء ثابتة، وأمامه حاسوب محمول على عربة، وهو نوع الانقطاع الهادئ الذي يقف وراء إشعارات الاسترداد الفائتة

أهم الخلاصات

  • تعيد Apple محاولة تسليم إشعار App Store Server Notifications V2 الفاشل خمس مرات، بعد 1 و12 و24 و48 و72 ساعة من المحاولة السابقة، لذا تصل المحاولة الثانية بعد نحو 13 ساعة من المحاولة الأولى.
  • تطلب Apple من المطورين الرد على CONSUMPTION_REQUEST خلال 12 ساعة من استلامه، لذا فإن الخادم الذي يفوته التسليم الأول وإعادة المحاولة بعد ساعة قد لا يرى الطلب إلا بعد أن تكون تلك المهلة قد انقضت على الأرجح.
  • تعيد نقطة النهاية Get Notification History من Apple إشعارات V2 الخاصة بآخر 180 يومًا في بيئة الإنتاج، بواقع 20 سجلًا في الصفحة، ويقصر خيار onlyFailures النتائج على الإشعارات التي لم تصل إلى خادمك قط، إضافة إلى ما لا يزال قيد إعادة المحاولة.
  • لا يرسل Google Play مراجعات رد المبالغ المدفوعة إلا عبر PendingRefundReviewNotification، ويأتي في هذا الإشعار pendingRefundToken اللازم لاستدعاء orders.reviewrefund خلال 24 ساعة. ولا توثّق Google أي واجهة برمجة منفصلة تسرد المراجعات المعلقة.
  • يحتفظ Google Cloud Pub/Sub بالرسائل غير المؤكَّد استلامها 7 أيام افتراضيًا، وبحد أقصى 31 يومًا، ويحذف الاشتراك بعد 31 يومًا من دون نشاط من المشترك ما لم تغيّر مدة انتهاء صلاحيته.
  • تستعيد واجهة Voided Purchases API في Google Play عمليات الاسترداد والإلغاء ورد المبالغ المدفوعة لآخر 30 يومًا، بحصة قدرها 6,000 استعلام يوميًا و30 استعلامًا في أي فترة مدتها 30 ثانية، لكنها لا تستطيع استعادة مراجعة رد مبالغ لم تُجب عنها قط.
  • ترسل بيئة sandbox من Apple كل إشعار مرة واحدة دون أي إعادة محاولة، لذا فإن روتين الاستعادة الذي لم يعمل إلا على sandbox لم يُختبر قط مع جدول إعادة المحاولة الحقيقي لدى Apple.

إشعارات الاسترداد الفائتة هي الطريقة الصامتة التي يخسر بها المطور القرارين الوحيدين في الاسترداد اللذين يكون له فيهما رأي. يبدأ كل من CONSUMPTION_REQUEST لدى Apple ومراجعة رد المبالغ المدفوعة لدى Google Play بإشعار، وكلاهما يُغلق خلال مهلة قصيرة: 12 ساعة لدى Apple و24 ساعة لدى Google. إذا كان خادمك متوقفًا أو بطيئًا أو مضبوطًا بشكل خاطئ عند وصول تلك الرسالة، فلن ينتظرك المتجر. سيقرر بما لديه من معلومات.

الخبر الجيد أن أيًّا من المتجرين لا يتخلص من الرسالة عند أول فشل. تعيد Apple المحاولة وتحتفظ بسجل لمدة 180 يومًا يمكنك الاستعلام عنه. وتنشر Google عبر Pub/Sub الذي يحتفظ بالرسائل غير المؤكَّد استلامها لعدة أيام. أما الخبر السيئ فهو أن توقيت إعادة المحاولة لا يتوافق مع مهل الرد، وأن أحد المسارين لا يملك أي واجهة برمجة للاستعادة على الإطلاق.

كيف يسلّم كل متجر إشعارات الاسترداد

ترسل Apple إشعارات App Store Server Notifications مباشرة إلى عنوان HTTPS تحدده في App Store Connect. أما Google فلا تستدعي خادمك مباشرة. بل تنشر Real-time developer notifications في topic على Google Cloud Pub/Sub، واشتراكك في ذلك الـ topic إما يدفعها إلى نقطة النهاية لديك أو ينتظر أن يسحبها خادمك.

السؤالApp StoreGoogle Play
قناة التسليمطلب HTTPS POST إلى عنوانكtopic على Cloud Pub/Sub، دفع أو سحب
ما يُعدّ نجاحًاHTTP من 200 إلى 206تأكيد استلام رسالة Pub/Sub، أو رمز نجاح من نقطة نهاية الدفع
إعادة المحاولة5 مرات في V2، بعد 1 و12 و24 و48 و72 ساعة من المحاولة السابقةيعيد Pub/Sub التسليم حتى تأكيد الاستلام أو انتهاء مدة الاحتفاظ
مدة بقاء الرسالة الفائتة180 يومًا في Get Notification History7 أيام افتراضيًا في الاشتراك، حتى 31 يومًا
الاسترداد الذي يطلب أدلتكCONSUMPTION_REQUEST، الرد خلال 12 ساعةPendingRefundReviewNotification، الرد خلال 24 ساعة
نسخة احتياطية بالسحب للاستردادات المقبولةGet Notification History وGet Refund HistoryVoided Purchases API، آخر 30 يومًا
سلوك sandbox أو الاختبارمحاولة واحدة، دون إعادة محاولةSend Test Message من Play Console

ما تعدّه Apple فشلًا

وثائق Apple واضحة. أعد أي حالة من 200 إلى 206 ويكتمل التسليم. أعد 40x أو 50x وستعيد Apple المحاولة. وتعدّ Apple أي رمز آخر غير ناجح أيضًا. تُسجَّل كل محاولة مع قيمة sendAttemptResult، وتبدو قيمها كقائمة تحقق لانقطاعات حقيقية: TIMED_OUT وTLS_ISSUE وCIRCULAR_REDIRECT وNO_RESPONSE وPREMATURE_CLOSE وUNSUCCESSFUL_HTTP_RESPONSE_CODE وغيرها. وبالنسبة إلى TIMED_OUT، تنصح Apple بالتحقق من أن خادمك لا يعالج الرسائل قبل الرد عليها.

ما تعدّه Google فشلًا

في اشتراك الدفع، يكون رمز النجاح من نقطة النهاية لديك هو تأكيد الاستلام. وفي اشتراك السحب، يجب على خادمك تأكيد استلام كل رسالة يسحبها، وإلا سيسلّمها Pub/Sub مرة أخرى. المهلة الافتراضية لتأكيد الاستلام 10 ثوانٍ والحد الأقصى 600 ثانية. ويضيف دليل RTDN من Google قاعدة أخرى تستحق التكرار: الإشعار يقول فقط إن شيئًا ما تغيّر، لذا ما زلت بحاجة إلى استدعاء Google Play Developer API لمعرفة حالة الشراء كاملة.

لماذا لا يتوافق جدول إعادة المحاولة لدى Apple مع مهلة الـ 12 ساعة

تُحسب فترات إعادة المحاولة لدى Apple من المحاولة السابقة، لا من المحاولة الأولى. اجمعها وستحصل على هذا الجدول الزمني لإشعار V2 واحد يستمر خادمك في الفشل في استلامه.

المحاولةالانتظار بعد المحاولة السابقةالساعات منذ المحاولة الأولى
التسليم الأوللا شيء0
إعادة المحاولة 1ساعة واحدة1
إعادة المحاولة 212 ساعة13
إعادة المحاولة 324 ساعة37
إعادة المحاولة 448 ساعة85
إعادة المحاولة 572 ساعة157

تطلب منك Apple الرد خلال 12 ساعة من استلام CONSUMPTION_REQUEST. إذا كان خادمك متوقفًا عند التسليم الأول وعند إعادة المحاولة بعد ساعة، فإن المحاولة التالية تصل بعد 13 ساعة من الأولى. ولا تقول Apple ما إذا كان الطلب الذي يُستلم لأول مرة في إعادة محاولة يحصل على 12 ساعة جديدة. والقراءة الحذرة هي اعتبار المحاولة الأولى بداية المهلة، ما يعني أن إعادة المحاولة وحدها لن تنقذ طلبًا فاتك لأكثر من ساعة.

هل تعيد Apple المحاولة بعد HTTP 400؟

نعم، وفقًا للوثائق. تذكر Apple أن الرموز 40x و50x هي التي تؤدي إلى إعادة المحاولة. في مارس 2026 أفاد مطور في منتديات Apple بأن إعادة المحاولة بعد ردود 400 بدت وكأنها توقفت، ثم قال إن التسليم استؤنف بعد يوم أو يومين، وطلبت Apple تقريرًا عبر Feedback Assistant. اعتبر السلوك الموثّق هو القاعدة، ومراقبتك الخاصة هي الدليل.

استعد إشعارات App Store الفائتة باستخدام Get Notification History

تعيد Get Notification History إشعارات الإصدار 2 التي حاولت Apple إرسالها إلى خادمك في فترة زمنية تختارها. يحمل كل سجل الحمولة الموقّعة كاملة، لذا يمكنك تمريرها إلى المعالج نفسه الذي يعالج الإشعارات الحية. ويتضمن كل سجل أيضًا مصفوفة sendAttempts تضم حتى ست إدخالات، واحد للمحاولة الأولى وواحد لكل من إعادات المحاولة الخمس.

  • الحقلان startDate وendDate مطلوبان، ويجب أن يقع startDate ضمن آخر 180 يومًا في الإنتاج أو آخر 30 يومًا في sandbox.
  • اضبط onlyFailures على true لتحصل فقط على الإشعارات التي لم تصل إلى خادمك، إضافة إلى ما لا تزال Apple تعيد محاولة إرساله.
  • رشّح حسب notificationType واحد، مثل CONSUMPTION_REQUEST أو REFUND، أو حسب transactionId لعميل واحد، لكن ليس كليهما في الطلب نفسه.
  • يعيد كل استدعاء حتى 20 سجلًا. واصل الاستدعاء باستخدام paginationToken ما دامت قيمة hasMore هي true، وأرسل جسم الطلب نفسه في كل مرة.

هناك تنبيه واحد مهم بالنسبة إلى الاستردادات. تقول Apple إن سجلات التاريخ تعكس حالة الشراء عند إرسال الإشعار أول مرة، لا حالته الآن. لذا فإن REFUND المستعاد حقيقة عن الماضي. قبل أن تسحب الوصول، تحقق من الحالة الحالية عبر نقاط نهاية حالة المعاملة أو الاشتراك.

لا يمكن استعادة إشعارات V1 بهذه الطريقة

لا تغطي Get Notification History إلا الإصدار 2. تعيد Apple محاولة إرسال إشعارات V1 ثلاث مرات، بعد 6 و24 و48 ساعة من المحاولة السابقة، وإذا فشلت جميعها فلا يوجد سجل يمكن إعادة تشغيله. وهذا سبب إضافي لنقل أي تطبيق لا يزال على V1 إلى V2.

استعد إشعارات الاسترداد الفائتة في Google Play

شبكة الأمان لدى Google هي Pub/Sub نفسه. ما دام اشتراكك موجودًا، تبقى الرسالة التي لم يؤكد أحد استلامها هناك طوال مدة الاحتفاظ، 7 أيام افتراضيًا وحتى 31 يومًا إذا رفعتها. وعندما تعود نقطة النهاية لديك، يُستأنف التسليم. لكن هناك إعدادين قد يُبطلان ذلك بصمت.

  • ينقل dead-letter topic الرسالة خارج اشتراكك بعد عدد محدد من محاولات التسليم الفاشلة. العدد الافتراضي 5، ومع سياسة إعادة المحاولة الافتراضية القائمة على إعادة التسليم الفوري، قد تمر خمس محاولات بسرعة. إذا كنت تستخدمه، فراقب dead-letter topic كأنه صندوق بريد ثانٍ.
  • الاشتراك الذي لا يشهد أي نشاط من المشترك، مثل الاتصالات المفتوحة أو عمليات السحب النشطة أو عمليات الدفع الناجحة، تنتهي صلاحيته بعد 31 يومًا افتراضيًا. ونقطة النهاية التي تبقى معطلة شهرًا كاملًا قد تفقد الاشتراك نفسه، ومعه كل ما ينتظر فيه.

للاستردادات الملغاة نسخة احتياطية لمدة 30 يومًا

بالنسبة إلى الاستردادات التي حدثت بالفعل، تمثل Voided Purchases API النسخة الاحتياطية القائمة على السحب. فهي تسرد عمليات الشراء الملغاة من آخر 30 يومًا، حتى 1,000 في الصفحة، بحصة قدرها 6,000 استعلام يوميًا و30 استعلامًا في أي فترة مدتها 30 ثانية لكل تطبيق. مرّر type 1 لتضمين الاشتراكات إلى جانب المنتجات لمرة واحدة. تشغيلها يوميًا يلتقط أي استرداد أسقطه مسار الإشعارات لديك، فتبقى الاستحقاقات وأرقام الإيرادات دقيقة.

مراجعات رد المبالغ المدفوعة لا نسخة احتياطية لها

أما PendingRefundReviewNotification فأمر مختلف. فهو يحمل pendingRefundToken الذي يجب أن تمرره إلى orders.reviewrefund، ولديك 24 ساعة من استلامه لإرسال تفضيلك بشأن الاسترداد وأدلة الاستخدام. تسجل Google استدعاءك الأول وتتجاهل ما بعده. ولا تصف وثائق Google أي نقطة نهاية تسرد المراجعات المعلقة، لذا إذا ضاعت رسالة Pub/Sub تلك، ضاعت معها أدلتك لذلك النزاع.

كم يكلفك إشعار الاسترداد الفائت ماليًا

الإشعار الفائت لاسترداد أصبح نهائيًا بالفعل يكلفك عملًا محاسبيًا فقط. تجده لاحقًا في Voided Purchases API أو Get Notification History، وتسحب الوصول إن كانت سياستك تقتضي ذلك، وتلحق تقاريرك بالواقع. أمر مزعج، لكنه رخيص.

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

والمال الذي أنفقته على تقديم الشراء كان قد ذهب قبل أن يبدأ النزاع.

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

لا يعود شيء من ذلك عند تنفيذ الاسترداد. الأدلة التي ترسلها خلال تلك الـ 12 أو 24 ساعة هي الأداة الوحيدة التي تملكها، والإشعار الفائت يسلبك إياها.

روتين استعادة يصمد

  • أكّد الاستلام أولًا. خزّن الحمولة الخام، وأعد رمز نجاح، ثم عالجها في طابور.
  • استعلم دوريًا عن Get Notification History من Apple مع onlyFailures كل بضع دقائق بحثًا عن CONSUMPTION_REQUEST، حتى لا يكلفك الانقطاع إلا دقائق من مهلة الـ 12 ساعة.
  • شغّل مسحًا يوميًا عبر Get Notification History مع onlyFailures على الأيام القليلة الماضية لكل الأنواع، وأعد معالجة ما تجده.
  • شغّل استدعاءً يوميًا لـ Voided Purchases API مع type 1 لكل تطبيق على Google Play، وطابقه مع الاستردادات التي سجلتها بالفعل.
  • في Pub/Sub، أبقِ مدة الاحتفاظ بالرسائل 7 أيام أو أكثر، وفعّل تنبيهًا على dead-letter topic إن وُجد، وتنبيهًا عند تراكم الرسائل غير المسلّمة.
  • اختبر المسار كاملًا في الإنتاج أيضًا. ترسل بيئة sandbox من Apple كل إشعار مرة واحدة دون إعادة محاولة، ويُظهر Request a Test Notification مع Get Test Notification Status بدقة كيف رد خادمك.
هاتف ذكي موضوع على ظهره بجوار كوب قهوة ودفتر على مكتب في ضوء الصباح الباكر، بداية هادئة لفحص يومي لإشعارات الاسترداد الفائتة

يستقبل RefundHalt إشعارات المتجرين نيابة عنك، ويرد تلقائيًا على CONSUMPTION_REQUEST ومراجعات رد المبالغ المدفوعة ضمن مهلها، فلا تكون أنت من يراقب الساعة.

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

إلى متى تواصل Apple إعادة محاولة إرسال إشعار خادم App Store الفاشل؟
نحو ستة أيام ونصف في الإصدار 2. تعيد Apple المحاولة خمس مرات، بعد 1 و12 و24 و48 و72 ساعة من المحاولة السابقة، لذا تأتي آخر محاولة بعد 157 ساعة من التسليم الأول. وتحصل إشعارات الإصدار 1 على ثلاث إعادات محاولة، بعد 6 و24 و48 ساعة من المحاولة السابقة.
إلى أي مدى زمني يمكنني استعادة إشعارات خادم App Store الفائتة؟
180 يومًا في الإنتاج. تعيد نقطة النهاية Get Notification History من Apple إشعارات الإصدار 2 من آخر 180 يومًا، أو آخر 30 يومًا في sandbox، بواقع 20 سجلًا لكل استدعاء، ويقصر خيار onlyFailures النتائج على الإشعارات التي لم تصل إلى خادمك قط.
هل تعيد Apple محاولة إرسال الإشعار إذا أعاد خادمي HTTP 400؟
نعم، وفقًا لوثائق Apple. تعيد Apple المحاولة عندما يعيد خادمك حالة 40x أو 50x، وتعدّ الحالات من 200 إلى 206 نجاحًا. وأي حالة أخرى تُحتسب أيضًا غير ناجحة.
هل يمكنني استعادة مراجعة رد مبالغ فائتة في Google Play؟
فقط ما دامت رسالة Pub/Sub موجودة. يصل pendingRefundToken الذي تحتاجه لـ orders.reviewrefund في PendingRefundReviewNotification، ولا توثّق Google أي واجهة برمجة تسرد المراجعات المعلقة، لذا فإن رسائل الاشتراك غير المؤكَّد استلامها، المحفوظة 7 أيام افتراضيًا، هي نسختك الوحيدة.
كيف أجد استردادات Google Play التي فاتت خادمي؟
استدعِ Voided Purchases API. فهي تعيد عمليات الشراء الملغاة من آخر 30 يومًا، بما فيها الاستردادات والإلغاءات ورد المبالغ المدفوعة، بحد أقصى 1,000 نتيجة في الصفحة وحصة قدرها 6,000 استعلام يوميًا لكل تطبيق. مرّر type 1 لتضمين الاشتراكات.

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

RefundHalt

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

تابع القراءة

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

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