بناء استقبال موثوق لإشعارات Webhook، وهي طلبات ترسلها خدمة خارجية عند وقوع حدث، يعني إنشاء نقطة تتحقق من المرسل وتقبل احتمال التكرار واختلاف الترتيب، ثم ترد سريعاً وتنقل الحدث إلى معالجة يمكن مراقبتها واستعادة ما فاتها. لا تضمن الشبكات وصول الإشعار مرة واحدة فقط، لذلك يجب أن يمنع النظام تكرار الأثر وأن يحتفظ بسجل يصلح للتسوية.
تختلف هذه المقالة عن مقارنة Webhooks والاستعلام الدوري. فالمقالة السابقة تساعدك على اختيار آلية اكتشاف التغيير والجمع بين الإشعار والاستعلام، أما هذا الدليل فيفترض اختيار Webhook ويركز على عقد الاستقبال: التوقيع، ومنع تكرار الأثر، والطابور، وإعادة المحاولة، وإعادة المعالجة.
اكتب عقد الحدث
حدّد اسم الحدث وإصداره ومعرفه ووقت إنشائه والحساب أو المستأجر والكيان والحقول المطلوبة. افصل غلافاً ثابتاً للبيانات عن محتوى كل نوع من الأحداث. لا تجعل النظام المستقبِل يستنتج النوع من وجود حقل، ووثّق الحقول التي تقبل قيمة فارغة والقيم الجديدة وكيف يتعامل إصدار قديم معها.
حدّد هل الحدث مجرد إشعار يطلب من النظام المستقبِل جلب الحالة الحالية، أم يحمل نسخة من الحالة وقت الإنشاء. الإشعار يقلل اعتماد الطرف الآخر على مخطط بياناتك لكنه يحتاج طلباً إضافياً، أما النسخة الكاملة فتحتاج قواعد أوضح للخصوصية والتوافق. لا ترسل بيانات لا يحتاجها الطرف.
استخدم معرف حدث مستقراً
كل محاولة لتسليم الحدث المنطقي نفسه تحمل event_id نفسه، ويمكن أن تحمل كل محاولة معرف تسليم مختلفاً عند الحاجة. لا تنشئ حدثاً جديداً عند إعادة المحاولة. ويجب أن تستطيع نقطة الاستقبال إنشاء قيد فريد يجمع المزود والحساب ومعرف الحدث.
إذا لم يقدم المزود معرفاً موثوقاً، فاشتق مفتاحاً بحذر من مرجع ثابت ونوع الحدث وإصداره، لا من طابع زمني عشوائي. وثّق احتمال تشابه المفاتيح، ولا تعتمد على بصمة محتوى الطلب وحدها إذا كانت حقول غير مؤثرة تتغير بين المحاولات.
وقّع البايتات الخام
استخدم آلية المزود الرسمية، وغالباً توقيع HMAC بمفتاح سري وطابع زمني ومحتوى الطلب كما وصل. تحقّق من التوقيع قبل تحويل JSON إذا كانت المواصفة توقّع البايتات نفسها، لأن إعادة الترميز أو ترتيب الحقول قد يغيّره. واستخدم دالة مقارنة ثابتة الزمن من مكتبة موثوقة.
لا تضع السر في URL أو الكود أو السجل. افصل أسرار الاختبار والإنتاج ولكل مستأجر إذا كان النموذج يقتضي. سجّل معرف المفتاح لا قيمته. لا تخترع خوارزمية تشفير خاصة؛ اتبع المواصفة المعلنة.
امنع إعادة التشغيل الخبيث
تحقق من الطابع الزمني ضمن نافذة تسمح بانحراف معقول بين الساعات، وسجّل معرف الحدث حتى لا يُقبل الطلب نفسه بعد معالجته. التوقيع الصحيح وحده لا يمنع إعادة إرسال طلب قديم إذا لم تضبط نافذة القبول وهوية الحدث.
لا تعتمد على ساعة العميل، وراقب فرق الوقت في الخوادم. إذا كان المزود يعيد أحداثاً قديمة عمداً، فاستخدم نقطة أو مفتاحاً مخصصاً لإعادة المعالجة، أو سياسة تسمح بالحدث المخزن مع بقاء منع التكرار. ولا توسع نافذة القبول لكل الطلبات.
دوّر الأسرار من دون توقف
ادعم مفتاحاً حالياً وسابقاً لفترة انتقال محدودة أو معرف مفتاح يختار السر. ابدأ التحقق بالجديد ثم السابق وفق السياسة، وراقب استخدام القديم حتى يصل للصفر، ثم ألغِه. لا تقبل قائمة غير محدودة من الأسرار.
اختبر الدوران في بيئة مناسبة، ووثق من يفعله وكيف يتراجع. إذا تسرب سر، نفذ استجابة حادث لا مجرد تغيير صامت. لا تعرض سبب فشل التوقيع بتفاصيل تساعد مهاجماً، لكن احتفظ بمرجع آمن للدعم.
افصل الاستقبال عن المعالجة
نفذ في المسار المتزامن: حد حجم الطلب، والتحقق من الطريقة والنوع والتوقيع والطابع والحساب، وحفظ الحدث أو كشف التكرار، ثم أعد الاستجابة المتوقعة بسرعة. انقل منطق العمل والاتصالات الخارجية إلى طابور.
لا تعُد 2xx قبل حفظ الحدث بشكل متين إذا كان ذلك يعني القبول. وإذا فشل الحفظ، أعد كوداً يسمح للمزود بالمحاولة وفق عقده. تجنب تنفيذ عملية مالية داخل request قد تنتهي مهلته بعد الأثر وقبل الرد.
خزّن الأحداث الواردة بهوية فريدة
أنشئ جدولاً يسجل المزود والحساب ومعرف الحدث ونوعه وإصداره ووقت استلامه وحالة المعالجة ومحاولاتها ومرجعاً محمياً للمحتوى. ضع قيداً فريداً على هوية الحدث، ونفّذ الإدخال واكتشاف التكرار داخل معاملة واحدة.
قرّر مدة الاحتفاظ بمحتوى الطلب الأصلي وفق الحاجة والخصوصية. قد يكفي بعد المعالجة حفظ بصمة رقمية وحقول آمنة. قيّد الوصول، ولا تجعل لوحة الدعم تعرض أسراراً أو بيانات شخصية كاملة. احتفظ فقط بما تحتاجه لإعادة المعالجة والتدقيق.
اجعل معالج العمل آمناً عند التكرار
منع إدخال الحدث مرتين لا يكفي إذا توقفت المهمة بعد تعديل الطلب وقبل تعليم سجل الحدث بأنه مكتمل. اربط الأثر بقيد فريد أو سجل تطبيقي، واستخدم معاملة محلية. وللآثار الخارجية استخدم سجل إرسال موثوقاً أو مفتاح منع التكرار لدى الطرف الآخر حيث يتوفر.
مثلاً، لا ترسل رسالة أو تمنح رصيداً من دون هوية مشتقة من الحدث والغرض. عند إعادة المحاولة، تحقق من الأثر السابق. وصمّم انتقال الحالة بحيث يقبل تكرار الحالة نفسها ولا يعيد السجل إلى الخلف. يوضح دليل تكامل المدفوعات أهمية هذا الفصل للأحداث المالية.
تعامل مع الوصول خارج الترتيب
قد يصل invoice.paid قبل invoice.created، أو يصل تحديث قديم بعد تحديث أحدث. لا تفترض أن الشبكة تحفظ الترتيب. استخدم رقم الإصدار أو التسلسل إن قدمه المصدر، أو اجلب الحالة الحالية، أو ضع الحدث في انتظار قصير لتبعية معروفة. ولا تؤخر كل الأحداث بسبب احتمال نادر.
طبّق حالات محددة وانتقالات تمنع التغيير غير الصالح. احتفظ بالحدث الذي لم يُطبّق وسبب القرار. إذا كان المصدر يرسل نسخة كاملة من الحالة، فقارن رقم الإصدار لا وقت الاستقبال فقط. واختبر الأحداث نفسها بكل ترتيباتها المهمة.
صنّف أخطاء المعالجة
قد يكون خطأ تحليل المحتوى أو إصدار غير مدعوم دائماً، فيحتاج إلى عزل الحدث للمراجعة. أما قفل قاعدة البيانات أو انقطاع المزود المؤقت فقد يستحق إعادة المحاولة. وقد يشير خطأ الصلاحية أو الحساب غير المعروف إلى خلل في الإعداد أو محاولة هجوم. لا تكرر كل فشل بلا حد.
حدّد عدد المحاولات والمهلة والفواصل الزمنية المتزايدة مع تفاوت صغير بينها، ثم انقل الحدث المستنفد إلى قائمة فشل ظاهرة. أنشئ تنبيهاً على عمر الأحداث وحجمها وتغير معدلها، لا على كل رسالة منفردة، واجعل إعادة المعالجة إجراءً مخولاً.
صمم إعادة التشغيل
تختار أداة إعادة المعالجة الأحداث بحسب معرف أو فترة أو سبب، وتعرض معاينة وعدد الأحداث، وتتطلب سبباً وموافقة عند وجود أثر حساس، وتستخدم المعالج الآمن نفسه. لا تعدّل معرف الحدث ولا تنسخ المحتوى يدوياً إلى نقطة استقبال الإنتاج.
سجل من أعاد ومتى والنتيجة. اختبر replay لحدث مكتمل فيجب ألا يكرر الأثر، ولحدث فشل بعد أثر جزئي فيكمل بأمان. افصل إعادة التسليم من المزود عن إعادة المعالجة الداخلية.
أضف تسوية دورية لاكتشاف الفوات
حتى مع إعادة المحاولات قد يفوت حدث بسبب خطأ في الإعداد أو انتهاء مدة الاحتفاظ. استخدم API أو تقريراً من المصدر لمقارنة الحالات الحرجة دورياً. يوفر Webhook السرعة، بينما تثبت التسوية الاكتمال. لا تجعل الاستعلام الدوري المكثف بديلاً غير معلن؛ حدّد نطاقه ومؤشر الاستئناف.
أنشئ قائمة فروق: سجل خارجي لا محلي، أو حالة مختلفة، أو حدث معلق. عالجها بنفس معرفات العمل. هذا يربط التنفيذ بقرار المقالة السابقة من دون تكرار نية اختيار transport.
اعزل المستأجر والحساب
حدّد المستأجر من اعتماد موثوق أو حساب المزود بعد التحقق من التوقيع، لا من حقل يستطيع أي عميل إرساله. استخدم مفتاحاً فريداً يشمل المزود والحساب إذا لم تكن معرفات الأحداث عالمية. ولا تسمح لحدث تابع لحساب أن يعدّل سجل حساب آخر ولو تطابق المعرف.
اختبر هذا الحد في Laravel كما يشرح دليل اختبار عزل المستأجرين. احمل سياق المستأجر صراحة إلى المهمة، ولا تتركه في كائن مشترك داخل عامل قد يخدم حدثاً تابعاً لمؤسسة أخرى.
احمِ نقطة الاستقبال
اقبل نوع محتوى وحجماً وطريقة طلب متوقعة، واستخدم مهلة قراءة وحدود معدل تراعي إعادة المحاولات المشروعة. لا تعتمد على قائمة عناوين IP المسموحة وحدها، لأن العناوين قد تتغير ولا تثبت الهوية دائماً. التوقيع هو الأساس عندما يدعمه المصدر.
لا تطبع محتوى الطلب في سجلات الوصول. خصص نقطة استقبال لكل بيئة، وأوقف وضع التصحيح في الإنتاج. راجع خطر SSRF إذا سمحت بإعداد عنوان إشعار صادر، وتأكد من أن إعادة التوجيه لا تغير مسار التوقيع بلا فهم. واضبط حماية DDoS من دون حجب المزود أثناء الذروة.
اختبر بعقود وتسلسلات عدائية
استخدم عينات موثقة لاختبار التوقيع، وغطِّ سراً خاطئاً وطابعاً قديماً وبايتاً متغيراً وJSON غير صالح وحجماً كبيراً وتكراراً وتزامناً ووصولاً خارج الترتيب وفشل عامل وحدثاً مجهولاً وتدوير المفتاح. واختبر الاستجابة التي تدفع المزود إلى إعادة المحاولة.
شغّل اختبارات العقد عند تحديث حزمة المزود (SDK) أو الخادم الوسيط، لأن البرمجيات الوسيطة قد تغير محتوى الطلب. اختبر إعادة محاولة الطابور وإعادة المعالجة والتسوية. ولا تستخدم نقطة استقبال الإنتاج لتجربة محتوى مصطنع إلا بخطة وأداة رسمية.
راقب رحلة الحدث
اجمع أعداد الأحداث المستلمة والمكررة والمرفوضة بسبب التوقيع والمخزنة والمعالجة والفاشلة، ومدة الاستقبال إلى الإكمال، وعمر أقدم حدث، ونتائج إعادة المعالجة والتسوية. استخدم معرفات ربط لا تحمل بيانات حساسة. لوحة تعرض استجابات 200 فقط لا تثبت أن العمل اكتمل.
تقدم خدمة التكاملات ملكية لهذا النوع من الحدود. وثق SLO داخلياً من خطك الأساسي وقدرة المزود، ولا تخترع وعد تسليم عام. راجع اتجاه الفشل بعد كل إصدار وتدوير.
الخلاصة: اجعل استقبال Webhook قابلاً للتتبع والتعافي
نقطة الاستقبال الموثوقة تتحقق من محتوى الطلب ووقته وحسابه، وتحفظ هوية الحدث مرة واحدة، وترد سريعاً، وتجعل تكرار المعالجة آمناً، ثم تعالج ما فاتها بإعادة المعالجة والتسوية. لا تفترض ترتيباً ثابتاً أو تسليماً وحيداً. اطلب مراجعة استقبال Webhooks مع عينة طلب موقعة وعقد الحدث وتسلسل الفشل، من دون مشاركة أي سر إنتاجي.


