+
A

بواسطة Avi

نُشر في 31 يوليو 2026

خطافات الويب في WhatsApp: كيفية إعداد الأحداث الواردة والتعامل معها باستخدام Chakra Chat

يبدأ كل تكامل ثنائي الاتجاه مع WhatsApp بخطاف ويب. يغطي هذا الدليل نوعَي خطافات الويب في Chakra، وحمولات الأحداث الفعلية، والتحقق من توقيع HMAC، والتعامل مع عمليات التسليم المكررة، وإنشاء موجّه للرسائل؛ أي كل ما يحتاج إليه n8n وZapier وأدوات إنشاء التكاملات المخصصة.

يبدأ كل تكامل ثنائي الاتجاه مع WhatsApp — سواء أكان روبوت محادثة، أم مزامنة CRM، أم أتمتة عبر n8n، أم مسار إشعارات مخصصاً — من المكان نفسه: خطاف ويب. تعمل Cloud API من WhatsApp بشكل غير متزامن. عند إرسال رسالة، تتلقى إقراراً بقبولها، لا تأكيداً بوصولها. وكل ما يحدث بعد ذلك — التسليم، وإيصالات القراءة، والردود، والإخفاقات — يصل إليك كحدث عبر خطاف ويب تتحكم فيه.

يغطي هذا الدليل كيفية إتاحة Chakra لهذه الأحداث، ونوعَي خطافات الويب المتاحين والمختلفين، وبُنى حمولاتهما، وكيفية التحقق من أن الأحداث واردة فعلاً من Chakra، والتعامل مع عمليات التسليم المكررة التي ستواجهها في نهاية المطاف، إلى جانب نمط توجيه بسيط لإدارة كل شيء بسلاسة في مكان واحد.

نوعان من خطافات الويب، لا نوع واحد

تتيح لك Chakra طريقتين منفصلتين لتلقي الأحداث الواردة، واختيار الطريقة المناسبة يؤثر في مقدار عمل تحليل البيانات الذي ستتولاه.

خطاف ويب لأحداث التمرير المباشرخطاف ويب لأحداث Chakra
التنسيقحمولة Meta Cloud API الأصلية، من دون تعديلحمولة مبسطة وموحّدة وفق تنسيق Chakra
تغطية الأحداثكل ما ترسله Meta — الرسائل، والحالة، وإرسال القوالب، وتحديثات الحسابمجموعة منتقاة: message, status, message_echo, smb_message_echo
الأنسب لـالفرق المُلِمّة بالفعل بمخطط خطافات الويب لدى Meta، أو التي تنقل عمليات التكامل الحاليةالفرق التي تريد تقليل عبء تحليل البيانات والحصول على بنية موحّدة، بصرف النظر عن تغييرات مخطط Meta
الاستخدام المعتادتدفقات n8n/Zapier المبنية وفق تنسيق خطاف الويب الموثّق لدى Metaتكاملات الأنظمة الخلفية المخصصة، ومزامنة CRM، ومنطق توجيه أبسط

يمكنك إعداد أي منهما أو كليهما؛ فهما إعدادان مستقلان، ولا يمنعك شيء من استخدام خطاف ويب من Chakra للتكامل الأساسي، وآخر للتمرير المباشر لأداة محددة مثل n8n تتوقع البنية الأصلية من Meta.

إعداد خطاف ويب التمرير المباشر

يرسل هذا التنسيق الأحداث بصيغة Meta الأصلية من دون أي تعديل، تماماً كما هو موثّق في مرجع خطافات الويب لـ Cloud API من Meta.

لإعداده:

  1. انتقل إلى صفحة WhatsApp Setup في لوحة تحكم Chakra
  2. انقر على علامة التبويب More
  3. اعثر على الحقل المسمى "Pass-through webhook URL for Meta events"
  4. الصق عنوان URL لنقطة النهاية
  5. انقر على Save

هذا هو المسار الذي تستخدمه معظم تكاملات n8n وZapier، إذ تتوقع هذه المنصات عادةً بنية خطاف الويب الأصلية من Meta أو تُبنى اعتماداً عليها.

إعداد خطاف ويب أحداث Chakra

هذا هو التنسيق الموحّد الخاص بـ Chakra؛ إذ يوفر بنية ثابتة بصرف النظر عن التغييرات التي تجريها Meta من جانبها.

لإعداده:

  1. انتقل إلى WhatsApp Setup → More
  2. فعّل مفتاح التبديل "Enable Chakra Webhooks"
  3. أدخل عنوان نقطة النهاية في الحقل "Chakra webhook URL"
  4. حدّد أنواع الأحداث التي تريدها ضمن "Which events to send" — لن يتم إرسال سوى الأنواع التي تحددها
  5. انقر على Save

يجب أن تكون نقطة النهاية متاحة للعامة، ولا تحتاج إلى إعداد مصادقة من جانبك (إذ يجري التحقق عبر توقيع HMAC بدلاً من ذلك — المزيد عن هذا أدناه).

أنواع الأحداث وبنية الحمولة

تنسيق التمرير المباشر (البنية الأصلية من Meta)

تصل جميع الأحداث ضمن بنية Meta القياسية entry → changes → value ، مع حقل field يبيّن نوع الحدث. ومن أكثرها شيوعاً:

رسالة نصية واردة (field: "messages"):

{  "object": "whatsapp_business_account",  "entry": [    {      "id": "83784929738012",      "changes": [        {          "value": {            "messaging_product": "whatsapp",            "metadata": {              "display_phone_number": "917259775805",              "phone_number_id": "694794789348887"            },            "contacts": [              { "profile": { "name": "John" }, "wa_id": "919911223344" }            ],            "messages": [              {                "from": "919911223344",                "id": "wamid.HBgMOTEST3AxMjU4NDMzFQIAEhgUM0VCMDM3RjlEQTNDQTBEMjQ2Q275",                "timestamp": "1756322278",                "type": "text",                "text": { "body": "Hi, can you please help me out with an issue" }              }            ]          },          "field": "messages"        }      ]    }  ]}

رسالة صورة واردة — البنية نفسها، لكن بقيمة مختلفة للحقل type:

{  "messages": [    {      "from": "919911223344",      "id": "wamid.HBgMOTEST3AxMjU4NDMzFQIAEhgUM0VCMDM3RjlEQTNDQTBEMjQ2Q275",      "timestamp": "1756322278",      "type": "image",      "image": {        "mime_type": "image/jpeg",        "sha256": "t8K9fuzwAoeBSOoIZWkBlI1hTflUHqSwCvGwJ+exm74=",        "id": "1402363984735353"      }    }  ]}

لاحظ أن حدث الصورة لا يتضمن سوى معرّف الوسائط، لا الملف نفسه؛ عليك جلب الوسائط الفعلية بشكل منفصل عبر نقطة نهاية جلب الوسائط في Chakra باستخدام ذلك المعرّف.

حدث إرسال قالب (field: "message_template_sends") — يُطلق عند إرسال رسالة قالب بدأت عبر API، وهو مفيد لتسجيل ما أُرسل وإلى من تحديداً من دون الاحتفاظ بسجل إرسال منفصل خاص بك:

{  "field": "message_template_sends",  "value": {    "message_template_sends": [      {        "id": "wamid.HBgMOTE5OTAxMjU4NDMzFQIAERgSMjNBQkQ5NDA5NTFEN0MzOTU2AA==",        "timestamp": 1763821065,        "to": "919911223344",        "type": "template",        "template": {          "language": { "policy": "deterministic", "code": "en_US" },          "name": "new_year_promo_24",          "components": [            { "type": "body", "parameters": [{ "type": "text", "text": "John" }] }          ]        }      }    ]  }}

بما أن خطاف الويب هذا يمرر تنسيق Meta من دون تعديل، فإن أحداث حالة التسليم والقراءة، وأحداث الأخطاء، وتحديثات الحساب تتبع جميعها البنية نفسها الموثّقة في مرجع خطافات الويب لـ Cloud API الخاص بـ Meta؛ لذا يجدر وضع تلك الصفحة في الإشارات المرجعية إلى جانب هذا الدليل.

تنسيق أحداث Chakra

يصل كل حدث متضمناً مفتاحين على مستوى الجذر بالضبط:

{  "event": "message",  "payload": { /* MessagePayload or DeliveryStatusPayload, depending on event type */ }}

event يأخذ إحدى أربع قيم:

  • message — رسالة واردة وصلت إلى رقمك
  • status — تحديث لحالة تسليم رسالة أُرسلت سابقاً عبر API (أُرسلت، تم التسليم، قُرئت، فشل الإرسال)
  • message_echo — رسالة صادرة أُرسلت من داخل منصة Chakra نفسها (مثل رد وكيل من صندوق الوارد المشترك)، وهي مفيدة إذا كنت تزامن سجل المحادثات الكامل مع نظام خارجي
  • smb_message_echo — رسالة صادرة أُرسلت من تطبيق WhatsApp Business، وهي مهمة تحديداً إذا كنت تستخدم Coexistence وتحتاج إلى تسجيل الرسائل المرسلة من التطبيق، لا من API فحسب

هذا الشكل الموحّد هو ما يجعل إنشاء موجّه يستند إلى خطاف Chakra أسهل؛ إذ ستتفرع دائمًا بناءً على الحقل event نفسه، بصرف النظر عن شكل المخطط الأساسي لدى Meta في ذلك الشهر.

التحقق من موثوقية خطاف الويب باستخدام HMAC

بما أن نقطة نهاية خطاف الويب لديك عامة ولا تتطلب مصادقة للطلبات الواردة، فمن المهم التحقق من أن الحدث قد وصل فعلًا من Chakra ولم يتم العبث به قبل اتخاذ أي إجراء بشأنه.

الإعداد:

  1. انتقل إلى Admin → Team → Secrets وأعِدّ سر HMAC
  2. بعد إعداد السر، سيتضمن كل استدعاء لخطاف الويب ترويسة X-Chakra-Signature-256

منطق التحقق: أنشئ تجزئة HMAC-SHA256 لسلسلة نص الطلب الخام باستخدام السر كمفتاح، ثم قارنها بقيمة الترويسة.

const crypto = require("crypto");function verifyChakraSignature(rawBody, signatureHeader, secret) {  const expectedHash = crypto    .createHmac("sha256", secret)    .update(rawBody) // must be the raw string, not a parsed object    .digest("hex");  // timing-safe comparison  return crypto.timingSafeEqual(    Buffer.from(expectedHash, "utf8"),    Buffer.from(signatureHeader, "utf8")  );}app.post("/webhooks/chakra", express.raw({ type: "*/*" }), (req, res) => {  const rawBody = req.body.toString("utf8");  const signature = req.headers["x-chakra-signature-256"];  if (!verifyChakraSignature(rawBody, signature, process.env.CHAKRA_HMAC_SECRET)) {    return res.status(401).send("Invalid signature");  }  const event = JSON.parse(rawBody);  handleEvent(event);  res.sendStatus(200);});

التفصيل الذي يوقع كثيرين في الخطأ: يجب تجزئة سلسلة نص الطلب الخام، لا نسخة تم تحليلها إلى JSON ثم تحويلها مجددًا إلى سلسلة؛ إذ تحلل معظم أُطر العمل نص الطلب تلقائيًا قبل تشغيل معالجك، لذا تحتاج عادةً إلى وسيط للنص الخام (كما هو موضح أعلاه باستخدام express.raw) لهذا المسار تحديدًا. ولاحظ أيضًا أن قيمة الترويسة لا تتضمن البادئة sha256= ، بخلاف اصطلاحات HMAC لدى بعض مزوّدي الخدمات الآخرين؛ فلا تحذف بادئة غير موجودة أصلًا.

التعامل مع الأحداث المكررة

يعتمد تسليم خطافات WhatsApp على مبدأ «مرة واحدة على الأقل» فعليًا، وليس «مرة واحدة بالضبط»؛ فقد تؤدي إعادة المحاولة بسبب الشبكة أو تعطل نقطة النهاية مؤقتًا أو إعادة المحاولة من جانب Meta إلى وصول الحدث نفسه أكثر من مرة. ويساعد تنفيذ إزالة التكرار منذ البداية على تجنب معالجة الرسالة مرتين (مثل إرسال ردين، أو احتساب حالة التسليم مرتين، أو تشغيل سير العمل مرتين).

مفتاح إزالة التكرار الموثوق هو معرّف الرسالة (wamid... للرسائل، أو حقل المعرّف المقابل لأحداث الحالة)؛ خزّن المعرّفات التي عولجت مؤخرًا وتحقق منها قبل اتخاذ أي إجراء:

const processedIds = new Map(); // swap for Redis/DB in productionconst DEDUP_TTL_MS = 10 * 60 * 1000; // 10 minutes is generally enoughfunction isDuplicate(messageId) {  const seenAt = processedIds.get(messageId);  if (seenAt && Date.now() - seenAt < DEDUP_TTL_MS) return true;  processedIds.set(messageId, Date.now());  return false;}function handleEvent(event) {  const messageId = event.payload?.id || event.payload?.messages?.[0]?.id;  if (messageId && isDuplicate(messageId)) {    return; // already processed, skip silently  }  routeEvent(event);}

في بيئة الإنتاج، استخدم Redis أو قاعدة بياناتك مع مدة صلاحية (TTL)، بدلًا من Map محفوظة في الذاكرة؛ إذ لن تصمد Map ذات العملية الواحدة أمام إعادة التشغيل، ولن تعمل عبر مثيلات خادم متعددة.

إنشاء موجّه بسيط للرسائل

بعد التحقق من الأحداث وإزالة التكرارات، تكون الخطوة العملية التالية هي توجيهها إلى المعالج المناسب حسب نوعها. إليك موجّهًا أساسيًا لتنسيق أحداث Chakra:

function routeEvent(event) {  switch (event.event) {    case "message":      return handleInboundMessage(event.payload);    case "status":      return handleStatusUpdate(event.payload);    case "message_echo":      return handleAgentReply(event.payload);    case "smb_message_echo":      return handleAppSentMessage(event.payload);    default:      console.warn("Unhandled event type:", event.event);  }}function handleInboundMessage(payload) {  const messageType = payload.type; // "text", "image", "interactive", etc.  switch (messageType) {    case "text":      return processTextMessage(payload);    case "image":    case "document":      return processMediaMessage(payload); // fetch media by ID separately    case "interactive":      return processButtonOrListReply(payload);    default:      console.log("Unrecognized message type:", messageType);  }}function handleStatusUpdate(payload) {  // payload.status: "sent" | "delivered" | "read" | "failed"  updateMessageRecordInDb(payload.id, payload.status, payload.errorCode);}

يمكن تطبيق نمط التفرع نفسه بسهولة إذا كنت تستخدم خطاف الويب الذي يمرّر البيانات كما هي؛ فستتفرع بناءً على changes[].field (messages, message_template_sends, message_status وما يقابلها) بدلًا من event، ثم تنتقل إلى value.messages[0].type بالطريقة نفسها.

ملاحظة حول أحداث المكالمات

إذا كنت تستخدم Calling API من Chakra إلى جانب المراسلة، فستُسلَّم الأحداث المتعلقة بالمكالمات (بدء المكالمة، والاتصال، والانتهاء، وعدم الرد) عبر آلية تمرير البيانات نفسها، وفق مخطط خطاف الويب الخاص بأحداث المكالمات لدى Meta. وإذا كان موجّهك يتفرع بالفعل بناءً على field للأحداث المتعلقة بالرسائل، فإن توسيعه للتعامل مع الحقل calls يتبع النمط نفسه تمامًا؛ راجع وثائق Cloud API الرسمية من Meta لمعرفة الأسماء الدقيقة لحقول أحداث المكالمات، لأن هذا المخطط يُمرَّر كما هو دون تعديل أو توحيد من Chakra.

استخدام هذا مع n8n

بالنسبة إلى n8n تحديدًا، يستخدم الإعداد المعتاد خطاف الويب الذي يمرّر البيانات كما هي، لأن مسارات العمل المخصصة لـ WhatsApp والقوالب المجتمعية في n8n مبنية عمومًا على التنسيق الأصلي لدى Meta:

  1. أضف عقدة تشغيل Webhook في n8n وانسخ عنوان URL للاختبار أو الإنتاج الخاص بها
  2. الصق عنوان URL في حقل "Pass-through webhook URL for Meta events" ضمن WhatsApp Setup → More
  3. أضف عقدة تصفية/شرط في بداية سير العمل لاستبعاد الأحداث غير المتعلقة بالرسائل (تحديثات الحالة وتأكيدات إرسال القوالب)، إذا كان مسار العمل يهتم بالرسائل الواردة فقط
  4. من هناك، وجّه البيانات إلى عقدة AI Agent أو عقدة CRM أو أي مكوّن يحتاج إليه سير عملك؛ إذ يمكنك الرجوع إلى حمولة Meta الخام في جميع مراحل سير العمل

وهنا تظهر فائدة إضافة خطوة تصفية مبكرة: فمن دونها، سيؤدي كل حدث حالة أو تسليم إلى تشغيل سير العمل بأكمله دون داعٍ، ما يزيد التكلفة والضوضاء على المنصات التي تحتسب الرسوم لكل عملية تنفيذ.

بعض الملاحظات العملية قبل إطلاق هذا

  • أرسل استجابة 200 بسرعة، ونفّذ المعالجة بشكل غير متزامن. أقرّ باستلام خطاف الويب فورًا، ونفّذ أي معالجة بطيئة (مثل الكتابة في قاعدة البيانات أو استدعاء API آخر) بعد إرسال الاستجابة أو في مهمة تعمل في الخلفية؛ فالاستجابة البطيئة قد تدفع Meta أو Chakra إلى اعتبار التسليم فاشلًا وإعادة المحاولة، ما يزيد العبء الناتج عن معالجة الأحداث المكررة.
  • سجّل الحمولات الخام أثناء التطوير. يتضمن مخطط Meta اختلافات طفيفة بين أنواع الرسائل، والاحتفاظ بأمثلة خام للرجوع إليها يوفر الوقت عند مواجهة حالة خاصة لم يغطّها موجّهك بعد.
  • لا تضع سر HMAC في نظام التحكم بالإصدارات، وهذا أمر بديهي، لكن عليك أيضًا تدويره إذا ساورك الشك في انكشافه؛ فإعادة إنشائه من Admin → Team → Secrets تُبطل التوقيع القديم فورًا.
  • راقب وقت تشغيل نقطة النهاية. إذا كانت نقطة نهاية خطاف الويب متوقفة عند وقوع حدث، فستفوتك رسالة أو تحديث حالة، ولن تتوفر إعادة تعبئة تلقائية؛ لذا يجدر بك مراقبة نقطة النهاية هذه كما تراقب أي خدمة أخرى بالغة الأهمية للإنتاج.

جمع كل ذلك معًا

خطافات الويب هي الأساس غير البراق الذي تعتمد عليه سائر مكونات تكامل WhatsApp؛ أتقن تنسيق الأحداث والتحقق منها وإزالة التكرارات مرة واحدة، وستستفيد كل روبوت محادثة أو مزامنة CRM أو عملية أتمتة تبنيها فوقها من هذه الموثوقية. ابدأ بنوع خطاف الويب الأنسب لأدواتك (تنسيق Chakra الموحّد للأنظمة الخلفية المخصصة، أو تمرير البيانات كما هي لـ n8n والأدوات المعتمدة على مخطط Meta)، وتحقق من التوقيعات منذ اليوم الأول بدلًا من إضافته لاحقًا، وأزل التكرارات باستخدام معرّف الرسالة قبل أن ينفّذ موجّهك أي إجراء يعتمد على الحالة.

إذا كنت بصدد بناء هذا التكامل، فإن وثائق API الكاملة من Chakra تتضمن مرجعًا شاملًا للأحداث ونقاط النهاية المذكورة في هذا الدليل.