تكامل Stripe مع React و Node.js: Payment Intents و Webhooks و 3D Secure
تكامل Stripe الإنتاجي مع Payment Intents و webhooks و 3D Secure. يغطي فواتير الاشتراكات ومعالجة الأخطاء وأنماط امتثال PCI.
جدول المحتويات
- لماذا هذا الدليل موجود
- نظرة عامة على البنية
- إعداد Stripe بشكل صحيح
- تنفيذ Payment Intents
- بناء نموذج الدفع في React
- تنفيذ Webhooks
- التعامل مع 3D Secure و SCA
- فواتير الاشتراكات
- معالجة الأخطاء التي تعمل فعلاً
- الأخطاء الشائعة في الإنتاج
لماذا هذا الدليل موجود
قمت بدمج Stripe في أكثر من عشرة أنظمة إنتاجية - منصات تجارة إلكترونية تعالج آلاف المعاملات اليومية، وتطبيقات SaaS بمستويات اشتراك معقدة، وأنظمة سوق بمدفوعات مقسمة. توثيق Stripe الرسمي جيد، لكنه لا يخبرك بما يحدث عندما تسوء الأمور في الساعة 2 صباحاً يوم الجمعة.
يغطي هذا الدليل ما كنت أتمنى معرفته قبل أول تكامل Stripe، وما تعلمته من تصحيح فشل المدفوعات في الإنتاج.
نظرة عامة على البنية
قبل كتابة الكود، افهم بنية تدفق الدفع:
┌─────────────────────────────────────────────────────────────────────┐
│ تطبيقك │
├─────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ React UI │────▶│ Your API │────▶│ Database │ │
│ │ (Stripe.js) │ │ (Node.js) │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ Stripe API │
│ • لا يرى أبداً أرقام البطاقات الخام من خادمك │
│ • يتعامل مع تحديات 3D Secure │
│ • يرسل webhooks للأحداث غير المتزامنة │
└─────────────────────────────────────────────────────────────────────┘
المبدأ الحاسم: خادمك لا يتعامل أبداً مع بيانات البطاقة الخام. Stripe.js يرمز تفاصيل البطاقة من جانب العميل.
إعداد Stripe بشكل صحيح
تكوين البيئة
// config/stripe.ts import Stripe from 'stripe'; if (!process.env.STRIPE_SECRET_KEY) { throw new Error('STRIPE_SECRET_KEY مطلوب'); } export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: '2023-10-16', // دائماً ثبت إصدار API typescript: true, maxNetworkRetries: 2, timeout: 30000, });
لماذا تثبت إصدار API؟ Stripe تجري تغييرات جذرية. رأيت أنظمة إنتاج تتعطل لأنها ترقت تلقائياً إلى إصدار API جديد.
تنفيذ Payment Intents
Payment Intents هي واجهة Stripe الحديثة. لا تستخدم أبداً Charges API القديمة للتكاملات الجديدة.
جانب الخادم: إنشاء Payment Intents
export class PaymentService { async createPaymentIntent(params: CreatePaymentParams): Promise<{ clientSecret: string; paymentIntentId: string; }> { const { orderId, amount, currency } = params; // تحقق من وجود الطلب وإمكانية الدفع const order = await this.orderRepo.findById(orderId); if (!order) { throw new PaymentError('ORDER_NOT_FOUND', 'الطلب غير موجود'); } // تحقق من تطابق المبلغ مع إجمالي الطلب (منع التلاعب بالسعر) if (amount !== order.totalAmountCents) { throw new PaymentError('AMOUNT_MISMATCH', 'مبلغ الدفع لا يطابق الطلب'); } const paymentIntent = await stripe.paymentIntents.create({ amount, currency, metadata: { orderId }, automatic_payment_methods: { enabled: true }, }); return { clientSecret: paymentIntent.client_secret!, paymentIntentId: paymentIntent.id, }; } }
بناء نموذج الدفع في React
إعداد Stripe Elements
import { Elements } from '@stripe/react-stripe-js'; import { loadStripe } from '@stripe/stripe-js'; const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!); export function StripeProvider({ clientSecret, children }) { const options = { clientSecret, appearance: { theme: 'stripe', variables: { colorPrimary: '#0070f3', borderRadius: '8px', }, }, }; return ( <Elements stripe={stripePromise} options={options}> {children} </Elements> ); }
مكون نموذج الدفع
export function PaymentForm({ orderId, amount, currency, onSuccess, onError }) { const stripe = useStripe(); const elements = useElements(); const [isProcessing, setIsProcessing] = useState(false); const handleSubmit = async (event) => { event.preventDefault(); if (!stripe || !elements) return; setIsProcessing(true); const { error, paymentIntent } = await stripe.confirmPayment({ elements, confirmParams: { return_url: `${window.location.origin}/order/${orderId}/confirmation`, }, redirect: 'if_required', }); if (error) { onError(error.message); } else if (paymentIntent?.status === 'succeeded') { onSuccess(paymentIntent.id); } setIsProcessing(false); }; return ( <form onSubmit={handleSubmit}> <PaymentElement /> <button disabled={!stripe || isProcessing}> {isProcessing ? 'جارٍ المعالجة...' : `ادفع ${formatAmount(amount, currency)}`} </button> </form> ); }
تنفيذ Webhooks
هذا هو المكان الذي تفشل فيه معظم تكاملات Stripe. Webhooks هي الطريقة التي يخبرك بها Stripe عن الأحداث غير المتزامنة.
أمان Webhook
// حاسم: استخدم الجسم الخام للتحقق من التوقيع export function stripeWebhookMiddleware(req, res, next) { const signature = req.headers['stripe-signature']; try { const event = stripe.webhooks.constructEvent( req.body, // يجب أن يكون buffer خام، وليس JSON محلل signature, STRIPE_WEBHOOK_SECRET ); req.stripeEvent = event; next(); } catch (err) { return res.status(400).json({ error: 'توقيع غير صالح' }); } }
معالج Webhook مستقر
export class WebhookService { async handleEvent(event: Stripe.Event): Promise<void> { // فحص الاستقرار - هل عالجنا هذا الحدث؟ const existingEvent = await this.webhookRepo.findByEventId(event.id); if (existingEvent) { console.log(`الحدث ${event.id} معالج بالفعل، تخطي`); return; } // سجل الحدث قبل المعالجة await this.webhookRepo.create({ eventId: event.id, eventType: event.type, status: 'processing', }); try { await this.processEvent(event); await this.webhookRepo.markCompleted(event.id); } catch (error) { await this.webhookRepo.markFailed(event.id, error); throw error; } } private async handlePaymentSucceeded(paymentIntent: Stripe.PaymentIntent) { const orderId = paymentIntent.metadata.orderId; await this.paymentRepo.updateByPaymentIntentId(paymentIntent.id, { status: 'succeeded', paidAt: new Date(), }); await this.orderService.fulfillOrder(orderId); await this.notificationService.sendOrderConfirmation(orderId); } }
الأخطاء الشائعة في الإنتاج
1. عدم استخدام مفاتيح الاستقرار
// ❌ سيء: ينشئ رسوم مكررة عند إعادة المحاولة const paymentIntent = await stripe.paymentIntents.create({ amount: 1000, currency: 'usd', }); // ✅ جيد: آمن لإعادة المحاولة const paymentIntent = await stripe.paymentIntents.create( { amount: 1000, currency: 'usd' }, { idempotencyKey: `order_${orderId}_payment` } );
2. الوثوق بالمبلغ من جانب العميل
// ❌ سيء: المبلغ يأتي من العميل app.post('/create-payment', (req, res) => { const { amount } = req.body; // لا تثق بهذا أبداً }); // ✅ جيد: المبلغ من الطلب في الخادم app.post('/create-payment', (req, res) => { const order = await Order.findById(req.body.orderId); stripe.paymentIntents.create({ amount: order.totalCents }); });
3. عدم التعامل مع فشل Webhook
// ❌ سيء: نقطة فشل واحدة router.post('/webhook', (req, res) => { await processEvent(event); // إذا فشل هذا، الدفع ضائع res.json({ received: true }); }); // ✅ جيد: طابور مستمر للموثوقية router.post('/webhook', (req, res) => { await webhookQueue.add('process-stripe-event', event); res.json({ received: true }); // إقرار فوري });
الخلاصة
تكامل Stripe الإنتاجي يتطلب:
- لا تتعامل أبداً مع بيانات البطاقة الخام - استخدم Stripe.js و Payment Elements
- Webhooks مستقرة - مصدر الحقيقة الأساسي لحالة الدفع
- معالجة أخطاء صحيحة - حول أخطاء Stripe لرسائل صديقة للمستخدم
- دعم SCA/3D Secure - مطلوب في مناطق كثيرة
- مفاتيح الاستقرار - منع الرسوم المكررة
- التحقق من المبلغ في الخادم - لا تثق بالعميل أبداً
مقالات ذات صلة
هندسة الأمانقراءة 23 دقيقة
أفضل ممارسات مصادقة JWT: Refresh Tokens و RBAC و OAuth 2.0
تنفيذ مصادقة JWT آمنة مع تدوير refresh token و RBAC وتدفقات OAuth 2.0. أنماط إنتاجية من أنظمة الرعاية الصحية والحكومة.
هندسة الأمانقراءة 20 دقيقة
قائمة فحص أمان API: Rate Limiting والتحقق من المدخلات وتكوين CORS
تأمين APIs مع rate limiting والتحقق من المدخلات وتكوين CORS. قائمة فحص مختبرة إنتاجياً تغطي المصادقة والتشفير ومعالجة الأخطاء.
تصميم الخلفيةقراءة 19 دقيقة
بنية قوائم الانتظار: دليل تنفيذ Redis و RabbitMQ و SQS
بناء أنظمة قوائم انتظار موثوقة مع Redis و RabbitMQ و AWS SQS. يغطي dead letter queues والتكافؤ وأنماط المعالجة الحقيقية.
تكامل بوابات الدفعقراءة 28 دقيقة
تكامل PayPal مع React و Node.js: دليل Orders API و Smart Buttons
تكامل PayPal مع Orders API و Smart Buttons. يغطي إعداد webhooks ومدفوعات الاشتراك وأنماط معالجة الأخطاء الحقيقية من الإنتاج.
تكامل بوابات الدفعقراءة 30 دقيقة
دليل تكامل Adyen: تنفيذ Drop-in Component و API
تكامل Adyen للمؤسسات مع Drop-in component و API. يغطي تكوين الدفع ومعالجة webhooks ودعم العملات المتعددة.