Skip to main content

دورة حياة التسليم

كل رسالة صادرة ترسلها عبر Orbit تحمل حقل status يتقدم بينما تنتقل الرسالة من استدعاءك للواجهة البرمجية نحو جهاز المستلم — أو نحو نتيجة فاشلة. تشرح هذه الصفحة هذه الآلة الحالة المفهومية: ما تعنيه الحالات، ما الذي يدفع كل انتقال، وأين توجد الحواف الخاصة بالمشغّل. اقرأها قبل اشتراكك في أول webhook لك أو تفرّع تكاملك على نتيجة الرسائل. تعيش دلالات الحالة، جدول الانتقالات الكامل، وخريطة حدث webhook في مرجع دورة حياة حالة الرسائل؛ مخطط الاستجابة لقراءة الحالة الحالية للرسالة موجود في مرجع واجهة API للمراسلة. هذه الصفحة تربط بينهما بمستوى أعلى.

المسار السعيد

رسالة تنجح من طرف إلى طرف تمر عبر: pending → queued → sending → sent → delivered → read كل انتقال يُدفَع بواسطة جهاز مختلف — لا طرف واحد يرى المسار كله: جهازان يجلسان بجانب هذا المسار ويمكنهما إخراج سجل منه:
  • جدولة no-DLR. عندما لا يُرجع مشغّل إيصالاً للتسليم على الإطلاق، تروّخ الجدولة sent إلى submitted_no_receipt بعد نافذة سماح خاصة بالقناة — راجع المؤكد من المشغّل مقابل. وسيط أولي على السلك.
  • أنت (المشغّل). إلغاء رسالة مجدوّلة لم تُرسَل أذّ بها إلى cancelled، حالة نهائية لا يلمسها أي استدعاء للمقدم ولا أي DLR. تُحل مرسلات الصندوق إلى test_sent، حالة نهائية يُبلّغ إليها قبل أي نشر للمقدم. حذف سجل ينقل أي حالة نهائية إلى deleted، بعدئذ لا شيء يمكن أن يلمسه.
رسالة مجدوّلة للمستقبل تتوقف في scheduled حتى وقت الإطلاق ثم تنضم إلى قائمة الانتظار. لا يمكن أن تغادر scheduled إلا ثلاث طرق: ترقيتها إلى queued عند وقت الإطلاق، cancelled منك، أو expired إذا انتهت نافذة صلاحيتها قبل النشر.

التحقق من المشغّل مقابل. وسيط أولي على السلك

أهم تمييز للتقارير والتسوية هو ما إذا كانت الحالة نتيجة مؤكَّدة من المشغّل أم حاربها القبّيل على السلك:
  • delivered و read مؤكَّدان من المشغّل. llegó DLR حقيقي؛ المشغّل نفسه اكتفى بالنتيجة.
  • submitted_no_receipt حاربه أولي. يعني “قُبِلت الإرسال، ولم يُعاد أي إيصال ضمن نافذة السماح.” يُوصَف أنه أولي (state_class: "intermediate", is_terminal: false) على كل webhook، لأن DLR delivered أو read أو فاشل حقيقي يمكن أن يصل لاحقًا ويستبدله.
عامل submitted_no_receipt على أنه نتيجة مجهولة، لا كتسليم. ما إذا كان “مجهول” يميل إلى إيجابي أو مجرد محوّل يعتمد على القناة — راجع تنوعات القناة. expired هو النظر عن الجانب الآخر: llegó DLR، لكن للغاية متاخرًا بحيث أن نافذة الإيصال كانت قد أُغلقَت. لا يمكن معرفة النتيجة والسجل مغلق؛ expired يُوزَّع على المشتركين كحدث message.failed.

تنـوعات القناة

  • قنوات DM من Meta (Instagram, Messenger). واجهة الإرسال الخاصة بـ Meta لا تصدر إيصالات التسليم أبدًا. يغادر الإرسال Orbit كـ sent، يعلمز no_dlr_channel في متطافات الرسالة، ويتحول إلى submitted_no_receipt بعد 5 دقائق. في مستلم تم مقبول اختيارياً، يضمن Meta التسليم على القبول — لذلك في هذه القنوات يتصرف submitted_no_receipt مثل إشارة وظيفية للتسليم، ومتطافات الرسالة تحمل no_dlr_channel: true لتستطيع التمييز بين الحالة.
  • قنوات تدعمها SMPP (SMS, MMS, صوت، فاكس، RCS). نافذة السماح 30 دقيقة. هنا submitted_no_receipt هو محوّل حقيقي: قد يكون الجهاز قد تلقّى الرسالة بدون إيصال تم الإبلاغ عنه، قد لا يُرسل المشغّل إيصالات أبدًا على ذلك الطريق، أو قد يكون الإيصال قد أُسقِطَ في العبور. تتبَّع هذه النسبة على إشارة منفصلة عن نسبة التسلميات — نسبة submitted_no_receipt المترسّخة على وجهة واحدة تُشير إلى طريق غير متوَلِيّ أو إلى طريق إيصال مكسور، وهي تستحق التحقيق في أيّ من الحالتين.
  • البريد الإلكتروني. يضيف نتيجة فاشلة لا يملكها غار Channels: bounced، عندما يرفُض خادم البريد الاستقبال الرسالة. عدد الارتداد ضد معدل الفشل النهائي الخاص بك مثل failed، لكنه حالة مفروقَة لتمكينك من فصل الرفضات من جانب المستلم عن تلك الجانب المقدم.
  • إلغاء المشغّل. cancelled يُبلّغ إليها فقط من أنت — عبر POST /messages/:id/cancel على رسالة لم تُرسَل. لا مشغّل يكتبها أبدًا، ونتيجةً لا تطلق أي حدث webhook؛ لا شيء يُخبِر المشترك عن الإلغاء. استشِر GET /messages/:id إذا كنت تُعرِّض الإلغاء في واجهتك وتحتاج إلى مراقبته.
  • الصندوق / وضع الاختبار. مرسلات الاختبار تحل إلى test_sent قبل أي نشر للمقدم. تطلق message.sent مع status: "test_sent" و metadata.test_mode: true، لذا المشترك يجب أن يُفرّع على metadata.test_mode ليبقي حركة الصندوق خارج معالجة الإنتاج.

ما يُفرّع عنه

يجب أن تتبدأ التكاملات على الحقول القابلة للقراءة آلياً فقط، أبدًا على الأوصاف العرضية:
  • status — الحالة الحالية للرسالة. هذه نقطة التفرّع الأولية. تعامل مع المجموعة كاملة: غير حالات المسار السعيد والنتيجة المتفقّلة، لا تنس cancelled، test_sent، submitted_no_receipt، و bounced.
  • metadata.classified_error_code — موجود على النتائج النهائية الفاشلة؛ الفئة الفاشلة المُعرَّفة آلياً والمُمَكِّنَة آلة. ادمِجها مع error_code / error_message خام على webhook message.failed عندما تريد كلمات المشغّل.
  • metadata.no_dlr_channel — موجود على سجلات DM من Meta؛ يخبرك أن submitted_no_receipt هو حالة التسليم المضمونة من Meta، لا الحالة المحوّلة من SMPP.
  • state_class / is_terminal — على webhook الحياة. is_terminal: true (بالم زوجة state_class: "terminal") يعني أن النتيجة نهائية؛ submitted_no_receipt تبلغ is_terminal: false بالضبط لكي لا تغلِق الكتاب عليها.

أخطاء شائعة

  1. تعامل message.created على القبول. message.created يطلق في اللحظة التي توضع السجل في قائمة الانتظار، قبل أي استدعاء للمقدم. رفض متزامن (4xx على الإرسال، أو rejected/failed فوري) يترك ذلك الحدث مسلَّم. اجمِعه مع message.sent قبل أن تستنتج أن الرسالة خرجت.
  2. تفترض أن delivered غير قابلة للتغيّر. المشغّلون على الطرق بعض يصدِرون إيصالًا للتسليم، ثم تصحيحًا بعد دقائق — بعض المشغّلين الهنديين والبرازيليين يفعلون ذلك. Orbit يحترم ذلك: يمكن للسجل أن ينتقل من delivered → undelivered أو من delivered → failed. إذا ربَّيت الحالات في مخزن بياناتك الخاص، طبِّق التحديثات بشكل عدم تثويري حسب معرف الرسالة بدلاً من تجاهل الانتقالات لرسالة وعلها من قبل.
  3. تنتظر webhook على cancelled. لن يأتي أبدًا — الإلغاء يرتَبط باستدعاءك للواجهة البرمجية، لا باستدعاء المشغّل، لذا المنصة لا تصدر حدثًا له. السجل يجلس ببساطة في cancelled حتى تحذِفه.
  4. ترمي submitted_no_receipt في مجرى الفشل. يصل على نوع حدث message.failed لأسباب التعَبب (لا يوجد حدود مخصص)، لكن حذرن يكتو حول data.status، لا نوع الحدث، واحصِر بها خارج مقاعع الفشل الثابت.
  5. تتوقع حدثًا نهائيًا واحدًا لكل رسالة. قد تصدر رسالة message.failed مع status: "submitted_no_receipt" ثم message.delivered، عندما يصل إيصال المشغّل البطيء أخيرًا ضمن نافذة الوصول المتراخَى. إحدِّثه وجهّزه بواسطة message_id، ودَع الحدث المتأخر يغلب.
بمجرد أن تكون الآلة الحالة واضحة، فإن مجموعات الإيزاء لكل حالة في مرجع أحداث webhook، والدلالات الوحيدة للحالة في مرجع دورة حياة حالة الرسائل.