Saudi commerce · Salla · Webhook architecture

Webhooks المشروطة في سلة: قلّل الضوضاء بلا نقاط عمياء

دليل إنتاجي لفلترة أحداث سلة من المصدر مع الحفاظ على الأمان وIdempotency وأدلة التدقيق والاستعادة من المصدر المرجعي.

المسار المرتبطهندسة التجارة الإلكترونية
آلة فرز رسائل عالية السرعة، في تشبيه بصري لفلترة Conditional Webhooks في سلة وتوجيه الأحداث إلى المسارات المختارة.
h

تسمح Conditional Webhooks في سلة بأن يستقبل تكاملك الأحداث التي تحقق شرطًا محددًا فقط؛ مثل Orders فوق قيمة معينة، أوفرع بعينه، أوPayment Method موثقة، أوCoupon Code، أوخاصية Product. فائدتها الحقيقية هي تقليل الضوضاء قبل وصولها إلى Queue، لكن الخطر يبدأ عندما يتحول Rule إلى المصدر الوحيد للحقيقة. التصميم الإنتاجي يحتاج Policy مسجلة بإصدار، وتحققًا من كل Delivery، وDurable Inbox قبل رد 2xx، وIdempotency للـRetries، ومطابقة دورية مع APIs سلة المرجعية.

هذا شرح هندسي عملي وليس خبرًا. الحقول والOperators واستراتيجيات حماية Webhooks وواجهات إدارتها حقائق موثقة في مستندات سلة. أما تصميم Control Plane وInbox وRollout وReconciliation والمراقبة فهو تحليل هندسي مبني على تلك العقود. تمت مراجعة الوثائق في 30 أكتوبر 2026.

الخلاصة أولًا

استخدم Conditional Webhook عندما يكون لدى Workflow سبب ثابت وواضح لاستبعاد بقية الأحداث. اجعل الشرط قصيرًا وقابلًا للمراجعة، ولا تستخدمه كAuthorization Policy، ولا تضع فيه Business Process كاملة، ولا تعتبر هدوء الـQueue دليلًا على أن المتجر لم يشهد أحداثًا مهمة.

المسار الآمن يتكون من خطين يلتقيان في Update واحدة Idempotent:

Salla Event -> Rule Gate -> Signed Webhook -> Durable Inbox
            -> Async Worker -> Domain Projection -> Outbox / ERP

Salla API -> Windowed Reconciliation --------------------^

يعطي Webhook زمن استجابة منخفضًا، بينما تكتشف Reconciliation ضياع Deliveries أوتغير Rule أوSchema أوConfiguration. لا يغني أحد الخطين عن الآخر في المال أوالمخزون أوالشحن.

ماذا توثق سلة؟

تشرح وثيقة Conditional Webhooks أن Rules تفلتر Events عبر Attributes مدعومة. تعرض أمثلة مثل total > 100 للطلب، وRule يستخدم OR للعرض الخاص، وRule يجمع City وLocation باستخدام AND. كما تسرد حقول Orders المدعومة، ومنها IDs وTotals وBranch وCoupon وPayment Method وCurrency وبيانات Shipment، وتفصل Attributes لمنتجات وعملاء وعروض وتصنيفات وعلامات وسلال ومراجعات.

توضح وثيقة Webhooks حقول event وversion وrule وurl وHeaders وSecurity Strategy وSecret. وتذكر أن التسجيل الجديد يستخدم Webhook Version 2 افتراضيًا، وأن Signature هي الاستراتيجية الافتراضية إذا لم تحدد غيرها. كما توثق Signature وToken، وتذكر أن Delivery غير الناجحة قد تعاد ثلاث مرات بفاصل يقارب خمس دقائق.

توفر سلة أيضًا APIs من أجل Register وUpdate وList Active وList Events وDeactivate. هذه Control Plane لإدارة الاشتراكات، وليست Data Plane تحفظ الأحداث وتعالجها.

متى تفلتر من المصدر؟

الحالةالاختيارلماذا؟
ERP يحتاج كل انتقال في حالة OrderEvents حرجة غير مفلترةضياع حدث قد يكسر Ledger أوFulfilment
Alert للطلبات عالية القيمة فقطConditional Webhookالأحداث المستبعدة غير مطلوبة لهذا Workflow
خدمة دفع تخص Payment Method واحدةRule مع Payment Reconciliationتقل الحركة وتبقى حالة المال قابلة للمطابقة
Analytics تتغير Segments فيها باستمرارStream أوسع وفلترة داخليةلا يمكنك إعادة تصنيف أحداث لم تستقبلها أصلًا
Fraud Policy معقدة وسريعة التغيرفلترة بعد الاستقبالمكانها Decision Service قابلة للاختبار والإصدار
Automation مرتبطة بفرع ثابتRule مع Configuration AuditBranch مناسب للفلترة لكن Drift يظل ممكنًا

اسأل قبل إنشاء Rule: هل قد نحتاج الحدث المستبعد لاحقًا لمحاسبة أوInventory أوFulfilment أوحق عميل أوAudit أوتدريب Model؟ إذا كانت الإجابة نعم، فلا تجعل الاشتراك المشروط طريقك الوحيد إلى البيانات.

مخطط هندسي أصلي: يمر حدث سلة عبر Rule بإصدار والتحقق من Signature وDurable Inbox وWorker بلا تكرار، بينما تكشف المطابقة المرجعية الفجوات. صورة الغلاف للمصور Mike Peel بترخيص CC BY-SA 2.0 UK عبر Wikimedia Commons؛ قد تُغيّر أبعادها للعرض المتجاوب.
مخطط هندسي أصلي: يمر حدث سلة عبر Rule بإصدار والتحقق من Signature وDurable Inbox وWorker بلا تكرار، بينما تكشف المطابقة المرجعية الفجوات. صورة الغلاف للمصور Mike Peel بترخيص CC BY-SA 2.0 UK عبر Wikimedia Commons؛ قد تُغيّر أبعادها للعرض المتجاوب. اضغط لعرض أكبر

حوّل Rule إلى Policy قابلة للإدارة

لا تعدل الاشتراكات يدويًا ثم تعتمد على الذاكرة. خزّن Desired State واضحًا:

{
  "merchant_id": "m_123",
  "event": "order.created",
  "rule": "total > 100 AND branch_id = 827301",
  "webhook_version": 2,
  "destination": "https://events.example.com/salla/v3",
  "security_strategy": "signature",
  "policy_version": 7,
  "status": "active"
}

يستخدم المثال Operators وAttributes تعرضها وثائق سلة، لكن يجب مراجعة القائمة الحالية لكل Event قبل التسجيل. وجود Field في Payload لا يعني تلقائيًا أنه صالح داخل Rule.

احتفظ لكل اشتراك بـ:

  • هوية Merchant وApp؛
  • Event وWebhook Version بدقة؛
  • Rule مطبّعة وConfiguration Hash؛
  • Destination Generation ومعرّف Secret لاقيمتها؛
  • Remote Webhook ID؛
  • Desired State وObserved State؛
  • وقت آخر Read-back ناجح؛
  • صاحب التغيير وسببه وRollback Target.

بهذه الطريقة يصبح تغيير Rule قابلًا للمراجعة وإعادة الإنتاج والعكس، ويمكن لـReconciler مقارنة Active Webhooks بالحالة المطلوبة آليًا.

Rule ليست مكان Business Logic

وظيفة Rule هي الإجابة عن سؤال Routing صغير: هل يدخل هذا Event هذا المسار؟ ليست مكان حساب Refund، أوتخصيص Stock، أوقرار Fraud، أوState Machine متعددة الخطوات.

Rule جيدة تستخدم Fields مستقرة موثقة ومقارنات بسيطة ولها Owner واضح؛ مثل Branch ID ثابتة أوPayment Method موثقة أوThreshold تملكها Operations. Rule سيئة تجمع Scoring وبيانات خارجية وThresholds تتغير يوميًا واستثناءات Merchant. ضع الثانية في Service مستقلة لها Tests وVersioned Inputs وقرار قابل للتفسير.

إذا جمعت AND وOR فلا تفترض Operator Precedence. قسّم Policy إلى اشتراكات أبسط أوتحقق من التعبير على Test Store. الشرط القصير أسهل في التدقيق وأقل عرضة للالتباس.

تحقق قبل Parsing وقبل أي Side Effect

Webhook Endpoint حد عام على الإنترنت، لذا تعامل معه كمدخل غير موثوق:

  1. افرض HTTPS وحدًا صارمًا لحجم Request.
  2. اقرأ Security Strategy وارفض أي قيمة غير متوقعة.
  3. تحقق من Salla Signature أوToken باستخدام Secret وConstant-time Comparison.
  4. احتفظ بالـRaw Bytes إذا كان Framework يعيد Serialization لـJSON قبل التحقق.
  5. لا تعمل Parse قبل نجاح التحقق من المصدر.
  6. تحقق من Event وMerchant وRequired Fields وSchema المتوقعة.
  7. اكتب Inbox Record ثابتة ثم Commit.
  8. أعد Success بسرعة، ونفذ Domain Work في Worker.

تعرض وثائق سلة التحقق باستخدام X-Salla-Signature وSecret مشتركة. اتبع العقد الحالي واختبره عبر Fixtures موقعة من Test Store. لا تقبل security_strategy: none في Production لمجرد أنها قيمة متاحة.

صمّم Inbox على أساس أن التكرار طبيعي

عندما تعيد المنصة المحاولة، قد يصل Payload نفسه أكثر من مرة. استخدم أكثر Identifiers ثباتًا للـEvent. إذا لم يوفر العقد Delivery ID، ابنِ Composite Key مراجعة من Merchant وEvent وEntity ID وSource Timestamp وCanonical Payload Hash.

insert into webhook_inbox
  (provider, merchant_id, event_name, entity_id, payload_hash, received_at, body)
values
  ('salla', :merchant, :event, :entity, :hash, now(), :body)
on conflict (provider, merchant_id, event_name, entity_id, payload_hash)
do nothing;

يحمي Unique Constraint من تكرار Effects نفسها، لكن على Worker أن تجعل Downstream Writes Idempotent أيضًا عبر Projection Version أوOutbox Command Key أوCompare-and-set Transition.

لا تعد 2xx قبل Commit إلى Durable Storage؛ الرد المبكر يصنع فقدًا صامتًا. وفي الاتجاه الآخر، لا تنتظر ERP أوEmail أوShipping API داخل Request، لأن بطء أي Dependency سيزيد Retries ويجعل توفر Endpoint تابعًا لكل خدماتك.

ماذا لا تستطيع Conditional Webhook إثباته؟

هي تثبت أن Event مطابقة وصلت، لكنها لا تثبت:

  • أن Event غير مطابقة لم تكن مهمة؛
  • أن Rule ما زالت مسجلة كما تريد؛
  • أن كل Event مطابقة وصلت فعلًا؛
  • أن Schema لم تتغير؛
  • أن Destination أوSecurity Strategy لم تنجرف.

لهذا شغّل Reconciliation على مستويين.

### مطابقة Control Plane

نفذ List Active Webhooks دوريًا وقارن Event وRule وVersion وDestination وSecurity Strategy بالحالة المطلوبة. أنذر عند Missing Registration أوUnexpected URL أوضعف Security أوDuplicate Subscription أوDisabled Hook أوConfiguration Drift. لا تصلح كل فرق تلقائيًا قبل تصنيفه؛ فقد يكون التغيير إجراء طوارئ مقصودًا.

### مطابقة Data Plane

لـOrders وPayments وRefunds وShipments وInventory الحرجة، اقرأ Resource API المرجعية ضمن Time Windows محدودة. أدخل النتائج عبر Domain Function نفسها التي تستخدمها Webhook Workers. حرك Checkpoint بعد Commit كل Pages فقط، واجعل Windows متداخلة قليلًا لاستيعاب Clock Differences وLate Updates.

إذا غيرت Threshold من total > 100 إلى total > 50 فلن تعاد Orders القديمة بين 50 و100 تلقائيًا. تحتاج Backfill محدودة إن كانت هذه الفترة مهمة للأعمال.

Rollout دون Blind Spot

  1. صدّر Active Registration الحالية وسجل Hash.
  2. راجع Event وAttributes وOperators في مستندات سلة الحالية.
  3. اختبر Positive وNegative وBoundary Cases في Store معزولة.
  4. انشر Endpoint تفهم Old وNew Policy Generations.
  5. حدّث Remote Webhook عبر API الموثقة.
  6. نفذ Read-back وقارن Routing وSecurity Fields.
  7. أنشئ Events تركيبية يجب أن تطابق وأخرى يجب ألا تطابق.
  8. ابدأ Authoritative Backfill للفترة الانتقالية.
  9. راقب Volume وDuplicates وSignature Failures وLag وReconciliation Diffs.
  10. أغلق Old Generation بعد إثبات المسار الجديد والـBackfill.

إذا أبقيت اشتراكين متداخلين مؤقتًا فتوقع Duplicate Deliveries. يجب أن يتجاهل Idempotency Key اختلاف Subscription ID إن كان Domain Event نفسه. ولا تعتبر نجاح Update Response دليلًا أن Traffic تصل إلى Destination المقصودة.

Observability تكشف الثقة الزائفة

لا تكتف بنسبة HTTP 200. راقب:

  • Drift في Active Webhooks حسب Merchant وPolicy Version؛
  • Signed Deliveries حسب Event وMerchant؛
  • Signature وSchema Rejections؛
  • Inbox Inserts وDuplicates وProcessing Failures؛
  • Receive-to-commit وReceive-to-effect Latency؛
  • Queue Age وDead Letters؛
  • Entities التي فحصتها Reconciliation؛
  • Missing وStale وConflicting Projections؛
  • Backfill Coverage بعد تغييرات Rules؛
  • Downstream Effects المرتبطة بـInbox وOutbox IDs.

لا تستطيع عد Events التي استبعدتها سلة عند Rule Gate مباشرة. لذلك Read-back وReconciliation Coverage أقوى من Queue هادئة.

Best Practices

  • اجعل لكل Subscription هدفًا تجاريًا واحدًا واضحًا.
  • استخدم أضيق Fields مدعومة من دون إخفاء حالة حرجة.
  • استخدم Signature افتراضيًا ودوّر Secrets مع Overlap في التحقق.
  • تحقق من المصدر قبل Parsing ومن Authorization قبل Effects.
  • Persist أولًا ثم Acknowledge ثم Process في الخلفية.
  • عامل Retries كأمر عادي واجعل كل Write Idempotent.
  • خزّن Rules وRemote IDs في Versioned Configuration.
  • طابق الاشتراكات والBusiness Entities كلتيهما.
  • اختبر Boundary Values وUnicode وEmpty Fields وMerchant IDs.
  • قلل PII في Logs وأدلة التغيير.

Anti-patterns والقيود

  • استخدام Rule كAuthorization Boundary.
  • افتراض أن كل Payload Field صالحة للفلترة.
  • خلط AND وOR بلااختبار.
  • إعادة 2xx قبل Durable Commit.
  • تنفيذ ERP أوEmail أوShipping Call داخل Webhook Request.
  • اعتبار غياب Events دليلًا على غياب نشاط مطابق.
  • توسيع Threshold بلاBackfill.
  • تسجيل Secrets أوSignatures أوCustomer Payload كاملة.
  • إصلاح كل Control-plane Diff تلقائيًا.
  • فلترة Financial أوInventory History حتى يستحيل Audit Reconstruction.

Conditional Webhooks تتنازل عمدًا عن الرؤية خارج Predicate. هي تقلل Transport وCompute، ولا تقلل الحاجة إلى Evidence وReconciliation وIncident Recovery. كما تعتمد على Contracts الحالية؛ أعد فحص الوثائق قبل كل Policy Change.

Checklist تنفيذية

  1. أثبت أن Workflow تستطيع استبعاد Nonmatching Events بأمان.
  2. اختر Event وVersion وRule Attributes موثقة.
  3. خزّن Desired Configuration وHash وOwner وRollback.
  4. تحقق من Signature أوToken قبل Parsing.
  5. Commit إلى Durable Inbox قبل 2xx.
  6. أزل أثر Retries واجعل Downstream Effects Idempotent.
  7. نفذ Read-back بعد كل تغيير.
  8. طابق Critical Entities عبر Windowed API Reads.
  9. نفذ Backfill عندما تتسع Rule.
  10. راقب Drift وLag وDuplicates وReconciliation Gaps.

اقرأ أيضًا: تدوير Endpoint لـSalla Webhooks، وBackfills لطلبات سلة، وحالات الطلب في سلة وزد، ومركز هندسة التجارة الإلكترونية، وخدمات Backend وAPI.

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

إعداد: Noor Yasser

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

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

إعداد: Noor Yasser

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

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

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

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