Đặt & thanh toán đơn Taobao/1688 qua Elim
Hướng dẫn này dành cho ai
Bạn là chủ doanh nghiệp (hoặc đội vận hành) — một đại lý mua hàng, công ty order hoặc nền tảng xuyên biên giới — đang tích hợp API Elim để đơn của khách chảy thẳng từ web/app của bạn lên Taobao/1688 mà không phải thao tác tay. Hướng dẫn đi hết một vòng đời đơn hàng: từ lúc kiểm tra ví, tạo đơn, thanh toán, đến khi hàng được giao — kèm những điểm bạn phải kiểm tra ở mỗi bước.
Phạm vi: Đã hỗ trợ nhiều thị trường. Việc thanh toán được thống nhất bằng VNĐ, USD hoặc RMB (CNY) — bạn nạp ví bằng một trong ba đồng tiền này và mọi đơn đều quy về cùng đơn vị bất kể thị trường nào.
Cần tra nhanh endpoint, tham số, giá trị trạng thái, mã lỗi? Xem Tham chiếu API đơn hàng.
Bức tranh tổng quan
Elim là nền tảng công nghệ lo khâu thực thi đơn và thanh toán cho hệ thống của bạn — không bán lẻ, không nhận khách trực tiếp, không phải một dịch vụ mua hàng song song. Bạn vẫn nắm giá bán, chính sách và khách hàng của mình; Elim chỉ tạo đơn trên nền tảng và thanh toán với người bán thay cho bạn. Vì tiền không đi thẳng từ khách tới Taobao/1688, dòng tiền chạy qua ba bên:
| Bên | Vai trò |
|---|---|
| Bạn (đại lý) | Nạp tiền vào ví mua hàng, tạo đơn, gửi yêu cầu thanh toán, theo dõi đơn |
| Elim | Lớp hạ tầng: giữ ví, duyệt yêu cầu thanh toán, tạo đơn và thanh toán với người bán trên nền tảng, đẩy cập nhật đơn về hệ thống của bạn |
| Taobao / 1688 | Xử lý đơn, xuất kho, vận chuyển |
Một đơn hàng có hai trạng thái riêng biệt
Đừng gộp chúng làm một — chúng thay đổi độc lập:
status— tiến trình đơn trên nền tảng (Taobao/1688):creating → pending_payment → paid → shipped → completed, hoặccancelled.payment_status— tiến trình thanh toán giữa bạn và Elim:unpaid → requested → approved → paid, hoặcrejected, hoặcrefunded.
Ví dụ hợp lệ: một đơn có thể status = shipped nhưng payment_status = paid từ trước đó — hai trục thời gian khác nhau.
Vòng đời một đơn hàng
BẠN ELIM NỀN TẢNG
│ │ │
1. Xem trước đơn (preview) ─────┼───────────────────────────┤
2. Tạo đơn ────────────────────►│ │ status: pending_payment
payment_status: unpaid │ │
3. Gửi yêu cầu thanh toán ─────►│ giữ (freeze) tiền trong ví │
payment_status: requested │ │
│ 4. Duyệt yêu cầu │
│ payment_status: approved│
│ 5. Thanh toán nền tảng ───►│ status: paid → shipped
│ trừ tiền ví │
payment_status: paid ◄───────┤ │
6. Nhận webhook cập nhật ◄──────┤◄──────────────────────────┤ status: completed
Bước 4 và 5 do Elim thực hiện — bạn không gọi API cho hai bước này, chỉ chờ và nhận kết quả.
Điều kiện trước
- Thông tin xác thực API (JWT hoặc API Key) — xem Xác thực API requests.
- Ví mua hàng đã có số dư khả dụng đủ cho giá trị đơn. Nạp tiền là thao tác ngoài hệ thống (chuyển khoản cho Elim); xem Bước 1.
product_refvàsku_refcủa từng mặt hàng — lấy từ tìm kiếm / chi tiết sản phẩm.- Địa chỉ nhận hàng hợp lệ tại Trung Quốc (thường là kho trung chuyển của bạn), ghi bằng tiếng Trung.
Bước 1 — Kiểm tra số dư ví
Ví mua hàng quy mọi khoản nạp (VND, USD…) về CNY. Trước khi tạo đơn, xác nhận ví đủ tiền.
GET /v1/purchasing/wallet
Bạn nhận về:
| Trường | Ý nghĩa |
|---|---|
balance | Tổng số dư CNY |
frozen_balance | Phần đang bị giữ cho các đơn đã gửi yêu cầu thanh toán nhưng chưa xong |
available_balance | Số thực sự dùng được = balance − frozen_balance |
Luôn so
available_balance(không phảibalance) với giá trị đơn. Tiền đang bị giữ cho đơn khác không tiêu lại được.
Nạp thêm khi thiếu: chuyển khoản cho Elim theo hướng dẫn nạp tiền (VND/USD). Sau khi Elim xác nhận nhận được tiền, số dư được cộng vào ví theo tỷ giá hiện hành. Xem tỷ giá đang áp dụng:
GET /v1/purchasing/exchange-rates
Bước 2 — Xem trước đơn hàng (preview)
Preview cho bạn tổng tiền ước tính và tình trạng còn hàng của từng SKU. Bước này không tạo đơn và không trừ tiền.
POST /v1/orders/preview
{
"platform": "alibaba",
"receiver_address": {
"name": "Nguyen Van A",
"phone": "02812345678",
"mobile": "13800138000",
"address": "广州市天河区体育西路123号",
"province": "广东省",
"city": "广州市",
"area": "天河区"
},
"line_items": [
{ "product_ref": "734467086498", "sku_ref": "5578084256927", "quantity": 2, "price": 15.5 }
]
}
Điểm phải kiểm tra trước khi đi tiếp:
unavailable_itemsphải rỗng. Nếu có phần tử (hết hàng, sai SKU, ngừng bán), không tạo đơn — xử lý các mặt hàng đó trước rồi preview lại.total_amount(tổng tiền hàng + phí ship nội địa TQ) khớp với dự tính của bạn.- Giữ lại
preview_tokentrong response — token dùng một lần, hết hạn sau 10 phút. Gửi kèm ở bước tạo đơn để chốt đúng mức giá vừa xem.
Bước 3 — Tạo đơn hàng
Gửi lại đúng payload đã preview (cùng platform, địa chỉ, danh sách hàng, số lượng), thêm preview_token và một idempotency_key do bạn tự đặt.
POST /v1/orders
{
"platform": "alibaba",
"receiver_address": { "...": "giống hệt bước preview" },
"line_items": [
{ "product_ref": "734467086498", "sku_ref": "5578084256927", "quantity": 2, "price": 15.5 }
],
"preview_token": "c5f75ec1-9f8d-4bf6-9de2-048d50fef349",
"idempotency_key": "checkout-2026-08-25-001",
"remark": "Ghi chú cho người bán"
}
idempotency_key là chốt an toàn: nếu request bị lặp (mạng chập chờn, người dùng bấm hai lần), Elim trả lại cùng một đơn thay vì tạo trùng. Dùng một khóa duy nhất cho mỗi lần checkout thật.
Đọc response:
| Trường | Ý nghĩa |
|---|---|
data.id | ID đơn nội bộ dạng ORD0000000123 — dùng cho mọi thao tác sau này |
status | pending_payment nếu tạo thành công |
data.order_list[] | Chi tiết shop + sản phẩm từ nền tảng — dùng để dựng biên nhận cho khách |
Sau khi tạo, đơn ở payment_status = unpaid. Hàng chưa được nền tảng xử lý cho đến khi thanh toán xong.
Nếu
status = "unknown": đơn có thể chưa được tạo trọn vẹn trên nền tảng. Dừng flow thanh toán, gọi chi tiết đơn để kiểm tra, và liên hệ hỗ trợ nếu tình trạng không tự rõ ra sau vài phút.
Bước 4 — Xác nhận đơn & gửi yêu cầu thanh toán
Đây là bước xác nhận đơn từ phía bạn: bạn chốt rằng đơn này đúng và sẵn sàng trả tiền. Elim giữ (freeze) số tiền tương ứng trong ví — tiền chưa bị trừ hẳn, nhưng không dùng cho đơn khác được nữa.
POST /v1/purchasing/orders/{id}/request-payment
Response cho bạn biết chính xác khoản bị giữ:
| Trường | Ý nghĩa |
|---|---|
frozen_amount | Tổng tiền bị giữ = tiền hàng + phí ship nội địa + phí dịch vụ |
goods_amount_cny | Tiền hàng (CNY) nền tảng báo |
shipping_fee_cny | Phí vận chuyển nội địa Trung Quốc |
service_fee_cny | Phí dịch vụ của Elim cho khâu thực thi đơn |
Đơn chuyển sang payment_status = requested.
Nếu ví không đủ
Bạn nhận 400 với chi tiết còn thiếu bao nhiêu:
{
"error": "insufficient_balance",
"current_balance": 120.00,
"available_balance": 90.00,
"required": 286.50,
"deficit": 196.50
}
Nạp thêm deficit CNY vào ví (Bước 1) rồi gọi lại request-payment.
Rút lại yêu cầu
Còn ở requested và muốn hủy (ví dụ khách đổi ý)? Gọi:
POST /v1/purchasing/orders/{id}/cancel-payment-request
Tiền bị giữ được giải phóng lại vào ví, đơn quay về payment_status = unpaid. Sau khi Elim đã duyệt thì không rút lại bằng cách này được nữa — lúc đó phải đi đường hoàn tiền.
Bước 5 — Elim duyệt và thanh toán nền tảng
Hai việc này do Elim thực hiện. Bạn không gọi API — chỉ theo dõi payment_status:
payment_status | Nghĩa là | Việc của bạn |
|---|---|---|
requested | Yêu cầu đang chờ Elim xem xét | Chờ |
approved | Elim đã duyệt, đang thanh toán với nền tảng | Chờ |
paid | Đã thanh toán xong; tiền đã trừ khỏi ví | Xong — chuyển sang theo dõi giao hàng |
rejected | Elim từ chối yêu cầu; tiền giữ đã trả lại ví | Đọc lý do ở rejection_reason, xử lý rồi gửi lại yêu cầu |
Khi thanh toán nền tảng hoàn tất, đơn đạt payment_status = paid và status trên nền tảng bắt đầu tiến (paid → shipped). Trường platform_payment_status cho biết kết quả phía nền tảng: success là ổn; failed nghĩa là Elim sẽ liên hệ bạn để xử lý.
Bạn không cần hỏi liên tục (polling). Cách gọn nhất để biết mốc này là đăng ký webhook ở bước tiếp theo.
Bước 6 — Nhận cập nhật đơn hàng qua webhook
Thay vì hỏi trạng thái đơn liên tục, đăng ký webhook để Elim chủ động gọi vào hệ thống của bạn mỗi khi đơn hoặc thanh toán đổi trạng thái.
6.1. Đăng ký endpoint nhận
POST /v1/webhooks
{
"url": "https://he-thong-cua-ban.example/webhooks/elim",
"events": ["order.updated", "payment.updated"],
"is_active": true
}
Response trả về secret — chỉ hiện đúng một lần. Lưu vào nơi an toàn; bạn cần nó để xác minh chữ ký. Mất thì tạo lại bằng POST /v1/webhooks/{id}/rotate-secret.
order.updated— gửi khi trạng thái đơn (status) đổi.payment.updated— gửi khi trạng thái thanh toán (payment_status) đổi.
6.2. Xử lý mỗi lần Elim gọi tới
Mỗi request mang một ảnh chụp đơn trong data.order (id, status, payment_status, platform_payment_status, total_amount_cny, updated_at). Việc của bạn:
- Xác minh chữ ký ở header
X-Elim-Signature=HMAC-SHA256(secret, "{X-Elim-Timestamp}.{body_thô}"):
import { createHmac, timingSafeEqual } from 'node:crypto';
function verifyElimWebhook(secret: string, timestamp: string, rawBody: string, signature: string) {
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 quá cũ (ví dụ lệch hơn 5 phút).
- Tra
data.order.id, cập nhật trạng thái đơn trong hệ thống của bạn. - Trả HTTP 2xx. Nếu không, Elim thử lại tối đa 3 lần (giãn cách 60 giây rồi 300 giây).
Cấu trúc payload đầy đủ, danh sách header và chính sách thử lại: xem Tham chiếu Webhook.
6.3. Nếu chưa dựng webhook
Hỏi trạng thái trực tiếp bất cứ lúc nào:
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 rồi mới trả về — bạn không phải tự lặp dồn dập, chỉ gọi khi cần (khách mở đơn, hoặc bấm làm mới).
Bước 7 — Theo dõi đơn và vận chuyển
Danh sách đơn (lọc + phân trang):
GET /v1/orders?page=1&size=20&platform=taobao&status=shipped&payment_status=paid
Lọc được theo platform, status, payment_status, created_from, created_to, client_order_id.
line_itemstrong danh sách là ảnh chụp lúc tạo đơn — có thể khác hiện trạng trên nền tảng. Khi khách mở chi tiết, luôn gọiGET /v1/orders/{id}để lấy bản mới nhất.
Chi tiết đơn — cấu trúc khác nhau theo nền tảng:
| Nền tảng | Danh sách hàng | Thông tin vận chuyển |
|---|---|---|
| 1688 | products[] | logistics.logistics_info[] — nhúng sẵn trong chi tiết đơn |
| Taobao | line_items[] | Gọi riêng GET /v1/orders/{id}/logistic-detail?package_id=<số> |
Trường platform có sẵn trong response danh sách — lưu lại để biết hiển thị kiểu nào trước khi mở chi tiết.
Tracking vận chuyển nội địa Trung Quốc (chỉ Taobao):
GET /v1/orders/{id}/logistic-detail?package_id=12345
package_id là số nguyên lấy từ response chi tiết đơn Taobao (không phải ID ORD...).
Bước 8 — Hủy đơn và hoàn tiền
Hủy đơn
POST /v1/orders/{id}/cancel
Chỉ hủy được khi status là creating hoặc pending_payment. Ở các trạng thái khác (đã paid, shipped…), nút hủy phải bị khóa. Sau khi hủy, gọi lại GET /v1/orders/{id} để lấy trạng thái mới.
Nếu đơn chưa kịp có mã đơn trên nền tảng, response là
{ "success": true, "message": "Internal order cancelled, no external order to cancel" }— đơn đã hủy ở Elim, không có gì để hủy phía Taobao/1688.
Hoàn tiền
Khi một đơn đã payment_status = paid cần trả lại tiền (hủy sau thanh toán, nền tảng đóng đơn…), Elim thực hiện hoàn tiền về ví mua hàng của bạn. Đơn chuyển sang payment_status = refunded và bạn nhận payment.updated. Khoản hoàn hiện dưới dạng một giao dịch order_refund trong lịch sử ví:
GET /v1/purchasing/wallet/transactions?type=order_refund
Xác minh toàn trình
-
GET /v1/purchasing/wallet→available_balance≥ giá trị đơn dự kiến. - Preview trả
unavailable_items: []vàtotal_amountkhớp dự tính. - Tạo đơn trả
data.iddạngORD...vàstatus = pending_payment. -
request-paymenttrảfrozen_amountđúng; ví cófrozen_balancetăng tương ứng. -
payment_statustiếnrequested → approved → paid;platform_payment_status = success. - Nhận được
order.updated/payment.updatedở endpoint webhook, chữ ký khớp. -
GET /v1/orders/{id}hiển thị đúng cảstatuslẫnpayment_status, kèm thông tin vận chuyển.
Xử lý lỗi thường gặp
| HTTP | Tình huống | Cách xử lý |
|---|---|---|
400 | insufficient_balance | Nạp thêm đúng deficit CNY rồi gửi lại yêu cầu thanh toán |
400 | Cannot request payment: current status is "..." | Đơn không còn ở unpaid — kiểm tra payment_status hiện tại |
400 | Sai định dạng ID nền tảng | Kiểm tra lại product_ref / sku_ref |
401 | JWT hết hạn | Lấy token mới, xem Xác thực |
403 | Gọi đơn không thuộc tài khoản của bạn | Chỉ thao tác trên đơn do chính bạn tạo |
404 | Đơn không tồn tại | Kiểm tra lại ID ORD... |
422 | LINE_ITEM_SKU_NOT_RESOLVABLE (Taobao) | sku_ref không thuộc sản phẩm — lấy lại từ chi tiết sản phẩm |
429 | Vượt giới hạn tần suất | Chờ ~60 giây rồi thử lại; giãn nhịp gọi |
502 | Nền tảng Taobao/1688 không phản hồi | Thử lại sau; không tạo đơn trùng |
Response lỗi theo dạng { statusCode, message, error }. message đôi khi là tiếng Việt và có thể hiển thị thẳng cho người dùng cuối.
Liên kết liên quan
- Tham chiếu API đơn hàng — endpoint, tham số, giá trị trạng thái, mã lỗi đầy đủ
- Tham chiếu Webhook — cấu trúc payload, header, chữ ký, chính sách thử lại
- Xác thực API requests
- Tìm kiếm & lấy ID sản phẩm