تخط وانتقل إلى المحتوى الرئيسي

نظرة عامة على Webhooks

كيف تعمل webhooks في DZBuild — الأحداث التي تُطلق، آلية التسليم وإعادة المحاولة، نموذج الأمان، والحصص.

بقلم: Support

Webhooks إشعارات دفع لحظية من DZBuild إلى خادمك عند حدوث شيء على متجرك. استخدمها بدلًا من الاستعلام المتكرر (polling) — حمل أقل، تأخير أقل، وتسليمات webhook لا تُحسب من حصة الطلبات الشهرية.

ℹ️ معلومة — هناك نظاما webhooks مختلفان في DZBuild

اختر الصحيح قبل أن تبني.

إضافة Webhooks للتاجر

webhooks الخاصة بـ API v1 (هذا القسم)

كيف تُعدّها

/dashboard/webhooks — بدون كود

POST /v1/webhooks — عبر الـ API فقط

من يمكنه استعمالها

خطة Unlimited فما فوق

أي متجر لديه مفتاح API مُسجَّل في البرنامج التجريبي

عدد النقاط لكل متجر

1 في Unlimited، 3 في Enterprise

لا يوجد حد مفروض

التوقيع

X-DZ-Signature: t=<ts>,v1=hex(hmac_sha256(secret, ts + "." + rawBody)) على الجسم الخام — يمكنك التحقق منه. كما تُرسل ترويسة X-DZ-Token: <secret> لأدوات الـ no-code التي لا تدعم إلا المصادقة بالترويسات.

موقّعة بمفتاح لا يُسلَّم إليك — لا يستطيع التجار التحقق منه اليوم. انظر التوقيع.

الطلبات التي تغطيها

order.created من كل المصادر (الواجهة، صفحة الهبوط، الإنشاء اليدوي من لوحة التحكم، الـ API) بالإضافة إلى 6 أحداث حالة، منها order.processing

فقط الطلبات المُنشأة أو المُحدَّثة عبر الـ API

تُرسَل من

نطاقات Cloudflare

عناوين خروج DZBuild الخاصة — اطلب من الدعم القائمة الحالية

إضافات

واجهة سجل التسليمات، إعادة توليد السر، التحقق من أن الوجهة HTTPS فقط، تعطيل تلقائي بعد 10 إخفاقات متتالية

إن كان كل ما تحتاجه إشعارات طلبات موثوقة، فالإضافة هي المنتج الأفضل. استخدم webhooks الخاصة بـ API v1 حين يكون تكاملك يتحدث أصلًا مع الـ REST API.

لماذا Webhooks

قارن:

الاستعلام المتكرر — تنادي شيفرتك GET /v1/orders?since=... كل دقيقة. 1440 نداءً يوميًا، 1440 رحلة، تستهلك حصة API بالتساوي، والتأخير من "إنشاء الطلب" حتى "علم كودك" 60 ثانية.

Webhooks — تسجّل https://yourapp/webhooks مرة واحدة. كل طلب يُنشأ عبر POST /v1/orders يضع تسليمًا في الطابور، والطابور يُستنزف باستمرار، فيكون التأخير أقل من دقيقة عادةً. صفر استعلام، صفر إهدار للحصة.

⚠️ تنبيه — webhooks الخاصة بـ API v1 ترى حركة الـ API فقط

order.created يُطلق فقط للطلبات المُنشأة عبر POST /v1/orders. طلبات واجهة المتجر وصفحات الهبوط والطلبات اليدوية من لوحة التحكم لا تُطلق شيئًا هنا. والأمر ذاته ينطبق على تغييرات الحالة — انظر كتالوج الأحداث.

الاستعلام يتفوّق فقط حين: - نقطتك غير قابلة للوصول من الإنترنت (استعلم من داخل شبكتك). - ليس لديك خادم (استعلم من Lambda مجدوَلة / cron).

كيف يعمل التسليم

تقع كتابة عبر API v1
        │
        ▼
يُوضع تسليم في الطابور لكل webhook مشترك في ذلك الحدث
        │
        ▼
الطابور يُستنزف باستمرار — أقل من دقيقة عادةً
        │
        ▼
جسم موقَّع  ─────►  POST لرابطك (5 ث للاتصال، 10 ث إجمالًا)
                              │
                              ├─ 2xx → علّم مسلَّمًا، انتهى
                              ├─ 5xx → يُعاد للطابور، ويُعاد كل دقيقة
                              ├─ 4xx أو 3xx → محاولة واحدة، بلا إعادة
                              └─ بدون رد (timeout / DNS / TLS) → محاولة واحدة، بلا إعادة

سلوك إعادة المحاولة

⚠️ تنبيه — إعادة المحاولة في v1 لا تتصرّف كتراجع أسّي عادي

اقرأ هذا قبل أن تبني تصميمك حول إعادة المحاولة.

  • HTTP 5xx — يُعاد إرسال التسليم مرة كل دقيقة، إلى ما لا نهاية، حتى تُرجع نقطتك 2xx أو تحذف الـ webhook. الفاصل الزمني لا يتزايد أبدًا ولا يُتخلّى عن التسليم، فلا تبنِ تصميمك حول سلّم تراجع — لا وجود له.

  • Timeout أو فشل DNS أو فشل TLS — تُجرَّب مرة واحدة بالضبط ثم تُهجر. لا إعادة، ولا يُلتقط التسليم ثانية أبدًا.

  • HTTP 4xx و 3xx — محاولة واحدة، بلا إعادة أبدًا. لا نتبع عمليات إعادة التوجيه، لذا يُعدّ 301/302 إخفاقًا.

لا يوجد تعطيل تلقائي. يزداد failure_count الخاص بالـ webhook مرة واحدة لكل محاولة فاشلة، ويعود إلى 0 عند أي نجاح؛ وتبقى status بقيمة active.

النتائج العملية:

  • أرجِع 2xx بسرعة. إن لم تستطع معالجة الحمولة، أرجِع 2xx على أي حال وتجاهلها — إرجاع 5xx يعني اشتراكك في POST كل 60 ثانية إلى الأبد.

  • لا تعتمد على إعادة المحاولة لتغطية نقطة بطيئة. الـ timeout يعني تسليمًا ضائعًا نهائيًا. خزّن الجسم في طابورك الخاص وأرجِع الإقرار فورًا.

  • طابِق بالاستعلام. بما أن الإخفاقات تُهجر بصمت، شغّل مسحًا دوريًا بـ GET /v1/orders?since=... كشبكة أمان.

ما يُعتبر "نجاحًا"

  • HTTP 200, 201, 202, 204 (أي 2xx) — نجاح.

  • HTTP 4xx (400, 401, 403, 404, 422…) — لا تُعاد المحاولة. أصلح نقطتك وأعد الاختبار عبر POST /v1/webhooks/{id}/test.

  • HTTP 3xx — لا تُعاد المحاولة. لا نتبع إعادة التوجيه؛ وجّه الـ webhook إلى الرابط النهائي.

  • Timeout وفشل DNS وفشل TLS — لا تُعاد كذلك. نتحقق من شهادات TLS بصرامة، لذا تفشل الشهادة الموقّعة ذاتيًا هنا.

  • HTTP 5xx — تُعاد، لكن انظر تحذير الحلقة أعلاه.

نموذج الأمان

ما نُرسله

Content-Type:    application/json
User-Agent:      dzbuild-webhook/1
X-DZ-Timestamp:  <unix seconds>
X-DZ-Signature:  <hex hmac-sha256>
X-DZ-Delivery-Id: <numeric delivery id>

التوقيع

⚠️ تنبيه — تواقيع API v1 غير قابلة للتحقق من طرف التجار بعد

X-DZ-Signature ليس مشتقًّا من السر secret الخاص بكل webhook الذي يُرجعه POST /v1/webhooks، وذلك السر لا يُستعمل للتوقيع إطلاقًا — لذا فأي شيفرة تحقق مكتوبة بالاعتماد عليه سترفض 100% من التسليمات الحقيقية.

تعامل مع X-DZ-Signature كقيمة مبهمة إلى أن يصدر التوقيع لكل webhook على حدة. إن احتجت توقيعًا يمكنك التحقق منه فعلًا، استخدم إضافة Webhooks للتاجر على /dashboard/webhooks، فهي توقّع كل نقطة بالسر الخاص بتلك النقطة.

ما يجب أن تفعله

  1. أعد القراءة قبل أن تتصرّف. بما أن التوقيع غير قابل للتحقق، تعامل مع الحمولة كإشعار لا كبيانات موثّقة — اجلب السجل عبر GET /v1/orders/{id} بمفتاح الـ API الخاص بك قبل أن تشحن أو تحصّل أو تنفّذ أي شيء.

  2. اجعل الرابط غير قابل للتخمين. مقطع مسار عشوائي طويل أو رمز مشترك في سلسلة الاستعلام هو مصادقتك العملية اليوم.

  3. تأكد أن الطابع الزمني خلال 5 دقائق من ساعة خادمك — حماية رخيصة من إعادة الإرسال.

  4. استخدم بايتات الجسم الخام إن كنت تُجزّئ أي شيء — لا تُعد تسلسل JSON.

  5. كن idempotent — الحدث المنطقي ذاته قد يُسلَّم أكثر من مرة (إعادة الطابور بعد 5xx). أزل التكرار بـ delivery_id أو بمعرّفات الحدث ذاتها.

ما لا نفعله

  • لا نوثّق صادراتنا بـ mTLS. إن تطلّبت نقطتك ذلك، اعتمد reverse proxy يُجرّد/يضيف mTLS أمام معالجك.

  • لا نُرسل تسليمات API v1 من نطاقات Cloudflare، لذا فإن السماح بتلك النطاقات فقط يحجب كل تسليم. إن احتجت قائمة IP مسموحة، راسل الدعم للحصول على عناوين الخروج الحالية — فهي قابلة للتغيير. (إضافة Webhooks للتاجر عكس ذلك تمامًا: تسليماتها تأتي من نطاقات Cloudflare.)

مظروف الحمولة

كل جسم webhook له نفس الشكل الخارجي:

{
  "event":       "order.confirmed",
  "store_id":    13,
  "occurred_at": "2026-04-30T21:18:21+00:00",
  "data":        { "order_id": 6894, "old_status": "pending", "new_status": "confirmed" },
  "delivery_id": "9f2c41ab77e05d18"
}

الحقل

ملاحظات

event

نوع الحدث (القائمة الكاملة في كتالوج الأحداث).

store_id

معرّف متجرك — مفيد إن كان لديك عدة webhooks لنفس المعالج.

occurred_at

متى حدث الأمر في نظامنا، ISO 8601 مع المنطقة.

data

حمولة خاصة بالحدث. انظر كتالوج الأحداث لشكل كل حدث.

delivery_id

سلسلة من 16 خانة ست عشرية، فريدة لكل تسليم (webhook واحد × حدث واحد). وهي متطابقة بايتًا ببايت في كل إعادة محاولة — وهذا ما يجعلها صالحة لإزالة التكرار.

ترويسة X-DZ-Delivery-Id قيمة مختلفة: معرّف تسليم رقمي، مثلًا 4127. وهي أيضًا ثابتة عبر إعادات المحاولة، لكنها لا تساوي delivery_id الموجود في الجسم. أزل التكرار بأحدهما باستمرار — لا تخلط بينهما.

الحصة

تسليمات webhook غير محسوبة وغير محدودة اليوم. يُبلَّغ عن رقم webhooks_per_month في GET /v1/usage و GET /v1/quotas، لكن لا شيء يزيده ولا شيء يفرضه. كما أن محاولات التسليم لا تستهلك حصة requests_per_month الخاصة بالـ API.

هذا ليس ترخيصًا بالبطء — النقطة التي تُرجع 5xx يُعاد إرسال POST إليها كل 60 ثانية إلى ما لا نهاية (انظر سلوك إعادة المحاولة).

التالي

هل أجاب هذا عن سؤالك؟