خطافات الويب الصادرة
خطاف الويب الصادر (outgoing webhook) رسالة ترسلها اللوحة إلى عنوان تملكه حين يحدث شيء لحساب استضافة، ليتمكن نظام آخر من التفاعل: فوترتك الخاصة، أو قناة دردشة، أو جدول بيانات، أو سكربت توفير.
خطافات الويب متاحة لـ المسؤولين والموزّعين. يسمع المسؤول عن كل حساب. ويسمع الموزّع عن الحسابات التي تخصه هو فقط. لا يستطيع العملاء ولا رموز API إنشاءها: فخطافات الويب تُعدّ في اللوحة نفسها، ضمن جلسة الشخص الخاصة، حتى لا يتحول رمز مسرَّب أبدًا إلى تغذية دائمة بأحداث اللوحة.
أضف واحدًا
افتح صفحة أمان حسابك (للمسؤول: الأمان؛ وللموزّع: أمان تسجيل الدخول)، وابحث عن خطافات الويب أسفل رموز API.
- اكتب العنوان، مثلًا
https://example.com/hooks/panel. - ضع علامة على الأحداث التي تريدها.
- اضغط إضافة خطاف ويب.
تعرض اللوحة سرّ التوقيع (يبدأ بـ whsec_) مرة واحدة. انسخه الآن. يُخزَّن مشفّرًا
ولا يمكن عرضه مجددًا؛ وإن فقدته فاحذف الخطاف وأضف واحدًا جديدًا.
يمكن لكل شخص أن يملك 10 خطافات ويب على الأكثر.
العنوان
- يجب أن يبدأ بـ
https://. يُرفضhttp://العادي لأن الاستدعاء يحمل تفاصيل الحسابات. - يجب ألا يحتوي على اسم مستخدم أو كلمة مرور. تحقّق من التوقيع بدلًا من ذلك.
- يمكن أن يبلغ طوله 500 حرف على الأكثر.
- يجب أن يكون على الإنترنت العام. تُرفض العناوين الواقعة على هذا الخادم، أو على شبكة خاصة، أو على واجهة loopback، أو في نطاق البيانات الوصفية (metadata) لمزوّد السحابة، عند حفظ العنوان وكذلك مرة أخرى لحظة اتصال اللوحة (فاسم المضيف الذي يشير لاحقًا إلى عنوان خاص لا يعمل أيضًا).
- لا تُتبَع عمليات إعادة التوجيه. أعطِ العنوان النهائي.
الأحداث
| الحدث | يُرسَل عندما |
|---|---|
account.created |
يُنشأ حساب استضافة |
account.suspended |
يُعلَّق حساب |
account.unsuspended |
يُعاد حساب معلَّق |
account.deleted |
يُحذف حساب |
account.activity |
يقع نشاط آخر على حساب |
يرسل زر اختبار على كل خطاف ويب حدثًا اسمه ping، لترى أن عنوانك يجيب. ولا يمكن أن ينتظر إلا
اختبار واحد في الوقت نفسه.
ما الذي يُرسَل
كل استدعاء هو طلب HTTP من نوع POST بجسم JSON:
{
"event": "account.created",
"at": "2026-10-23T08:15:00Z",
"account": { "id": 42, "username": "example", "domain": "example.com" },
"detail": "short text about what happened"
}
at وقت UTC. وللحدث ping الشكل {"event":"ping","at":"…","webhook_id":7}.
تأتي هذه الترويسات مع كل استدعاء:
| الترويسة | المعنى |
|---|---|
X-Nimbopanel-Event |
اسم الحدث، مثل account.created |
X-Nimbopanel-Delivery |
رقم يعرّف هذا التسليم. إعادة محاولة التسليم نفسه تحتفظ بالرقم نفسه، فاستخدمه لتجاهل التكرارات |
X-Nimbopanel-Timestamp |
وقت توقيع الاستدعاء، بثوانٍ على طريقة Unix |
X-Nimbopanel-Signature |
sha256= متبوعًا بالتوقيع (أدناه) |
Content-Type |
application/json |
User-Agent |
Nimbopanel-Webhook/1 |
تحقّق من التوقيع
يستطيع أي أحد إرسال طلب إلى عنوانك. والتوقيع هو ما تعرف به أن الاستدعاء جاء من لوحتك.
التوقيع هو HMAC-SHA256 بصيغة سداسية عشرية (hex) للطابع الزمني ثم نقطة ثم الجسم الخام تمامًا كما وصل، يُحسب بسرّ التوقيع الخاص بك:
X-Nimbopanel-Signature == "sha256=" + hex( HMAC_SHA256( secret, X-Nimbopanel-Timestamp + "." + body ) )
تحقّق بهذا الترتيب:
- احسب القيمة أعلاه من جسم الطلب الخام (قبل أي تحليل JSON أو إعادة تنسيق).
- قارنها بالترويسة باستخدام مقارنة زمنها ثابت (constant-time).
- ارفض الاستدعاء إن كان الطابع الزمني يبعد أكثر من 5 دقائق عن ساعتك. هذا يمنع من يعيد إرسال استدعاء قديم.
- استخدم
X-Nimbopanel-Deliveryلتجاهل تسليم عالجته بالفعل.
مثال بلغة PHP:
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_NIMBOPANEL_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_NIMBOPANEL_SIGNATURE'] ?? '';
$want = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!hash_equals($want, $sig) || abs(time() - (int) $ts) > 300) {
http_response_code(401);
exit;
}
مثال بلغة Node.js:
const crypto = require('crypto');
function valid(rawBody, headers, secret) {
const ts = headers['x-nimbopanel-timestamp'] || '';
const want = 'sha256=' + crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex');
const got = headers['x-nimbopanel-signature'] || '';
return got.length === want.length
&& crypto.timingSafeEqual(Buffer.from(got), Buffer.from(want))
&& Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
}
الإجابة وإعادة المحاولة والإيقاف المؤقت
- أجب بأي حالة 2xx خلال 10 ثوانٍ. أي شيء آخر يُحتسب إخفاقًا.
- يُعاد الاستدعاء الفاشل بعد دقيقة واحدة، ثم 5 دقائق و30 دقيقة وساعتين. هذه خمس محاولات في المجموع، موزّعة على نحو ساعتين ونصف، ثم يُعلَّم التسليم بأنه فاشل.
- تُرسَل الاستدعاءات إلى عنوان واحد واحدًا تلو الآخر، الأقدم أولًا. التسليم الذي ينتظر إعادة المحاولة لا يؤخّر الأحدث منه، فلا تعتمد على وصول الأحداث بترتيب صارم. والعنوان البطيء يؤخّر نفسه فقط.
- بعد 50 تسليمًا فاشلًا متتاليًا، يتوقف خطاف الويب مؤقتًا: لا تُوضع أحداث جديدة في طابوره. ويمسح الاختبار الناجح العدّاد فتعود الأحداث إلى التدفق.
- ينتظر ما لا يزيد على 200 استدعاء غير مسلَّم لخطاف ويب واحد. وبعد ذلك لا تُوضع أحداث إضافية له في الطابور حتى يُسلَّم بعضها أو يفشل.
- تحتفظ اللوحة بأحدث 50 تسليمًا منتهيًا لكل خطاف ويب، مع الإجابة التي تلقّتها، لترى ما الذي فشل. وتُسرد أحدثها أسفل الخطاف.
إن عرضت اللوحة سببًا بدلًا من حالة، فهو واحد من التالي: العنوان ليس على الإنترنت العام، أو لا إجابة خلال 10 ثوانٍ، أو اسم المضيف غير موجود، أو شهادة HTTPS غير صالحة، أو تعذّر اتصال اللوحة.
عادات جيدة
- أجب بسرعة بـ
200وأنجز العمل الفعلي بعد ذلك. المستقبِل الذي يستغرق أكثر من 10 ثوانٍ يبدو إخفاقًا، فيتلقى الحدث نفسه مرة أخرى. - عالج التسليم نفسه مرتين دون ضرر. إعادات المحاولة وأخطاء الشبكة تجعل التكرار ممكنًا.
- أبقِ السرّ خارج مستودع شيفرتك. وإن تسرّب، فاحذف الخطاف وأضف واحدًا جديدًا.
ذو صلة: دليل الموزّع · استكشاف الأخطاء