为门店新增 Webhook 端点。每个门店在所有通道下最多可配置 20 个 Webhook。
POST /v1/actions/store/add-webhook
认证方式: API Key(需要 owner 或 admin 角色)
请求体
| 字段 | 类型 | 必需 | 说明 |
|---|
storeId | string | 是 | Store ID(Short ID 格式 STO_xxx) |
channel | string | 是 | 取值为 http、feishu、discord、telegram、slack 之一 |
url | string | 是 | 目标 Webhook URL(HTTPS;商户需确保 URL 与所选通道匹配) |
events | string[] | 是 | 订阅的事件类型 —— 例如 ["order.completed", "refund.succeeded"]。空数组表示不向该 Webhook 触发任何事件。 |
testMode | boolean | 是 | true = 仅对测试交易触发;false = 仅对生产交易触发 |
secret | string | null | 否 | 通道特定凭据(如 Telegram 的 chat_id)。以不透明字符串形式存储。 |
请求示例
import { WaffoPancake } from "@waffo/pancake-ts";
const client = new WaffoPancake({
merchantId: process.env.WAFFO_MERCHANT_ID!,
privateKey: process.env.WAFFO_PRIVATE_KEY!,
});
// 标准 HTTPS Webhook(RSA 签名信封)
const { webhook } = await client.webhooks.add({
storeId: "STO_2aUyqjCzEIiEcYMKj7TZtw",
channel: "http",
url: "https://example.com/webhooks/pancake",
events: ["order.completed", "refund.succeeded"],
testMode: false,
});
成功响应 (200)
{
"data": {
"webhook": {
"id": "11111111-2222-3333-4444-555555555555",
"storeId": "uuid-of-store",
"channel": "http",
"url": "https://example.com/webhooks/pancake",
"events": ["order.completed", "refund.succeeded"],
"testMode": false,
"secret": null,
"createdAt": "2026-05-07T00:00:00.000Z",
"updatedAt": "2026-05-07T00:00:00.000Z"
}
}
}
返回的 webhook.id 是 UUID,而非 Short ID —— Webhook ID 不属于 IdPrefix 范围。请将其原样传入 update-webhook 与 remove-webhook。
响应字段
| 字段 | 类型 | 说明 |
|---|
id | string | Webhook UUID |
storeId | string | 所属门店的 UUID |
channel | string | Webhook 通道(http、feishu、discord、telegram 或 slack) |
url | string | 目标 Webhook URL |
events | string[] | 订阅的事件类型 |
testMode | boolean | true 对测试交易触发,false 对生产交易触发 |
secret | string | null | 通道特定凭据(不透明字符串),未设置时为 null |
createdAt | string | 创建时间戳(ISO 8601) |
updatedAt | string | 最后更新时间戳(ISO 8601) |
错误响应
重试策略:4xx 一律不要重试 — 修正请求后重发。5xx 指数退避重试(起步 5s,最多 3 次)。
| 状态码 | errors[0].message | 含义 | 推荐处理 |
|---|
| 400 | Missing required field: storeId | 未提供 storeId | 修正请求体后重发 |
| 400 | Expected format: STO_xxx, got "..." | storeId Short ID 解码失败 | 修正 storeId 格式后重发 |
| 400 | testMode must be a boolean | testMode 不是布尔值 | 传布尔值后重发 |
| 400 | Invalid channel: must be one of http, feishu, discord, telegram, slack | channel 不在允许列表 | 使用允许的 channel |
| 400 | Invalid URL format | url 不是合法 URL | 修正 URL 后重发 |
| 400 | events must be a string array | events 不是字符串数组 | 传字符串数组后重发 |
| 400 | secret must be a string or null | secret 不是 string 或 null | 传 string 或 null 后重发 |
| 400 | Webhook limit reached (max 20 per store) | 门店已达 20 个 Webhook 上限 | 先删除已有 Webhook |
| 401 | Missing merchantId in request context | API Key 认证未解析出 merchant | 检查 API Key 请求头与签名 |
| 403 | Not authorized to manage webhooks for this store | 商户不是该门店的 owner 或 admin | 验证商户在该门店的角色 |
| 500 | Internal server error | 服务端意外失败 | 指数退避重试(起步 5s,最多 3 次) |