يدفع العميل، يرسل Stripe حدث payment_intent.succeeded إلى الواجهة الخلفية، ومن المفترض أن يتحول الطلب إلى حالة «مدفوع». المشكلة الشائعة: يصل الويب هوك، يفشل المعالج بصمت، ولا يظهر الخطأ إلا عندما يقول العميل: «دفعت، لكن حسابي ما زال غير مدفوع». الحل العملي هو اختبار CI يثبت في كل نشر أن الحدث وصل، وسُجّل، وحدّث حالة الطلب.
الويب هوك طلب HTTP وارد من Stripe إلى تطبيقك، وليس طلبًا ترسله أنت. لذلك لا يكفي اختبار API تقليدي يرسل طلبًا ثم يفحص الاستجابة. تحتاج إلى إثبات أن Stripe سلّم الحدث وأن تطبيقك عالجه. يشرح هذا الدليل النمط المدعوم باستخدام Apidog: التقاط الحدث ثم الاستعلام عنه.
للسياق الأوسع حول اختبار نقاط النهاية المعتمدة على الأحداث، راجع كيفية اختبار الويب هوكس، وراجع أيضًا وثائق Stripe للويب هوكس.
قيد مهم: Apidog لا يستمع مباشرةً إلى Stripe webhooks
تنص وثائق Apidog بوضوح على أن Apidog لا يدعم الاستماع الأصلي للويب هوكس الواردة في الوقت الفعلي.
بمعنى آخر، لا يمكنك توجيه Stripe إلى عنوان URL تابع لـ Apidog ثم انتظار وصول الحدث هناك.
بدلًا من ذلك، استخدم هذا التدفق:
- يستقبل تطبيقك حدث Stripe.
- يتحقق التطبيق من توقيع Stripe.
- يحفظ التطبيق الحدث ونتيجة معالجته في قاعدة البيانات.
- يستعلم Apidog عن السجل المحفوظ ويتحقق من القيم المتوقعة.
هذا التصميم مناسب لـ CI لأن الاستعلامات على قاعدة البيانات قابلة للتكرار ولا تعتمد على مراقبة بشرية.
البنية المطلوبة
ستحتاج إلى أربعة أجزاء:
- نقطة نهاية تستقبل ويب هوكات Stripe.
- جدول لتسجيل الأحداث، مثل
stripe_event_logs. - اتصال قاعدة البيانات في بيئة Apidog.
- سيناريو اختبار في Apidog يحتوي على
Post-Request Processorللاستعلام والتحقق.
المسؤوليات مقسمة بوضوح:
- تطبيقك: يستقبل الحدث، يتحقق من التوقيع، ويحدّث البيانات.
- Apidog: يقرأ ما خزّنه التطبيق ويتحقق من أن المعالجة نجحت.
الخطوة 1: أنشئ نقطة نهاية لالتقاط Stripe webhook
أنشئ مسار POST يمكن لـ Stripe استدعاؤه. في Express، يجب استخدام الجسم الخام للطلب قبل التحقق من توقيع Stripe:
import express from "express";
import Stripe from "stripe";
const app = express();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;
app.post(
"/webhooks/stripe",
express.raw({ type: "application/json" }),
async (req, res) => {
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
req.headers["stripe-signature"],
endpointSecret
);
} catch (err) {
return res.status(400).send(`Signature check failed: ${err.message}`);
}
// احفظ الحدث لكي تسترجعه اختبارات CI لاحقًا.
await db.query(
`INSERT INTO stripe_event_logs (event_id, type, payload, handled_at)
VALUES ($1, $2, $3, now())
ON CONFLICT (event_id) DO NOTHING`,
[event.id, event.type, JSON.stringify(event.data.object)]
);
if (event.type === "payment_intent.succeeded") {
const intent = event.data.object;
await markOrderPaid(intent.metadata.order_id);
}
res.json({ received: true });
}
);
ما الذي يجب التحقق منه هنا؟
- استخدم
stripe.webhooks.constructEventللتحقق من التوقيع قبل معالجة أي بيانات. - لا تحلل أو تغيّر جسم الطلب قبل التحقق؛ Stripe يحتاج الجسم الخام لحساب التوقيع.
- خزّن
event.idلمنع معالجة الحدث نفسه أكثر من مرة. - استخدم
ON CONFLICT DO NOTHINGلأن Stripe قد يعيد تسليم الحدث.
للتفاصيل الأمنية، راجع التحقق من توقيع الويب هوك.
الخطوة 2: اربط قاعدة البيانات ببيئة Apidog
في Apidog، أنشئ اتصال قاعدة بيانات للبيئة التي سيعمل عليها اختبار CI، مثل:
- قاعدة بيانات اختبار مخصصة.
- قاعدة بيانات staging.
- قاعدة بيانات مؤقتة لكل تشغيل CI.
القاعدة المهمة: يجب أن يشير سيناريو الاختبار إلى نفس قاعدة البيانات التي تسجل فيها نقطة نهاية الويب هوك الأحداث.
إذا أرسل Stripe الحدث إلى staging بينما يستعلم Apidog عن قاعدة بيانات اختبار مختلفة، فسيفشل التحقق حتى لو كان معالج الويب هوك يعمل بشكل صحيح.
الخطوة 3: شغّل الدفع ثم استعلم عن سجل الحدث
أضف Post-Request Processor إلى سيناريو الاختبار في Apidog. بعد تنفيذ طلب الاختبار، يستعلم المعالج عن جدول الأحداث ويتحقق من نتيجة المعالجة.
تدفق اختبار واقعي لـ payment_intent.succeeded:
- شغّل عملية دفع في وضع الاختبار أو أرسل حدث اختبار معروف.
- يرسل Stripe الويب هوك إلى
/webhooks/stripe. - يتحقق تطبيقك من التوقيع ويكتب الحدث في
stripe_event_logs. - يستعلم Apidog عن السجل ويتحقق من القيم.
استخدم استعلامًا يربط السجل بالحدث الذي شغّلته، لا بمجرد «آخر حدث». مثال أساسي:
SELECT event_id, type, payload, handled_at
FROM stripe_event_logs
WHERE type = 'payment_intent.succeeded'
ORDER BY handled_at DESC
LIMIT 1;
لكن في CI، الأفضل تمرير event_id أو معرف فريد مرتبط بتشغيل الاختبار:
SELECT event_id, type, payload, handled_at
FROM stripe_event_logs
WHERE event_id = '{{event_id}}'
LIMIT 1;
تحقق من الآتي:
-
typeيساويpayment_intent.succeeded. -
event_idيطابق الحدث الذي شغّلته. - مبلغ الدفع داخل
payloadيطابق المبلغ المتوقع. -
handled_atيحتوي على قيمة. - حالة الطلب في جدول
ordersأصبحتpaid.
مثال لاستعلام ثانٍ يثبت الأثر التجاري للحدث:
SELECT id, status, paid_at
FROM orders
WHERE id = '{{order_id}}';
لا تكتفِ بإثبات أن الحدث وصل. الاختبار الأقوى يثبت أن الطلب انتقل فعليًا إلى الحالة الصحيحة.
تعامل مع التأخير غير المتزامن
تسليم Stripe webhook ليس لحظيًا دائمًا. إذا استعلم الاختبار مباشرةً بعد تشغيل الدفع، فقد يسبق وصول الحدث.
استخدم أحد الخيارين:
- تأخير قصير قبل الاستعلام.
- حلقة استقصاء تعيد المحاولة عدة مرات قبل الفشل.
منطق الاستقصاء المقترح:
- استعلم عن
event_id. - إذا لم يوجد السجل، انتظر فترة قصيرة.
- أعد المحاولة عدة مرات.
- افشل فقط بعد انتهاء مهلة محددة.
بهذا تتجنب فشلًا زائفًا سببه التوقيت، لا منطق التطبيق.
التطوير المحلي: استخدم Stripe CLI أو Ngrok
نمط الالتقاط ثم الاستعلام مناسب لـ CI. أما أثناء التطوير المحلي، فإن Stripe لا يستطيع الوصول إلى localhost مباشرةً.
استخدم Stripe CLI لإعادة توجيه الأحداث إلى تطبيقك المحلي:
stripe listen --forward-to localhost:3000/webhooks/stripe
أو استخدم Ngrok لكشف منفذ محلي عبر عنوان URL عام.
استخدم أدوات الترحيل أثناء بناء وتصحيح المعالج محليًا، ثم استخدم تسجيل قاعدة البيانات وPost-Request Processor لإثبات السلوك في CI.
لا تخلط ذلك مع ميزة Webhook في Apidog
ميزة Webhook الأصلية في Apidog مخصصة لتعريف وتوثيق الويب هوكات الصادرة من نظامك، وليست لالتقاط الأحداث الواردة من Stripe.
لاستخدامها لتوثيق webhook صادر:
- انقر على أيقونة
+في الشريط الجانبي. - اختر
New Other Protocol APIs. - اختر
Webhook. - حدّد
Request MethodوWebhook Name. - أضف جسم الطلب والرؤوس ضمن
Other Info. - استخدم
Debug URLللاختبار فقط. - انقر
Save.
يمكنك إدخال عنوان في Debug URL ثم النقر على Send لمحاكاة طلب webhook صادر.
مهم: Debug URL مخصص للاختبار ولا يظهر في الوثائق المنشورة أو تصدير OpenAPI.
للمزيد عن توثيق وتصميم الويب هوكات، راجع الويب هوكس في تصميم واجهة برمجة التطبيقات.
عزّز الاختبار قبل اعتماده في الإنتاج
بعد نجاح المسار الأساسي، أضف هذه التحققات:
1. اربط كل تشغيل اختبار بحدث محدد
لا تعتمد على آخر حدث في الجدول فقط. استخدم event_id أو order_id أو معرف تشغيل فريد لتجنب قراءة حدث متبقٍ من تشغيل سابق.
2. اختبر المسارات الفاشلة
اختبر حالات مثل:
- توقيع Stripe غير صالح.
- نوع حدث غير متوقع.
- حدث مكرر.
- بيانات
metadata.order_idغير صالحة.
في هذه الحالات، تحقق من أن التطبيق لا يحدّث الطلب إلى paid، وأن handled_at لا يدل على معالجة ناجحة عند رفض الحدث.
راجع أفضل ممارسات الويب هوك للدفع لتغطية عدم التكرار وإعادة المحاولة.
3. اختبر نتيجة الأعمال، لا التسليم فقط
التحقق من وصول الحدث وحده غير كافٍ. أضف تحققًا يؤكد أن:
SELECT status
FROM orders
WHERE id = '{{order_id}}';
يُرجع:
paid
4. شغّل السيناريو دوريًا
بعد حفظ السيناريو في Apidog، يمكنك جدولته ليعمل دوريًا، وليس فقط عند الدمج أو النشر.
راجع كيفية جدولة اختبارات API في Apidog.
شغّل التحقق في CI باستخدام Apidog CLI
ثبّت Apidog CLI وسجّل الدخول باستخدام رمز وصول:
npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
بعد ذلك، شغّل سيناريو اختبار الويب هوك المحفوظ مقابل البيئة الصحيحة:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t <SCENARIO_ID> -e <ENV_ID> -r cli
المعاملات الأساسية:
-
-t: معرف سيناريو الاختبار. -
-e: معرف البيئة. -
-r: نوع المخرجات أو المبلّغ.
لإنشاء تقرير HTML إلى جانب مخرجات الطرفية:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t <SCENARIO_ID> -e <ENV_ID> -r html,cli
يحمل السيناريو استعلامات قاعدة البيانات وPost-Request Processor. إذا فشل التحقق، يعيد الأمر رمز خروج غير صفري، ما يسمح لخط CI بمنع الدمج أو النشر.
راجع دليل تثبيت Apidog CLI وشرح مسار عمل CI/CD.
الأسئلة المتداولة
هل يستطيع Apidog استقبال Stripe webhook مباشرةً؟
لا. التقط الحدث داخل نقطة نهاية الواجهة الخلفية، واحفظه في قاعدة البيانات، ثم استخدم Post-Request Processor في Apidog للاستعلام عنه والتحقق منه.
أين تنفذ التحققات؟
داخل Post-Request Processor المرتبط بطلب في سيناريو الاختبار. يستعلم المعالج عن جدول stripe_event_logs عبر اتصال قاعدة البيانات المعرّف في البيئة.
كيف أتعامل مع تأخير وصول الحدث؟
أضف انتظارًا قصيرًا أو استقصاءً مع إعادة محاولة قبل الفشل. لا تجعل الاختبار يفترض أن Stripe سلّم الحدث فورًا.
هل أحتاج إلى ميزة Webhook الأصلية في Apidog؟
ليست لالتقاط أحداث Stripe الواردة. استخدمها لتوثيق الويب هوكات الصادرة من نظامك، واستخدم نمط الالتقاط ثم الاستعلام للتحقق من الأحداث الواردة.
هل أحتاج إلى خطة مدفوعة؟
لا تذكر الوثائق الخاصة بهذا التدفق قيدًا محددًا على الخطط. تحقق من صفحة الأسعار الحالية، أو نزّل Apidog لإعداد مشروع اختبار وتجربة اتصال قاعدة البيانات ومعالج ما بعد الطلب.
الخلاصة
لا توجّه Stripe إلى Apidog على أمل التقاط الويب هوك مباشرةً. استخدم مسارًا يمكن اختباره بوضوح:
- استقبل Stripe webhook في تطبيقك.
- تحقق من التوقيع.
- سجّل الحدث في
stripe_event_logs. - حدّث حالة الطلب.
- استعلم عن السجل وحالة الطلب من Apidog.
- شغّل السيناريو في CI عبر
apidog run.
بهذا لا يثبت خط الأنابيب أن Stripe أرسل حدثًا فقط، بل يثبت أن الدفع غيّر حالة الطلب إلى paid.
Top comments (0)