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 is essential for handling events like subscription updates, payment success or failures, and other critical business logic. In this guide, I’ll walk you through the process of creating a robust Stripe webhook in Node.js, complete with code snippets and best practices.


What is a Stripe Webhook?

Stripe webhooks allow your application to receive real-time notifications about events happening in your Stripe account. These events include successful payments, failed charges, subscription updates, and more. Webhooks are crucial for automating workflows and keeping your backend in sync with Stripe.


Prerequisites

Before diving into the implementation, ensure you have the following:

  1. Node.js (v16 or higher) installed.
  2. A Stripe account (sign up at Stripe).
  3. The stripe Node.js library installed (npm install stripe).
  4. A webhook endpoint URL (you can use tools like ngrok for local development).

Step 1: Initialize a Node.js Project

Create a new Node.js project if you don’t already have one:

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 a Basic Express Server

Create an index.js file and set up a basic Express server:

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

const app = express();

// Middleware to parse JSON bodies
app.use(bodyParser.json());

app.get('/', (req, res) => {
  res.send('Stripe Webhook is running.');
});

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

Replace 'your_stripe_secret_key' with your actual Stripe secret key (found in the Stripe Dashboard).


Step 3: Create the Webhook Endpoint

Webhooks require a secure endpoint to verify the authenticity of incoming requests. Use Stripe’s constructEvent method to verify the webhook signature.

First, install the crypto package:

npm install crypto
Enter fullscreen mode Exit fullscreen mode

Next, create the webhook endpoint:

const crypto = require('crypto');

// Your webhook signing secret (from Stripe Dashboard)
const endpointSecret = 'your_webhook_signing_secret';

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

  try {
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    console.error(`Webhook Error: ${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;
      console.log('PaymentIntent was successful:', paymentIntent.id);
      break;
    case 'payment_intent.payment_failed':
      const failedPaymentIntent = event.data.object;
      console.log('PaymentIntent failed:', failedPaymentIntent.id);
      break;
    default:
      console.log(`Unhandled event type: ${event.type}`);
  }

  res.status(200).end();
});
Enter fullscreen mode Exit fullscreen mode

Step 4: Test the Webhook

To test your webhook locally, use ngrok to expose your local server:

  1. Install ngrok: npm install -g ngrok.
  2. Start ngrok: ngrok http 3000.
  3. Update your webhook URL in the Stripe Dashboard to your ngrok URL (e.g., https://abc123.ngrok.io/webhook).

Step 5: Simulate a Webhook Event

Stripe provides a tool to simulate webhook events. In the Stripe Dashboard:

  1. Go to Developers > Webhooks.
  2. Select your endpoint and click Send test webhook.
  3. Choose an event to simulate (e.g., payment_intent.succeeded).

Check your terminal logs to verify the event was received and handled correctly.


Step 6: Add Event Handling Logic (Optional)

Expand your webhook handler to include more event types and custom logic. For example:

switch (event.type) {
  case 'customer.subscription.created':
    const subscription = event.data.object;
    console.log('Subscription created:', subscription.id);
    break;
  case 'customer.subscription.deleted':
    const deletedSubscription = event.data.object;
    console.log('Subscription deleted:', deletedSubscription.id);
    break;
  default:
    console.log(`Unhandled event type: ${event.type}`);
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Deploy to Production

Once your webhook is working locally, deploy it to a production environment. Common options include:

  1. Heroku: Free and easy deployment.
  2. Vercel: Great for serverless functions.
  3. AWS Lambda: Fully serverless with high scalability.

Ensure your production URL is updated in the Stripe Dashboard.


Best Practices

  1. Verify Webhook Signatures: Always verify the signature to prevent malicious requests.
  2. Secure Your Endpoint: Use HTTPS for your webhook endpoint.
  3. Idempotency Key: Handle duplicate events gracefully using Stripe's idempotency key.
  4. Logging: Log all webhook events for debugging and auditing.
  5. Rate Limiting: Implement rate limiting to prevent abuse.

Conclusion

Building a Stripe webhook in Node.js is straightforward with the right tools and knowledge. By following this guide, you've created a secure, production-ready webhook capable of handling critical Stripe events. Expand your implementation to suit your business needs, and leverage Stripe’s powerful API to automate your workflows.

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)