Webhook 是 Stripe 在支付发生时通知你服务器的方式。添加端点、验证签名、通过 Stripe CLI 本地测试——前后大约十分钟。
打开 Stripe 控制台。开发阶段请切换到测试模式(橙色横幅)。
进入 开发者 → Webhook,点击添加端点。
填入你的 Webhook URL:
https://yourdomain.com/api/stripe/webhook
选择要监听的事件。常用事件包括:
checkout.session.completed — Stripe Checkout 完成payment_intent.succeeded — 自定义支付流程成功invoice.paid / invoice.payment_failed — 订阅相关customer.subscription.deleted — 订阅已终止charge.refunded — 已退款完整列表见:Stripe 事件类型参考 ↗。先从一两个事件开始,随着业务增长再逐步添加。
点击添加端点。Stripe 会显示签名密钥:
whsec_xxxxxxxxxxxxxxxxxxxxxx
复制该密钥,并存入你的后端环境变量:
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxx
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const app = express();
app.post(
'/api/stripe/webhook',
express.raw({ type: 'application/json' }),
(req, res) => {
const sig = req.headers['stripe-signature'];
try {
const event = stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
if (event.type === 'checkout.session.completed') {
console.log('Payment successful', event.data.object);
// Grant access, send email, etc.
}
res.sendStatus(200);
} catch (err) {
console.error('Webhook error:', err.message);
res.sendStatus(400);
}
}
);
SDK 参考:stripe-node ↗。
express.raw(),而非 express.json()。签名验证需要读取原始字节。如果先经过 JSON 中间件解析请求体,验证将会失败。
安装 Stripe CLI(Stripe CLI 文档 ↗):
brew install stripe/stripe-cli/stripe
stripe login
将事件转发到本地服务器:
stripe listen --forward-to localhost:3000/api/stripe/webhook
CLI 会打印一个 Webhook 签名密钥(与控制台中的密钥相互独立)。将其用作本地 .env 中的 STRIPE_WEBHOOK_SECRET。
触发一个测试事件:
stripe trigger checkout.session.completed
你的本地处理器应能接收并验证该事件。
Stripe 在失败时会重试,同一事件 ID 可能多次送达。请以 event.id 做去重处理:
const exists = await db.processedEvents.findOne({ id: event.id });
if (exists) return res.sendStatus(200); // Already handled
// ... process event ...
await db.processedEvents.insert({ id: event.id });
测试模式与正式模式的 Webhook 端点是相互独立的。准备就绪后:
STRIPE_WEBHOOK_SECRET。constructEvent,模式完全相同(原始请求体、签名头、签名密钥)。快速链接: