Các bước tạo đơn Viettel Post
Back to viettel post sandboxSau khi cài đặt Viettel Post Sandbox, bạn có thể tích hợp API theo cùng luồng nghiệp vụ thường dùng với Viettel Post: đăng nhập, lấy dịch vụ phù hợp, lấy thông tin cửa hàng và tạo vận đơn.
Các API trong tài liệu này chạy trên EzyPlatform của bạn, không kết nối đến Viettel Post và không tạo vận đơn thật.
Chuẩn bị
Trong các ví dụ bên dưới:
-
<WEB_URL>là địa chỉ web EzyPlatform, ví dụhttp://localhost:8080hoặchttps://example.com; -
<TOKEN_TAM>là token trả về từ API/user/login; -
<TOKEN_DAI_HAN>là token trả về từ API/user/ownerconnect.
Base URL của sandbox là:
<WEB_URL>/viettel-post-sandbox/v2
Bạn có thể xem request và response đầy đủ của các API tại:
<WEB_URL>/viettel-post-sandbox/swagger
Luồng tạo vận đơn
flowchart TD
A[Chuẩn bị WEB_URL] --> B[Gọi user/login]
B --> C{Đăng nhập thành công?}
C -- Không --> D[Kiểm tra USERNAME và PASSWORD]
D --> B
C -- Có --> E[Nhận token tạm]
E --> F[Gọi user/ownerconnect]
F --> G[Nhận token dài hạn]
G --> H[Gọi order/getPriceAllNlp]
H --> I[Chọn mã dịch vụ và lấy ID địa chỉ]
I --> J[Gọi user/listInventory]
J --> K[Chọn GROUPADDRESS_ID và CUS_ID]
K --> L[Gọi order/createOrder]
L --> M{Tạo đơn thành công?}
M -- Không --> N[Kiểm tra token và dữ liệu bắt buộc]
N --> L
M -- Có --> O[Kiểm tra vận đơn trên trang quản lý]
Kết quả của mỗi bước được dùng cho bước tiếp theo:
- token từ
user/loginđược gửi đếnuser/ownerconnect; - token từ
user/ownerconnectđược gửi trong headerTokencủa các API còn lại; - mã dịch vụ và ID địa chỉ từ
order/getPriceAllNlpđược dùng để tạo đơn; -
GROUPADDRESS_IDvàCUS_IDtừuser/listInventoryđược dùng để tạo đơn.
Đăng nhập để lấy token
Bạn không cần tạo tài khoản sandbox trước. Ở lần đăng nhập đầu tiên, plugin tự động tạo tài khoản từ
USERNAME và PASSWORD được gửi lên.Trên môi trường sandbox:
-
USERNAMEvàPASSWORDcó thể là giá trị giả lập nhưng không được để trống; - nên dùng một số điện thoại giả lập làm
USERNAMEđể gần với dữ liệu Viettel Post; - không nên sử dụng tài khoản hoặc mật khẩu thật;
- token mặc định có hiệu lực trong 7 ngày.
Lấy token tạm
Gọi API
/user/login:curl --request POST '<WEB_URL>/viettel-post-sandbox/v2/user/login' \ --header 'Content-Type: application/json' \ --data-raw '{ "USERNAME": "0987654321", "PASSWORD": "sandbox-password" }'
Response có dạng:
{
"status": 200,
"error": false,
"message": "OK",
"data": {
"userId": 123,
"partner": 123,
"phone": "0987654321",
"token": "<TOKEN_TAM>",
"expired": 1750000000000,
"source": 5
}
}
Trường
expired là Unix timestamp theo millisecond cho biết thời điểm token hết hạn.Lấy token dài hạn
Tiếp theo, gọi API
/user/ownerconnect với cùng username, password và token tạm trong header Token:curl --request POST '<WEB_URL>/viettel-post-sandbox/v2/user/ownerconnect' \ --header 'Content-Type: application/json' \ --header 'Token: <TOKEN_TAM>' \ --data-raw '{ "USERNAME": "0987654321", "PASSWORD": "sandbox-password" }'
Lưu giá trị
data.token trong response làm <TOKEN_DAI_HAN>. Tất cả các bước tiếp theo sử dụng token này trong header Token.Lấy danh sách dịch vụ vận chuyển
Gọi API
/order/getPriceAllNlp với địa chỉ người gửi và người nhận ở dạng văn bản:curl --request POST '<WEB_URL>/viettel-post-sandbox/v2/order/getPriceAllNlp' \ --header 'Content-Type: application/json' \ --header 'Token: <TOKEN_DAI_HAN>' \ --data-raw '{ "SENDER_ADDRESS": "61 K2 Cầu Diễn, Nam Từ Liêm, Hà Nội", "RECEIVER_ADDRESS": "Định Công, Hoàng Mai, Hà Nội", "PRODUCT_TYPE": "HH", "PRODUCT_WEIGHT": 500, "PRODUCT_PRICE": 200000, "MONEY_COLLECTION": 200000, "PRODUCT_LENGTH": 20, "PRODUCT_WIDTH": 15, "PRODUCT_HEIGHT": 10, "TYPE": 1 }'
Đơn vị dữ liệu:
- trọng lượng tính bằng gram;
- kích thước tính bằng centimet;
- giá trị hàng và tiền thu hộ tính bằng VND;
-
PRODUCT_TYPEnhậnHHcho hàng hóa hoặcTHcho thư, tài liệu; -
TYPEnhận1cho vận chuyển trong nước hoặc0cho quốc tế.
Ví dụ response rút gọn:
{
"SENDER_ADDRESS": {
"PROVINCE_ID": 1,
"DISTRICT_ID": 25,
"WARD_ID": 498
},
"RECEIVER_ADDRESS": {
"PROVINCE_ID": 1,
"DISTRICT_ID": 4,
"WARD_ID": 74
},
"RESULT": [
{
"MA_DV_CHINH": "PHS",
"TEN_DICHVU": "Nội tỉnh tiết kiệm",
"GIA_CUOC": 16500,
"THOI_GIAN": "24 giờ"
}
]
}
Bạn cần lưu:
- ID tỉnh, huyện và xã trong
SENDER_ADDRESSvàRECEIVER_ADDRESS; -
RESULT[].MA_DV_CHINHđể truyền vàoORDER_SERVICEkhi tạo đơn.
Nếu response trả về nhiều dịch vụ, ứng dụng tự chọn dịch vụ phù hợp theo mã dịch vụ, cước phí hoặc thời gian giao hàng.
Lấy thông tin cửa hàng
Gọi API
/user/listInventory:curl --request GET '<WEB_URL>/viettel-post-sandbox/v2/user/listInventory' \ --header 'Token: <TOKEN_DAI_HAN>'
Ví dụ response:
{
"status": 200,
"error": false,
"message": "OK",
"data": [
{
"groupaddressId": 5818802,
"cusId": 1456467,
"name": "Cửa hàng sandbox",
"phone": "0987654321",
"address": "61 K2 Cầu Diễn",
"provinceId": 1,
"districtId": 25,
"wardsId": 493
}
]
}
Chọn một cửa hàng và sử dụng:
-
groupaddressIdlàmGROUPADDRESS_ID; -
cusIdlàmCUS_ID.
Tạo vận đơn
Kết hợp dịch vụ, địa chỉ đã chuẩn hóa và thông tin cửa hàng từ các bước trước để gọi
/order/createOrder:curl --request POST '<WEB_URL>/viettel-post-sandbox/v2/order/createOrder' \ --header 'Content-Type: application/json' \ --header 'Token: <TOKEN_DAI_HAN>' \ --data-raw '{ "ORDER_NUMBER": "ORDER-SANDBOX-001", "GROUPADDRESS_ID": 5818802, "CUS_ID": 1456467, "DELIVERY_DATE": "11/09/2026 10:00:00", "SENDER_FULLNAME": "Cửa hàng sandbox", "SENDER_ADDRESS": "61 K2 Cầu Diễn, Nam Từ Liêm, Hà Nội", "SENDER_PHONE": "0987654321", "SENDER_EMAIL": "sender@example.com", "SENDER_PROVINCE": 1, "SENDER_DISTRICT": 25, "SENDER_WARD": 498, "RECEIVER_FULLNAME": "Người nhận sandbox", "RECEIVER_ADDRESS": "Định Công, Hoàng Mai, Hà Nội", "RECEIVER_PHONE": "0912345678", "RECEIVER_EMAIL": "receiver@example.com", "RECEIVER_PROVINCE": 1, "RECEIVER_DISTRICT": 4, "RECEIVER_WARD": 74, "PRODUCT_NAME": "Sản phẩm thử nghiệm", "PRODUCT_DESCRIPTION": "Đơn hàng dùng để kiểm thử tích hợp", "PRODUCT_QUANTITY": 1, "PRODUCT_PRICE": 200000, "PRODUCT_WEIGHT": 500, "PRODUCT_LENGTH": 20, "PRODUCT_WIDTH": 15, "PRODUCT_HEIGHT": 10, "PRODUCT_TYPE": "HH", "ORDER_PAYMENT": 3, "ORDER_SERVICE": "PHS", "ORDER_SERVICE_ADD": "", "ORDER_NOTE": "Cho kiểm tra hàng", "MONEY_COLLECTION": 200000, "LIST_ITEM": [ { "PRODUCT_NAME": "Sản phẩm thử nghiệm", "PRODUCT_QUANTITY": 1, "PRODUCT_PRICE": 200000, "PRODUCT_WEIGHT": 500 } ] }'
Ý nghĩa của
ORDER_PAYMENT:-
1: không thu tiền; -
2: thu tiền hàng và phí vận chuyển; -
3: thu tiền hàng; -
4: thu phí vận chuyển.
Khi thành công, response trả về
data.ORDER_NUMBER cùng tiền thu hộ và các khoản phí mẫu.
Bạn có thể kiểm tra vận đơn vừa tạo tại:
<WEB_URL>/viettel-post-sandbox/delivery-orders
Lỗi thường gặp
Username hoặc password bắt buộc
Body đăng nhập phải dùng đúng tên trường viết hoa
USERNAME và PASSWORD. Cả hai giá trị đều không được để trống.Token không hợp lệ hoặc hết hạn
- Gửi token trong header
Token. - Sử dụng token trả về từ
ownerconnect, không sử dụng webhook token. - Thực hiện lại luồng đăng nhập nếu token đã hết hạn.
Không tìm thấy dịch vụ phù hợp
Kiểm tra địa chỉ người gửi, người nhận, loại hàng, trọng lượng, kích thước, giá trị hàng và tiền thu hộ.
Request tạo đơn thiếu dữ liệu
Kiểm tra các trường bắt buộc, đặc biệt là:
-
ORDER_NUMBER,GROUPADDRESS_ID,CUS_ID,DELIVERY_DATE; - ID tỉnh, huyện và xã của người gửi, người nhận;
-
PRODUCT_NAME,PRODUCT_QUANTITY,PRODUCT_WEIGHT,PRODUCT_TYPE; -
ORDER_PAYMENT,ORDER_SERVICE,MONEY_COLLECTION; -
LIST_ITEMphải có ít nhất một sản phẩm.
Tham khảo Swagger để xem đầy đủ request, response và các API khác của phiên bản plugin đang sử dụng.