شرح Webhooks: الحمولات الموقعة وإعادة المحاولة

Backend2026-11-09TryQuickToolBox

لقد قمت للتو بدمج بوابة دفع أو خدمة CI/CD، والآن تحتاج إلى استقبال الأحداث في الوقت الفعلي. webhooks هي الحل القياسي، لكنها تأتي مع تحديثين حاسمين: التحقق من أن الطلب يأتي فعلاً من المرسل وضمان عدم فقدان الأحداث إذا كان خادمك غير متاح مؤقتًا. تشرح هذه المقالة كيفية تنفيذ الحمولات الموقعة وآليات إعادة المحاولة لبناء مستقبل webhook قوي.

ما هي Webhooks؟

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

لماذا توقيع الحمولات؟

بدون التحقق، يمكن لأي شخص يكتشف نقطة نهاية webhook الخاصة بك إرسال أحداث مزيفة، مما قد يؤدي إلى إجراءات غير مصرح بها. يتيح لك توقيع الحمولات باستخدام سر مشترك تأكيد هوية المرسل وضمان عدم التلاعب بالحمولة. الطريقة الأكثر شيوعًا هي HMAC (رمز المصادقة القائم على التجزئة) باستخدام SHA-256.

كيف يعمل توقيع HMAC

يحسب المرسل ملخص HMAC لجسم الطلب الخام باستخدام مفتاح سري ويضمّنه في رأس (مثل X-Signature). يعيد خادمك حساب HMAC بنفس السر ويقارنه بالتوقيع المستلم. إذا تطابقا، يكون الطلب أصليًا.

// مثال Node.js: التحقق من توقيع webhook
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(payload);
  const digest = hmac.digest('hex');
  // استخدم timingSafeEqual لمنع هجمات التوقيت
  return crypto.timingSafeEqual(
    Buffer.from(digest, 'hex'),
    Buffer.from(signature, 'hex')
  );
}

هام: استخدم دائمًا دالة مقارنة ثابتة الوقت (مثل timingSafeEqual) لتجنب تسريب المعلومات من خلال فروق التوقيت. أيضًا، احسب HMAC على الجسم الخام، وليس JSON المحلل، لأن إعادة التسلسل يمكن أن تغير تسلسل البايت.

تنفيذ إعادة المحاولة

حتى مع التوقيعات، يمكن أن تتسبب مشكلات الشبكة أو أخطاء الخادم في فشل توصيل webhook. سيعيد المرسل الموثوق محاولة التوصيلات الفاشلة، عادةً باستخدام تأخير أسي. بصفتك مستقبلًا، يجب عليك تصميم نقطة النهاية الخاصة بك لتكون متسقة (idempotent) وإرجاع رموز الحالة المناسبة.

استراتيجية إعادة المحاولة من منظور المرسل

تصميم مستقبل متسق (Idempotent)

نظرًا لأن إعادة المحاولة يمكن أن تسبب توصيلات مكررة، يجب على مستقبلك التعامل مع نفس الحدث عدة مرات دون آثار سلبية. قم بتضمين معرف حدث فريد في الحمولة (أو الرأس) وقم بتخزين المعرفات المعالجة. إذا تمت معالجة معرف الحدث بالفعل، فأرجع 200 OK على الفور دون إعادة المعالجة.

// كود زائف للتعامل مع webhook متسق
function handleWebhook(event) {
  if (processedEvents.has(event.id)) {
    return { status: 200, body: 'Already processed' };
  }
  // معالجة الحدث...
  processedEvents.add(event.id);
  return { status: 200, body: 'Success' };
}

أفضل الممارسات لأمان وموثوقية Webhook

مقارنة: الاستقصاء مقابل Webhooks

الجانبالاستقصاءWebhooks
زمن الوصوليعتمد على الفاصل الزمنيشبه فوري
حمل الخادممرتفع (طلبات متكررة)منخفض (فقط عند الأحداث)
التعقيدبسيط التنفيذيتطلب التحقق من التوقيع ومعالجة إعادة المحاولة
الموثوقيةأنت تتحكم في إعادة المحاولةيعتمد على سياسة إعادة المحاولة للمرسل

الأسئلة الشائعة

كيف أتحقق من توقيع webhook؟

احسب HMAC لجسم الطلب الخام باستخدام السر المشترك، ثم قارنه بالتوقيع في الرأس باستخدام دالة مقارنة ثابتة الوقت.

ماذا يجب أن ترجع نقطة نهاية webhook الخاصة بي؟

أرجع رمز حالة 2xx (مثل 200 OK) بمجرد استلامك للحدث. إذا أرجعت 4xx أو 5xx، فقد يعيد المرسل المحاولة أو يضع علامة على التوصيل كفاشل.

هل يمكنني استخدام webhooks بدون توقيعات؟

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

عند تصحيح حمولات webhook، تنسيق JSON ضروري. استخدم منسق JSON الخاص بنا لطباعة وتنسيق بيانات JSON الواردة والتحقق منها بسرعة.