Files
template-nuxt4/content/docs/api/webhook.md
2026-04-29 01:33:33 +08:00

4.4 KiB
Raw Permalink Blame History

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在控制台配置

  1. 进入 开发者中心 → Webhook
  2. 点击 添加端点
  3. 填写配置:
配置项 说明
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))
})