الويبهوك

الويبهوك

استقبل استدعاءات HTTP لحظية عند وقوع الأحداث في مساحة عملك — المحادثات والرسائل والتذاكر وتقييمات الرضا.

نظرة عامة

الويبهوك نقطة HTTPS تستضيفها أنت. يرسل عون كير إليها حدث JSON موقّعًا كلما وقع حدث مشترَك فيه.

استخدم الويبهوك لمزامنة التذاكر مع أنظمتك، أو إطلاق سير عمل، أو التنبيه للمحادثات الجديدة، أو تغذية مستودع بيانات — دون استطلاع الواجهة.

إدارة النقاط

أنشئ وأدِر النقاط من كونسول المطورين (أو عبر واجهة REST). لكل نقطة عنوان، ومجموعة أحداث مشترَك فيها، وسر توقيع خاص بها.

احفظ سر التوقيع

يُعرَض سر التوقيع مرة واحدة فقط عند إنشاء النقطة. احفظه بأمان — ستحتاجه للتحقق من التواقيع.

كتالوج الأحداث

الأحداث التي يمكنك اشتراك نقطة فيها.

الحدثالوصف
conversation.createdبدأت محادثة جديدة (من الودجت أو قناة تكامل).
message.createdأُرسلت رسالة في محادثة (واردة أو صادرة).
ticket.createdتم إنشاء تذكرة دعم جديدة.
ticket.status_changedانتقلت التذكرة إلى حالة جديدة.
ticket.comment_createdأُضيف رد عام على تذكرة (تُستثنى الملاحظات الداخلية).
csat.receivedقدّم العميل تقييماً للرضا.

غلاف الحدث

لكل تسليم الغلاف نفسه: معرّف تسليم ثابت، واسم الحدث، وطابع زمني، وبيانات الحدث.

json
{
  "id": "dlv_20",
  "event": "ticket.created",
  "createdAt": "2026-07-31T09:01:00.000Z",
  "data": {
    "id": "tkt_5",
    "number": 1043,
    "subject": "Cannot log in",
    "status": "OPEN"
  }
}

ترافق كل تسليم ترويستان — اسم الحدث والتوقيع.

http
X-AwnCare-Event: ticket.created
X-AwnCare-Signature: t=1753952460,v1=4f8c1e…hex-hmac…

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

تحقّق دائمًا من التوقيع قبل الوثوق بأي حمولة.

ترويسة X-AwnCare-Signature بالصيغة t=TIMESTAMP,v1=SIGNATURE. احسب HMAC-SHA256 على النص المكوّن من الطابع الزمني ثم نقطة ثم جسم الطلب الخام (أي TIMESTAMP.RAWBODY) باستخدام سر نقطتك، وقارنه بـ v1 بزمن ثابت. تحقّق دائمًا من جسم الطلب الخام قبل تحليل JSON.

Node.js (Express + crypto)

js
import crypto from "node:crypto";
import express from "express";

const app = express();
const SECRET = process.env.AWNCARE_WEBHOOK_SECRET; // whsec_…

// IMPORTANT: verify against the RAW body, before JSON parsing.
app.post(
  "/hooks/awncare",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const header = req.get("X-AwnCare-Signature") || "";
    const rawBody = req.body.toString("utf8");

    // Header format: "t=<unix>,v1=<hex hmac-sha256('<t>.<rawBody>')>"
    const parts = Object.fromEntries(
      header.split(",").map((kv) => kv.split("="))
    );
    const timestamp = parts.t;
    const signature = parts.v1;

    const expected = crypto
      .createHmac("sha256", SECRET)
      .update(`${timestamp}.${rawBody}`)
      .digest("hex");

    const valid =
      signature &&
      crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expected)
      );

    if (!valid) return res.status(400).send("invalid signature");

    // Optional: reject old timestamps to prevent replay.
    const ageSec = Math.abs(Date.now() / 1000 - Number(timestamp));
    if (ageSec > 300) return res.status(400).send("stale timestamp");

    const event = JSON.parse(rawBody);
    console.log("Verified", event.event, event.id);

    res.sendStatus(200); // ack fast — process async
  }
);

app.listen(3000);

PHP (hash_hmac)

php
<?php
// AwnCare webhook receiver — signature verification.
$secret = getenv('AWNCARE_WEBHOOK_SECRET'); // whsec_…
$rawBody = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_AWNCARE_SIGNATURE'] ?? '';

// Parse "t=<unix>,v1=<hex>"
parse_str(str_replace(',', '&', $header), $parts);
$timestamp = $parts['t'] ?? '';
$signature = $parts['v1'] ?? '';

$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(400);
    exit('invalid signature');
}

// Optional replay guard.
if (abs(time() - (int) $timestamp) > 300) {
    http_response_code(400);
    exit('stale timestamp');
}

$event = json_decode($rawBody, true);
error_log('Verified ' . $event['event'] . ' ' . $event['id']);

http_response_code(200); // ack fast

إعادة المحاولة والإخفاقات

التسليم مرة واحدة على الأقل. تُعاد محاولة التسليمات الفاشلة بتباطؤ.

  • جدول التباطؤ بعد كل محاولة فاشلة: دقيقة واحدة، ثم 5 دقائق، ثم 30 دقيقة.
  • حتى 4 محاولات إجمالًا (1 أولية + 3 إعادات) قبل التخلي عن التسليم.
  • تُعطَّل تلقائيًا أي نقطة تبلغ 10 إخفاقات متتالية.
  • تُعيد المحاولات إرسال جسم مطابق بايتًا ببايت بالمعرّف نفسه، فيمكنك إزالة التكرار به.
يُعدّ التسليم ناجحًا عند أي استجابة 2xx. استجب بـ 2xx بسرعة وعالج المهمة لاحقًا.

أفضل الممارسات

بضع قواعد تُبقي تكاملك متينًا مع إعادة المحاولة وعند التوسع.

كن مُعادًا بأمان

قد يصل الحدث نفسه أكثر من مرة. أزِل التكرار باستخدام معرّف الغلاف.

أقرّ بالاستلام بسرعة

أعِد 2xx فورًا ونفّذ العمل الثقيل لاحقًا؛ الاستجابات البطيئة تُحتسب إخفاقًا وتُطلق إعادة المحاولة.

تحقّق ثم حلّل

افحص التوقيع مقابل الجسم الخام قبل تحليل JSON أو التصرف بناءً على الحدث.

استخدم HTTPS

يجب أن تكون النقاط عبر HTTPS في الإنتاج لتبقى الحمولات والتواقيع سرّية أثناء النقل.