当事件发生在您的组织中时,实时接收通知。Webhooks 允许您构建响应式集成,立即响应二维码扫描和其他事件。
当事件发生时立即收到通知,无需轮询
HMAC 签名验证 Webhooks 来自 iloveQR
对失败的交付进行自动重试,采用指数退避策略
通过仪表板或 API 配置 Webhooks,以开始接收事件。
在您的服务器上设置 HTTPS 端点以接收 Webhook 负载。
添加您的端点 URL 并选择要订阅的事件。
实施签名验证以确保负载是正宗的。
curl -X POST \
"https://api.iloveqr.com/api/v1/organizations/org_abc123/webhooks" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/iloveqr",
"events": ["qr.scanned", "qr.created", "qr.updated"],
"secret": "your_webhook_secret"
}'订阅您需要的事件。每种事件类型都有特定的负载结构。
qr.created创建了一个新的二维码qr.updated更新了一个二维码qr.deleted删除了一个二维码qr.scanned扫描了一个二维码qr.archived归档了一个二维码qr.restored从归档中恢复了一个二维码subscription.created创建了一个新的订阅subscription.updated更新了一个订阅subscription.cancelled取消了一个订阅subscription.payment_succeeded支付成功subscription.payment_failed支付失败member.joined成员加入了组织member.left成员离开了组织member.role_changed成员的角色被更改所有 Webhook 负载遵循一致的结构,包含事件元数据和数据。
{
"id": "evt_1a2b3c4d5e6f",
"event": "qr.scanned",
"createdAt": "2024-01-15T14:30:00Z",
"organizationId": "org_abc123",
"data": {
"qrCodeId": "qr_xyz789",
"qrCodeName": "Product Landing Page",
"shortCode": "xyz789",
"destinationUrl": "https://example.com/product",
"scan": {
"id": "scan_123abc",
"timestamp": "2024-01-15T14:30:00Z",
"location": {
"country": "US",
"city": "New York",
"latitude": 40.7128,
"longitude": -74.0060
},
"device": {
"type": "mobile",
"os": "iOS",
"browser": "Safari"
},
"isUnique": true
}
}
}{
"id": "evt_7g8h9i0j1k2l",
"event": "qr.created",
"createdAt": "2024-01-15T10:00:00Z",
"organizationId": "org_abc123",
"data": {
"qrCode": {
"id": "qr_newcode",
"type": "URL",
"name": "New Campaign QR",
"shortUrl": "https://ilqr.co/newcode",
"destinationUrl": "https://example.com/campaign",
"createdBy": "user_abc123"
}
}
}始终验证 Webhook 签名,以确保负载来自 iloveQR,并且在传输过程中未被篡改。
每个 Webhook 请求都包含一个 X-Webhook-Signature 头,包含请求体的 HMAC-SHA256 签名。
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// In your webhook handler
app.post('/webhooks/iloveqr', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook
const event = req.body;
console.log('Received event:', event.event);
res.status(200).send('OK');
});import hmac
import hashlib
def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# In your Flask handler
@app.route('/webhooks/iloveqr', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Webhook-Signature')
payload = request.get_data()
if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.get_json()
print(f"Received event: {event['event']}")
return 'OK', 200在 5 秒内返回 2xx 响应。如果处理时间较长,请异步处理 Webhooks。
存储事件 ID 并检查重复项。在少数情况下,Webhooks 可能会被多次交付。
始终使用 HTTPS 端点。我们不向 HTTP URL 交付 Webhooks。
设置 Webhook 交付失败的监控。在仪表板中检查 Webhook 日志以进行调试。
如果您的端点返回错误或没有响应,我们会自动进行重试,采用指数退避:
| 尝试 | 延迟 |
|---|---|
| 第一次重试 | 1 分钟 |
| 第二次重试 | 5分钟 |
| 第3次重试 | 30分钟 |
| 第4次重试 | 2小时 |
| 第5次重试(最后一次) | 24小时 |
注意: 在5次失败尝试后,网络钩子将被标记为失败,我们将停止重试。您将收到关于失败的电子邮件通知。
准备好开始了吗?探索更多资源: