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

Backend2026-11-08TryQuickToolBox

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

ما هي Webhooks؟

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

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

تأمين Webhooks باستخدام الحمولات الموقعة

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

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

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

إليك مثالًا بسيطًا في Python باستخدام Flask:

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = b'your_shared_secret'

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Signature')
    if not signature:
        abort(400, 'Missing signature')
    body = request.get_data()
    expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, signature):
        abort(401, 'Invalid signature')
    # Process the event
    return '', 200

استخدم دائمًا hmac.compare_digest للمقارنة في وقت ثابت لمنع هجمات التوقيت. أيضًا، تحقق من التوقيع قبل تحليل جسم JSON لتجنب المعالجة غير الضرورية.

أفضل الممارسات للتوقيعات

التعامل مع الفشل بإعادة المحاولة

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

استراتيجيات إعادة المحاولة التي يستخدمها المزودون

يعيد معظم المزودين المحاولة باستخدام التراجع الأسي: على سبيل المثال، فورًا، ثم بعد دقيقة واحدة، 5 دقائق، 30 دقيقة، إلخ، حتى الحد الأقصى لعدد المحاولات (غالبًا 5-10). يسمح لك بعضهم أيضًا بتكوين جدول إعادة المحاولة. يختلف السلوك الدقيق، لذا اقرأ وثائق المزود.

تصميم نقطة النهاية الخاصة بك لإعادة المحاولة

يجب أن تقوم نقطة النهاية الخاصة بك بما يلي:

مثال على التحقق من التنفيذ الموحد في Python:

processed_events = set()  # In production, use a database or cache

@app.route('/webhook', methods=['POST'])
def webhook():
    # ... signature verification ...
    event = request.json
    event_id = event['id']
    if event_id in processed_events:
        return '', 200  # Already processed
    # Process event
    processed_events.add(event_id)
    return '', 200

اختبار تنفيذ Webhook الخاص بك

قبل الانتقال إلى الإنتاج، اختبر نقطة النهاية الخاصة بك بدقة:

  1. محاكاة الطلبات الموقعة: اكتب اختبارات وحدة تولد توقيعات صالحة وغير صالحة.
  2. اختبار سيناريوهات إعادة المحاولة: حاكي حالات الفشل وتأكد من أن نقطة النهاية الخاصة بك تتعامل مع التكرارات.
  3. استخدم أدوات المزود: يقدم العديد من المزودين واجهة سطر أوامر أو لوحة تحكم لإرسال أحداث اختبارية.
  4. المراقبة والتسجيل: سجل الأحداث الواردة (بدون بيانات حساسة) وقم بإعداد تنبيهات لفشل التوقيع أو معدلات الخطأ العالية.

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

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

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

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

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

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

أعد رمز حالة 2xx (على سبيل المثال، 200 OK) بمجرد استلام الحدث ووضعه في قائمة الانتظار للمعالجة. تجنب المعالجة الطويلة في معالج الطلب لمنع المهلات.

كيف يمكنني التعامل مع تسليمات webhook المكررة؟

استخدم مفتاح التنفيذ الموحد من حمولة الحدث (أو معرف حدث فريد) لتتبع الأحداث المعالجة. قم بتخزين هذه المعرفات في قاعدة بيانات أو ذاكرة تخزين مؤقت وتخطَّ المعالجة إذا تم رؤية المعرف من قبل.

هل أنت مستعد لاختبار حمولات webhook الخاصة بك؟ استخدم JSON Formatter الخاص بنا لتنسيق والتحقق من جسم JSON لـ webhooks الواردة، مما يسهل تصحيح الأخطاء.