لاختبار webhook، عليك تزويد المزود بعنوان URL يمكن الوصول إليه، وتشغيل حدث حقيقي، ثم التأكد من أن المعالج الخاص بك يقبل الحمولة ويتفاعل بشكل صحيح. الجزء الصعب هو أن تطبيقك هو المُستقبل، وليس المُتصل، لذلك لا يمكنك ببساطة الضغط على "إرسال" وقراءة الاستجابة. يرشدك هذا الدليل خلال الأدوات التي تحتاجها (خدمات الفحص، الأنفاق المحلية، مشغلات المزود) وعملية قابلة للتكرار للتأكد من أن المعالج الخاص بك يعمل بشكل كامل.
لماذا يصعب اختبار Webhooks أكثر من واجهات برمجة التطبيقات (APIs) العادية
مع استدعاء واجهة برمجة تطبيقات (API) عادي، يمكنك التحكم في الطلب. تختار الطريقة، وتحدد محتوى الجسم، وتطلقه، وتقرأ الاستجابة. لكن Webhooks تعكس هذا. يرسل المزود الطلب إليك، وفقًا لجدوله الزمني الخاص، مع حمولة يحددها هو. هذا الانعكاس في الأدوار يخلق أربع مشاكل في الاختبار.
أولاً، لا يمكنك تشغيل الحدث بنفسك افتراضيًا. لا يتم تشغيل حدث payment_intent.succeeded إلا عندما يقرر Stripe ذلك، لذا تحتاج إلى أدوات المزود لفرضه.
ثانيًا، التسليم غير متزامن. يصل الحدث بمجرد اكتمال الإجراء السابق، لذا يجب على اختبارك التقاط طلب وارد بدلاً من الانتظار على قيمة إرجاع.
ثالثًا، شكل الحمولة يحدده المزود. يجب على المعالج الخاص بك تحليل ما يرسله GitHub أو Stripe أو Slack بالضبط.
رابعًا، معظم المزودين يوقعون طلباتهم. يجب أن تتحقق نقطة النهاية الخاصة بك من رأس التوقيع قبل الوثوق بالجسم، والاختبار الذي يتخطى هذا يخفي أخطاء حقيقية. لمزيد من التفاصيل، راجع دليلنا حول التحقق من توقيع الـ webhook.
إذا كنت لا تزال تقرر ما إذا كانت الـ webhooks هي النمط الصحيح لتكاملك، فإن مقارنة الـ webhooks بالاستقصاء (polling) و مقارنة الـ webhook بالـ WebSocket تعرض لك المفاضلات.
أدوات اختبار الـ Webhook
ستحتاج إلى أربعة أنواع من الأدوات، غالبًا في نفس الجلسة: خدمة التقاط لرؤية الحمولات الأولية، نفق للوصول إلى جهاز الكمبيوتر المحمول الخاص بك، مشغلات المزود لإطلاق أحداث حقيقية، وأداة تأكيد للتحقق من المعالج الخاص بك.
1. خدمات الفحص والالتقاط
قبل أن تكتب سطرًا واحدًا من تعليمات المعالج البرمجية، وجه المزود إلى عنوان URL مؤقت وانظر إلى ما يرسله بالفعل. تمنحك هذه الخدمات نقطة نهاية عامة وتعرض كل طلب في الوقت الفعلي.
يمنحك **webhook.site** عنوان URL عشوائيًا فريدًا وعنوان بريد إلكتروني بمجرد تحميل الصفحة. يظهر كل ما يُرسل إليه على الفور: الجسم الكامل، الرؤوس (headers)، والطريقة. تنتهي صلاحية عناوين URL المجانية بعد 7 أيام وتصل إلى 100 طلب كحد أقصى، بحجم طلب أقصى 10 ميجابايت. تضيف الخطط المدفوعة عناوين URL دائمة، وطلبات غير محدودة، وسجل محفوظ لآخر 10000 طلب.
يقدم **Beeceptor** نقطة نهاية HTTPS مجانية يمكنك استخدامها كـمستقبل webhook وفحص الحمولات الواردة في الوقت الفعلي. كما يوفر نقاط نهاية لخادم وهمي (mock-server)، حتى تتمكن من الالتقاط والمحاكاة من نفس الأداة.
**Pipedream RequestBin** هي أداة أخرى شائعة الاستخدام لالتقاط الطلبات. تحقق من وثائقها الحالية لمعرفة تفاصيل المستويات، حيث تغير خدمات الالتقاط حدودها المجانية غالبًا.
استخدم هذه الأدوات للإجابة على سؤال واحد: كيف تبدو الحمولة الحقيقية؟ انسخ عينة للاستخدام لاحقًا، عندما تقوم بإنشاء اختبارات قابلة للتكرار.
2. التطوير المحلي: كشف localhost باستخدام نفق
لا يمكن للمزودين الوصول إلى localhost:3000 على جهازك. يقوم النفق بإنشاء عنوان URL عام بتقنية HTTPS يعيد توجيه حركة المرور إلى المنفذ المحلي الخاص بك، حتى تتمكن من تشغيل المعالج الخاص بك في المحرر وتصحيحه مباشرة.
**ngrok** هو الخيار الشائع. قم بتثبيته، وقم بالمصادقة مرة واحدة، ثم قم بتحويل منفذ.
brew install ngrok # macOS
ngrok config add-authtoken $YOUR_TOKEN
ngrok http 3000 # يحول عنوان URL عام HTTPS إلى localhost:3000
تحصل حسابات ngrok المجانية على نطاق تطوير يتم اختياره تلقائيًا. تتطلب النطاقات المخصصة خطة مدفوعة.
يقوم **cloudflared** بتشغيل نفق سريع بأمر واحد إذا كنت تفضل Cloudflare.
cloudflared tunnel --url http://localhost:3000
الصق عنوان URL العام الذي يطبعه النفق في إعدادات webhook الخاصة بالمزود، وستهبط الأحداث الواردة على الخادم المحلي الخاص بك. للحصول على شرح كامل لهذا النمط، راجع كيفية اختبار واجهات برمجة تطبيقات localhost باستخدام خدمات الـ webhook.
3. تشغيل أحداث الاختبار من المزود
لا يفيد عنوان URL للالتقاط إلا بمجرد إرسال شيء إليه. يقدم معظم المزودين الرئيسيين أدوات لتشغيل أحداث الاختبار عند الطلب، لذلك لا يتعين عليك إنشاء مدفوعات أو دفعات حقيقية.
**Stripe CLI** هو أوضح مثال. يقوم الأمر stripe listen بإعادة توجيه الأحداث المباشرة من بيئة Stripe التجريبية (sandbox) الخاصة بك إلى مسار محلي، ويطبع سر توقيع webhook تضعه في تكوين تطبيقك.
# أعد توجيه جميع الأحداث إلى المعالج المحلي الخاص بك:
stripe listen --forward-to localhost:3000/webhooks
# تصفية لأحداث محددة فقط:
stripe listen --events payment_intent.succeeded,checkout.session.completed \
--forward-to localhost:3000/webhooks
مع تشغيل المستمع، يقوم stripe trigger بإطلاق حدث اختبار. لاحظ أن التشغيل ينشئ كائنات API مدعومة بشكل صحيح وله آثار جانبية: payment_intent.succeeded يطلق أيضًا payment_intent.created.
stripe trigger payment_intent.succeeded
stripe trigger checkout.session.completed
stripe trigger --help # سرد كل حدث مدعوم
يحتفظ **GitHub** بسجل تسليم قصير يمكنك إعادة تشغيله. اذهب إلى المستودع الخاص بك، ثم الإعدادات (Settings)، ثم Webhooks تحت "التعليمات البرمجية والأتمتة" (Code and automation). انقر على عنوان URL للـ webhook، افتح علامة التبويب "التسليمات الأخيرة" (Recent deliveries)، انقر على معرف التسليم (GUID)، ثم انقر على "إعادة التسليم" (Redeliver). هناك قيدان مهمان: يمكنك فقط إعادة تسليم التسليمات من الأيام الثلاثة الماضية، وتحتاج إلى صلاحيات المسؤول (admin access) للمستودع. لا يقوم GitHub بإعادة تسليم التسليمات الفاشلة تلقائيًا، لذا فإن إعادة التشغيل يدوية.
تعد الـ webhooks الواردة في **Slack** الأبسط للاختبار. يمكنك إرسال رسالة عن طريق إرسال (POST) JSON إلى عنوان URL للـ webhook. الحد الأدنى للحمولة هو مجرد حقل text.
curl -X POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX \
-H 'Content-type: application/json' \
-d '{"text":"Hello, world."}'
عنوان URL للـ webhook الخاص بـ Slack هو سر. يقوم Slack بإلغاء عناوين URL التي تتسرب، لذا احتفظ بها بعيدًا عن تعليمات البرمجة من جانب العميل والمستودعات العامة.
4. التأكد من المعالج الخاص بك
يثبت الالتقاط والتشغيل أن البنية التحتية تعمل. لكنهما لا يثبتان أن المعالج الخاص بك صحيح. ترسل الأداة النهائية حمولة مصممة خصيصًا وتتحقق من الاستجابة بالإضافة إلى الآثار الجانبية. في أبسط صورها، هذا هو أمر curl مع جسم تمثيلي.
curl -X POST http://localhost:3000/webhooks \
-H 'Content-Type: application/json' \
-H 'Stripe-Signature: t=...,v1=...' \
-d '{"id":"evt_test","type":"payment_intent.succeeded","data":{"object":{"id":"pi_123","status":"succeeded"}}}'
أمر `curl` واحد جيد لاختبار الدخان (smoke test). لكنه يقصر عندما تريد اختبارات قابلة للتكرار ومؤكدة تعمل في التكامل المستمر (CI). هنا تكتسب أداة API المخصصة مكانتها.
اختبار الـ webhooks باستخدام Apidog
Apidog هو منصة API شاملة لتصميم واجهات برمجة التطبيقات وتصحيحها واختبارها ومحاكاتها وتوثيقها. لا يحتوي على "صندوق وارد للـ webhook" مخصص، لذا فإن هذا القسم يتحدث بصراحة عما يفعله جيدًا بالفعل: صياغة الحمولات، وحفظها، وتأكيد الاستجابات، والوقوف مكان المزود باستخدام خادم وهمي (mock server).
صياغة وحفظ حمولة نموذجية كطلب قابل لإعادة الاستخدام
خذ الحمولة التي التقطتها من webhook.site (أو نسختها من وثائق المزود) وقم بإنشائها كطلب في Apidog. اضبط الطريقة على POST، الصق جسم JSON، وأضف الرؤوس التي يرسلها المزود، بما في ذلك رأس التوقيع الذي يتحقق منه المعالج الخاص بك.
احفظ هذا الطلب مقابل نقطة النهاية الخاصة بك. لديك الآن طريقة قابلة للتكرار ومتحكم بها لإرسال حمولة معروفة الصلاحية (أو مشوهة عمدًا) إلى المعالج الخاص بك، بدلاً من إعادة كتابة أمر `curl` في كل مرة.
تأكيد الاستجابة باستخدام منشئ التأكيدات المرئي
إرسال الحمولة هو نصف الاختبار. النصف الآخر هو التحقق مما يعيده المعالج الخاص بك. في خطوة الطلب أو السيناريو، افتح Post Processors، انقر على "+ إضافة" (+ Add)، واختر "تأكيد" (Assertion). يضيف Apidog قاعدة تحقق تقوم بتكوينها بدون تعليمات برمجية.
وجه التأكيد إلى جسم الاستجابة واستخدم `$` لجذر JSON. على سبيل المثال، استهدف `$.data.status`، اضبط الشرط على يساوي (Equals)، وقارنه بـ `succeeded`. شغل الطلب، وستظهر النتيجة في علامة تبويب التأكيد (Assertion tab). تقارن التأكيدات المرئية القيم كسلاسل نصية. عندما تحتاج إلى فحوصات دقيقة للنوع (رقم حقيقي، قيمة منطقية)، قم بالتبديل إلى نص برمجي مخصص باستخدام بناء جملة `pm.test` المتوافق مع Postman.
هذا يحول عبارة "لقد أعاد 200" إلى "لقد أعاد 200، وحقل الحالة هو 'succeeded'، ومعرف الطلب متطابق." قم ببناء عدة تأكيدات في سيناريو واحد لتغطية مسار النجاح، وحالة الحقل المفقود، ورفض التوقيع السيء.
استخدام خادم وهمي (Mock Server) ليحل محل المزود
أحيانًا ترغب في اختبار الاتجاه الآخر: خدمة في مكدسك تستدعي مزودًا. أثناء الاختبار المحلي، قد لا ترغب في الوصول إلى المزود الحقيقي على الإطلاق. يسمح لك خادم Apidog الوهمي بأن تحل محله.
يقدم Apidog ثلاثة أنواع من المحاكاة (mock): يعمل Local Mock مع عميل سطح المكتب ويعمل فقط أثناء فتح العميل. Cloud Mock مستضاف على خوادم Apidog، ويعمل على مدار الساعة طوال أيام الأسبوع، ويمكن تشغيله أو إيقافه (هو متوقف افتراضيًا). يعمل Runner Mock على بنية تحتية لمشغل مستضافة ذاتيًا ويتم مشاركته عبر فريقك. تحتوي كل نقطة نهاية HTTP على وحدة Mock؛ انسخ عنوان URL للمحاكاة من علامة تبويب API في وضع التصميم (Design mode) أو علامة تبويب Mock في وضع التصحيح (Debug mode). فقط المسارات التي تبدأ بـ `/` يتم توجيهها إلى بيئة المحاكاة. وجه رمزك إلى عنوان URL للمحاكاة هذا أثناء الاختبارات، وسيحصل تكاملك على استجابات مزود متوقعة بدون استدعاءات API حقيقية أو آثار جانبية.
تشغيل اختبارات الـ webhook في CI باستخدام Apidog CLI
بمجرد اجتياز السيناريو الخاص بك محليًا، قم بتشغيله مع كل دفع باستخدام Apidog CLI. يتطلب Node.js الإصدار 16 أو أحدث.
npm install -g apidog-cli
node -v && apidog -v && which node && which npm && which apidog # تحقق من التثبيت
شغل سيناريو محفوظ عبر الإنترنت، مع تمرير رمز الوصول والمعرفات من علامة تبويب "سطر الأوامر" (Command line) في CI/CD للسيناريو.
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 637132 -e 358171 -d 3497013 -r html,cli
هنا `-t` هو سيناريو الاختبار، و`-e` هي البيئة (مطلوبة)، و`-d` هي بيانات الاختبار (مسار ملف CSV أو JSON، أو معرف مجموعة بيانات مخزنة)، و`-r` يحدد المُبلغين (reporters)، الذين يقبلون `cli` و`html` و`json` و`junit`. للحصول على شرح كامل لسطر الأوامر، راجع برنامج Apidog CLI التعليمي.
هل ترغب في بناء واختبار الـ webhooks الخاصة بك بصريًا؟ جرب Apidog مجانًا، لا يلزم وجود بطاقة ائتمان.
سير عمل اختبار الـ Webhook خطوة بخطوة
بجمع الأدوات معًا، إليك تسلسل قابل للتكرار.
- افحص الحمولة الحقيقية. وجه المزود إلى عنوان URL لـ webhook.site والتقط حدثًا حقيقيًا واحدًا. لاحظ شكل الجسم، الرؤوس، وتنسيق التوقيع.
- الوصول إلى الكود الخاص بك. ابدأ المعالج الخاص بك محليًا، وافتح نفقًا باستخدام
ngrok http 3000أوcloudflared، وضع عنوان URL العام في إعدادات webhook للمزود. - شغل حدثًا حقيقيًا. استخدم
stripe trigger، أو زر إعادة التسليم (Redeliver) في GitHub، أو طلب POST من Slack لإرسال حدث حقيقي عبر النفق. - تحقق من معالجة التوقيع. أرسل نفس الحمولة بتوقيع صالح ومرة أخرى بتوقيع مزور. يجب أن يقبل المعالج الخاص بك الأول ويرفض الثاني.
- تأكد من الاستجابة والآثار الجانبية. احفظ الحمولة كطلب Apidog، وأضف تأكيدات على جسم الاستجابة وحالتها، وتأكد من حدوث صف قاعدة البيانات أو الاستدعاء اللاحق.
- أتمتة العملية. انقل السيناريو إلى Apidog CLI بحيث يعمل في التكامل المستمر (CI) عند كل تغيير.
إذا كنت تصمم نظام الـ webhook نفسه بدلاً من مجرد استهلاكه، فإن كيفية تصميم webhooks موثوقة و أفضل ممارسات الـ webhooks للدفع تغطي إعادة المحاولة، التحملية (idempotency)، والأمان. للحصول على الصورة الأوسع، يشرح دليل API للـ webhooks و الـ webhooks والبنية المعتمدة على الأحداث مكان توافق الـ webhooks في نظام أكبر.
الأسئلة المتكررة
كيف تختبر الـ webhook؟
زود المزود بعنوان URL يمكن الوصول إليه، وشغل حدثًا حقيقيًا أو اختباريًا، ثم تأكد من أن المعالج الخاص بك يستقبل الحمولة، ويتحقق من التوقيع، ويعيد الحالة الصحيحة، ويقوم بالآثار الجانبية المتوقعة. التقط حمولة حقيقية أولاً، ثم أنشئ طلبًا قابلاً للتكرار مع تأكيدات لضمان أن الاختبار يعمل بنفس الطريقة في كل مرة.
كيف تختبر الـ webhooks محليًا؟
شغل المعالج الخاص بك على منفذ محلي، ثم اكشفه باستخدام نفق ليتمكن المزود من الوصول إلى جهازك. استخدم ngrok http 3000 أو cloudflared tunnel --url http://localhost:3000، الصق عنوان URL العام لـ HTTPS في إعدادات webhook الخاصة بالمزود، وشغل حدثًا. تهبط الطلبات الواردة على الخادم المحلي الخاص بك، حيث يمكنك تعيين نقاط توقف وفحصها مباشرة.
كيف تختبر الـ webhook باستخدام Postman؟
يمكن لـ Postman إرسال (POST) حمولة مصممة خصيصًا إلى نقطة النهاية الخاصة بك وتأكيد الاستجابة، ولكنه لا يستطيع استقبال webhook وارد حقيقي بمفرده. وينطبق الشيء نفسه على Apidog: يمكنك بناء طلب بحمولة ورؤوس المزود، وإضافة تأكيدات على جسم الاستجابة وحالتها، وحفظه كاختبار قابل لإعادة الاستخدام. لالتقاط حدث وارد حقيقي، قم بإقران الأداة بخدمة التقاط أو نفق.
كيف تختبر الـ webhooks الخاصة بـ Stripe؟
استخدم Stripe CLI. شغل stripe listen --forward-to localhost:3000/webhooks لإعادة توجيه أحداث sandbox إلى المعالج الخاص بك والحصول على سر التوقيع. ثم شغل stripe trigger payment_intent.succeeded (أو أي حدث من stripe trigger --help) لإطلاق حدث اختبار حقيقي. يؤدي التشغيل إلى إنشاء كائنات API مدعومة وقد يتسلسل، لذا فإن payment_intent.succeeded يطلق أيضًا payment_intent.created.
كيف تختبر الـ webhook الخاصة بـ Slack؟
أرسل (POST) JSON إلى عنوان URL للـ webhook الوارد. الحد الأدنى للحمولة الصالحة هو {"text":"Hello, world."}، يُرسل مع رأس Content-type: application/json. ينشر الاختبار الناجح الرسالة في القناة المكونة. حافظ على سرية عنوان URL، حيث يقوم Slack بإلغاء عناوين URL للـ webhook التي تتسرب.
كيف تختبر عنوان URL لـ webhook؟
أرسل طلب POST نموذجي إلى عنوان URL وتأكد من أنه يعيد حالة نجاح ويتصرف بشكل صحيح. أسرع فحص هو أمر curl واحد مع جسم تمثيلي. لاختبار حقيقي، التقط حمولة فعلية أولاً، أرسلها بتوقيعات صالحة وغير صالحة، وتأكد من الاستجابة والآثار الجانبية بدلاً من مجرد التحقق من الرقم 200.
