تكامل خطافات الويب

إعداد خطافات الويب الخاصة بمزوّد الدفع والتعامل معها لأحداث الاشتراك.

ملاحظة: هذا محتوى تجريبي/مؤقت لأغراض العرض التوضيحي.

تُخطِر خطافات الويب تطبيقك عند وقوع أحداث الفوترة، مما يضمن بقاء تطبيقك متزامنًا مع مزوّد الدفع.

لماذا خطافات الويب؟

تُعدّ خطافات الويب ضرورية لما يلي:

  • التحديثات الفورية - إشعار لحظي بأحداث الدفع
  • الموثوقية - تعالج الأحداث حتى إذا أغلق المستخدمون متصفحاتهم
  • الأمان - اتصال مباشر من خادم إلى خادم
  • الأتمتة - تحديثات تلقائية لحالة الاشتراك

نقطة نهاية خطاف الويب

تستقبل نقطة نهاية خطاف الويب الخاصة بك الأحداث من مزوّد الدفع:

// app/api/billing/webhook/route.ts
export async function POST(request: Request) {
  const body = await request.text();
  const signature = request.headers.get('stripe-signature');

  // Verify webhook signature
  const event = stripe.webhooks.constructEvent(
    body,
    signature,
    process.env.STRIPE_WEBHOOK_SECRET
  );

  // Handle the event
  await handleBillingEvent(event);

  return new Response('OK', { status: 200 });
}

الأحداث الشائعة

إنشاء الاشتراك

case 'customer.subscription.created':
  await prisma.subscription.create({
    data: {
      id: event.data.object.id,
      accountId: event.data.object.metadata.accountId,
      status: 'active',
      planId: event.data.object.items.data[0].price.id,
      currentPeriodEnd: new Date(event.data.object.current_period_end * 1000),
    },
  });
  break;

تحديث الاشتراك

case 'customer.subscription.updated':
  await prisma.subscription.update({
    where: { id: event.data.object.id },
    data: {
      status: event.data.object.status,
      planId: event.data.object.items.data[0].price.id,
      currentPeriodEnd: new Date(event.data.object.current_period_end * 1000),
    },
  });
  break;

حذف الاشتراك

case 'customer.subscription.deleted':
  await prisma.subscription.update({
    where: { id: event.data.object.id },
    data: {
      status: 'canceled',
      canceledAt: new Date(),
    },
  });
  break;

فشل الدفع

case 'invoice.payment_failed':
  const subscription = await prisma.subscription.findUnique({
    where: { id: event.data.object.subscription },
  });

  // Send payment failure notification
  await sendPaymentFailureEmail(subscription.accountId);
  break;

إعداد خطافات الويب

Stripe

  1. التطوير المحلي (باستخدام Stripe CLI):
stripe listen --forward-to localhost:3000/api/billing/webhook
  1. بيئة الإنتاج:
  • انتقل إلى لوحة تحكم Stripe ← Developers ← Webhooks
  • أضف نقطة النهاية: https://yourdomain.com/api/billing/webhook
  • حدّد الأحداث التي تريد الاستماع إليها
  • انسخ سرّ توقيع خطاف الويب إلى ملف .env الخاص بك

Paddle

  1. اضبط عنوان URL لخطاف الويب في لوحة تحكم Paddle
  2. أضف سرّ خطاف الويب إلى متغيرات البيئة
  3. تحقّق من توقيع خطاف الويب:
const signature = request.headers.get('paddle-signature');
const verified = paddle.webhooks.verify(body, signature);

if (!verified) {
  return new Response('Invalid signature', { status: 401 });
}

أفضل ممارسات الأمان

  1. تحقّق دائمًا من التواقيع - يمنع ذلك الطلبات غير المصرّح بها
  2. استخدم HTTPS - يشفّر بيانات خطاف الويب أثناء النقل
  3. تحقّق من صحة بيانات الحدث - تأكّد من وجود الحقول المطلوبة
  4. اجعل المعالجة متساوية القوى (Idempotent) - عالج الأحداث المكرّرة بأمان
  5. أعِد الرمز 200 بسرعة - أكّد الاستلام، ثم عالج الحدث بشكل غير متزامن

معالجة الأخطاء

async function handleBillingEvent(event: Event) {
  try {
    await processEvent(event);
  } catch (error) {
    // Log error for debugging
    console.error('Webhook error:', error);

    // Store failed event for retry
    await prisma.failedWebhook.create({
      data: {
        eventId: event.id,
        type: event.type,
        payload: event,
        error: error.message,
      },
    });

    // Throw to trigger provider retry
    throw error;
  }
}

اختبار خطافات الويب

استخدام أدوات CLI الخاصة بالمزوّد

# Stripe
stripe trigger customer.subscription.created

# Test specific scenarios
stripe trigger payment_intent.payment_failed

الاختبار اليدوي

curl -X POST https://your-app.com/api/billing/webhook \
  -H "Content-Type: application/json" \
  -H "stripe-signature: test_signature" \
  -d @test-event.json

المراقبة

تتبّع تسليم خطافات الويب:

  • أوقات الاستجابة
  • معدلات النجاح/الفشل
  • مدة معالجة الأحداث
  • الأحداث الفاشلة التي تتطلّب تدخّلًا يدويًا

يوفّر معظم المزوّدين لوحات تحكم لمراقبة خطافات الويب تعرض محاولات التسليم وحالات الفشل.