
# Webhooks شركات التوصيل

تدفع شركات التوصيل تحديثات التوصيل إلى CodFlow. يتحقق الخادم من التوقيع، ويخزّن الأحداث في صندوق وارد، ويجيب شركة التوصيل فورًا، ثم يعالج الأحداث بعد الاستجابة. ويقرأ تكاملك حالة الشحنة الناتجة عبر API.

لاستقبال أحداث متجرك أنت على خادمك، اقرأ [Webhooks](/ar/webhooks) بدلًا من هذه الصفحة.

توجد Webhooks واردة لـ **Yalidine** و**ZR Express**. أما NOEST وEcoTrack فلا ترسلان Webhooks؛ بل تُزامَن شحناتهما كل خمس دقائق عبر مهمة cron وعند الطلب عبر نقاط نهاية مزامنة الشحنات.

## نقاط النهاية

| شركة التوصيل | نقطة النهاية | شكل الإرسال | التوقيع |
| --- | --- | --- | --- |
| Yalidine | `POST /webhooks/yalidine` | دفعة أحداث من نوع واحد | HMAC-SHA256 في `x-yalidine-signature` |
| Yalidine | `GET /webhooks/yalidine` | تحدّي CRC | يعيد `crc_token` كنص عادي |
| ZR Express | `POST /webhooks/zr_express` | حدث Svix واحد لكل طلب | Svix HMAC-SHA256 |

المسارات هي عناوين URL التي تحتفظ بها شركات التوصيل. لا تضعها خلف مصادقة: فشركات التوصيل لا تستطيع إرسال مفتاح API الخاص بك. التوقيع هو المصادقة.

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

<Stepper>

1. **من شركة التوصيل إلى CodFlow**

   ترسل شركة التوصيل طلب `POST` موقّعًا إلى `/webhooks/yalidine` أو `/webhooks/zr_express`.

1. **التحقق والتقسيم**

   يتحقق CodFlow من التوقيع باستخدام سر الشركة ويقسّم غلاف شركة التوصيل إلى أحداث فردية.

1. **التخزين في صندوق الوارد**

   يُخزَّن كل حدث في `webhook_events` بمفتاح معرّف الحدث من المزوّد.

1. **الرد على شركة التوصيل**

   يعيد CodFlow `200 {"received":true}` دون انتظار المعالجة.

1. **المعالجة بعد الاستجابة**

   بعد ثوانٍ توقظ طابور الأحداث الـ drain، فيطبّق مراحل الشحنة لكل حدث ويسجّل أحداث الأعمال (Business Events) الخاصة بها. وتشغّل المهمة المجدولة كل خمس دقائق الـ drain نفسه، فيُعالَج أيضًا أي حدث فاته إيقاظ ضائع.

</Stepper>

تحصل شركة التوصيل على `200` بمجرد تخزين الأحداث. ولا تُفشل إخفاقات المعالجة الـ webhook؛ إذ يعيد الـ drain محاولتها وفق جدول صندوق الوارد. وتتطلب Yalidine استجابة خلال 10 ثوانٍ وتعيد محاولة التسليم الفاشل سبع مرات على مدى 40 ساعة، ولهذا يهم هذا الفصل.

## إعداد Webhook

يبدأ المساران من صفحة بيانات اعتماد شركة التوصيل في لوحة التحكم.

### Yalidine

1. افتح صفحة بيانات اعتماد الشركة وانسخ عنوان URL للاستقبال من بطاقة إعداد الـ webhook.
2. في Webhooks Dashboard الخاصة بـ Yalidine، أنشئ نقطة نهاية بهذا العنوان.
3. اشترك في أنواع الأحداث التي تحتاجها. تتحقق Yalidine من العنوان عبر تحدّي CRC.
4. انسخ سر التوقيع من Yalidine إلى البطاقة واحفظه. واحفظ القيمة نفسها في مدير الأسرار لديك.

### ZR Express

1. افتح صفحة بيانات اعتماد الشركة واختر **Register webhook**.
2. يسجّل الخادم نقطة النهاية لدى ZR Express ويجلب سر التوقيع نيابة عنك.
3. تعرض البطاقة نقطة النهاية كمسجّلة. استخدم **Unregister** لإزالتها.

أرسل حدث اختبار من الشركة الناقلة وتأكد من وصوله إلى شركة التوصيل في لوحة التحكم.

يحتاج webhook إلى سره. يُرفض التسليم الذي لا يتحقق منه سر أي شركة بالرمز `401` ولا يُخزَّن أبدًا: فما تبلّغ عنه شركة التوصيل يصبح حدثًا تجاريًا قد تُبلَّغ به أنظمة التجار والعملاء، لذا يجب إثبات أنه صادر عن شركة التوصيل. وإذا لم تُعطِ ZR Express سر التوقيع، يُلغى التسجيل ولا يُحفظ شيء؛ سجّل من جديد.

## التحقق من التوقيع

### Yalidine

توقّع Yalidine جسم الطلب الخام بـ HMAC-SHA256 باستخدام سر webhook الخاص بالشركة. يصل التوقيع في `x-yalidine-signature` (أو `x_yalidine_signature`). ويقبل الخادم التمثيلات السداسية العشرية (hex) بالأحرف الصغيرة والكبيرة وbase64، ويقارن في زمن ثابت.

تحدّي GET منفصل: عندما ترسل Yalidine معاملات الاستعلام `subscribe` و`crc_token`، يعيد الخادم الرمز كنص عادي. يتيح ذلك لـ Yalidine التحقق من العنوان قبل بدء إرسال الأحداث.

### ZR Express

تستخدم ZR Express نظام Svix. المحتوى الموقّع هو:

```text
{svix-id}.{svix-timestamp}.{rawBody}
```

يصل التوقيع في `svix-signature`، ويقبل الخادم أي عنصر `v1,<base64>` مفصول بمسافات. ويُرفض أي `svix-id` أو `svix-timestamp` أو `svix-signature` مفقود.

## التكرار الآمن والترتيب

- تجمع Yalidine أحداثًا كثيرة في طلب واحد. ولكل حدث `event_id` خاص به، وهو مفتاح صندوق الوارد.
- ترسل ZR Express حدثًا واحدًا لكل طلب. و`svix-id` هو مفتاح صندوق الوارد.
- يتجاهل صندوق الوارد التسليمات المكررة، لذا لا تستطيع إعادة محاولة شركة التوصيل تطبيق الحدث نفسه مرتين.
- قد تصل الأحداث بترتيب مختلف. يطبّق الخادم مراحل الشحن وفق طابع وقت الحدث، لا وفق ترتيب الوصول.

## التطوير المحلي

تحتاج شركات التوصيل إلى عنوان HTTPS عام. اكشف Worker المحلي عبر نفق تثق به، ثم اضبط ذلك الأصل لدى شركة التوصيل. بالنسبة إلى Yalidine، أنشئ نقطة النهاية على `<tunnel-origin>/webhooks/yalidine` واحفظ سرها في بطاقة webhook الخاصة بالشركة. وبالنسبة إلى ZR Express، أرسل أصل النفق كـ `X-Worker-URL` عند التسجيل، حتى تشير نقطة النهاية المنشأة إلى النفق بدلًا من `localhost`.

يبقى المستقبل المحلي `http://localhost:8787/webhooks/yalidine` أو `/webhooks/zr_express`، لذا يمكنك إعادة إرسال حمولة موقّعة باستخدام `curl` أثناء التطوير:

```bash
curl -X POST http://localhost:8787/webhooks/yalidine \
  -H "Content-Type: application/json" \
  -H "x-yalidine-signature: <hex hmac of the raw body>" \
  --data-binary @event.json
```

## ذو صلة

- [الشحنات](/api/shipments) في مرجع API
- [الأخطاء](/ar/errors) لغلاف إخفاق التوصيل
- [شركات التوصيل](/api/delivery-companies) لإعداد المزوّد والمزامنة
