4.4 KiB
4.4 KiB
title, description, category, order
| title | description | category | order |
|---|---|---|---|
| Webhook 事件接入 | 订阅业务事件,处理订单支付、AI 任务完成等异步通知。 | api | 3 |
Webhook 事件接入
订阅业务事件,处理订单支付、AI 任务完成等异步通知。
🔔 什么是 Webhook?
Webhook 是一种「反向 API 调用」机制:
- 传统 API:你 → 平台(主动拉取)
- Webhook:平台 → 你(被动接收)
当某个事件发生时(如支付成功),平台主动通知你的服务器。
📋 可订阅的事件
| 事件类型 | 说明 |
|---|---|
payment.completed |
支付完成 |
payment.failed |
支付失败 |
subscription.created |
订阅创建 |
subscription.cancelled |
订阅取消 |
ai.task.completed |
AI 任务完成 |
ai.task.failed |
AI 任务失败 |
file.uploaded |
文件上传完成 |
project.created |
项目创建 |
user.invited |
用户被邀请 |
workflow.triggered |
工作流触发 |
🚀 配置 Webhook
步骤 1:创建 Webhook 端点
在你的服务器创建一个 API 端点:
// Node.js Express 示例
app.post('/webhook/websopy', express.raw({ type: 'application/json' }), (req, res) => {
// 验证签名
const signature = req.headers['x-websopy-signature']
const timestamp = req.headers['x-websopy-timestamp']
if (!verifySignature(req.body, signature, timestamp)) {
return res.status(401).send('Invalid signature')
}
// 处理事件
const event = JSON.parse(req.body)
console.log('收到事件:', event.type)
// 立即返回 200(重要!)
res.status(200).send('OK')
// 异步处理业务逻辑
processEvent(event)
})
步骤 2:在控制台配置
- 进入 开发者中心 → Webhook
- 点击 添加端点
- 填写配置:
| 配置项 | 说明 |
|---|---|
| URL | 你的服务器地址,如 https://your-server.com/webhook/websopy |
| 事件类型 | 选择要订阅的事件 |
| 密钥 | 用于验证签名的密钥 |
步骤 3:验证签名
import crypto from 'crypto'
function verifySignature(body, signature, timestamp) {
const secret = process.env.WEBSOPY_WEBHOOK_SECRET
// 检查时间戳(5分钟内有效)
const ts = parseInt(timestamp)
if (Date.now() - ts > 5 * 60 * 1000) {
return false
}
// 计算签名
const payload = `${timestamp}.${body}`
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
)
}
📨 事件数据格式
通用结构
{
"id": "evt_abc123xyz",
"type": "payment.completed",
"created_at": "2024-01-15T10:30:00Z",
"data": {
// 事件相关数据
}
}
支付完成事件
{
"id": "evt_abc123xyz",
"type": "payment.completed",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"order_id": "ord_xyz789",
"amount": 29900,
"currency": "CNY",
"payment_method": "alipay",
"status": "completed",
"user_id": "user_123"
}
}
⏰ 失败重试
如果你的服务器返回非 200 状态码,Websopy 会自动重试:
| 重试次数 | 延迟 |
|---|---|
| 第 1 次 | 1 分钟 |
| 第 2 次 | 5 分钟 |
| 第 3 次 | 30 分钟 |
| 第 4 次 | 2 小时 |
| 第 5 次 | 12 小时 |
超过重试次数仍未成功,事件将被标记为失败,可在控制台手动重试。
幂等处理
const processedEvents = new Set()
app.post('/webhook/websopy', async (req, res) => {
const event = JSON.parse(req.body)
// 幂等检查
if (processedEvents.has(event.id)) {
return res.status(200).send('Already processed')
}
try {
await processEvent(event)
processedEvents.add(event.id)
res.status(200).send('OK')
} catch (error) {
res.status(500).send('Error')
}
})
🧪 本地开发测试
使用 ngrok
# 安装 ngrok
npm install -g ngrok
# 启动本地服务
ngrok http 3000
# 复制输出的 https URL 到 Webhook 配置
# https://abc123.ngrok.io/webhook/websopy
❓ 常见问题
Q: 收到重复事件怎么办?
使用事件 ID 做幂等检查,参考上文示例。
Q: 处理超时怎么办?
app.post('/webhook', async (req, res) => {
// 立即返回
res.status(200).send('OK')
// 异步处理
setImmediate(() => processEvent(req.body))
})