§ 00ما هي Webhooks
عندما يحدث شيء من جانب EasyLiveChat — يرسل عميل رسالة في الويدجت، يُغلق وكيل محادثة، يحدث إجراء يهم التدقيق — نُرسل POST عبر HTTPS إلى كل URL سجّلته. الجسم JSON ويحتوي على حمولة الحدث كاملة، حتى يستطيع خادمك التفاعل دون استطلاع.
اعتبره الصورة المرآة لـ REST API. الواجهة لكي يمتد كودك إلى EasyLiveChat. الـ Webhooks لكي تمتد EasyLiveChat إلى كودك. معظم التكاملات تستخدم كليهما.
كل نقطة مسجّلة لها سرّها الخاص. نوقّع كل جسم طلب بـ HMAC-SHA256 باستخدام ذلك السر ونرسل البصمة السداسية في رأس x-easylivechat-signature. خادمك يعيد حساب الـ HMAC بنفس السر ويقارن — التطابق يعني أن الطلب جاء منا فعلاً، وعدم التطابق يعني تجاهله.
§ 01توفر الخطة
يمكن إنشاء نقاط Webhook على كل خطة مدفوعة وخلال التجربة المجانية لمدة 14 يومًا. لا توجد فوترة لكل حدث — التوزيع على نقاط متعددة مشمول.
تدفّق audit.event مقصور على خطة Enterprise، يحرسه استحقاق auditWebhookExport. الحدثان message.created و conversation.updated يُطلقان في كل خطة تسمح بالوصول للـ API.
§ 02إعداد نقطة نهاية
أضف نقطة في https://app.livechattools.com/settings/webhooks. سننشئ سرًّا عشوائيًا خاصًا بكل نقطة ونعرضه لك مرة واحدة فقط عند الإنشاء. عامله مثل كلمة مرور — انسخه فورًا إلى مخزن أسرار خادمك.
- العنوان (URL) — يجب أن يكون https:// ويُحلَّ إلى عنوان IP عام. نرفض عناوين الاسترجاع والخاصة وعناوين بيانات السحابة عند الإنشاء وأثناء التسليم.
- الأحداث — إما اختر أسماء أحداث محددة أو اشترك في * (كل الأحداث). علامة النجمة مريحة للنماذج الأولية، لكن قوائم الأحداث الأضيق تجعل المُعالج أسهل في الفهم.
- السر — يُنشأ تلقائيًا ويُعرض مرة واحدة. يُستخدم لتوقيع كل توصيل. إذا فقدته، احذف النقطة وأنشئ نقطة جديدة — لا يوجد مسار للاسترداد.
نشطة افتراضيًا. يمكنك إلغاء نقطة في أي وقت من نفس الصفحة — يتوقف التسليم على الفور.
§ 03شكل الحمولة
كل توصيل هو POST بنوع المحتوى application/json. الرؤوس تحدد الحدث وتحمل التوقيع؛ غلاف الجسم دائمًا { event, deliveredAt, data }:
POST https://your-server.example.com/webhook
content-type: application/json
user-agent: EasyLiveChat-Webhooks/1.0
x-easylivechat-event: message.created
x-easylivechat-signature: sha256=<hex>
{
"event": "message.created",
"deliveredAt": "2026-05-27T08:55:25.841Z",
"data": {
"conversationId": "cmp...",
"message": {
"id": "cmp...",
"body": "Hi!",
"senderType": "CUSTOMER",
"createdAt": "2026-05-27T08:55:25.840Z"
}
}
}event هو نفس قيمة رأس x-easylivechat-event. شكل data يختلف حسب الحدث — انظر كتالوج الأحداث أدناه.
§ 04تحقق من التوقيع
أي شخص يعرف عنوان نقطتك يمكنه إرسال POST بمحتوى غير مرغوب فيه. توقيع HMAC هو الطريقة لتمييز طلباتنا عن المزيّفة. أعِد حسابه بسرّك وارفض الطلب عند عدم التطابق.
اقرأ بايتات الجسم الخام (لا تقم بـ json.parse أولاً — إعادة التسلسل ستعيد ترتيب المفاتيح وتُكسر التجزئة). أزل البادئة sha256= من رأس التوقيع. احسب HMAC-SHA256(rawBody, secret) وقارن بطريقة آمنة زمنيًا مع الـ hex المستلم.
Node.js
import crypto from 'node:crypto';
import express from 'express';
const SECRET = process.env.WEBHOOK_SECRET;
const app = express();
app.use(express.raw({ type: 'application/json' }));
app.post('/webhook', (req, res) => {
const received = (req.header('x-easylivechat-signature') || '').replace(/^sha256=/, '');
const expected = crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
const ok =
received.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(received, 'hex'), Buffer.from(expected, 'hex'));
if (!ok) return res.status(401).send('bad signature');
const event = JSON.parse(req.body.toString('utf8'));
// handle event.event, event.data...
res.status(200).send('ok');
});Python (Flask)
import hmac, hashlib, os
from flask import Flask, request, abort
SECRET = os.environ["WEBHOOK_SECRET"].encode()
app = Flask(__name__)
@app.post("/webhook")
def webhook():
received = request.headers.get("x-easylivechat-signature", "").removeprefix("sha256=")
expected = hmac.new(SECRET, request.get_data(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(received, expected):
abort(401)
event = request.get_json()
# handle event["event"], event["data"]...
return "ok", 200curl (debugging)
# Recompute the signature locally and compare with the header. echo -n "$RAW_BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET"
timingSafeEqual / hmac.compare_digest — استخدم دائمًا مقارنة بزمن ثابت حتى لا يستطيع المهاجمون فحص السر بايتًا بايتًا.
§ 05كتالوج الأحداث
تطلق المنصة اليوم أربعة أنواع أحداث. نضيف المزيد مع شحن الميزات — اشترك في * إذا أردت توافقًا مستقبليًا.
| الحدث | يُطلق عند | شكل البيانات |
|---|---|---|
| message.created | تصل رسالة جديدة إلى محادثة، بغض النظر عن من أرسلها (عميل وارد، وكيل صادر، إرسال REST API). | { conversationId, message } |
| conversation.updated | تتغير حالة محادثة (OPEN · SNOOZED · CLOSED) أو assignedAgentId الخاص بها. | { conversationId, status?, assignedAgentId? } |
| audit.event | كلما كُتب سجل تدقيق — تسجيل دخول وكيل، تغيير دور، إنشاء تكامل، إلغاء مفتاح، إلخ. (خطة Enterprise.) | { action, entity, entityId, actorId, metadata } |
| webhook.test | تنقر على "Test" في الإعدادات ← Webhooks. موقّع ومشكّل تمامًا مثل حدث حقيقي. | { tenantId, test: true } |
اشترك في * لاستلام كل حدث حالي ومستقبلي. اشترك بأسماء محددة إذا أردت تقييد ما يجب أن يعرفه المُعالج.
§ 06اختبار التكامل
زر "Test" في الإعدادات ← Webhooks يُطلق حدث webhook.test على نقطتك ويُبلّغ بحالة HTTP والوقت المنقضي. استخدمه للتحقق من معالجك قبل توجيه حركة حقيقية إليه.
تستخدم حمولة الاختبار نفس غلاف الجسم وأسماء الرؤوس ومخطط HMAC تمامًا كأحداث الإنتاج — إذا نجح تحققك من webhook.test، فسينجح من message.created وكل شيء آخر.
§ 07إعادة المحاولة والمهلات
نمنح خادمك 10 ثوانٍ للرد. أي حالة غير 2xx أو خطأ شبكة هو فشل. التوصيلات الفاشلة تُعاد محاولتها حتى 5 مرات بتراجع أُسّي يبدأ من ثانيتين، فحتى نقطة غير مستقرة تحصل على عدة فرص قبل أن نتخلى عن ذلك الحدث.
لا نضمن التسليم لمرة واحدة بالضبط — تحت تذبذب الشبكة قد يصل الحدث نفسه مرتين. اجعل المُعالج عند نقطته (idempotent): أزل التكرار بناءً على data.message.id الداخلي (أو أي معرّف منطقي لذلك الحدث).
§ 08قائمة الأمان
- استخدم https:// دائمًا — تُرفض نقاط http:// العادية عند الإنشاء.
- نحجب عناوين IP الخاصة وlooking وcloud-metadata في وقت الإنشاء والتسليم، حتى لا يُستخدم سجل DNS مُكوّن خطأ للتمحور داخل شبكتك.
- قارن التواقيع باستخدام مساواة آمنة زمنيًا (Node crypto.timingSafeEqual، Python hmac.compare_digest، Go hmac.Equal).
- قم بالتدوير بحذف النقطة وإنشاء جديدة بنفس الـ URL. حدّث مخزن الأسرار بشكل ذرّي.