Node.js8 min read

Payment Integration with Stripe

Accept payments with Stripe. Handle webhooks and subscriptions.

Sarah Chen
December 19, 2025
0.0k0

Stripe Payment Integration

Accept payments securely with Stripe.

Setup

npm install stripe
const stripe = require('stripe')('sk_test_your_secret_key');

Create Payment Intent

const express = require('express');
const app = express();

app.use(express.json());

app.post('/create-payment-intent', async (req, res) => {
  const { amount } = req.body;
  
  try {
    const paymentIntent = await stripe.paymentIntents.create({
      amount: amount,
      currency: 'usd',
      payment_method_types: ['card'],
      metadata: {
        orderId: 'order_123'
      }
    });
    
    res.json({
      clientSecret: paymentIntent.client_secret
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000);

Client Side (React)

import { loadStripe } from '@stripe/stripe-js';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';

const stripePromise = loadStripe('pk_test_your_publishable_key');

function CheckoutForm() {
  const stripe = useStripe();
  const elements = useElements();
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    
    const { clientSecret } = await fetch('/create-payment-intent', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ amount: 5000 })
    }).then(r => r.json());
    
    const { error, paymentIntent } = await stripe.confirmCardPayment(
      clientSecret,
      {
        payment_method: {
          card: elements.getElement(CardElement)
        }
      }
    );
    
    if (error) {
      console.error(error.message);
    } else if (paymentIntent.status === 'succeeded') {
      console.log('Payment successful!');
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <CardElement />
      <button type="submit" disabled={!stripe}>Pay</button>
    </form>
  );
}

Webhooks

app.post('/webhook', 
  express.raw({ type: 'application/json' }),
  async (req, res) => {
    const sig = req.headers['stripe-signature'];
    const webhookSecret = 'whsec_your_webhook_secret';
    
    let event;
    
    try {
      event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
    } catch (err) {
      return res.status(400).send(\`Webhook Error: \${err.message}\`);
    }
    
    switch (event.type) {
      case 'payment_intent.succeeded':
        const paymentIntent = event.data.object;
        console.log('Payment succeeded:', paymentIntent.id);
        await updateOrderStatus(paymentIntent.metadata.orderId, 'paid');
        break;
        
      case 'payment_intent.payment_failed':
        console.log('Payment failed');
        break;
    }
    
    res.json({ received: true });
  }
);

Subscriptions

app.post('/create-subscription', async (req, res) => {
  const { customerId, priceId } = req.body;
  
  try {
    const subscription = await stripe.subscriptions.create({
      customer: customerId,
      items: [{ price: priceId }],
      payment_behavior: 'default_incomplete',
      expand: ['latest_invoice.payment_intent']
    });
    
    res.json({
      subscriptionId: subscription.id,
      clientSecret: subscription.latest_invoice.payment_intent.client_secret
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Key Takeaway

Never expose secret keys. Verify amounts server-side. Use webhooks for payment confirmations. Test with Stripe test cards. Handle errors gracefully. Always use HTTPS in production.

#Node.js#Payments#Stripe#E-commerce