Tham chiếu Webhook
Tóm tắt
Đăng ký một endpoint HTTPS để Elim chủ động gọi vào hệ thống của bạn mỗi khi đơn hàng hoặc thanh toán đổi trạng thái — thay cho việc hỏi trạng thái liên tục. Trang này mô tả sự kiện, endpoint quản lý, cấu trúc payload, cách xác minh chữ ký và chính sách thử lại.
Để xem webhook nằm ở đâu trong vòng đời đơn hàng, xem Hướng dẫn đặt & thanh toán đơn Taobao/1688 và Tham chiếu API đơn hàng.
Mọi endpoint yêu cầu xác thực JWT (Authorization: Bearer <token>) hoặc API Key (x-api-key).
Sự kiện
| Sự kiện | Khi nào gửi |
|---|---|
order.updated | Trạng thái đơn (status) đổi: đồng bộ từ nền tảng, đồng bộ định kỳ, hoặc hủy đơn |
payment.updated | Trạng thái thanh toán (payment_status) đổi: gửi yêu cầu, rút yêu cầu, duyệt, từ chối, nền tảng thanh toán xong/lỗi, hoặc hoàn tiền |
Đăng ký sự kiện nào thì chỉ nhận sự kiện đó. Thường đăng ký cả hai.
Endpoint quản lý đăng ký
Prefix /v1/webhooks.
| Endpoint | Method | Mô tả |
|---|---|---|
/v1/webhooks | GET | Danh sách đăng ký hiện có |
/v1/webhooks | POST | Tạo đăng ký — trả secret một lần duy nhất |
/v1/webhooks/:id | PATCH | Sửa url, events, hoặc is_active |
/v1/webhooks/:id | DELETE | Xóa đăng ký |
/v1/webhooks/:id/rotate-secret | POST | Đổi secret — trả giá trị mới một lần |
/v1/webhooks/:id/deliveries | GET | Nhật ký các lần gửi gần đây |
/v1/webhooks/:id/test | POST | Gửi một lần gọi thử tới url đã đăng ký |
Body tạo đăng ký
{
"url": "https://he-thong-cua-ban.example/webhooks/elim",
"events": ["order.updated", "payment.updated"],
"is_active": true
}
secret chỉ trả về ngay sau khi tạo hoặc rotate-secret. Lưu vào nơi an toàn — bạn cần nó để xác minh mọi request. Mất secret thì gọi rotate-secret để cấp lại (chữ ký cũ ngừng hợp lệ).
Cấu trúc payload
Cả hai sự kiện dùng chung một dạng — khác nhau ở trường event:
{
"id": "evt_4a1f2c...",
"event": "payment.updated",
"created_at": "2026-06-19T00:00:00.000Z",
"data": {
"order": {
"id": "ORD0000000123",
"platform": "taobao",
"order_id": "123456789",
"status": "paid",
"payment_status": "paid",
"platform_payment_status": "success",
"total_amount_cny": 123.45,
"updated_at": "2026-06-19T00:00:00.000Z"
}
}
}
| Trường | Mô tả |
|---|---|
id | ID sự kiện, dạng evt_... — dùng để chống xử lý trùng |
event | order.updated hoặc payment.updated |
created_at | Thời điểm sinh sự kiện (ISO 8601) |
data.order.id | ID đơn nội bộ ORD... — khóa để tra đơn trong hệ thống của bạn |
data.order.order_id | Mã đơn nền tảng (có thể null nếu chưa tạo xong trên nền tảng) |
data.order.status | Trạng thái nền tảng — xem bảng status |
data.order.payment_status | Trạng thái thanh toán Elim — xem bảng payment_status |
data.order.platform_payment_status | Kết quả thanh toán phía nền tảng |
data.order.total_amount_cny | Số tiền của đơn (CNY), có thể null |
data.order.updated_at | Lần cập nhật gần nhất của đơn (ISO 8601) |
Xử lý phía bạn: tra data.order.id, cập nhật trạng thái đơn trong hệ thống, rồi trả HTTP 2xx. Payload có thể đến không đúng thứ tự — luôn tin updated_at mới hơn và bỏ qua sự kiện cũ hơn trạng thái bạn đang giữ.
Header mỗi lần gọi
| Header | Giá trị |
|---|---|
Content-Type | application/json |
User-Agent | elim-api-webhooks/1.0 |
X-Elim-Event | Tên sự kiện |
X-Elim-Delivery | ID lần gửi (đổi theo từng lần thử lại) |
X-Elim-Timestamp | Unix time, đơn vị giây |
X-Elim-Signature | sha256=<hmac> |
Xác minh chữ ký
Chuỗi ký: "{X-Elim-Timestamp}.{raw_json_body}" — dùng body thô nguyên trạng, không parse rồi serialize lại.
Thuật toán: HMAC-SHA256(secret, chuỗi_ký), so sánh với phần sau sha256= trong X-Elim-Signature bằng hàm so sánh an toàn thời gian.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyElimWebhook(
secret: string,
timestamp: string,
rawBody: string,
signature: string,
): boolean {
const expected = `sha256=${createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex')}`;
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
Từ chối request có X-Elim-Timestamp lệch quá xa hiện tại (ví dụ hơn 5 phút) để hạn chế bị phát lại.
Chính sách thử lại
| Điều kiện | Kết quả |
|---|---|
Response 2xx | Đánh dấu thành công |
Timeout / lỗi mạng / mã khác 2xx | Lên lịch thử lại |
| Tổng số lần thử | 3 |
| Giãn cách giữa các lần | 60 giây, rồi 300 giây |
| Timeout mỗi request | 10 giây |
Xem kết quả từng lần gửi ở GET /v1/webhooks/:id/deliveries. Dùng POST /v1/webhooks/:id/test để kiểm tra nhanh cấu hình nhận.
Bảo mật
- URL ở môi trường thật phải là HTTPS. Môi trường dev chấp nhận
localhost. - IP nội bộ / private / metadata bị chặn ở môi trường thật.
secretchỉ hiển thị sau khi tạo hoặcrotate-secret.- Payload không chứa mật khẩu, API key, JWT hay access token nền tảng.
Nếu chưa dựng webhook
Hỏi trạng thái trực tiếp bất cứ lúc nào bằng GET /v1/orders/:id — mỗi lần gọi, Elim tự đồng bộ trạng thái mới nhất từ nền tảng trước khi trả về. Xem Tham chiếu API đơn hàng.