DEV Community

Apollo
Apollo

Posted on

How I built a Stripe Webhook in Node.js (Full Guide)

How I Built a Stripe Webhook in Node.js (Full Guide)

Building a Stripe webhook in Node.js allows you to handle real-time events from Stripe, such as successful payments, failed charges, or subscription updates. This tutorial will walk you through the entire process, from setting up a Node.js server to securely handling webhook events.


Prerequisites

Before we begin, ensure you have the following installed:

  • Node.js (version 16 or higher)
  • npm or yarn
  • Stripe account (with access to API keys)
  • A basic understanding of Express.js

Step 1: Install Required Dependencies

Start by creating a new Node.js project and installing the necessary dependencies.

mkdir stripe-webhook
cd stripe-webhook
npm init -y
npm install express stripe body-parser
Enter fullscreen mode Exit fullscreen mode

Step 2: Set Up the Express Server

Create a basic Express server to handle incoming webhook requests.

const express = require('express');
const bodyParser = require('body-parser');
const Stripe = require('stripe');

const app = express();
const stripe = Stripe(process.env.STRIPE_SECRET_KEY);

app.use(bodyParser.json());

const PORT = process.env.PORT || 4242;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Webhook Endpoint

Stripe sends webhook events to your server via HTTP POST requests. Let's create an endpoint to handle these requests.

app.post('/webhook', async (req, res) => {
  const sig = req.headers['stripe-signature'];

  let event;

  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      const paymentIntent = event.data.object;
      console.log('PaymentIntent was successful!', paymentIntent.id);
      break;
    case 'payment_method.attached':
      const paymentMethod = event.data.object;
      console.log('PaymentMethod was attached:', paymentMethod.id);
      break;
    default:
      console.log(`Unhandled event type: ${event.type}`);
  }

  res.json({ received: true });
});
Enter fullscreen mode Exit fullscreen mode

Step 4: Validate Webhook Requests

Webhook requests must be validated using the stripe-signature header and your webhook signing secret. This ensures that the request is genuinely from Stripe and hasn't been tampered with.

The stripe.webhooks.constructEvent method handles this validation automatically. If the validation fails, it throws an error.


Step 5: Retrieve Your Webhook Signing Secret

To validate webhook requests, you need your webhook signing secret. This can be found in your Stripe Dashboard:

  1. Go to the Developers section.
  2. Click on Webhooks.
  3. Select your endpoint or create a new one.
  4. Copy the Signing secret.

Store this secret in your .env file:

STRIPE_SECRET_KEY=sk_test_51...
STRIPE_WEBHOOK_SECRET=whsec_...
Enter fullscreen mode Exit fullscreen mode

Step 6: Handle Specific Events

Stripe sends various events based on user actions. You can handle specific events by checking the event.type property. Here are a few common events:

  • payment_intent.succeeded: A payment was successfully completed.
  • payment_intent.payment_failed: A payment attempt failed.
  • customer.subscription.created: A new subscription was created.
  • invoice.payment_succeeded: An invoice was paid successfully.

Example:

case 'customer.subscription.created':
  const subscription = event.data.object;
  console.log('Subscription created:', subscription.id);
  break;
case 'invoice.payment_succeeded':
  const invoice = event.data.object;
  console.log('Invoice payment succeeded:', invoice.id);
  break;
Enter fullscreen mode Exit fullscreen mode

Step 7: Test Your Webhook Locally

To test your webhook locally, you’ll need to expose your local server to the internet. Use tools like ngrok or localtunnel for this purpose.

  1. Install ngrok:
   npm install -g ngrok
Enter fullscreen mode Exit fullscreen mode
  1. Start ngrok:
   ngrok http 4242
Enter fullscreen mode Exit fullscreen mode
  1. Update your Stripe webhook endpoint URL to the ngrok URL (e.g., https://your-ngrok-url.ngrok.io/webhook).

Step 8: Simulate Webhook Events

Stripe provides a built-in tool for simulating webhook events:

  1. Go to the Webhooks section in the Stripe Dashboard.
  2. Select your endpoint.
  3. Click Send test webhook.

Step 9: Deploy Your Webhook

Once tested, deploy your Node.js server to a production environment. Use platforms like Heroku, Vercel, or AWS Lambda.

Example deployment to Heroku:

heroku create
git push heroku main
Enter fullscreen mode Exit fullscreen mode

Step 10: Monitor Webhook Activity

Stripe logs all webhook events in your Dashboard. Use this to monitor activity and debug issues.


Best Practices

  1. Always validate webhook requests. Never trust incoming requests without proper validation.
  2. Use idempotency keys. Ensure that handling the same event multiple times doesn’t cause unintended side effects.
  3. Log all events. Logging helps with debugging and auditing.
  4. Secure your endpoint. Use HTTPS and restrict access to your webhook endpoint.

By following this guide, you’ve built a secure and functional Stripe webhook in Node.js. This setup allows you to handle real-time events and automate your payment workflows effectively. Happy coding!


🚀 Stop Writing Boilerplate Prompts

If you want to skip the setup and code 10x faster with complete AI architecture patterns, grab my Senior React Developer AI Cookbook ($19). It includes Server Action prompt libraries, UI component generation loops, and hydration debugging strategies.

Browse all 10+ developer products at the Apollo AI Store | Or snipe Solana tokens free via @ApolloSniper_Bot.

Top comments (0)