Chuyển đến nội dung chính
Elimapi

Đặ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ênVai 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
ElimLớ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 / 1688Xử 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ặc cancelled.
  • payment_status — tiến trình thanh toán giữa bạn và Elim: unpaid → requested → approved → paid, hoặc rejected, hoặc refunded.

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_ref và sku_ref củ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
balanceTổng số dư CNY
frozen_balancePhần đang bị giữ cho các đơn đã gửi yêu cầu thanh toán nhưng chưa xong
available_balanceSố thực sự dùng được = balance − frozen_balance

Luôn so available_balance (không phải balance) 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:

  1. unavailable_items phả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.
  2. 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.
  3. Giữ lại preview_token trong 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.idID đơn nội bộ dạng ORD0000000123 — dùng cho mọi thao tác sau này
statuspending_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_amountTổng tiền bị giữ = tiền hàng + phí ship nội địa + phí dịch vụ
goods_amount_cnyTiền hàng (CNY) nền tảng báo
shipping_fee_cnyPhí vận chuyển nội địa Trung Quốc
service_fee_cnyPhí 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_statusNghĩa làViệc của bạn
requestedYêu cầu đang chờ Elim xem xétChờ
approvedElim đã duyệt, đang thanh toán với nền tảngChờ
paidĐã thanh toán xong; tiền đã trừ khỏi víXong — chuyển sang theo dõi giao hàng
rejectedElim 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:

  1. 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).

  1. Tra data.order.id, cập nhật trạng thái đơn trong hệ thống của bạn.
  2. 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_items trong 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ọi GET /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ảngDanh sách hàngThông tin vận chuyển
1688products[]logistics.logistics_info[] — nhúng sẵn trong chi tiết đơn
Taobaoline_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_amount khớp dự tính.
  • Tạo đơn trả data.id dạng ORD... và status = pending_payment.
  • request-payment trả frozen_amount đúng; ví có frozen_balance tăng tương ứng.
  • payment_status tiến requested → 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ả status lẫn payment_status, kèm thông tin vận chuyển.

Xử lý lỗi thường gặp

HTTPTình huốngCách xử lý
400insufficient_balanceNạp thêm đúng deficit CNY rồi gửi lại yêu cầu thanh toán
400Cannot request payment: current status is "..."Đơn không còn ở unpaid — kiểm tra payment_status hiện tại
400Sai định dạng ID nền tảngKiểm tra lại product_ref / sku_ref
401JWT hết hạnLấy token mới, xem Xác thực
403Gọi đơn không thuộc tài khoản của bạnChỉ thao tác trên đơn do chính bạn tạo
404Đơn không tồn tạiKiểm tra lại ID ORD...
422LINE_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
429Vượt giới hạn tần suấtChờ ~60 giây rồi thử lại; giãn nhịp gọi
502Nền tảng Taobao/1688 không phản hồiThử 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