أدلة

خطافات الويب (Webhooks) في واتساب: التحقق ومنع التكرار

ما فائدة Webhooks في تشغيل واتساب للأعمال للشركات؟

ملخّص سريع

تشغيل خطافات الويب في واتساب يتطلب فصل ميتا إلى Wats، وWats إلى أنظمة الشركة، والأنظمة الخارجية إلى Wats. في كل اتجاه يجب التحقق من المصدر على الجسم الخام، وتخزين معرف ثابت، ومنع التكرار، وإرجاع 2xx سريعًا، ثم المعالجة غير المتزامنة مع مراقبة وإعادة معالجة آمنة وتدوير للأسرار.

النقاط الرئيسية

  • حدد اتجاه خطاف الويب والعقد الأمني قبل كتابة الكود؛ تواقيع ميتا وWats لها أسرار ورؤوس مختلفة.
  • تحقق من HMAC على bytes الجسم الخام قبل JSON parsing، وقارن القيم بطريقة ثابتة الزمن.
  • أعد 2xx بعد التحقق والتخزين المقبول، ثم انقل العمل البطيء إلى صف (queue) أو عامل خلفي (worker).
  • افترض إمكان التكرار والتأخير والوصول خارج الترتيب؛ اجعل المعالجة idempotent ولا تعد بزمن حقيقي مضمون.
  • دوّر الأسرار بتداخل مؤقت، وراقب عمر الأحداث الفاشلة والمكررة وغير المعالجة.

لتشغيل خطافات الويب (webhooks) في واتساب بأمان، افصل أولًا بين ثلاثة اتجاهات: ميتا إلى Wats، وWats إلى أنظمة شركتك، ونظام خارجي إلى Wats. لكل اتجاه سر ورؤوس وصلاحيات مختلفة. تحقق من التوقيع على الجسم الخام، وخزّن الحدث بمعرف ثابت، وامنع التكرار، وأعد 2xx بسرعة، ثم عالج العمل غير المتزامن مع إعادة محاولة ومراقبة وتدوير أسرار.

خطاف الويب إشعار حدث، لا ضمانًا بأن العملية التجارية اكتملت فورًا. قد يتأخر الطلب أو يتكرر أو يصل بعد حدث أحدث، وقد يكون النظام المستقبل متوقفًا مؤقتًا. لذلك تكون الاعتمادية نتيجة تصميم المستقبل والسجل والصف وسياسة الاستعادة، لا نتيجة وجود نقطة نهاية (endpoint) عامة فقط.

افصل اتجاهات الأحداث قبل تصميمها

عبارة «خطاف ويب لواتساب» قد تشير إلى عقود مختلفة:

الاتجاه

المرسل

المستقبل

طريقة الثقة الأساسية

مثال

Meta → Wats

WhatsApp Business Platform لدى Meta

endpoint الوارد في Wats

verify token للمصافحة ثم X-Hub-Signature-256 مع Meta app secret

رسالة واردة أو تحديث حالة رسالة

Wats → نظام الشركة

Wats

CRM أو ERP أو برمجية وسيطة (middleware)

سر خطاف الويب ورأس X-Wats-Signature

message.inbound أو conversation.assigned

نظام خارجي → Wats

CRM أو ERP أو خدمة تكامل

API أو endpoint مخصص في Wats

API token محدود الصلاحيات والقنوات، وعقد idempotency

طلب إرسال مؤهل أو تحديث سياق

لا تستخدم سر تطبيق ميتا لتوقيع خطاف ويب صادر من Wats، ولا تضع رمز API في الحمولة (payload). السر يثبت هوية المرسل، والرمز يمنح صلاحية لاستدعاء واجهة؛ لكل منهما دورة حياة مستقلة.

إذا لم يكتمل ربط الرقم والأصول لدى Meta، ابدأ بدليل تكامل واتساب للأعمال مع Meta قبل بناء مستهلك الأحداث.

مسار Meta إلى Wats: المصافحة ثم الأحداث

توضح وثائق ميتا الرسمية لخطافات Cloud API الاشتراك في الأحداث وبنية الاستقبال. يبدأ تفعيل نقطة النهاية عادةً بطلب GET للتحقق، ثم تستخدم الأحداث طلبات POST.

1. مصافحة GET

يصل الطلب بمعاملات:

المعامل

الغرض

hub.mode

يجب أن يطابق وضع الاشتراك المتوقع

hub.verify_token

قيمة مشتركة تختارها أنت وتقارنها بأمان

hub.challenge

قيمة يعيدها endpoint كما هي عند نجاح التحقق

إذا تطابق الوضع والرمز، يعيد المستقبل hub.challenge مع استجابة ناجحة. verify token ليس توقيع كل حدث ولا بديلًا عن app secret.

2. POST للأحداث

عند وصول الحمولة، يجب التحقق من X-Hub-Signature-256 باستخدام HMAC SHA-256 وسر تطبيق ميتا على بايتات الجسم الخام. تشرح وثائق ميتا للتحقق من الحمولات نموذج التوقيع. بعد النجاح، استخرج معرفات الرسالة والحالة والقناة، وسجل الحدث قبل تنفيذ عمل خارجي طويل.

Meta                 Wats endpoint             Event store / worker
  | GET verification      |                              |
  |---------------------->| compare verify token         |
  |<----------------------| 200 + challenge              |
  |                       |                              |
  | POST event + signature|                              |
  |---------------------->| verify raw body              |
  |                       | persist + deduplicate ------>|
  |<----------------------| 2xx after safe acceptance    |
  |                       |                process async |

الـ2xx هنا يعني أن الحدث قُبل بأمان، وليس أن كل API لاحق اكتمل. إذا ربطت استجابة Meta بانتظار CRM بطيء، تزيد احتمالات انتهاء المهلة وإعادة التسليم والتكرار.

مسار Wats إلى CRM أو ERP

يستطيع Wats إرسال أحداث صادرة مثل message.inbound وmessage.outbound وconversation.assigned وconversation.escalated وcampaign.completed، مع فلترة نوع الحدث والقنوات. يحتوي الطلب على رؤوس سياقية مثل:

X-Wats-Event
X-Wats-Webhook-Id
X-Wats-Company-Id
X-Wats-Timestamp
X-Wats-Signature: sha256=<hex-hmac-of-raw-body>

يحسب المستقبل HMAC باستخدام السر المضبوط لهذا الخطاف، لا سر ميتا. ثم يستخدم معرف الخطاف ونوع الحدث ومعرفًا ثابتًا من الحمولة لبناء مفتاح منع تكرار، ويخزن الحدث ويعيد 2xx قبل تشغيل تحديثات ثقيلة.

Wats event → event/channel filter → sign raw payload → HTTPS POST
                                                     ↓
CRM receiver ← 2xx ← verify → deduplicate → persist → queue
                                                     ↓
                                             update CRM/ERP async

راجع دليل تكامل واتساب مع CRM وERP لتحديد مصدر الحقيقة والمعرفات واتجاه التحديث قبل اختيار الأحداث.

مسار النظام الخارجي إلى Wats

عندما يريد ERP أو CRM بدء إجراء داخل Wats، فهذا غالبًا استدعاء API أو سير عمل وارد مصمم لهذا الغرض، لا «إعادة خطاف ويب» بلا عقد. استخدم رمزًا له أقل الصلاحيات المطلوبة واقصره على القنوات اللازمة، مع انتهاء وإلغاء. أرسل مفتاح عدم التكرار (idempotency) أو معرف الحدث الخارجي حتى لا تنشئ إعادة المحاولة رسالتين أو إجراءين.

مثال: يرسل ERP حدث shipment.updated إلى خدمة التكامل. تتحقق الخدمة من الحدث وتخزنه، ثم تقرر بوابة السياسة هل التحديث داخلي فقط أم مؤهل لإرسال واتساب. إذا كان مؤهلًا، تستدعي Wats بمعرف العملية نفسه. لا تسمح لكل نظام خلفي بإرسال نص حر مباشرة إلى العميل.

يمكن أن ينسق سير عمل أتمتة واتساب هذا المسار، لكن يجب أن تبقى المصادقة ومنع التكرار وبوابة السياسة صريحة خارج الموجّه (prompt) أو النص الحر.

مثال حمولة (payload) آمنة ومحدودة

المثال التالي توضيحي لشكل حدث موحد داخل طبقة التكامل، وليس وعدًا بأن كل مزود يستخدم أسماء الحقول نفسها:

{
  "event": "message.inbound",
  "eventId": "evt_demo_01",
  "occurredAt": "2026-05-31T06:05:12Z",
  "companyId": "cmp_demo",
  "channelId": "chn_demo",
  "data": {
    "messageId": "wamid.demo_123",
    "conversationId": "conv_demo_45",
    "direction": "inbound",
    "contentType": "text"
  }
}

لا تضع app secret أو access token أو بيانات عميل لا يحتاجها المستهلك في payload. وإذا احتاج CRM نص الرسالة فعلًا، طبّق تقليل البيانات وسياسة الاحتفاظ والحجب في logs.

مثال HMAC صحيح على الجسم الخام

المثال التالي في Node.js يصلح لفحص رأس بالشكل sha256=<hex>. يجب تمرير rawBody كما وصل قبل JSON parsing، وقراءة السر من secret manager أو متغير بيئة آمن:

import crypto from "node:crypto";

export function validSignature(rawBody, signatureHeader, secret) {
  if (!signatureHeader?.startsWith("sha256=")) return false;

  const received = Buffer.from(signatureHeader.slice(7), "hex");
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest();

  return received.length === expected.length &&
    crypto.timingSafeEqual(received, expected);
}

استخدم سر تطبيق ميتا مع X-Hub-Signature-256 للأحداث الواردة من ميتا، واستخدم سر خطاف الويب مع X-Wats-Signature للأحداث الصادرة من Wats. ارفض الرأس المفقود أو القيمة السداسية غير الصالحة أو عدم التطابق، وسجل سببًا غير حساس دون طباعة السر أو التوقيع الكامل أو الحمولة الشخصية.

وجود X-Wats-Timestamp يسمح بإضافة سياسة رفض للطلبات القديمة للحد من replay، لكن نفذ هامشًا معقولًا لاختلاف الساعات، ولا تستخدم timestamp بدل مفتاح deduplication.

دورة حياة حدث تتحمل الفشل

اعتمد حالات واضحة بدل تنفيذ كل شيء داخل request:

received → verified → persisted → queued → processing → processed
                                      └────→ failed → retry / review
duplicate → acknowledge without repeating the business action
  1. Received: التقط raw body والرؤوس اللازمة فقط.

  2. Verified: تحقق من التوقيع والوقت والعقد المتوقع.

  3. Persisted: خزّن معرف الحدث وhash ومصدره وحالة أولية.

  4. Deduplicated: احجز مفتاحًا فريدًا ذريًا قبل الأثر التجاري.

  5. Queued: أعد 2xx ثم مرر المهمة إلى worker.

  6. Processed: سجل المعرف الناتج، مثل سجل CRM أو رسالة واتساب.

  7. Failed: صنف الخطأ إلى مؤقت أو دائم، مع عدد المحاولات وموعد التالي.

استخدم exponential backoff مع jitter للأخطاء المؤقتة، وحدًا للمحاولات، ثم dead-letter queue أو مراجعة بشرية. لا تعِد المحاولة تلقائيًا عند أخطاء دائمة مثل payload غير صالح أو صلاحية مفقودة قبل تصحيح السبب.

يعيد Wats معالجة أحداث ميتا الواردة التي سُجل فشلها ضمن مسار إعادة محاولة داخلي. أما خطاف الويب الصادر إلى نظام الشركة، فلا تفترض سياسة إعادة محاولة أو ترتيبًا أو تنفيذًا مرة واحدة فقط (exactly-once) إلا إذا كانت موثقة في عقد النسخة التي تستخدمها؛ اختبر السلوك واجعل المستقبل آمنًا عند التكرار وراقب الفجوات في كل الأحوال.

كيف تتعامل مع التكرار والترتيب؟

مفتاح dedup الجيد يعتمد على معرف مستقر من المصدر ونوع الحدث، مثل:

meta + message_id + status_type
wats + webhook_id + event_id
erp + source_event_id + requested_action

نفذ حجز المفتاح بقيد unique أو معاملة ذرية، لا بفحص ثم إنشاء منفصلين قد يتسابقان. احتفظ بالنتيجة النهائية حتى تستطيع إعادة 2xx للنسخة المكررة.

أما الأحداث خارج الترتيب فتحتاج قواعد مجال. إذا وصل read ثم وصل تحديث أقدم، فلا تعد الحالة إلى الوراء. وإذا وصل تحديث طلب بإصدار أقل من الإصدار المخزن، سجله للتدقيق وتجاهل أثره. الوقت وحده قد لا يكفي؛ استخدم sequence أو version من المصدر عندما يكون متاحًا.

تدوير الأسرار والمراقبة

للتدوير بلا توقف، أضف السر الجديد إلى المستقبل، واقبل القديم والجديد خلال نافذة قصيرة، ثم حدّث المرسل، وراقب أي استخدام للقديم، وألغِه بعد التأكد. لا تجعل النافذة مفتوحة بلا نهاية. في Meta قد تحتاج إلى دعم app secrets النشطة أثناء الانتقال، وفي Wats حدّث secret الخاص بتكوين webhook والمستقبل وفق ترتيب منسق.

راقب مؤشرات تشغيلية لا تحتوي بيانات عميل:

  • عدد الأحداث المقبولة والمرفوضة بسبب التوقيع.

  • نسبة التكرار وأسباب الفشل حسب endpoint.

  • عمر أقدم حدث في queue وأقدم حدث failed.

  • عدد المحاولات ووقت المعالجة من الاستلام إلى الاكتمال.

  • فجوات sequence أو اختلاف العد بين المصدر والمستقبل.

لا تعد العميل بـ«real-time مضمون». الوصف الأدق هو معالجة مدفوعة بالأحداث وقريبة من الزمن الحقيقي، تتأثر بالشبكة والصفوف وإعادة المحاولة. صمم تجربة المستخدم لتتحمل حالة «قيد التحديث» وتوفر reconciliation للحالات المهمة.

كيف يستخدم Wats هذه العقود؟

في اتجاه Meta الوارد، يتحقق Wats من مصافحة GET ومن توقيع POST، ويسجل الأحداث ويمنع التكرار ثم يتابع حالات المعالجة والفشل وإعادة المعالجة. وفي الاتجاه الصادر، يتيح تكوين URL وsecret وفلاتر أحداث وقنوات واختبار endpoint، ويرسل رؤوس Wats والتوقيع المبني على الجسم الخام.

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

الخلاصة: صمم للاستلام أكثر من مرة

خطاف الويب الموثوق هو عقد أمني وسجل حالة ومسار استعادة، وليس طلب POST ناجحًا في اختبار واحد. افصل الاتجاهات والأسرار، وتحقق من الجسم الخام، واحجز مفتاح التكرار، وأعد 2xx بعد القبول الآمن، ثم نفذ العمل خارج الطلب. اختبر التكرار والتأخير والوصول خارج الترتيب وتعطل النظام وتدوير السر؛ عندها يصبح الحدث جزءًا يمكن تشغيله ومراجعته بدل نقطة اتصال هشة.

أسئلة شائعة

هل خطاف الويب هو نفسه API؟

لا. واجهة برمجة التطبيقات (API) تُستدعى عادةً عندما يطلب نظام إجراءً أو بيانات، بينما خطاف الويب إشعار يدفعه المصدر عند وقوع حدث. غالبًا يستخدم التكامل الاثنين: خطاف الويب يوقظ التدفق ثم الواجهة تجلب أو تحدّث البيانات.

هل استجابة 200 تعني أن العملية التجارية اكتملت؟

ليس بالضرورة. الأفضل أن تعني أن المستقبل تحقق من الحدث وقبله للتخزين أو المعالجة. قد يكتمل تحديث CRM أو ERP لاحقًا في worker غير متزامن.

هل يمكن تحليل JSON قبل فحص التوقيع؟

احتفظ بالـraw body أولًا وافحص HMAC عليه. إعادة تسلسل JSON قد تغير المسافات أو ترتيب الحقول فتنتج قيمة مختلفة، كما أن معالجة محتوى غير موثوق قبل التحقق توسع سطح المخاطر.

ماذا أفعل إذا وصل الحدث نفسه مرتين؟

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

هل تضمن خطافات الويب وصول الأحداث بالترتيب؟

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

جرّب واتس مجاناً

ابدأ مجاناً مع تجربة 30 يوم وابنِ قناة واتساب احترافية لفريقك.

ابدأ الآن