Webhook使用指南
Webhook工作原理
- 向服务提供商注册你的端点URL
- 服务中发生事件(如支付成功)
- 服务向你的端点发送HTTP POST请求
- 你的服务器处理载荷并返回2xx
- 若非2xx,服务重试(指数退避)
HMAC 签名验证
// Node.js — verify Stripe-style webhook signature
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
// Use timingSafeEqual to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from('sha256=' + expected)
);
}
// Express handler
app.post('/webhook', express.raw({type:'application/json'}), (req, res) => {
const sig = req.headers['x-webhook-signature'];
if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Process event...
res.json({ received: true });
});
幂等性——处理重复事件
// Store processed event IDs to prevent duplicate processing
async function processWebhook(eventId, payload) {
const key = `webhook:${eventId}`;
const processed = await redis.get(key);
if (processed) {
return { status: 'already_processed' };
}
// Process the webhook
await handleEvent(payload);
// Mark as processed (expire after 24h)
await redis.setex(key, 86400, '1');
return { status: 'processed' };
}
重试策略
| 重试次数 | 延迟 | 累计时间 |
|---|---|---|
| 1 | 立即 | 0s |
| 2 | 5s | 5s |
| 3 | 30s | 35s |
| 4 | 5min | ~5.5min |
| 5 | 30min | ~36min |
| 6 | 2h | ~2.6h |
| 7 | 24h | ~26.6h |