Handle Stripe webhook events with signature verification
✓Works with OpenClaudeYou are a backend developer integrating Stripe webhooks. The user wants to receive, verify, and process Stripe webhook events securely with proper signature validation.
What to check first
- Run
npm list stripeto confirm the Stripe Node library is installed (version 8.0.0+) - Verify your Stripe webhook signing secret is stored in environment variables (e.g.,
STRIPE_WEBHOOK_SECRET) - Check your server framework supports raw request body parsing (Express needs
express.raw()middleware)
Steps
- Install Stripe:
npm install stripe - Set up a raw body parser middleware in Express — Stripe signature verification requires the raw request body, not parsed JSON
- Create a webhook endpoint that accepts POST requests at a path like
/webhookor/api/webhooks/stripe - Extract the Stripe signature from the
stripe-signatureheader usingrequest.headers['stripe-signature'] - Verify the webhook signature using
stripe.webhooks.constructEvent()— this validates the request came from Stripe - Extract the event type from the verified event object (e.g.,
event.type === 'charge.succeeded') - Handle specific event types with dedicated switch cases or conditional logic
- Return a 200 status code immediately to acknowledge receipt, then process events asynchronously if needed
Code
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const app = express();
// Raw body parser MUST come before JSON parser for webhook route
app.post(
'/webhook',
express.raw({ type: 'application/json' }),
async (req, res) => {
const sig = req.headers['stripe-signature'];
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
let event;
try {
// Verify signature and construct event
event = stripe.webhooks.constructEvent(
req.body,
sig,
webhookSecret
);
} catch (err) {
console.error(`Webhook signature verification failed: ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Acknowledge receipt immediately
res.status(200).json({ received: true });
// Process event asynchronously
try {
switch (event.type) {
case 'charge.succeeded': {
const charge = event.data.object;
console.log(`Charge succeeded: ${charge.id} for $${charge.amount / 100}`);
// Update database, send confirmation email, etc.
break;
}
case 'charge.failed': {
const charge = event.data.object;
console.log(`Charge failed: ${charge.id}`);
// Notify user, retry logic, etc.
break;
}
case 'customer.subscription.updated': {
Note: this example was truncated in the source. See the GitHub repo for the latest full version.
Common Pitfalls
- Treating this skill as a one-shot solution — most workflows need iteration and verification
- Skipping the verification steps — you don't know it worked until you measure
- Applying this skill without understanding the underlying problem — read the related docs first
When NOT to Use This Skill
- When a simpler manual approach would take less than 10 minutes
- On critical production systems without testing in staging first
- When you don't have permission or authorization to make these changes
How to Verify It Worked
- Run the verification steps documented above
- Compare the output against your expected baseline
- Check logs for any warnings or errors — silent failures are the worst kind
Production Considerations
- Test in staging before deploying to production
- Have a rollback plan — every change should be reversible
- Monitor the affected systems for at least 24 hours after the change
Related Payments Skills
Other Claude Code skills in the same category — free to download.
Stripe Integration
Integrate Stripe payments with checkout and payment intents
Stripe Subscriptions
Set up recurring subscription billing with Stripe
PayPal Integration
Integrate PayPal payments and checkout
Payment Form
Build secure PCI-compliant payment forms
Invoice System
Build invoice generation and management system
Pricing Page
Build dynamic pricing page with plan comparison
Payment Testing
Set up payment testing with test cards and sandbox environments
Want a Payments skill personalized to YOUR project?
This is a generic skill that works for everyone. Our AI can generate one tailored to your exact tech stack, naming conventions, folder structure, and coding patterns — with 3x more detail.