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

Webhooks

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

لماذا Webhooks

قارن:

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

Webhooks — تسجّل https://yourapp/webhooks مرة واحدة. ننادي عليه كلما أُنشئ طلب. التأخير ~2-5 ثوانٍ. صفر استعلام. صفر إهدار للحصة.

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

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

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

حدث/طلب يقع على الخادم الأصلي


INSERT صف في api_v1_webhook_deliveries


كرون يستنزف كل دقيقة (next_retry_at <= NOW())


توقيع HMAC للجسم ─────► POST لرابطك مع timeout 10 ث
│ │
│ ├─ 2xx → علّم مسلَّمًا، انتهى
│ ├─ 5xx → أعد: 1د، 5د، 30د، 2س، 12س
│ ├─ 4xx → اعتبره سامًّا؛ لا تُعد
│ └─ بدون رد (timeout/DNS) → أعد

└─ 5 إخفاقات → انقل إلى DLQ

جدول إعادة المحاولة

بعد كل محاولة فاشلة، يُضبط next_retry_at إلى now() + delay[attempt]:

المحاولةالتأخير
1دقيقة
25 دقائق
330 دقيقة
4ساعتان
512 ساعة
السادسةDLQ — تدخل يدوي

نافذة إعادة المحاولة الإجمالية ~14.5 ساعة. بعدها يُرسَل التسليم إلى DLQ ويزداد failure_count للـ webhook. خمس رسائل ميتة متتالية تُعطّل الـ webhook تلقائيًا (status → dead)؛ راسل الدعم لإعادة التفعيل.

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

  • HTTP 200, 201, 202, 204 (أي 2xx) — نجاح.
  • HTTP 4xx (400, 401, 403, 404, 422…) — لا تُعاد المحاولة. نعتبر 4xx "نقطتك ترفض هذه الحمولة بشكل قاطع"؛ المزيد لن يُجدي. أصلح نقطتك وأعد الاختبار عبر POST /v1/webhooks/{id}/test.
  • HTTP 5xx، timeout، DNS، TLS — تُعاد.

إن أردت أن نعيد على 4xx محدد (نادر)، أعد 503 Service Unavailable بدلًا من 4xx.

نموذج الأمان

ما نُرسله

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

التوقيع

X-DZ-Signature = hex( hmac_sha256( WEBHOOK_SECRET, X-DZ-Timestamp + "." + sha256(body) ) )

WEBHOOK_SECRET هو ما حصلت عليه عند تسجيل webhook (POST /v1/webhooks). لا نكشفه ثانية — احفظه.

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

  1. تحقق من التوقيع على كل طلب (انظر التحقق من التواقيع).
  2. تأكد أن الطابع الزمني خلال 5 دقائق من ساعة خادمك — يرفض الإعادة.
  3. استخدم بايتات الجسم الخام للتجزئة — لا تُعد تسلسل JSON.
  4. كن idempotentX-DZ-Delivery-Id فريد لكل محاولة، لكن الحدث المنطقي ذاته قد يُسلَّم أكثر من مرة (مشاكل شبكة، إعادة بعد نجاح). أزل التكرار من جانبك بـ delivery_id أو معرّفات الحدث ذاتها.

ما لا نفعله

  • لا نوثّق صادراتنا بـ mTLS. إن تطلّبت نقطتك ذلك، اعتمد reverse proxy يُجرّد/يضيف mTLS أمام معالجك.
  • لا نقفل بحسب IP. نُرسل من CF Workers — الـ IP المصدر ضمن نطاقات Cloudflare. إن أردت whitelist استخدم قائمة 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": "abc123def456"
}
الحقلملاحظات
eventنوع الحدث (القائمة الكاملة في كتالوج الأحداث).
store_idمعرّف متجرك — مفيد إن كان لديك عدة webhooks لنفس المعالج.
occurred_atمتى حدث الأمر في نظامنا، ISO 8601 مع المنطقة.
dataحمولة خاصة بالحدث. انظر كتالوج الأحداث لشكل كل حدث.
delivery_idفريد لكل محاولة. استخدمه لإزالة التكرار من جانبك.

الحصة

كل محاولة تسليم — نجاح، 4xx، إعادة — تُحسب 1 ضمن webhooks_per_month. حدث واحد يُعاد 5 مرات يكلّف 5. إذًا:

  • اجعل نقطتك موثوقة (تردّ 2xx بسرعة) → محاولة واحدة لكل حدث.
  • الإخفاقات تكلّف أكثر → أصلح الأخطاء بسرعة لتفادي حرق الحصة.

التالي