用于报价与任务事件的Webhook
通过实时通知将 Quote3D 集成到您的工作流程中。
什么是 Webhooks?
Webhooks 允许您的应用程序接收有关 Quote3D 中发生的事件的实时通知。 您无需轮询我们的 API 以获取更新(例如,检查报价是否完成),Quote3D 会在事件发生后立即向您指定的 URL 发送 HTTP POST 请求。
这效率更高,并允许您在自己的系统中触发自动化工作流程,例如更新订单状态、通知客户或启动生产作业。
可用事件
- quote.completed: 当3D报价计算成功完成时触发。
- quote.failed: 如果报价计算因任何原因失败时触发。
- file.uploaded: 当新的模型文件成功上传到您的帐户时触发。
- file.deleted: 当模型文件从您的存储空间中删除时触发。
- job.status_changed: 异步任务的每次状态变更都会触发(queued、processing、completed、failed)。一次报价会产生多个此类事件。
- widget.added_to_cart: 当客户使用您的嵌入式小部件将模型添加到购物车时触发。
端点要求
您的端点URL在保存时会被校验,并在每次投递尝试前再次校验。未通过这些规则的URL会以400响应被拒绝。
- 必须使用 http 或 https。其他协议一律拒绝。
- 不得内嵌凭据。https://user:[email protected] 会被拒绝。
- 不得解析到私有或保留地址:localhost、回环地址、链路本地地址(含云实例元数据)、私有网段、CGNAT、组播和保留空间。
- 主机名在每次尝试时都会通过DNS解析,因此指向私有空间的公网主机名同样会被拒绝。
- 不会跟随重定向。请直接从您注册的URL返回响应。
有效载荷示例
所有Webhook请求都以JSON格式发送。以下是一个quote.completed事件有效载荷的示例:
{
"event": "quote.completed",
"timestamp": "2026-03-10T14:30:00.000Z",
"data": {
"jobId": "job_01HXYZ123456789",
"quoteId": "job_01HXYZ123456789",
"status": "completed",
"fileName": "gearbox-housing.stl",
"fileId": "fl_987654321",
"processingTimeMs": 22134,
"result": {
"quote_id": "job_01HXYZ123456789",
"total_price": 25.5,
"currency": "USD",
"estimated_time": "2h 15m",
"estimated_time_seconds": 8100,
"filament_weight": 42.8,
"printInfo": {
"technology": "FDM",
"material": "PLA",
"color": "Black"
}
},
"error": null
}
}安全与验证
为了确保 webhook 请求确实来自 Quote3D 且未被篡改,我们在 X-Webhook-Signature 标头中包含一个 HMAC-SHA256 签名。
当您在仪表板中创建 webhook 时,将显示一个唯一的 Secret Key。您应该使用此密钥来验证每个传入请求的签名。
验证步骤:
- 将原始请求体读取为字符串。
- 从 X-Webhook-Signature 标头中检索签名,并从 X-Webhook-Event 中检索事件名称。
- 使用您的 Webhook 密钥计算原始体的 HMAC-SHA256 哈希值。
- 将您计算出的摘要以 sha256= 为前缀,并将其与签名进行比较。如果它们匹配,则请求是真实的。
const crypto = require('crypto');
// Secret Key from your Quote3D Dashboard
const SECRET = 'your_webhook_secret_here';
function verifySignature(req) {
const signature = req.headers['x-webhook-signature'];
const event = req.headers['x-webhook-event'];
const body = req.rawBody; // Keep the exact raw JSON string
const hmac = crypto.createHmac('sha256', SECRET);
const digest = 'sha256=' + hmac.update(body).digest('hex');
if (typeof signature !== 'string' || typeof event !== 'string') {
return false;
}
const received = Buffer.from(signature, 'utf8');
const expected = Buffer.from(digest, 'utf8');
return received.length === expected.length &&
crypto.timingSafeEqual(received, expected);
}管理 Webhooks
您可以直接从仪表盘管理您的 Webhooks:
- 前往仪表盘中的 Webhooks 页面。
- 点击“新建 Webhook”以添加新的端点。
- 输入您的端点URL并选择要监听的事件。强烈建议使用HTTPS;请参见上文的端点要求。
- 立即复制您的密钥并安全地存储它。您将无法再次查看它!
- 可选择关联一个API令牌。留空时,账户上的每个请求都会触发该Webhook;关联令牌后,只有使用该令牌发出的请求才会触发。
重试失败的投递
自动重试
投递失败会在您需要介入之前自动重试。每次投递最多尝试3次;之后该投递会被标记为失败并关闭,同时仍在控制台中可见。
- 首次尝试在事件触发时立即进行。其余尝试由后台巡检任务接手,因此两次尝试之间的实际间隔取决于该巡检周期,而不是固定的秒数。
- 如果我们的进程在尝试过程中被中断,该投递会被回收并重试,而不会丢失。
- 每次投递在发送前都会被原子性地占用,因此重试绝不会导致同一投递被并发发送两次。
- 重试发送的请求体和 X-Webhook-Signature 与首次尝试完全相同,因此您现有的验证逻辑无需改动即可正常工作。
如果 webhook 目标地址暂时不可用或返回错误,您可以在仪表板中检查投递并为该特定投递记录触发重发。
POST /v2/webhooks/{webhook_id}/deliveries/{delivery_id}/resend
此端点为现有的 webhook 投递创建新的投递尝试。在您修复了接收服务器或希望为了调试重放特定事件后,它会很有用。
- 使用 webhook 详情视图来识别您想要重放的投递 ID。
- 使用 webhook ID 和 delivery ID 调用重发端点。API 将返回 202 Accepted 并创建一个新的待处理投递记录。
- webhook 必须仍然处于活动状态并属于经过身份验证的用户,否则重发请求将被拒绝。
最佳实践
- 立即返回 200 OK 状态以确认已收到 webhook。
- 异步执行繁重处理(例如,使用后台任务队列)以避免超时。
- 始终验证签名以保护您的端点免受未经授权的请求。
- 幂等性:确保您的系统可以优雅地处理相同的 webhook 多次,因为我们可能会在瞬时错误的情况下重试交付。