自定义 Webhook:推送到任意接收端
自定义 Webhook 集成把你创建的每条分享以结构化、带 HMAC 签名的 JSON 推送到任意公网 https 地址 —— 自动化平台(n8n、Zapier、Make、IFTTT)、你自己的后端 / 工单系统,或机器人中转。
只需一个 URL:无需注册应用、无需申请凭证。服务端自动生成 HMAC 签名密钥,你的接收端可据此验证请求确实来自 BugCapturer。
第 1 步:在接收端创建 Webhook 地址
Section titled “第 1 步:在接收端创建 Webhook 地址”在目标系统里创建一个 Webhook 接收节点,复制它的 https 地址:
- n8n:添加 Webhook 节点 → 使用 Production URL(方法:POST)
- Zapier:用 Catch Hook 触发器建 Zap,复制 hook 地址
- Make:添加 Custom webhook 模块,复制其地址
- 自有系统:暴露任意接受 POST JSON 的公网 https 接口
第 2 步:在 BugCapturer 添加集成
Section titled “第 2 步:在 BugCapturer 添加集成”- 登录 app.bugcapturer.com 打开「集成」页
- 左侧平台列表选择「自定义 Webhook」→ 点击「添加集成」
- 填写名称与 Webhook URL(https、公网)
- 点击「验证并保存」—— 服务端校验 URL(仅公网 https)并向你的接收端发送一条签名的测试事件(
event=test) - 测试通过后会一次性展示 HMAC 密钥——请立即复制保存到你的接收端配置。之后卡片只显示末 4 位;可随时通过卡片菜单「重置密钥」轮换
BugCapturer 发送什么
Section titled “BugCapturer 发送什么”每条分享会触发一次 POST 请求,Content-Type: application/json(UTF-8),payload 为 schema v1:
{ "event": "share.created", "source": "BugCapturer", "schema_version": 1, "sent_at": "2026-09-14T21:30:00+08:00", "share": { "token": "a1b2c3d4", "report_url": "https://app.bugcapturer.com/share/a1b2c3d4", "screenshot_url": "https://api.bugcapturer.com/api/shares/a1b2c3d4/file", "submitted_at": "2026-09-14T21:29:58+08:00", "expires_at": "2026-12-13T21:29:58+08:00" }, "report": { "description": "提交订单按钮点击后无响应", "feedback_type": "", "page_url": "https://example.com/checkout", "page_title": "结算页 - Example Shop", "browser": "Chrome 128", "os": "Windows 11", "screen": "1920x1080", "console_errors_count": 2, "network_errors_count": 0 }}| 字段 | 说明 |
|---|---|
event | share.created(分享创建)/ test(保存校验与「测试」按钮) |
schema_version | 固定 1;仅破坏性变更时递增,消费端按此兼容 |
share.token | 分享唯一 token |
share.report_url | 报告完整页面(浏览器打开,链接不过期) |
share.screenshot_url | 截图代理地址(302 至带签名的存储 URL) |
share.expires_at | 分享到期时间,到期后文件自动删除 |
report.description | 问题描述,超 2000 字符截断 |
report.page_url | 采集报告时的页面 URL(已脱敏) |
report.feedback_type | 预留字段——schema v1 中恒为空(插件表单已不再采集报告类型) |
report.*_errors_count | 仅条数——隐私红线,不包含控制台 / 网络错误正文;完整内容点 report_url 查看 |
| 全部时间字段 | ISO 8601,带 +08:00 时区 |
每个请求都携带请求头:
X-BugCapturer-Signature: t=<unix 时间戳>,v1=<十六进制摘要>其中 v1 = HMAC-SHA256(secret, "{t}.{原始请求体}")。验签时用 "{t}." + 原始 body 重新计算 HMAC 并以恒定时间比较,同时拒绝与本地时钟偏差超过 5 分钟的时间戳(防重放)。
Python:
import hmac, hashlib, time
def verify(secret: str, header: str, raw_body: bytes, tolerance: int = 300) -> bool: parts = dict(p.split("=", 1) for p in header.split(",")) if abs(time.time() - int(parts["t"])) > tolerance: return False # 超出时钟容差,疑似重放 expected = hmac.new(secret.encode(), f'{parts["t"]}.'.encode() + raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, parts["v1"])
# Flask 示例@app.route("/webhooks/bugcapturer", methods=["POST"])def hook(): if not verify(SECRET, request.headers["X-BugCapturer-Signature"], request.get_data()): return "bad signature", 401 payload = request.get_json() ... # 按自有逻辑处理 return "", 204Node.js:
const crypto = require("crypto");
function verify(secret, header, rawBody, tolerance = 300_000) { const parts = Object.fromEntries(header.split(",").map((p) => p.split("="))); if (Math.abs(Date.now() - Number(parts.t) * 1000) > tolerance) return false; const expected = crypto .createHmac("sha256", secret) .update(`${parts.t}.${rawBody}`, "utf8") .digest("hex"); return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));}
// Express 示例(需要原始 body)app.post("/webhooks/bugcapturer", express.raw({ type: "application/json" }), (req, res) => { if (!verify(SECRET, req.get("X-BugCapturer-Signature"), req.body)) { return res.status(401).send("bad signature"); } const payload = JSON.parse(req.body); ... // 按自有逻辑处理 res.status(204).end(); });- 创建(及轮换)后仅展示一次;之后卡片只显示
······<末 4 位> - 菜单「重置密钥」会让旧密钥立即失效——请先更新接收端,再点「测试」确认
- 密钥不会出现在投递日志、错误信息或邮件中
保存时提示「URL 不合法」?
仅接受公网 https 地址(不支持 http://、localhost / 内网 IP、携带用户凭证的 URL)。这是为了防止 SSRF 攻击,保护我们的网络。
测试请求返回 401/403?
你的接收端有自己的鉴权。要么放行携带 X-BugCapturer-Signature 头的请求,要么把接收端认可的鉴权 token 放进 URL 路径(n8n / Zapier 的 hook 地址本身已内嵌 token)。
一条报告能推给多个集成吗? 可以——配置多个集成后,分享前在插件里用「同步目标」选择器指定目标,只有选中的那个集成会收到这条报告。