التجارة السعودية · معمارية الأحداث

Conditional Webhooks في سلة: صفِّ الأحداث قبل وصولها إلى تطبيقك

دليل عملي لقواعد Webhooks في سلة: اختيار الشروط، وتسجيلها بأمان، واختبار التغييرات، والحفاظ على معالجة موثوقة بعد التصفية.

المسار المرتبطهندسة التجارة الإلكترونية
رسم تصوري أصلي لتدفق أحداث متجر يمر عبر مرشح انتقائي إلى Queue دائمة؛ ولا يمثل البنية الداخلية لسلة.
تصوّر بصري للفكرة — يتبعه شرح ومخطط تنفيذي داخل المقال.

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

تتيح وثائق Conditional Webhooks في سلة حقل `rule` ضمن اشتراك Webhook، بحيث تقيّم المنصة الشروط المدعومة قبل إرسال الحدث. هذه ليست ميزة أُطلقت اليوم؛ تم التحقق من الوثائق في 26 سبتمبر 2026، ويعرضها المقال كنمط تكامل عملي لا كخبر جديد.

ماذا تغيّر Conditional Webhook؟

يختار اشتراك Webhook العادي حدثًا مثل `order.created` أو `product.quantity.low`. ويضيف الاشتراك المشروط predicate فوق attributes المدعومة لعائلة الحدث. توثق سلة عوامل علائقية ومنطقية منها `=` و`!=` و`AND` و`OR`، وتقدم `total > 100` مثالًا عند التسجيل. كما تسرد عائلات مدعومة تشمل الطلبات والمنتجات والعملاء والعروض والتصنيفات والعلامات والسلات المتروكة والمراجعات.

يعمل الفلتر قبل التسليم؛ فإذا لم يطابق الحدث فلن يصل payload إلى endpoint تطبيقك. يفيد ذلك عندما ينطبق الإجراء التجاري فعلًا على subset ثابت: إرسال الطلبات عالية القيمة فقط إلى مراجعة يدوية، أو التفاعل مع شروط عرض محددة، أو تشغيل workflow متخصص لمنتجات معرّفة.

التصفية ليست payload projection. تحدد القاعدة هل يُرسل Webhook أم لا، لكنها لا تعد بحذف الحقول غير المستخدمة من payload المطابق. لذلك طبّق تقليل البيانات وسياسة retention داخل التطبيق أيضًا. واستخدم فقط attributes الموثقة لعائلة الحدث المحددة؛ لا تفترض أن حقلًا ظهر في payload طلب يصلح في قاعدة منتج أو سلة.

تسجيل القاعدة عبر Merchant API

واجهة Register Webhook الحالية هي `POST /admin/v2/webhooks/subscribe`، وتتطلب scope باسم `webhooks.read_write`، وتستخدم version 2 افتراضيًا للاشتراكات الجديدة. ويجب أن يقبل URL طلبات `POST`. قد يبدو الطلب الأدنى هكذا:

{
  "name": "High-value order review",
  "event": "order.created",
  "url": "https://app.example.com/webhooks/salla/orders",
  "version": 2,
  "rule": "total > 100",
  "headers": [
    {"key": "Authorization", "value": "<per-app-secret>"}
  ]
}

استخدم OAuth token الخاص بالتاجر فقط لاستدعاء API التسجيل في سلة، ولا تضعه في callback URL. خزّن webhook identifier العائد والقاعدة بصيغة موحدة في إعدادات تطبيقك حتى يعرف المشغّل ما هو منشور. وتوفر سلة كذلك List Active Webhooks، التي تعيد event وversion وrule وURL وheaders؛ استخدمها لمقارنة الإعداد المرغوب مع الفعلي.

هناك تفصيل تعاقدي يحتاج اختبار نشر: تقول وثائق التسجيل إن الاشتراك الجديد باستخدام URL نفسه يحدّث Webhook موجودًا أو يعيده. لا تفترض أن تكرار التسجيل لأحداث مختلفة على URL متطابق سينشئ اشتراكات مستقلة. افحص قائمة الاشتراكات النشطة في demo store، واستخدم callback paths ثابتة ومختلفة عمدًا عندما يحتاج التكامل إدارة الاشتراكات كلًا على حدة.

ما الذي لا تستبدله القواعد؟

يقلل الشرط عدد عمليات التسليم، لكنه لا يجعلها exactly once. ما زال Core Development Playbook في سلة يوصي بالتسلسل نفسه: تحقق من المرسل، وأكد الاستلام بسرعة، وأرسل payload إلى Queue، وعالجه خارج request، واجعل المعالجة idempotent.

لذلك على public handler التحقق من signature باستخدام raw body، وفحص envelope، وحفظه في durable inbox، وإعادة 2xx، وترك التنفيذ للـworker. أعطِ كل side effect—إنشاء شحنة أو إصدار كوبون أو إشعار ERP—مفتاح idempotency مستقلًا. يجب أن تصل retry إلى الحالة نفسها لا أن تكرر الإجراء المالي أو التشغيلي.

ولا تستعيد القاعدة حدثًا لم يصل أو شرطًا كان خاطئًا. يبقى Platform API مصدر الحقيقة. احتفظ بـreconciliation مجدولة للطلبات والمخزون والمدفوعات والشحن الحرجة. يشرح دليل تعافي Webhooks في سلة وزد durable inbox وcheckpoints وAPI backfill بالتفصيل؛ تقع القواعد المشروطة قبل تلك المعمارية ولا تستبدلها.

تحدد القاعدة المشروطة الأحداث التي ترسلها سلة؛ وعلى التطبيق أن يتحقق ويحفظ ويؤكد الاستلام ويرسل للـQueue ويعالج كل حدث مطابق بتكرار آمن.
تحدد القاعدة المشروطة الأحداث التي ترسلها سلة؛ وعلى التطبيق أن يتحقق ويحفظ ويؤكد الاستلام ويرسل للـQueue ويعالج كل حدث مطابق بتكرار آمن. اضغط لعرض أكبر

تصميم قواعد تبقى مفهومة

ابدأ من business invariant لا من صياغة expression. عبارة «أرسل الطلبات فوق 100 فقط» ناقصة حتى يحدد الفريق العملة والخصومات والاسترجاعات وهل العتبة مبنية على `total` الموثق في الحدث. وإذا كان الإجراء مكلفًا أو غير قابل للعكس، فأعد قراءة حالة الطلب الموثوقة في worker قبل التنفيذ.

اجعل القواعد قصيرة. تصعب مراجعة قاعدة تحتوي فروعًا كثيرة من `AND` و`OR`، ويسهل إساءة فهمها عندما لا تكون أولوية التنفيذ واضحة. فضّل عدة اشتراكات مسماة أو فلترًا أوسع في المنصة يتبعه policy صريح في التطبيق عندما يتغير القرار كثيرًا. يجب أن يزيل الفلتر الحركة غير المهمة بوضوح؛ أما business logic التي تحتاج versioning أوfeature flags أوaudit trail أوrollback سريع فيجب أن يملكها التطبيق.

مثّل كل اشتراك كإعداد يُراجع مع الكود:

subscription: high_value_order_review_v1
event: order.created
rule: total > 100
owner: risk-operations
on_match: enqueue manual-review workflow
recovery: reconcile orders every 15 minutes

تشير `v1` هنا إلى إصدار إعدادك، لا إصدار Webhook payload في سلة. خزّن expression القديم وسبب التغيير عند كل تعديل. بذلك يستطيع فريق الحوادث الإجابة عن سؤال: «أي طلبات كان يمكن أن يستبعدها الفلتر خلال هذه الفترة؟».

إجراء طرح وتغيير آمن

أنشئ fixture matrix من أشكال payload الموثقة: حدثًا تحت الحد، وآخر مساويًا له، وثالثًا فوقه، وحقولًا مفقودة أو nullable حيث يسمح schema، وتركيبات لكل فرع `AND` أو`OR`. اختبر policy تطبيقك بوحدات، ثم نفذ أحداث متجر حقيقية في Salla demo store لتتأكد مما ترسله المنصة فعلًا.

قبل تغيير قاعدة إنتاج، سجّل الاشتراك الحالي الذي تعيده List Active Webhooks. طبّق expression الجديد عبر مسار التسجيل أو التحديث الموثق، ثم اقرأ الإعداد النشط مجددًا، وشغّل حدث business تجريبيًا. راقب عدد عمليات التسليم المطابقة، وفشل signatures، وكتابات inbox، ونسبة التكرار، وworker lag، وفروقات reconciliation.

لا تنشر قاعدة أضيق ثم تحذف قدرتك على إعادة بناء الحالة فورًا. احتفظ بمطابقة API متداخلة لمدة تكفي لمقارنة المجموعة التي اختارتها القاعدة بالسجلات الموثوقة. إذا زاد drift، فتراجع عن القاعدة ومرر repairs عبر worker نفسه وحدود idempotency نفسها.

حدود التكلفة والمراقبة

يمكن للتسليم المشروط تقليل HTTP requests وتخزين الأحداث الخام ورسائل Queue وتشغيل workers. يعتمد الوفر على انتقائية القاعدة وتكلفة العمل اللاحق؛ ولا يوجد benchmark عام يضمن نسبة معينة. قِس قبل التطبيق وبعده بالأعداد، لا بالانطباع.

من المؤشرات المفيدة لكل اشتراك: حجم مجموعة المصدر المتوقعة، والأحداث المستلمة، ونسبة التطابق، ورفض signatures، وزمن acknowledgment، والمحاولات، وتكرار inbox، وفشل المعالجة، وإصلاحات reconciliation. لا يستطيع فلتر المنصة إخبار تطبيقك بما لم يستلمه، لذلك يجب أن تأتي تقديرات مجموعة المصدر من API query محدودة أو عدد تجاري موثوق آخر.

تجنب labels عالية cardinality مثل order IDs في metrics. ضع المعرفات في structured logs مع retention مناسبة، واجمع metrics حسب فئة التاجر والحدث وإصدار القاعدة والنتيجة. يربط ذلك التكامل بممارسات مراقبة الـbackend دون تحويل بيانات العملاء إلى monitoring labels.

القرار العملي

استخدم Conditional Webhooks في سلة عندما يستطيع predicate ثابت وموثق إزالة جزء كبير وغير مهم من event stream. تصبح مفيدة خصوصًا قبل الأتمتة المكلفة أو AI calls أو تكاملات الطرف الثالث. وأبقِ business policy المتغيرة أو الدقيقة داخل كودك، حيث يمكن اختبارها ووضع إصدار لها والتراجع عنها.

تتكون المعمارية الموثوقة من طبقتين مختلفتين: تختار Salla Rules ما يصل إليك، بينما يحدد ingress والـworkers هل ستُعالج الأحداث المطابقة بأمان. حافظ على signature verification والتخزين الدائم والـQueues وidempotency وreconciliation والمراقبة حتى لو بدا الفلتر بسيطًا. يمنح هذا الفصل التاجر ضوضاء أقل دون التخلي عن صحة البيانات.

المراجع الرسمية

تدعم هذه المراجع سلوك الأدوات المذكورة. الأمثلة وقرارات التصميم توضيحية، ويجب تكييفها مع متطلبات المشروع وإصداراته.

إعداد: Noor Yasser

من القرار إلى التنفيذ

تعمل على تحدٍ تقني مشابه؟

أساعد الفرق على تحويل القرار المعماري إلى نطاق واضح وتنفيذ يمكن تشغيله ومراجعته بثقة.

احجز لقاءً لمدة ٣٠ دقيقةالخدمة المرتبطةتطبيقات سلة وزد وأدوات التجّارمشروع من الأعمالواتساب هيرو