أعِدّ الـ Webhooks في لوحة التحكم، واستقبل عمليات التسليم، وتحقّق من توقيع HMAC، مع أمثلة لـ curl وNode.js وPHP.
يرسل الـ Webhook طلب HTTP إلى خادمك فور حدوث شيء في مساحة عملك، مثلًا عند نشر صفحة. وبذلك لا تحتاج إلى السؤال باستمرار عمّا إذا كان شيء قد تغيّر. وكل عملية تسليم موقّعة، حتى يستطيع خادمك تمييز الرسائل الحقيقية من المزوّرة.
المتطلبات
- مالك أو مسؤول في مساحة العمل؛ فعنصر القائمة «Webhooks» لا يظهر إلا لهذين الدورين
- ابتداءً من Creator Pro؛ وفي Creator Free تظهر العبارة «الـ Webhooks متاحة ابتداءً من Creator Pro.»
- حتى 5 Webhooks في Creator Pro، و25 في Creator Agency، و100 في Enterprise (قابل للتعديل)
- خادم يمكن الوصول إليه على عنوان https عام
تدير الـ Webhooks في لوحة التحكم فقط. ولا يمكن إنشاؤها أو تغييرها بمفاتيح API.
إنشاء Webhook
- افتح «Webhooks» في التنقل
- انقر «+ Webhook جديد»
- أدخل الرابط الهدف واختر الأحداث
- اختياري: أدخل وصفًا واختر الحالة
- انقر «إنشاء Webhook»
- في خطوة «تم» انسخ سر التوقيع («سر التوقيع – يظهر الآن فقط») واحفظه على خادمك، فهو لا يُعرض إلا الآن
- اختبر الـ Webhook بـ «اختبار». تبقى النتيجة على البطاقة حتى الاختبار التالي: «تم التسليم بنجاح» أو «لم يتم التسليم» مع رمز HTTP (أو «لا يوجد رد») والمدة وبداية الاستجابة
- «الرابط الهدف (https://…)»
- حتى 2048 حرفًا. https فقط، دون بيانات اعتماد في الرابط، ودون عناوين localhost، ودون أسماء داخلية مثل .local أو .internal أو .lan. ويجب أن يشير الاسم إلى عناوين IP عامة؛ ويتحقق LinkHarbor من ذلك مجددًا قبل كل عملية تسليم.
- «الأحداث»
- حدث واحد على الأقل. ولكل مجموعة «تحديد الكل» و«إلغاء تحديد الكل».
- «الوصف»
- اختياري، حتى 255 حرفًا، مثلًا الغرض من الـ Webhook.
- «الحالة»
- «نشط» أو «معطّل». الـ Webhooks المعطّلة لا تتلقى عمليات تسليم.
الأحداث
| الحدث | في لوحة التحكم | متى | محتوى data |
|---|---|---|---|
| page.published | نشر صفحة | نُشرت صفحة، في لوحة التحكم أو عبر الـ API أو بواسطة مساعد ذكاء اصطناعي | page_id، version، checksum، published_by_user_id (قيمته null لمفاتيح API ومساعدي الذكاء الاصطناعي) |
| form.submitted | إرسال نموذج | أرسل زائر نموذجًا على إحدى صفحاتك | form_id، form_name، submission_id، page_id، block_id، submitted_at، values (مفتاح الحقل ← القيمة)، consent (مفتاح الموافقة ← true/false) |
| domain.verified | التحقق من نطاق | تم التحقق من نطاق مخصص بنجاح | domain_id، hostname، verification_method، status |
| domain.disabled | تعطيل نطاق | عُطّل نطاق مخصص في لوحة التحكم (لا عند تخفيض الخطة) | domain_id، hostname، status |
| webhook.test | – (زر «اختبار») | تنقر «اختبار» | message (نص بلغة حساب من يبدأ الاختبار، فلا تعتمد عليه في المطابقة) |
يحتوي form.submitted على القيم تمامًا كما أرسلها الزائر، لكنه لا يحتوي أبدًا على عنوان IP الخاص به أو متصفحه. وتجري عملية التسليم في الخلفية: لا ينتظرها الزائر، وفشلها لا يمنع الإرسال.
بنية عملية التسليم
يرسل LinkHarbor كل عملية تسليم كطلب POST بجسم JSON وبهذه الترويسات:
| الترويسة | المحتوى |
|---|---|
| Content-Type | application/json |
| X-LinkHarbor-Event | اسم الحدث، مثل page.published |
| X-LinkHarbor-Delivery-Id | المعرّف الفريد لعملية التسليم هذه (UUID)، وهو مطابق لـ id في الجسم |
| X-LinkHarbor-Timestamp | وقت الإرسال بثواني Unix |
| X-LinkHarbor-Signature | sha256= متبوعًا بتوقيع HMAC-SHA256 بالنظام الست عشري (hex) |
| X-LinkHarbor-Signature-Version | v1 |
{
"id": "3f1c2a9e-8d4b-4a51-9f0e-6b7c1d2e3f40",
"event": "page.published",
"created_at": "2026-11-01T09:30:12+00:00",
"data": {
"page_id": 42,
"version": 8,
"checksum": "9b1e5c…",
"published_by_user_id": 7
}
} تحصل عمليات إعادة التسليم على id جديد، إضافة إلى الحقلين redelivery_of (معرّف عملية التسليم المُعادة) وdelivery_root (معرّف أول عملية تسليم في هذه السلسلة).
التحقق من التوقيع
لكل Webhook سر توقيع خاص به (32 حرفًا ست عشريًا). تراه مرة واحدة فقط: في الخطوة الأخيرة عند إنشاء الـ Webhook، وبعد «السر ↺» مباشرة. انسخه إلى خادمك فورًا، فلن يعرضه LinkHarbor مرة أخرى لاحقًا. ويحسب LinkHarbor التوقيع به على النحو التالي:
- تكوين الرسالة: الطابع الزمني، ثم نقطة، ثم معرّف التسليم، ثم نقطة، ثم الجسم الخام، أي timestamp.delivery_id.body
- حساب HMAC-SHA256 على هذه الرسالة باستخدام سر التوقيع مفتاحًا
- إرسال النتيجة كسلسلة ست عشرية مع البادئة sha256=
ينبغي أن يتحقق خادمك من التوقيع بمقارنة ثابتة الزمن (constant-time)، وأن يرفض عمليات التسليم التي يزيد عمر طابعها الزمني على 300 ثانية، وأن يحفظ معرّفات التسليم لهذه المدة على الأقل للتعرّف على التكرارات. مهم: الموقَّع هو الجسم الخام كما يصل تمامًا، لا JSON أعدت ترميزه.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const SECRET = process.env.LH_WEBHOOK_SECRET;
const seen = new Set(); // in production: a database or Redis with expiry
app.post('/webhooks/linkharbor', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-LinkHarbor-Timestamp') || '';
const id = req.get('X-LinkHarbor-Delivery-Id') || '';
const sig = req.get('X-LinkHarbor-Signature') || '';
if (!/^\d+$/.test(ts) || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
return res.status(400).send('timestamp');
}
const expected = 'sha256=' + crypto
.createHmac('sha256', SECRET)
.update(ts + '.' + id + '.')
.update(req.body) // raw body as a Buffer
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(sig);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).send('signature');
}
const event = JSON.parse(req.body.toString('utf8'));
const key = event.delivery_root || event.id; // recognise redeliveries of the same chain
if (!seen.has(key)) {
seen.add(key);
// process here, ideally asynchronously in a queue
}
res.sendStatus(200);
});
app.listen(3000); <?php
$secret = getenv('LH_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_LINKHARBOR_TIMESTAMP'] ?? '';
$id = $_SERVER['HTTP_X_LINKHARBOR_DELIVERY_ID'] ?? '';
$sig = $_SERVER['HTTP_X_LINKHARBOR_SIGNATURE'] ?? '';
if (!ctype_digit($ts) || abs(time() - (int)$ts) > 300) {
http_response_code(400);
exit('timestamp');
}
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $id . '.' . $body, $secret);
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit('signature');
}
$event = json_decode($body, true);
// Recognise duplicate deliveries by $event['delivery_root'] ?? $event['id'],
// then process.
http_response_code(200); اختبر نقطة النهاية لديك باستخدام curl
يرسل هذا السكربت عملية تسليم تجريبية موقّعة بشكل صحيح إلى خادمك، وهو مفيد قبل أن تنشئ الـ Webhook في LinkHarbor. وفي عمليات التسليم التجريبية الحقيقية يأتي data.message بلغة الطلب، فلا تعتمد عليه في المطابقة:
SECRET="your-signing-secret"
URL="https://example.com/webhooks/linkharbor"
TS=$(date +%s)
ID=$(uuidgen | tr 'A-Z' 'a-z')
BODY='{"id":"'"$ID"'","event":"webhook.test","created_at":"2026-11-01T09:30:12+00:00","data":{"message":"هذا حدث اختبار لهذا الـ Webhook."}}'
SIG="sha256=$(printf '%s' "$TS.$ID.$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')"
curl -X POST "$URL" \
-H "Content-Type: application/json" \
-H "X-LinkHarbor-Event: webhook.test" \
-H "X-LinkHarbor-Delivery-Id: $ID" \
-H "X-LinkHarbor-Timestamp: $TS" \
-H "X-LinkHarbor-Signature: $SIG" \
-H "X-LinkHarbor-Signature-Version: v1" \
-d "$BODY" الاستجابة والمهلة وإعادة التسليم
- أي استجابة بحالة 2xx تُعد نجاحًا؛ ولا تُتبع عمليات إعادة التوجيه (3xx)
- لدى خادمك 10 ثوانٍ للرد، و5 ثوانٍ كحد أقصى لإنشاء الاتصال
- كل الـ Webhooks لحدث واحد تتشارك 25 ثانية إجمالًا؛ وما لم يحن دوره حتى ذلك الحين يُعلَّم بأنه فاشل ويمكن إعادة تسليمه
- لا يعيد LinkHarbor محاولة عمليات التسليم الفاشلة تلقائيًا
- يمكنك إعادة إرسال عمليات التسليم الفاشلة يدويًا، لكن ليس تلك التي نجحت لاحقًا. ولإعادة التسليم id جديد وcreated_at جديد
- يُسمح بـ 3 محاولات كحد أقصى لكل حدث، بما فيها التسليم الأول؛ وبعدها ينتهي تحت «الرسائل الفاشلة نهائيًا» ولا يمكن إعادة إرساله
عمليات التسليم في لوحة التحكم
يفتح «عمليات التسليم» سجل الـ Webhook. وفيه ثلاثة تبويبات:
- «كل عمليات التسليم»
- كل عمليات التسليم، مع مرشّحات للحدث والحالة («نجاح (2xx)»، «خطأ في العميل (4xx)»، «خطأ في الخادم (5xx)»، «فشل») و«الحد». ويعيد «↺ إعادة المحاولة» تسليم عملية فاشلة، ما دامت لا توجد عملية لاحقة ناجحة. والنقر على صف يعرض الطلب والاستجابة والجسم وJSON الخام.
- «إعادات التشغيل»
- سلاسل عمليات إعادة التسليم مع النتيجة «تمت الاستعادة» أو «ما زال يفشل» وعدد المحاولات.
- «الرسائل الفاشلة نهائيًا»
- عمليات التسليم التي فشلت فيها كل المحاولات المسموح بها، التسليم الأول وعمليات إعادة التسليم معًا. هذا التبويب للعرض فقط: لم يعد بالإمكان إعادة تسليمها. تحقّق من نقطة النهاية لديك؛ بعدها تُسلَّم الأحداث الجديدة كالمعتاد. وإذا احتجت إلى البيانات، فاجلبها عبر الـ API.
إذا لم تنجح إعادة التسليم، تذكر لوحة التحكم السبب:
- «لم تتم إعادة الإرسال: فشل هذا الحدث بالفعل … مرات، ولا يمكن إجراء محاولات أخرى. ستجده ضمن "الرسائل الفاشلة نهائيًا".»
- استُنفدت كل المحاولات الـ 3.
- «لم تتم إعادة الإرسال: تم تسليم هذا الحدث بنجاح في هذه الأثناء.»
- نجحت بالفعل عملية تسليم لاحقة في السلسلة نفسها.
التحقق في لوحة التحكم
تحت «التحقق» تجد أداتين مساعدتين:
- «حزمة التحقق»
- يعرض «تحميل الحزمة» الخوارزمية وأسماء الترويسات وتنسيق الرسالة الموقّعة والتسامح الموصى به البالغ 300 ثانية. أما السر نفسه فغير مشمول.
- «التحقق من التوقيع»
- أدخل معرّف التسليم والطابع الزمني والتوقيع والجسم الخام لطلب عملية تسليم تلقيتها. فيخبرك LinkHarbor بعدها «التوقيع صالح» أو «التوقيع غير صالح». انسخ الطابع الزمني والتوقيع من الترويستين X-LinkHarbor-Timestamp وX-LinkHarbor-Signature. ولا يعمل الفحص إلا لعمليات التسليم من آخر 5 دقائق؛ أما للأقدم منها فيبلّغ «التوقيع غير صالح» حتى لو كان التوقيع صحيحًا.
تدوير السر والتعطيل والحذف
- «السر ↺» يُنشئ سر توقيع جديدًا ويعرضه مرة واحدة؛ ويتوقف القديم عن العمل فورًا، ويجب أن يستخدم خادمك الجديد
- تحت «تعديل» اضبط الحالة على «معطّل» لإيقاف عمليات التسليم مؤقتًا
- أيقونة سلة المهملات تحذف الـ Webhook؛ وإلى أن تغلق الرسالة يمكنك الإلغاء بـ «تراجع»
عند الانتقال إلى خطة أصغر، تُعطَّل الـ Webhooks التي تتجاوز الحد الجديد، وفي Creator Free تُعطَّل كلها. وهي تبقى محفوظة؛ وبعد الترقية يعيد LinkHarbor تلقائيًا تفعيل الـ Webhooks المعطّلة حتى حد الخطة الجديدة، بما في ذلك التي عطّلتها بنفسك.
قد يفيدك أيضًا
لم تجد ما تبحث عنه؟
أخبرنا بما تحتاج إليه، وسيساعدك فريق الدعم لدينا شخصيًا.