# Webhooks

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

هناك نظاما webhooks مختلفان في DZBuild

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

|                     | **إضافة Webhooks للتاجر**                                                                                                                                                                                         | **webhooks الخاصة بـ API v1** (هذا القسم)                                                                                                                                                                                                                                                                                                      |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| كيف تُعدّها         | `/dashboard/webhooks` — بدون كود                                                                                                                                                                                  | `POST /v1/webhooks` — عبر الـ API فقط                                                                                                                                                                                                                                                                                                          |
| من يمكنه استعمالها  | خطة Unlimited فما فوق                                                                                                                                                                                             | المتاجر على خطة Enterprise سارية، بمفتاح API خاص بالتاجر (رموز التطبيقات المثبّتة مرفوضة)                                                                                                                                                                                                                                                      |
| عدد النقاط لكل متجر | 1 في Unlimited، 3 في Enterprise                                                                                                                                                                                   | لا يوجد حد مفروض                                                                                                                                                                                                                                                                                                                               |
| التوقيع             | `X-DZ-Signature: t=<ts>,v1=hex(hmac_sha256(secret, ts + "." + rawBody))` على **الجسم الخام**، ويمكنك التحقق منه. كما تُرسل ترويسة `X-DZ-Token: <secret>` لأدوات الـ no-code التي لا تدعم إلا المصادقة بالترويسات. | الصيغة نفسها: `X-DZ-Signature: t=<ts>,v1=hex(hmac_sha256(secret, ts + "." + rawBody))` على **الجسم الخام**، بالسر `secret` الذي يُرجعه `POST /v1/webhooks` مرة واحدة. يمكنك التحقق منه. أما webhooks المسجّلة قبل التوقيع بسر كل webhook فتبقى على توقيع قديم لا يمكن التحقق منه: انظر [التوقيع](#%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%B9). |
| الطلبات التي تغطيها | `order.created` من **كل** المصادر (الواجهة، صفحة الهبوط، الإنشاء اليدوي من لوحة التحكم، الـ API) بالإضافة إلى 6 أحداث حالة، منها `order.processing`                                                               | الطلبات المُنشأة أو المُحدَّثة **عبر الـ API**، إضافة إلى التأكيد والإلغاء بأزرار إشعار Telegram بطلب جديد، بما فيها طلبات الواجهة وصفحات الهبوط                                                                                                                                                                                               |
| تُرسَل من           | نطاقات Cloudflare                                                                                                                                                                                                 | عناوين خروج DZBuild الخاصة — اطلب من الدعم القائمة الحالية                                                                                                                                                                                                                                                                                     |
| إضافات              | واجهة سجل التسليمات، إعادة توليد السر، التحقق من أن الوجهة HTTPS فقط، تعطيل تلقائي بعد 10 إخفاقات متتالية                                                                                                         | التحقق من أن الوجهة HTTPS فقط                                                                                                                                                                                                                                                                                                                  |

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

## لماذا Webhooks[​](#لماذا-webhooks "رابط مباشر إلى لماذا Webhooks")

قارن:

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

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

webhooks الخاصة بـ API v1 لا تُطلَق عند الشراء من واجهة المتجر ولا عند التغيير من لوحة التحكم

`order.created` يُطلق **فقط** للطلبات المُنشأة عبر `POST /v1/orders`. طلبات واجهة المتجر وصفحات الهبوط والطلبات اليدوية من لوحة التحكم لا تُطلق شيئًا هنا. وتغييرات الحالة من لوحة التحكم لا تُطلق شيئًا كذلك؛ وحدها التغييرات عبر الـ API وزرّا التأكيد والإلغاء في إشعار Telegram بطلب جديد تُطلق حدثًا. انظر [كتالوج الأحداث](https://dzbuild.com/ar/ar/api-docs/webhooks/events.md).

الاستعلام يتفوّق فقط حين:

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

## كيف يعمل التسليم[​](#كيف-يعمل-التسليم "رابط مباشر إلى كيف يعمل التسليم")

```
تقع كتابة عبر API v1

        │

        ▼

يُوضع تسليم في الطابور لكل webhook مشترك في ذلك الحدث

        │

        ▼

الطابور يُستنزف باستمرار — أقل من دقيقة عادةً

        │

        ▼

جسم موقَّع  ─────►  POST لرابطك (5 ث للاتصال، 10 ث إجمالًا)

                              │

                              ├─ 2xx: علّم مسلَّمًا، انتهى

                              ├─ 5xx أو 408 أو 429 أو timeout أو فشل DNS أو TLS: يُعاد مع تباعد متزايد

                              ├─ أي 4xx آخر، أو 3xx: إلى قائمة الرسائل الميتة فورًا، بلا إعادة

                              └─ 5 محاولات فاشلة: ينتقل إلى قائمة الرسائل الميتة، بلا إعادة بعدها
```

### سلوك إعادة المحاولة[​](#سلوك-إعادة-المحاولة "رابط مباشر إلى سلوك إعادة المحاولة")

* تُعاد محاولة الإرسال عند استجابة **5xx** أو **408** أو **429** أو فشل الشبكة (انتهاء المهلة، DNS، TLS) بعد دقيقة، ثم 5 دقائق، ثم 30 دقيقة، ثم ساعتين. بعد الفشل الخامس ينتقل الإرسال إلى قائمة الرسائل الميتة ولا يُعاد.
* أي استجابة **4xx أخرى**، وكل استجابة **3xx**، تُرسَل مرة واحدة فقط: ينتقل التسليم فورًا إلى قائمة الرسائل الميتة ولا يُعاد أبدًا. لا نتبع عمليات إعادة التوجيه، لذا يُعدّ `301`/`302` إخفاقًا.

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

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

* **أرجِع 2xx بسرعة.** إن لم تستطع معالجة الحمولة، أرجِع 2xx على أي حال وتجاهلها؛ إرجاع 5xx يكلّفك أربعة تسليمات أخرى للجسم نفسه خلال نحو ساعتين ونصف.
* **لا تعتمد على إعادة المحاولة لتغطية نقطة بطيئة.** خمسة إخفاقات خلال نحو ساعتين ونصف تُسقط التسليم. خزّن الجسم في طابورك الخاص وأرجِع الإقرار فورًا.
* **طابِق بالاستعلام.** بما أن التسليم يُسقط بعد خمسة إخفاقات، شغّل مسحًا دوريًا بـ `GET /v1/orders?since=...` كشبكة أمان. يُصفّي `since` حسب وقت إنشاء الطلب، فالمسح يجد الطلبات التي فاتك `order.created` الخاص بها؛ أما تغيير الحالة الفائت، فأعِد قراءة الطلبات التي ما زلت تتابعها وقارن `status` الخاص بها.

### ما يُعتبر "نجاحًا"[​](#ما-يُعتبر-نجاحًا "رابط مباشر إلى ما يُعتبر \"نجاحًا\"")

* HTTP 200, 201, 202, 204 (أي 2xx) — نجاح.
* HTTP 4xx غير `408` و`429` (400 و401 و403 و404 و422 وغيرها): **لا تُعاد المحاولة**، وينتقل التسليم مباشرة إلى قائمة الرسائل الميتة. أصلح نقطتك وأعد الاختبار عبر `POST /v1/webhooks/{id}/test`.
* HTTP 3xx: **لا تُعاد المحاولة**، وينتقل التسليم فورًا إلى قائمة الرسائل الميتة. لا نتبع إعادة التوجيه؛ وجّه الـ webhook إلى الرابط النهائي.
* Timeout وفشل DNS وفشل TLS: تُعاد المحاولة كما في 5xx. نتحقق من شهادات TLS بصرامة، لذا تفشل الشهادة الموقّعة ذاتيًا في كل محاولة.
* HTTP 5xx و`408` و`429`: تُعاد المحاولة وفق الجدول أعلاه، 5 محاولات إجمالًا.

## نموذج الأمان[​](#نموذج-الأمان "رابط مباشر إلى نموذج الأمان")

### ما نُرسله[​](#ما-نُرسله "رابط مباشر إلى ما نُرسله")

```
Content-Type:    application/json

User-Agent:      dzbuild-webhook/1

X-DZ-Timestamp:  <unix seconds>

X-DZ-Signature:  t=<unix seconds>,v1=<hex hmac-sha256>

X-DZ-Delivery-Id: <numeric delivery id>
```

### التوقيع[​](#التوقيع "رابط مباشر إلى التوقيع")

يُحسب `X-DZ-Signature` بالسر `secret` الذي أرجعه `POST /v1/webhooks` عند تسجيل الـ webhook:

```
X-DZ-Signature: t=<unix seconds>,v1=<hex hmac-sha256>



expected = hex( hmac_sha256( WEBHOOK_SECRET, t + "." + raw_body ) )



if (!constant_time_equal(expected, v1)) reject 401

if (abs(now - t) > 300)                 reject 401   # نافذة إعادة ±5 دقائق
```

للتحقق من تسليم:

1. قسّم الترويسة عند `,` واقرأ قيمتي `t` و`v1`.
2. احسب HMAC-SHA256 للقيمة `t + "." + raw_body` بسر الـ webhook لديك، حيث `raw_body` هو البايتات التي استلمتها كما هي، ثم رمّز الناتج بالست عشري (hex).
3. قارن الناتج مع `v1` بمقارنة ذات زمن ثابت.
4. ارفض التسليم إذا ابتعدت `t` عن ساعتك بأكثر من 300 ثانية.

كل محاولة تُوقَّع لحظة إرسالها، لذا تحمل إعادة المحاولة `t` جديدة و`v1` جديدة على الجسم نفسه. الشيفرة بأربع لغات موجودة في [التحقق من التواقيع](https://dzbuild.com/ar/ar/api-docs/webhooks/verifying-signatures.md).

webhooks المسجّلة قبل التوقيع بسر كل webhook

الـ webhook الذي أُنشئ قبل أن تبدأ DZBuild التوقيع بالسر الخاص بكل webhook يبقى على التوقيع القديم: قيمة ست عشرية مجرّدة بلا جزء `t=`، محسوبة بمفتاح لا تُسلّمه DZBuild. لا يمكنك التحقق منها. احذف ذلك الـ webhook وسجّله من جديد، فالتسجيل الجديد يُرجع سرًّا يُوقَّع به كل تسليم.

### ما يجب أن تفعله[​](#ما-يجب-أن-تفعله "رابط مباشر إلى ما يجب أن تفعله")

1. **تحقّق من التوقيع قبل أن تتصرّف.** ارفض أي تسليم لا تطابق فيه `v1`، قبل أن تحلّل JSON أو تلمس أي طلبية.
2. **استعمل HTTPS.** يرفض `POST /v1/webhooks` أي `url` لا يبدأ بـ `https://`، وتُفحص الشهادات بصرامة.
3. **تأكد أن الطابع الزمني خلال 5 دقائق** من ساعة خادمك — حماية رخيصة من إعادة الإرسال.
4. **استخدم بايتات الجسم الخام** لحساب HMAC، ولا تُعد تسلسل JSON.
5. **كن idempotent.** قد يصلك التسليم نفسه أكثر من مرة: بعد 5xx أو `408` أو `429` أو انتهاء المهلة يُرسَل من جديد بالجسم نفسه. أزل التكرار بالاعتماد على `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`       | نوع الحدث (القائمة الكاملة في [كتالوج الأحداث](https://dzbuild.com/ar/ar/api-docs/webhooks/events.md)).                                                      |
| `store_id`    | معرّف متجرك — مفيد إن كان لديك عدة webhooks لنفس المعالج.                                                                                                    |
| `occurred_at` | متى حدث الأمر في نظامنا، ISO 8601 مع المنطقة.                                                                                                                |
| `data`        | حمولة خاصة بالحدث. انظر [كتالوج الأحداث](https://dzbuild.com/ar/ar/api-docs/webhooks/events.md) لشكل كل حدث.                                                 |
| `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 تستقبل الجسم نفسه حتى أربع مرات إضافية خلال نحو ساعتين ونصف (انظر [سلوك إعادة المحاولة](#%D8%B3%D9%84%D9%88%D9%83-%D8%A5%D8%B9%D8%A7%D8%AF%D8%A9-%D8%A7%D9%84%D9%85%D8%AD%D8%A7%D9%88%D9%84%D8%A9)).

## التالي[​](#التالي "رابط مباشر إلى التالي")

* [التسجيل](https://dzbuild.com/ar/ar/api-docs/webhooks/registering.md) — `POST /v1/webhooks` بكامل الجسم والاستجابة والأمثلة.
* [كتالوج الأحداث](https://dzbuild.com/ar/ar/api-docs/webhooks/events.md) — كل حدث بحمولة بيانات نموذجية.
* [التحقق من التواقيع](https://dzbuild.com/ar/ar/api-docs/webhooks/verifying-signatures.md) — كود بأربع لغات.
