كل المقالات
Playbookمدة القراءة 7 دقائق

تصل ثلاثة إشعارات استرداد من App Store بعد أن يقرر Apple، وإشعار REFUND_REVERSED يعيد البيع إليك

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

هاتف ذكي يعرض إيصال دفع بجانب ظرف مُعاد وعملة معدنية واحدة، يوضح إشعارات استرداد App Store التي يرسلها Apple بعد أن يقرر بشأن الاسترداد

أهم الخلاصات

  • يرسل Apple أربع رسائل متعلقة بالاسترداد عبر App Store Server Notifications V2. يطلب إشعار CONSUMPTION_REQUEST أدلتك، بينما تُبلغ إشعارات REFUND وREFUND_DECLINED وREFUND_REVERSED بالنتيجة بعد أن يكون Apple قد قرر بالفعل.
  • يعني إشعار REFUND أن App Store قد استرد قيمة المعاملة. يحمل الإشعار الحقلين revocationDate وrevocationReason، وهو إشارتك لإلغاء الاستحقاق المرتبط بتلك المعاملة الواحدة، وليس كل عملية شراء لذلك المنتج.
  • للحقل revocationReason قيمتان. القيمة 1 تعني أن الاسترداد مُنح بسبب مشكلة في منتجك، والقيمة 0 تعني أنه مُنح لسبب آخر. قيمة المشكلة إشارة جودة تستحق التسجيل وتتبع اتجاهها.
  • يعني إشعار REFUND_DECLINED أن Apple رفض طلب استرداد العميل. تحتفظ بالبيع ولا تغيّر شيئاً، وهذا آمن فقط إذا لم تكن قد ألغيت الوصول قبل أن يصبح القرار نهائياً.
  • يعني إشعار REFUND_REVERSED أن Apple قد ألغى استرداداً كان قد منحه سابقاً، عادة بعد أن يعترض العميل عليه. تختفي حقول الإلغاء من المعاملة، وتعليمات Apple نفسها هي أنه إذا كنت قد ألغيت المحتوى، فعليك إعادته.
  • رُد على الإشعارات الأربعة جميعها بـ HTTP 200. إذا كان خادمك متوقفاً وفاته أحدها، فإن نقطة نهاية Get Refund History تتيح لك البحث عن المعاملات المستردة عبر transaction id والمطابقة.
  • لا يعني استرداد فترة اشتراك سابقة دائماً أن الوصول يجب أن ينتهي. إذا كانت هناك فترة مدفوعة أحدث لا تزال نشطة، فإن الإلغاء على المعاملة القديمة يقطع الوصول عن عميل ما زال مسدداً.

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

هذه الثلاثة منفصلة عن CONSUMPTION_REQUEST، وهو رسالة الاسترداد الوحيدة التي تطلب منك الرد. إشعارات ما بعد القرار لا تريد جدالاً. تريد HTTP 200 والتغيير الصحيح في وصول العميل. إليك ما يعنيه كل واحد منها، والحقول الدقيقة التي تحمل الحقائق، وأين يتسرب المال عندما تتعامل معها بشكل خاطئ.

إشعارات الاسترداد الأربعة، وأيها يريد رداً

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

الإشعارما يخبرك به Appleإجراؤكالرد المتوقع
CONSUMPTION_REQUESTطلب عميل استرداداً ويريد Apple بياناتكأرسل Send Consumption Information خلال 12 ساعةنعم، بيانات حقيقية
REFUNDاسترد App Store قيمة المعاملةألغِ الاستحقاق لتلك المعاملةلا، HTTP 200
REFUND_DECLINEDرفض App Store الاسترداداحتفظ بالوصول، لا تغيّر شيئاًلا، HTTP 200
REFUND_REVERSEDألغى Apple استرداداً كان قد منحهأعِد المحتوى الذي ألغيتهلا، HTTP 200

ماذا يخبرك إشعار REFUND فعلاً

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

يحمل الحقلان revocationDate وrevocationReason الحقائق

الحقل revocationDate هو توقيت UNIX، بالمللي ثانية، الذي استرد فيه App Store قيمة المعاملة أو ألغاها. يخبرك الحقل revocationReason بفئة الاسترداد، ويأخذ قيمتين بالضبط.

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

وجود revocationDate على معاملة هو بحد ذاته العلامة. إذا جلبت معاملة لاحقاً ووجدت فيها revocationDate، فإن عملية الشراء تلك قد استُردت، بإشعار أو بدونه. اقرأ السبب إلى جانبه حتى لا تمر موجة من عمليات الاسترداد بقيمة 1 على إصدار واحد بجوارك كأنها ضجيج.

ألغِ حسب المعاملة، لا حسب المنتج

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

يعني إشعار REFUND_DECLINED أنك فزت بالفعل، فلا تتراجع عن ذلك

يصل إشعار REFUND_DECLINED عندما يرفض App Store طلب استرداد العميل. طلب العميل، ورفض Apple، وأنت تحتفظ بالبيع. ظاهرياً لا يوجد ما تفعله، وهذا هو المقصود. الخطأ الذي يكشفه هذا الإشعار مختلف: إلغاء الوصول مبكراً.

إذا كان شفرتك تتفاعل مع CONSUMPTION_REQUEST بسحب وصول العميل قبل أن يحكم Apple، فإن إشعار REFUND_DECLINED هو اللحظة التي ينفجر فيها ذلك القرار. احتفظ Apple بمالك، وحرمت عميلاً رُفض استرداده من الوصول. ذلك العميل يدفع الآن مقابل منتج لا يستطيع استخدامه، ويفتح تذكرة دعم، ويتذكر ذلك. الحل قاعدة، لا ميزة: ألغِ عند REFUND، ولا تلغِ أبداً عند الطلب. إشعار REFUND_DECLINED هو ببساطة تأكيد من Apple بأن الإلغاء المبكر كان سيكون القرار الخاطئ.

إشعار REFUND_REVERSED هو الإشعار الذي يعيد إليك المال

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

مشكلة ما بعد أسابيع

السؤال الحقيقي الذي يطرحه المطورون، على منتديات Apple نفسها، هو التوقيت. قد يصل إشعار REFUND_REVERSED بعد أسابيع من إشعار REFUND الأصلي، بعد فترة طويلة من انتهاء فترة الاشتراك. هل تستعيد الوصول حينها؟ أعِد ما تمنحه المعاملة فعلاً، محدداً بما تغطيه تلك المعاملة. بالنسبة لمنتج استهلاكي أو غير استهلاكي، أعِد تشغيل الفتح. بالنسبة لفترة اشتراك انقضت بالفعل، أنت لا توزّع وقتاً جديداً، بل تصحّح السجل حتى يكون تاريخ العميل دقيقاً وأي استحقاق لا يزال صالحاً يعمل من جديد. استعِد المعاملة المحددة، ومنطق التداخل لديك يقرر ما هو نشط حالياً.

عملة معدنية تُعاد بجانب هاتف ذكي، توضح استرداد App Store المُلغى الذي يعيد البيع إلى المطور

أين يكمن المال في إتقان هذا

كل من هذه الإشعارات يرتبط برقم حقيقي، وتكلفة سوء التعامل معه ليست سعر البيع وحده.

REFUND: توقف عن الدفع لخدمة عميل استُرد ماله

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

REFUND_DECLINED: لا تحوّل فوزاً إلى استرداد من حسن النية

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

REFUND_REVERSED: أسوأ اقتران هو ذهاب مالهم ووصولهم معاً

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

ماذا تُعِد

التعامل بسيط بمجرد أن يكون النموذج صحيحاً. اربط الاستحقاقات بـ transaction id حتى يشير كل إشعار إلى عملية شراء واحدة. عند CONSUMPTION_REQUEST، أرسل بياناتك خلال 12 ساعة. عند REFUND، ألغِ تلك المعاملة. عند REFUND_DECLINED، لا تفعل شيئاً. عند REFUND_REVERSED، أعِد الوصول. أرجِع HTTP 200 بسرعة على جميعها ونفّذ تغيير الوصول في وقتك الخاص.

بالنسبة للفجوة التي تتركها الإشعارات، استخدم نقطة نهاية Get Refund History. إذا كان خادمك متوقفاً أثناء انقطاع وفاته إشعار REFUND، فاستدعِ بحث الاسترداد في App Store Server API لأجل transaction id، على /inApps/v2/refund/lookup/{transactionId}، واقرأ المعاملات الموقّعة مع revocationDate وrevocationReason الخاصة بها. يطابق معاملة واحدة في كل مرة ويتصفح عمليات الشراء المستردة للعميل، فلا يصبح webhook فائت استحقاقاً مضبوطاً بشكل خاطئ بشكل دائم.

هذا هو الجزء الذي يشغّله RefundHalt نيابة عنك. يستمع للأنواع الأربعة، يلغي عند REFUND، يبقي الوصول دون مساس عند REFUND_DECLINED، ويعيد الوصول تلقائياً عند REFUND_REVERSED، كل منها مرتبط بالمعاملة الدقيقة. استرداد مُلغى لا يبقى في طابور بينما يظل عميل يدفع محروماً، واسترداد مرفوض لا يطلق أبداً إلغاءً ستضطر للتراجع عنه.

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

ما الفرق بين REFUND وREFUND_REVERSED؟
يعني إشعار REFUND أن App Store استرد قيمة معاملة وعليك إلغاء ذلك الاستحقاق، بينما يعني إشعار REFUND_REVERSED أن Apple تراجع عن استرداد كان قد منحه وعليك إعادة المحتوى الذي ألغيته. الاثنان زوج: يمكن لعملية شراء أن تمر بـ REFUND ثم، إذا نُقض نزاع العميل، بـ REFUND_REVERSED. اربط تغييرات الوصول لديك بـ transaction id حتى يعمل كل إشعار على عملية الشراء الصحيحة.
هل يلزمني إرسال أي شيء رداً على إشعار REFUND؟
لا. ترد على REFUND وREFUND_DECLINED وREFUND_REVERSED بـ HTTP 200 دون أي محتوى. إشعار CONSUMPTION_REQUEST وحده يطلب منك إرسال بيانات، ويفعل ذلك عبر نقطة نهاية Send Consumption Information خلال 12 ساعة. الثلاثة الأخرى هي إبلاغ من Apple بقرار، لا طرح لسؤال.
ماذا عليّ أن أفعل عند تلقي إشعار REFUND_DECLINED؟
لا شيء يتغير، لأن استرداد العميل رُفض وأنت تحتفظ بالبيع. الطريقة الوحيدة التي يسبب بها إشعار REFUND_DECLINED عملاً هي أن تكون قد ألغيت الوصول مبكراً، قبل أن يحكم Apple. ألغِ عند REFUND بدلاً من CONSUMPTION_REQUEST، فيصبح إشعار REFUND_DECLINED تأكيداً بأن الوصول تُرك دون مساس بشكل صحيح.
هل ينبغي أن أستعيد الوصول عندما يصل إشعار REFUND_REVERSED بعد أسابيع من الاسترداد؟
نعم، أعِد الاستحقاق الذي تمنحه تلك المعاملة المحددة. يذكر Apple أنه إذا كان تطبيقك قد ألغى محتوى بسبب الاسترداد ذي الصلة، فعليه إعادته. بالنسبة لمنتج استهلاكي أو غير استهلاكي، أعِد تشغيل الفتح. بالنسبة لفترة اشتراك انتهت بالفعل، أنت تصحّح السجل، لا تمنح وقتاً جديداً، لذا لا يزال منطق التداخل لديك يقرر ما هو نشط حالياً.
كيف ألتقط إشعار استرداد فات خادمي؟
استخدم نقطة نهاية Get Refund History في App Store Server API، التي تبحث عن المعاملات المستردة لعميل عبر transaction id على /inApps/v2/refund/lookup/{transactionId}. تُرجع معاملات موقّعة مع revocationDate وrevocationReason، فبعد انقطاع يمكنك مطابقة الوصول دون انتظار إشعار انطلق بالفعل. تتعامل مع transaction id واحد لكل نداء وتتصفح عمليات الشراء المستردة للعميل.

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

RefundHalt

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

تابع القراءة

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

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