How I Built a Stripe Webhook in Node.js (Full Guide)
Stripe webhooks are essential for handling asynchronous events in payment processing systems. They allow your application to respond to events like successful payments, failed charges, or subscription cancellations in real-time. In this guide, I'll walk you through building a robust Stripe webhook endpoint in Node.js, complete with event validation and error handling.
Prerequisites
Before diving into the implementation, ensure you have the following:
- A Stripe account (sign up here)
- Node.js installed (preferably version 14 or higher)
- Basic knowledge of JavaScript and Node.js
- Stripe CLI for testing webhooks locally
To install the Stripe CLI:
brew install stripe/stripe-cli/stripe
Setting Up Your Node.js Project
First, create a new Node.js project:
mkdir stripe-webhook
cd stripe-webhook
npm init -y
Next, install the necessary dependencies:
npm install express body-parser stripe
Creating the Webhook Endpoint
Let's start by creating a basic Express server with a webhook endpoint.
Step 1: Initialize Express Server
Create a file named server.js and add the following code to set up an Express server:
const express = require('express');
const bodyParser = require('body-parser');
const stripe = require('stripe')('your_stripe_secret_key'); // Add your Stripe secret key
const app = express();
app.use(bodyParser.json());
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Step 2: Add the Webhook Endpoint
Now, add the webhook endpoint. Stripe requires you to verify the event's authenticity using the stripe-signature header.
const endpointSecret = 'your_webhook_signing_secret'; // Add your Stripe webhook signing secret
app.post('/webhook', async (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 'charge.failed':
const charge = event.data.object;
console.log('Charge failed:', charge.id);
break;
// Add more cases for other event types as needed
default:
console.log(`Unhandled event type: ${event.type}`);
}
res.json({ received: true });
});
Step 3: Testing the Webhook Locally
To test the webhook locally, use the Stripe CLI to forward events to your endpoint:
stripe listen --forward-to localhost:3000/webhook
Trigger a test event from the Stripe Dashboard or using the Stripe CLI:
stripe trigger payment_intent.succeeded
You should see the event being logged in your terminal.
Handling Complex Events
In a production environment, you might need to handle more complex events, such as subscription lifecycle events or invoice payments. Here's an example of handling a subscription creation event:
case 'customer.subscription.created':
const subscription = event.data.object;
console.log('Subscription created:', subscription.id);
// Implement your logic here, e.g., update user subscription status in your database
break;
Error Handling and Logging
Robust error handling is crucial for production-ready webhooks. Implement logging for better debugging and monitoring:
app.post('/webhook', async (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}`);
}
try {
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log('PaymentIntent was successful:', paymentIntent.id);
break;
// Add more cases
default:
console.log(`Unhandled event type: ${event.type}`);
}
} catch (err) {
console.error(`Event handling error: ${err.message}`);
return res.status(500).send('Internal Server Error');
}
res.json({ received: true });
});
Securing Your Webhook Endpoint
Ensure your webhook endpoint is secure:
- Use HTTPS in production.
- Keep your Stripe secret keys and webhook signing secrets secure.
- Validate the
stripe-signatureheader for every event.
Deployment
Deploy your Node.js application to a cloud provider like Heroku, AWS, or Google Cloud. Ensure your webhook URL is correctly set in the Stripe Dashboard.
Conclusion
Building a Stripe webhook in Node.js involves setting up an Express server, validating incoming events, and handling them appropriately. By following this guide, you can create a robust webhook endpoint capable of handling various Stripe events securely and efficiently.
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)