Webhook vận chuyển
Cách này dành cho cửa hàng muốn tự nối đơn vị giao hàng riêng thay vì dùng kênh Ahamove / AllinGo có sẵn ở Hub kết nối. Chủ cửa hàng dựng 2 webhook (ví dụ bằng n8n) (báo giá, tạo đơn giao) gọi AllinGo/Ahamove, rồi khai báo địa chỉ ở Cài đặt → Giao hàng.
Luồng: nhân viên mở đơn → Giao hàng → nhập/kiểm tra địa chỉ giao → SieuTroly gọi webhook báo giá → hiện danh sách giá của nhiều hãng/dịch vụ → chọn một → Giao hàng → SieuTroly gọi webhook tạo đơn → đơn chuyển sang trạng thái «Đang giao hàng» (tự tạo nếu workspace chưa có) → n8n gọi về webhook trạng thái khi có tài xế/đang giao/đã giao.
Yêu cầu: URL https công khai (không nhận địa chỉ nội bộ/localhost). Mỗi lần gọi tối đa 25 giây, phản hồi ≤ 512KB, JSON.
1) Webhook báo giá — SieuTroly → n8n
POST {quote_url}
{
"event": "shipping.quote",
"provider": "allingo",
"order": { "id": "…", "number": "DH20261012-001", "total": 120000, "paid": false, "cod_amount": 120000, "note": "",
"items": [{ "name": "Heo quay", "quantity": 2, "price": 60000 }] },
"pickup": { "name": "Heo Quay", "phone": "0281234567", "address": "1 Lê Lợi, Q1", "lat": 10.77, "lng": 106.70 },
"dropoff": { "name": "An", "phone": "0900000000", "address": "12 Nguyễn Huệ, Q1", "lat": null, "lng": null },
"package": { "weight_kg": 2 }
}cod_amount = số tiền tài xế thu hộ (0 nếu đơn đã thanh toán). lat/lng chỉ có khi đã nhập.
Phản hồi — danh sách báo giá (một trong các dạng: {quotes:[…]}, {data:{quotes:[…]}}, hoặc mảng thuần; cũng nhận khóa services/rates/options):
{ "quotes": [
{ "id": "grab-bike", "carrier": "GrabExpress", "service": "Bike", "fee": 38000, "eta": "25 phút" },
{ "id": "aha-bike", "carrier": "Ahamove", "service": "Bike", "fee": 32000, "eta_minutes": 20, "logo": "https://…/logo.png" }
] }fee(hoặcprice,total_price,ship_fee…): số VND (38000), chuỗi"38.000đ","38k". Báo giá không có giá (≤ 0) bị bỏ.idnên duy nhất; thiếu thì SieuTroly tự đặt. Mọi trường khác của từng báo giá được giữ nguyên và gửi lại ở bước tạo đơn (quote.raw) để n8n dùng.- Lỗi:
{ "error": "1", "message": "Địa chỉ ngoài vùng phục vụ" }(hoặcsuccess:false) → hiện thông điệp cho nhân viên.
2) Webhook tạo đơn giao — SieuTroly → n8n
POST {create_url}
{
"event": "shipping.create", "provider": "allingo",
"order": { … như trên … }, "pickup": { … }, "dropoff": { … }, "package": { "weight_kg": 2 },
"quote": { "id": "grab-bike", "carrier": "GrabExpress", "service": "Bike", "fee": 38000, "raw": { …nguyên báo giá… } },
"callback_url": "https://api.example.com/webhooks/shipping/<workspaceId>"
}Chỉ nhận báo giá đã trả về ở bước 1 (trong vòng 15 phút) — phí không do máy khách quyết định.
Phản hồi (bắt buộc có mã đơn giao):
{ "order_id": "AHM123", "tracking_url": "https://…", "driver_name": "Tài xế A", "driver_phone": "0987654321", "status": "ASSIGNING", "fee": 38000 }(order_id có thể là tracking_id/id/shipment_id; có thể đặt trong data.) Lỗi như bước 1.
3) Webhook trạng thái — n8n → SieuTroly
POST {callback_url} (hiện ở Cài đặt → Giao hàng) kèm header X-SieuTroly-Token: <khóa> — khóa sinh ở nút Tạo khóa webhook trạng thái (chỉ hiện một lần; hệ thống chỉ lưu băm).
{ "order_id": "AHM123", "status": "delivering", "status_text": "Tài xế đang giao", "driver_name": "…", "driver_phone": "…", "tracking_url": "https://…", "fee": 38000 }- Xác định đơn bằng
order_id(mã đơn giao ở bước 2) hoặcorder_numbercủa SieuTroly. status:delivered/completed/done/đã giao… → đã giao;failed/cancelled/returned/huỷ… → thất bại (cho phép tạo lại đơn giao); còn lại → đang giao.- Bật Tự chuyển sang Hoàn thành khi đã giao để đơn tự sang trạng thái
completed(nếu workspace có trạng thái này). - Phản hồi:
{ "ok": true, "state": "delivered" }; sai khóa → 401.
Dữ liệu trên đơn
GET /api/orders/:id và API công khai trả shipping: { provider, carrier, service, fee, state (created|delivering|delivered|failed), status_text, tracking_id, tracking_url, driver_name, driver_phone }. Webhook thuê bao có thêm sự kiện order.shipping_created.
