Learn how to test Stripe webhooks locally using the Stripe CLI, set up a local server, forward events, debug issues, and prepare for production—all step by step.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
How to Test Webhooks Locally for Stripe
Step 1: Understand What Webhooks Are
Webhooks are a way for Stripe to notify your application when an event happens in your account. For example, when a customer's payment succeeds or fails, Stripe can send an HTTP POST request to your specified endpoint with information about the event.
Step 2: Install the Stripe CLI
The Stripe CLI is a tool that helps you interact with your Stripe account from the command line. It also allows you to forward webhooks to your local server.
For macOS (using Homebrew):
brew install stripe/stripe-cli/stripe
For Windows (using Scoop):
scoop bucket add stripe https://github.com/stripe/scoop-stripe-cli.git
scoop install stripe
For Linux:
curl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/public | gpg --dearmor | sudo tee /usr/share/keyrings/stripe.gpg
echo "deb [signed-by=/usr/share/keyrings/stripe.gpg] https://packages.stripe.dev/stripe-cli-debian-local stable main" | sudo tee -a /etc/apt/sources.list.d/stripe.list
sudo apt update
sudo apt install stripe
Step 3: Login to Your Stripe Account via CLI
Run the following command and follow the instructions to authenticate:
stripe login
This will open your browser and ask you to authorize the Stripe CLI to access your account. Once authorized, you'll be redirected back to your terminal.
Step 4: Set Up Your Local Development Server
Before testing webhooks, you need a local server that can receive HTTP requests. Here's a simple example using Express.js in Node.js:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = 3000;
// Use JSON parser for webhooks
app.use(
bodyParser.json({
// We need the raw body to verify webhook signatures.
// Let's compute it only when hitting the Stripe webhook endpoint.
verify: function(req, res, buf) {
if (req.originalUrl.startsWith('/webhook')) {
req.rawBody = buf.toString();
}
}
})
);
// Stripe webhook endpoint
app.post('/webhook', (req, res) => {
const sig = req.headers['stripe-signature'];
const endpointSecret = 'whsec\_...'; // Your webhook signing secret
let event;
try {
// Verify the event came from Stripe
const stripe = require('stripe')('sk_test_...');
event = stripe.webhooks.constructEvent(req.rawBody, sig, endpointSecret);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the event
console.log(`Received event: ${event.type}`);
switch (event.type) {
case 'payment\_intent.succeeded':
const paymentIntent = event.data.object;
console.log(`PaymentIntent ${paymentIntent.id} succeeded!`);
// Then define and call a function to handle the event payment\_intent.succeeded
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});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Step 5: Start Forwarding Webhooks to Your Local Server
Now that your local server is running, use the Stripe CLI to forward webhooks:
stripe listen --forward-to http://localhost:3000/webhook
After running this command, you'll see a webhook signing secret that looks like whsec_...
. Save this secret as it will be used to verify the webhook signatures.
Step 6: Update Your Webhook Handler with the Signing Secret
Update the endpointSecret
variable in your webhook handler code with the signing secret provided by the Stripe CLI:
const endpointSecret = 'whsec\_...'; // Replace with your webhook signing secret from the CLI
Step 7: Trigger Test Events
You can trigger test webhook events using the Stripe CLI. For example, to simulate a successful payment:
stripe trigger payment\_intent.succeeded
Here are some other common events you might want to test:
stripe trigger payment_intent.payment_failed
stripe trigger charge.succeeded
stripe trigger invoice.payment\_succeeded
stripe trigger customer.subscription.created
You can see a full list of available events by running:
stripe trigger --help
Step 8: Check the Webhook Response
When you trigger an event, the Stripe CLI will forward it to your local server. You should see logs in both your terminal running the Stripe CLI and your server application showing the event being received and processed.
Step 9: Debug Webhook Issues
If your webhook handler isn't working as expected, you can use the Stripe CLI's logs to help debug:
stripe logs tail
This will show you recent API requests, responses, and webhook events in real-time.
Step 10: Test with Real Data (Optional)
If you want to test with real data from your Stripe account (instead of simulated events), you can use:
stripe listen --forward-to http://localhost:3000/webhook --live
This will forward actual webhook events from your Stripe account to your local server. Be careful when using this with a production account!
Step 11: Use ngrok for External Testing (Optional)
If you need to test webhooks from external services that can't reach your localhost, you can use ngrok:
npm install -g ngrok
ngrok http 3000
This will give you a public URL that forwards to your local server. You can use this URL in the Stripe dashboard to register your webhook endpoint.
Then update your Stripe CLI forwarding:
stripe listen --forward-to https://your-ngrok-url.ngrok.io/webhook
Step 12: Set Up Webhook in Stripe Dashboard for Production
Once you've tested your webhook locally and are confident it works correctly, you can set it up in the Stripe Dashboard:
Stripe will provide you with a signing secret for this endpoint. Make sure to store this securely in your production environment.
Conclusion
Testing Stripe webhooks locally helps ensure your application correctly handles events before deploying to production. The Stripe CLI makes this process straightforward by forwarding webhook events to your local server, allowing you to develop and debug without deploying your code.
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.