Integrate Stripe payments in Node.js and React — payment intents, webhooks, subscription billing, and secure checkout best practices.

Abdur Razzak
Full-Stack Web Developer
Stripe is the most developer-friendly payment platform available. The integration involves two parts: your server (Node.js) creates payment intents and handles webhooks, and your client (React) uses Stripe.js and Stripe Elements to collect payment details. Your server never sees raw card numbers — Stripe's JavaScript tokenizes the card on the client side before it ever reaches your backend.
Install the stripe npm package on your Node.js backend. When a user initiates checkout, create a PaymentIntent with the amount (in cents) and currency. Return the PaymentIntent's client_secret to your React frontend. The client_secret is used by Stripe.js to confirm the payment — it authorizes exactly one payment of the specified amount. Never log or expose the Stripe secret key in client-side code.
Install @stripe/stripe-js and @stripe/react-stripe-js on the frontend. Wrap your checkout form with Elements provider and load Stripe with your publishable key. Use the CardElement or individual elements (CardNumberElement, CardExpiryElement, CardCvcElement) for PCI-compliant card collection. On submit, call stripe.confirmCardPayment() with the client_secret and the Elements instance to complete the payment.
Webhooks are essential — never fulfill an order based solely on the client-side payment confirmation. A user can close their browser mid-payment, losing the confirmation. Instead, Stripe sends a payment_intent.succeeded webhook to your server when payment completes. Verify the webhook signature using stripe.webhooks.constructEvent() with your webhook signing secret. Fulfill the order only in the webhook handler.
For SaaS subscription billing, create Stripe Products and Prices in the Stripe dashboard. When a user subscribes, create a Stripe Customer and attach a PaymentMethod, then create a Subscription with the Price ID. Stripe handles recurring billing automatically. Listen to customer.subscription.updated and customer.subscription.deleted webhooks to update your database when subscriptions change.
Test with Stripe's test card numbers (4242 4242 4242 4242 for success, 4000 0000 0000 9995 for declined). Use the Stripe CLI to forward webhooks to your local development server: stripe listen --forward-to localhost:3000/api/webhooks/stripe. Before going live, complete Stripe's activation checklist, configure Radar fraud rules, and enable 3D Secure for card payments to reduce chargebacks.