Stripe Webhooks and Testing
Webhooks, the dashboard, test payments, pricing and built-in security
Buzz presents
webhooks tell your app when a payment realy worked, and test cards let you practice without spending a penny. yay!webhooks tell your app when a payment realy worked, and test cards let you practice without spending a penny. yay!

Webhooks: Getting Notified#
So how does your app find out a payment happened? Stripe uses "webhooks," which just means Stripe sends a message to your server.
Here's the catch though. ANYONE can send a fake message to your webhook URL pretending to be Stripe. So before you trust it, you check the signature Stripe puts on every webhook, using the signing secret (it starts with whsec_) from your webhook settings.
// Express server receiving Stripe webhooks
const express = require('express')
const Stripe = require('stripe')
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY)
const app = express()
// Stripe needs the RAW body to check the signature, so don't parse it as JSON first
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
let event
try {
event = stripe.webhooks.constructEvent(
req.body,
req.headers['stripe-signature'],
process.env.STRIPE_WEBHOOK_SECRET
)
} catch (err) {
// Signature didn't match, so this didn't come from Stripe
return res.status(400).send(`Webhook Error: ${err.message}`)
}
if (event.type === 'checkout.session.completed') {
const session = event.data.object
// 'unpaid' means the money hasn't landed yet (like a bank transfer still processing)
if (session.payment_status !== 'unpaid') {
// Payment succeeded! Unlock access for this order.
fulfillOrder(session.id)
}
}
res.json({ received: true })
})
app.listen(4242, () => console.log('Listening on port 4242'))Install the two libraries first with npm install express stripe. fulfillOrder is your own function, the spot where you mark the order paid in your database and give access.
A couple of things Stripe's docs are serious about. Stripe can send the same event more than once, so fulfillOrder should check whether that order was already handled before it does anything. And answer fast, then do slow work afterward, or Stripe thinks the delivery failed and tries again. While you're building, the Stripe CLI command stripe listen --forward-to localhost:4242/webhook sends test events to your laptop and prints the signing secret to use.
Webhooks tell you about all kinds of things.
- Successful payments
- Failed payments
- Subscription renewals
- Subscription cancellations
- Refunds
- Disputes
The Stripe Dashboard#
Stripe gives you a powerful dashboard where you can do all of this.
- View payments. See every transaction, successful and failed
- Manage customers. Look at a customer's payment history
- Handle refunds. Process refunds with a click
- Create products. Set up what you're selling
- View reports. Understand your revenue trends
- Sandboxes. Try everything without real money
Testing Payments#

Stripe has test environments, which its docs now call sandboxes (you'll also still hear people say test mode), plus fake card numbers to use in them. You can build and test your whole payment flow without spending a single real dollar (your bank account says thanks).
Here are the test card numbers.
4242 4242 4242 4242- Always succeeds4000 0000 0000 0002- Always declines4000 0000 0000 9995- Fails with "insufficient funds"
Use any future date for expiry and any 3 digits for CVC.
Pricing#
Stripe takes a fee on each successful payment, and subscriptions run through Stripe Billing, which has its own pricing on top. The exact numbers depend on your country, the payment method and the product, and they change. Like the payments intro said, don't trust fee numbers from a tutorial... and yes, that includes this one.
Check stripe.com/pricing for payment fees and stripe.com/billing/pricing for subscription fees BEFORE you set your prices.
Security You Get for Free#
Just by using Stripe, you automatically get all of this.
- PCI Compliance. Stripe does the heavy lifting, and with Checkout or Elements card numbers never touch your server. You still confirm your own compliance once a year (Stripe walks you through it in the dashboard)
- Fraud Detection. Machine learning catches sketchy transactions
- 3D Secure. Extra verification for risky payments
- Encryption. All data is encrypted in transit and at rest
- Global Security Team. Stripe employs security experts so you don't have to
TL;DR#
- Never handle credit card numbers directly, use Stripe
- Stripe handles security, fraud prevention and compliance
- One-time payments and subscriptions are both supported
- Stripe Checkout is the fastest way to add payments
- Webhooks tell your app when payment events happen
- Sandboxes (aka test mode) let you build without real money
- Check Stripe's own pricing pages for current fees, since they vary and change
This lesson ends with a short activity.