SuperAPI AI 工具集

webflow-webhooks

部署与运维

查看项目

更新于 10-15 08:55

技能介绍

Webflow Webhooks 技能帮助你接收、验证并处理 Webflow 平台的 webhook 事件。

用途

在需要为 Webflow 站点搭建 webhook 处理程序、调试签名验证问题,或处理表单提交、CMS 变更、电商订单、站点发布等 Webflow 事件时使用本技能。

快速开始流程

前提:需要一个已激活站点的 Webflow 账户。如需签名验证,必须通过 API(而非控制台)创建 webhook。

  1. 创建 webhook:通过 Webflow API 针对目标事件类型注册 webhook。
  2. 接收事件:搭建接受 POST 请求的端点,并启用原始请求体(raw body)解析。
  3. 验证签名:校验 x-webflow-signature 与 x-webflow-timestamp 请求头。
  4. 处理事件:按 triggerType 路由事件并分别处理。
  5. 确认接收:返回 200 表示已收到,其他状态会触发重试。

签名验证

使用 HMAC-SHA256 进行验证,并将时间戳作为签名内容的一部分:

const crypto = require('crypto');

function verifyWebflowSignature(rawBody, signature, timestamp, secret) {
  // 检查时间戳以防止重放攻击(5 分钟窗口 = 300000 毫秒)
  const currentTime = Date.now();
  if (Math.abs(currentTime - parseInt(timestamp)) > 300000) {
    return false;
  }

  // 生成 HMAC 签名
  const signedContent = `${timestamp}:${rawBody}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedContent)
    .digest('hex');

  // 时序安全的比较
  try {
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature)
    );
  } catch {
    return false; // 长度不同即视为无效
  }
}

处理事件

app.post('/webhooks/webflow', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webflow-signature'];
  const timestamp = req.headers['x-webflow-timestamp'];

  if (!signature || !timestamp) {
    return res.status(400).send('Missing required headers');
  }

  const isValid = verifyWebflowSignature(
    req.body.toString(),
    signature,
    timestamp,
    process.env.WEBFLOW_WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(400).send('Invalid signature');
  }

  const event = JSON.parse(req.body);

  switch (event.triggerType) {
    case 'form_submission':
      console.log('New form submission:', event.payload.data);
      break;
    case 'ecomm_new_order':
      console.log('New order:', event.payload);
      break;
    case 'collection_item_created':
      console.log('New CMS item:', event.payload);
      break;
    case 'collection_item_published':
      console.log('Published CMS items:', event.payload.items);
      break;
  }

  res.status(200).send('OK');
});

事件类型

Webflow 支持 6 大类共 14 种 webhook 事件类型。各类别、事件与所需权限范围对应如下:

  • 表单(Forms):form_submission,权限 forms:read
  • 站点(Site):site_publish,权限 sites:read
  • 页面(Pages):page_created、page_metadata_updated、page_deleted,权限 pages:read
  • 电商(Ecommerce):ecomm_new_order、ecomm_order_changed、ecomm_inventory_changed,权限 ecommerce:read
  • CMS:collection_item_created、collection_item_changed、collection_item_deleted、collection_item_unpublished、collection_item_published,权限 cms:read
  • 评论(Comments):comment_created,权限 comments:read

完整参考(含所有 payload schema 与示例)见 references/event-types.md。

环境变量

# 通过 OAuth App 创建的 webhook
WEBFLOW_WEBHOOK_SECRET=your_oauth_client_secret

# 通过 API 创建的 webhook(2025 年 4 月之后)
WEBFLOW_WEBHOOK_SECRET=whsec_xxxxx  # 创建 webhook 时返回

最佳实践

  • 始终验证签名:对通过 OAuth 或 API 创建的 webhook 使用 HMAC-SHA256 验证。
  • 使用原始请求体验证:切勿对已解析的 JSON 进行验证,需相应配置框架。
  • 校验时间戳:强制 5 分钟窗口(300000 毫秒)以防重放攻击。
  • 快速返回 200:立即确认接收;对繁重负载采用异步处理。
  • 优雅处理重试:失败时 Webflow 最多重试 3 次(间隔 10 分钟)——需实现幂等性。
  • 生产环境使用 HTTPS:webhook 端点必须使用 HTTPS。

重要说明

  • 切勿明文处理密钥。API token、OAuth client secret 与 webhook 签名密钥必须存放于环境变量或密钥管理器,不得直接向用户索要 token 或密钥,也不得硬编码到源文件中。
  • 通过 Webflow 控制台创建的 webhook 不包含签名请求头。
  • 只有通过 OAuth 应用或 API 创建的 webhook 才包含 x-webflow-signature 与 x-webflow-timestamp。
  • 时间戳校验(5 分钟窗口 = 300000 毫秒)对防止重放攻击至关重要。
  • 返回 200 状态以确认接收;其他状态会触发重试(最多 3 次,间隔 10 分钟)。

参考文档

每个参考文件均含 YAML frontmatter(name、description、tags)以便检索,可使用 scripts/search_references.py 按标签或关键词查找。

  • references/event-types.md:全部 14 种事件类型的完整参考,含权限范围、payload schema 与示例
  • references/webhook-api.md:用于创建、列出、获取、删除 webhook 的 REST API v2 端点
  • references/overview.md:webhook 概念、投递行为、限制与安全考量
  • references/setup.md:控制台与 API 配置、OAuth、权限范围、环境设置
  • references/verification.md:HMAC-SHA256 签名验证、常见陷阱、调试
  • references/faq.md:投递问题、签名失败与 API 错误的常见问题与排障

检索参考

# 列出所有参考及其元数据
python scripts/search_references.py --list

# 按标签检索(精确匹配)
python scripts/search_references.py --tag <tag>

# 按关键词检索(覆盖 name、description、tags 与内容)
python scripts/search_references.py --search <query>

脚本

scripts/search_references.py:按标签、关键词检索参考文件,或列出全部及其元数据。