npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

express-stripe-webhook-middleware

v1.0.0

Published

Express middleware for Stripe webhook signature verification

Readme

Express Stripe Webhook Middleware

npm version License: MIT

A modern, type-safe Express middleware for verifying Stripe webhook signatures. Built with TypeScript and Vite.

Features

  • Type-safe: Full TypeScript support with strict type checking
  • 🔒 Secure: Automatic signature verification using Stripe's SDK
  • 🎯 Simple API: Easy to use with Express applications
  • 🔧 Flexible: Custom error handlers and logging
  • Modern: Built with Vite and latest dependencies
  • 🧪 Well-tested: Comprehensive test coverage with Vitest

Installation

npm install express-stripe-webhook-middleware stripe express
# or
yarn add express-stripe-webhook-middleware stripe express
# or
pnpm add express-stripe-webhook-middleware stripe express

Quick Start

TypeScript

import Stripe from 'stripe';
import express from 'express';
import { createStripeWebhookMiddleware } from 'express-stripe-webhook-middleware';

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

app.post(
  '/webhook',
  ...createStripeWebhookMiddleware(process.env.STRIPE_WEBHOOK_SECRET!, stripe),
  (req, res) => {
    const event = req.body as Stripe.Event;

    // Handle the event
    switch (event.type) {
      case 'payment_intent.succeeded':
        console.log('PaymentIntent was successful!');
        break;
      case 'payment_method.attached':
        console.log('PaymentMethod was attached to a Customer!');
        break;
      default:
        console.log(`Unhandled event type ${event.type}`);
    }

    res.json({ received: true });
  }
);

app.listen(4242, () => console.log('Server running on port 4242'));

JavaScript (CommonJS)

const Stripe = require('stripe');
const express = require('express');
const { createStripeWebhookMiddleware } = require('express-stripe-webhook-middleware');

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

app.post(
  '/webhook',
  ...createStripeWebhookMiddleware(process.env.STRIPE_WEBHOOK_SECRET, stripe),
  (req, res) => {
    const event = req.body;
    console.log('Received event:', event.type);
    res.json({ received: true });
  }
);

app.listen(4242);

Advanced Usage

Using the Factory Pattern

import { StripeWebhookMiddlewareFactory } from 'express-stripe-webhook-middleware';

const factory = new StripeWebhookMiddlewareFactory(
  process.env.STRIPE_WEBHOOK_SECRET!,
  stripe
);

app.post('/webhook', ...factory.create(), (req, res) => {
  const event = req.body as Stripe.Event;
  // Handle event
  res.json({ received: true });
});

Custom Error Handling

const factory = new StripeWebhookMiddlewareFactory(
  process.env.STRIPE_WEBHOOK_SECRET!,
  stripe,
  {
    onError: (error, req, res) => {
      console.error('Webhook error:', error.message);
      res.status(400).json({
        error: 'Webhook signature verification failed',
        message: error.message
      });
    }
  }
);

app.post('/webhook', ...factory.create(), (req, res) => {
  res.json({ received: true });
});

Custom Logger

import pino from 'pino';

const logger = pino();

const factory = new StripeWebhookMiddlewareFactory(
  process.env.STRIPE_WEBHOOK_SECRET!,
  stripe,
  {
    logger: (error) => logger.error({ error }, 'Webhook verification failed')
  }
);

Why This Package?

Stripe recommends verifying webhook signatures to ensure the requests actually come from Stripe.

Without This Package

Following Stripe's official example, you need to manually set up body parsing and signature verification:

const stripe = require('stripe')('sk_test_...');
const bodyParser = require('body-parser');
const app = require('express')();

app.post('/webhook', bodyParser.raw({type: 'application/json'}), (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

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

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      console.log('PaymentIntent succeeded!');
      break;
    // ... more cases
  }

  res.json({ received: true });
});

With This Package

Much cleaner and type-safe:

import { createStripeWebhookMiddleware } from 'express-stripe-webhook-middleware';

app.post(
  '/webhook',
  ...createStripeWebhookMiddleware('whsec_...', stripe),
  (req, res) => {
    const event = req.body as Stripe.Event;

    switch (event.type) {
      case 'payment_intent.succeeded':
        console.log('PaymentIntent succeeded!');
        break;
    }

    res.json({ received: true });
  }
);

API Reference

createStripeWebhookMiddleware(endpointSecret, stripe, options?)

Convenience function that creates and returns the middleware array.

Parameters:

  • endpointSecret (string): Your Stripe webhook secret (starts with whsec_)
  • stripe (Stripe): Stripe SDK instance
  • options (optional): Configuration options
    • logger: Custom logger function
    • onError: Custom error handler

Returns: RequestHandler[] - Array of Express middleware

StripeWebhookMiddlewareFactory

Factory class for creating the middleware.

Constructor:

new StripeWebhookMiddlewareFactory(
  endpointSecret: string,
  stripe: Stripe,
  options?: StripeWebhookMiddlewareOptions
)

Methods:

  • create(): Returns RequestHandler[]

Testing Your Webhooks

Using Stripe CLI

  1. Install Stripe CLI

  2. Forward webhooks to your local server:

stripe listen --forward-to localhost:4242/webhook
  1. Trigger test events:
stripe trigger payment_intent.succeeded

Example Test Server

import Stripe from 'stripe';
import express from 'express';
import { createStripeWebhookMiddleware } from 'express-stripe-webhook-middleware';

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

app.post(
  '/webhook',
  ...createStripeWebhookMiddleware(process.env.STRIPE_WEBHOOK_SECRET!, stripe),
  (req, res) => {
    const event = req.body as Stripe.Event;
    console.log('✅ Received event:', event.type);
    res.json({ received: true });
  }
);

app.listen(4242, () => {
  console.log('🚀 Webhook server running on http://localhost:4242');
});

Requirements

  • Node.js >= 18
  • Express ^4.18.0 || ^5.0.0
  • Stripe SDK ^14.0.0 || newer

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT © Hidetaka Okamoto

Changelog

v0.2.0

  • 🚀 Migrated from TSDX to Vite
  • 📦 Updated to latest dependencies (Stripe SDK v17+, TypeScript 5.7)
  • ✨ Added createStripeWebhookMiddleware helper function
  • 🔧 Added custom error handler support via onError option
  • 🎯 Improved type safety with strict TypeScript settings
  • ✅ Enhanced test coverage with Vitest
  • 📝 Comprehensive JSDoc documentation
  • ⚡ Better error handling for missing signatures
  • 🔄 Now exports both ESM and CommonJS formats

v0.1.0

  • Initial release with TSDX