Stripe for Next.js: A Developer's Guide to Seamless Payments

Handling Common Stripe Events

Section 4

Handling Webhooks and Real-time Updates

Stripe for Next.js: A Developer's Guide to Seamless PaymentsHandling Webhooks and Real-time Updates

Stripe sends notifications about events occurring in your account via webhooks. These events are crucial for keeping your application's state synchronized with Stripe's, enabling real-time updates for your users and backend processes. In this section, we'll explore some of the most common Stripe events and how to handle them effectively in your Next.js application.

The fundamental principle is to create an API route in your Next.js application that acts as your webhook endpoint. This endpoint will receive POST requests from Stripe containing event data. It's vital to verify the authenticity of these requests to prevent malicious actors from triggering actions in your system.

import { buffer } from 'micro';
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export default async (req, res) => {
  if (req.method === 'POST') {
    const buf = await buffer(req);
    const sig = req.headers['stripe-signature'];

    let event;

    try {
      event = stripe.webhooks.constructEvent(buf, sig, process.env.STRIPE_WEBHOOK_SECRET);
    } catch (err) {
      console.log(`Webhook signature verification failed.`, err.message);
      return res.status(400).send(`Webhook Error: ${err.message}`);
    }

    // Handle the event
    switch (event.type) {
      case 'payment_intent.succeeded':
        const paymentIntent = event.data.object;
        // Fulfill the order or provide access to the service
        console.log(`PaymentIntent for ${paymentIntent.amount} was successful!`);
        break;
      case 'payment_method.attached':
        const paymentMethod = event.data.object;
        // Update customer payment methods, etc.
        console.log(`PaymentMethod ${paymentMethod.id} was attached to a Customer!`);
        break;
      // ... handle other event types
      default:
        console.log(`Unhandled event type ${event.type}`);
    }

    // Return a 200 response to acknowledge receipt of the event
    res.json({ received: true });
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
}; 

export const config = {
  api: {
    bodyParser: false
  }
};

Let's break down the key events you'll likely encounter and how to handle them:

payment_intent.succeeded: This is one of the most important events. It fires when a customer successfully pays for an order. In your webhook handler, you'll want to update your database to mark the order as paid, grant the user access to the purchased content or service, and potentially send confirmation emails.

case 'payment_intent.succeeded':
  const paymentIntent = event.data.object;
  // Find your order in the database using paymentIntent.id or metadata
  // Update order status to 'paid'
  // Grant access to the user
  console.log(`PaymentIntent ${paymentIntent.id} succeeded.`);
  break;

checkout.session.completed: This event is triggered when a customer completes the checkout process using Stripe Checkout. It's useful for scenarios where you're using Stripe Checkout as your primary payment interface. You'll often use this to fulfill orders, similar to payment_intent.succeeded.

case 'checkout.session.completed':
  const session = event.data.object;
  // If the session is in live mode, fulfill the purchase
  if (session.payment_status === 'paid') {
    // Retrieve the associated order/customer details from metadata
    // Fulfill the order
    console.log(`Checkout session ${session.id} completed and paid.`);
  } else {
    console.log(`Checkout session ${session.id} completed but not paid.`);
  }
  break;
チャプターへ戻る