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

Backend2026-11-06TryQuickToolBox

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

ما هي Webhooks؟

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

ومع ذلك، تعتمد webhooks على الدفع، مما يعني أن نقطة النهاية الخاصة بك يجب أن تكون متاحة للجمهور، وتتعامل مع الحمل غير المتوقع، وتتعامل مع الطلبات المكررة أو الضارة. هنا يأتي دور التوقيع وإعادة المحاولة.

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

بدون التحقق، يمكن لأي شخص يعرف عنوان URL الخاص بـ webhook أن يرسل أحداثًا مزيفة. يتيح لك توقيع الحمولات باستخدام سر مشترك مصادقة المرسل وضمان عدم التلاعب بالحمولة.

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

تنفيذ التحقق من HMAC

إليك مثال بسيط في Node.js باستخدام Express:

const crypto = require('crypto');
const express = require('express');
const app = express();

// Use raw body for signature verification
app.use(express.raw({ type: 'application/json' }));

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  const payload = req.body; // Buffer

  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).send('Invalid signature');
  }

  // Process the event
  const event = JSON.parse(payload);
  console.log('Received event:', event.type);
  res.status(200).send('OK');
});

app.listen(3000, () => console.log('Webhook server running'));

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

التعامل مع إعادة المحاولة: جعل Webhooks موثوقة

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

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

أنماط إعادة المحاولة الشائعة تشمل:

تنفذ معظم المزودين شيئًا مثل: إعادة المحاولة حتى 5 مرات مع التراجع الأسي على مدى 24 ساعة.

Idempotency: مفتاح إعادة المحاولة الآمنة

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

مثال باستخدام مجموعة في الذاكرة (استخدم قاعدة بيانات في الإنتاج):

const processedEvents = new Set();

app.post('/webhook', (req, res) => {
  // ... signature verification ...
  const event = JSON.parse(payload);
  if (processedEvents.has(event.id)) {
    return res.status(200).send('Already processed');
  }
  // Process event
  processedEvents.add(event.id);
  res.status(200).send('OK');
});

للإنتاج، استخدم قاعدة بيانات مع قيد فريد على معرف الحدث.

أفضل الممارسات لمستهلكي Webhook

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

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

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

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

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

ماذا أفعل إذا كانت نقطة نهاية webhook الخاصة بي معطلة؟

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

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

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

عند اختبار حمولات webhook، قد تحتاج إلى فحص بيانات JSON. استخدم JSON Formatter لتنسيق الحمولات والتحقق منها بسرعة.