Webhooks API
Webhook 允許您的應用程式在 Mercozy 商店發生事件時接收即時 HTTP 通知。無需輪詢 API,只需註冊一個 URL,Mercozy 會自動將事件資料 POST 到該位址。
快速開始
3 個步驟即可開始接收事件:
步驟 1:註冊您的端點
從以下位置取得 API 金鑰 設定 > 整合 > API 金鑰. 需要管理員權限。Webhook 簽名密鑰(whsec_xxx)在建立端點時自動產生,且僅顯示一次。
curl -X POST "https://api.mercozy.com/api/v1/external/webhooks" \
-H "X-API-Key: mk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "My ERP Integration",
"url": "https://your-app.com/webhooks/mercozy",
"events": ["order.created", "order.cancelled", "payment.received"]
}'步驟 2:處理傳入的事件
app.post('/webhooks/mercozy', (req, res) => {
// 1. Verify signature (see below)
const signature = req.headers['x-webhook-signature'];
if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// 2. Process the event
const { type, data } = req.body;
switch (type) {
case 'order.created':
syncOrderToERP(data);
break;
case 'payment.received':
updateAccountingSystem(data);
break;
}
// 3. Respond quickly with 200
res.status(200).json({ received: true });
});步驟 3:測試您的端點
curl -X POST "https://api.mercozy.com/api/v1/external/webhooks/{id}/test" \
-H "X-API-Key: mk_live_your_key_here"端點列表
/webhooks
列出所有已註冊的 Webhook 端點。
/webhooks
註冊新的 Webhook 端點以接收事件通知。
/webhooks/:id
更新現有 Webhook 端點(URL、事件或啟用狀態)。
/webhooks/:id
刪除 Webhook 端點。事件將不再推送。
欄位參考
| 欄位 | 類型 | 必填 | 描述 |
|---|---|---|---|
id | string | 否 | 唯一 Webhook 識別碼(唯讀) |
name | string | 是 | 端點的描述性名稱 |
url | string | 是 | 接收 Webhook 事件的 HTTPS 端點 URL |
events | string[] | 是 | 要訂閱的事件類型陣列 |
secret | string | 否 | 用於驗證負載的簽名金鑰(唯讀,建立時產生) |
isActive | boolean | 否 | Webhook 是否啟用(預設:true) |
createdAt | datetime | 否 | ISO 8601 時間戳(唯讀) |
可用事件類型
Mercozy 支援 6 個類別共 18 種 Webhook 事件類型。只需訂閱您需要的事件。
訂單
- order.created
建立新訂單時觸發
- order.updated
訂單資訊修改時觸發
- order.cancelled
訂單取消時觸發
- order.completed
訂單標記為已完成時觸發
- order.status_changed
訂單狀態變更時觸發
付款
- payment.received
收款成功或貨到付款收款時觸發
- payment.refunded
退款或取消付款時觸發
商品
- product.created
新增商品時觸發
- product.updated
商品資訊變更時觸發
- product.deleted
刪除商品時觸發
庫存
- stock.low
庫存低於閾值時觸發
- stock.updated
庫存數量變更時觸發
客戶
- customer.created
新客戶註冊時觸發
- customer.updated
客戶資訊更新時觸發
配送
- delivery.batch_started
配送批次發車時觸發
- delivery.batch_completed
批次中所有站點完成時觸發
- delivery.completed
單筆配送完成時觸發
- delivery.failed
配送嘗試失敗時觸發
Webhook 負載
每次 Webhook 推送包含事件類型、時間戳和相關資源資料。
訂單事件資料
{
"id": "evt_clx1abc2def3",
"type": "order.created",
"timestamp": "2026-03-19T10:30:00Z",
"data": {
"id": "clx9order123",
"orderNumber": "ORD-1042",
"status": "PENDING",
"total": 4999,
"currency": "USD"
}
}付款事件資料
{
"id": "evt_clx2pay4ghi5",
"type": "payment.received",
"timestamp": "2026-03-19T10:35:00Z",
"data": {
"orderId": "clx9order123",
"orderNumber": "ORD-1042",
"amount": 4999,
"currency": "USD",
"paymentMethod": "CARD",
"status": "CAPTURED"
}
}商品事件資料
{
"id": "evt_clx3prod6jkl",
"type": "product.created",
"timestamp": "2026-03-19T11:00:00Z",
"data": {
"id": "clx9prod789",
"name": "Organic Coffee Beans",
"sku": "COF-001",
"price": 1299,
"status": "ACTIVE"
}
}配送事件資料
{
"id": "evt_clx4del7mno",
"type": "delivery.completed",
"timestamp": "2026-03-19T14:22:00Z",
"data": {
"orderId": "clx9order123",
"orderNumber": "ORD-1042"
}
}HTTP 標頭
每個 Webhook 請求包含以下標頭:
| 欄位 | 類型 | 必填 | 描述 |
|---|---|---|---|
Content-Type | string | 是 | application/json |
X-Webhook-Signature | string | 是 | HMAC-SHA256 簽章:sha256={十六進位摘要} |
X-Webhook-Timestamp | string | 是 | Unix 毫秒時間戳記 |
X-Webhook-ID | string | 是 | 用於去重的唯一事件 ID |
User-Agent | string | 是 | Mercozy-Webhook/1.0 (+https://www.mercozy.com/docs/webhooks) |
簽名驗證
每個 Webhook 請求都包含 X-Webhook-Signature 標頭,其中包含 HMAC-SHA256 簽章。在處理事件前務必驗證此簽章,確保請求來自 Mercozy。
Node.js
const crypto = require('crypto');
function verifyWebhook(rawBody, signature, timestamp, secret) {
// Signature is computed over "timestamp.body"
const message = timestamp + '.' + rawBody;
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express middleware
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-webhook-signature'];
const ts = req.headers['x-webhook-timestamp'];
if (!verifyWebhook(req.body, sig, ts, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Process event...
res.status(200).json({ received: true });
});Python
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, timestamp: str, secret: str) -> bool:
# Signature is computed over "timestamp.body"
message = (timestamp + '.').encode() + payload
expected = 'sha256=' + hmac.new(
secret.encode(),
message,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# Flask example
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
sig = request.headers.get('X-Webhook-Signature')
ts = request.headers.get('X-Webhook-Timestamp')
if not verify_webhook(request.data, sig, ts, WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.get_json()
# Process event...
return {'received': True}, 200PHP
<?php
function verifyWebhook(string $payload, string $signature, string $timestamp, string $secret): bool {
// Signature is computed over "timestamp.body"
$message = $timestamp . '.' . $payload;
$expected = 'sha256=' . hash_hmac('sha256', $message, $secret);
return hash_equals($expected, $signature);
}
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
if (!verifyWebhook($payload, $signature, $timestamp, $webhookSecret)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($payload, true);
// Process event...
http_response_code(200);
echo json_encode(['received' => true]);重試策略
如果您的端點回傳非 2xx 狀態碼或逾時(10 秒),Mercozy 將使用指數退避進行重試:
| 欄位 | 類型 | 必填 | 描述 |
|---|---|---|---|
第 1 | 否 | 立即 | |
第 2 | 否 | 延遲 ~1s | |
第 3 | 否 | 延遲 ~4s |
3 次重試失敗後,投遞將標記為失敗。您可以透過控制面板或 API 手動重試。
最佳實踐
5 秒內回應 — 立即回傳 200 狀態碼,非同步處理事件。Mercozy 逾時時間為 10 秒。
始終驗證簽章 — 處理事件前檢查 X-Webhook-Signature 標頭,防止偽造請求。
處理重複(冪等性) — 使用 X-Webhook-ID 標頭去重。儲存已處理的事件 ID,跳過重複事件。
使用 HTTPS 端點 — 正式環境要求使用 HTTPS URL 以保護傳輸中的資料。
記錄日誌並監控 — 記錄所有傳入的 Webhook 並監控失敗情況。使用投遞日誌 API 檢查投遞狀態。