Lệnh chi
Quy trình
Mô tả:
- Mỗi request là 1 lệnh chi cho 1 người nhận, định danh bằng
ReferenceIddo CashPlus sinh. Amountphải bằng đúng số đã đăng ký cho người nhận đó.- Mỗi người nhận chỉ có 1 lệnh hiệu lực: chỉ gọi được khi người nhận chưa có lệnh ở
Status0, 99 hoặc 200. - Lệnh của người nhận này không chặn lệnh của người nhận khác.
- Baokim không tự gọi lại khi lệnh thất bại. Lệnh
Status=11cóRetryable=truethì CashPlus được gọi lệnh mới (vớiReferenceIdmới) trước cutoff. - Chỉ nhận lệnh mới trước cutoff 23:50:59 ngày T. Sau cutoff, phần chưa chi được Baokim tự quyết toán về Merchant (xem Tổng quan).
Kết quả trả về ngay trong response:
| Status | Khi nào | CashPlus làm tiếp |
|---|---|---|
| 200 | Lệnh realtime chi thành công | Ghi nhận. Vẫn nhận webhook kết quả chi |
| 99 | Lệnh realtime đã tiếp nhận, chưa có kết quả cuối | Chờ webhook kết quả chi hoặc tra cứu. Không gọi lệnh mới cho người nhận này |
| 11 | Lệnh realtime thất bại, tiền chưa ra | Xem Retryable và ErrorCode |
| 0 | Lệnh T+1 đã tiếp nhận, chờ chi theo kỳ quyết toán | Chờ webhook kết quả chi |
Thông tin API
Method: POST
URL: {BASE_URL}/transaction/v2/spend
Header: Signature — chữ ký RSA-SHA1 của raw body (xem Bảo mật).
Request
Bảng tham số chính
| Tên trường | Kiểu dữ liệu | Bắt buộc | Mô tả |
|---|---|---|---|
| RequestId | String | ✅ | ID request. Tối đa 50 ký tự, chỉ gồm chữ, số và - |
| RequestTime | Datetime | ✅ | Thời gian request. Format: YYYY-MM-DD HH:mm:ss. Lệch không quá 5 phút so với giờ Baokim |
| PartnerCode | String | ✅ | Mã merchant của giao dịch thu hộ |
| TransactionId | String | ✅ | Mã giao dịch thu hộ Baokim |
| ReferenceId | String | ✅ | Mã lệnh chi phía CashPlus, tối đa 50 ký tự, duy nhất. Gọi lại cùng ReferenceId không tạo lệnh mới |
| Receiver | Integer | ✅ | Người nhận: 1 = User, 2 = Merchant, 3 = CashPlus |
| Type | Integer | ✅ | Hình thức chi: 1 = realtime, 2 = T+1. Xem quy tắc Type |
| Amount | Integer | ✅ | Số tiền chi (VND), bằng đúng số đã đăng ký cho Receiver, đã bao gồm phí chi |
| Code | String | ✅ (khi Receiver = 1) | Mã User đã đồng bộ tài khoản |
| AccountNo | String | ✅ (khi Receiver = 1) | Số tài khoản nhận của User. Phải khớp tài khoản đã đồng bộ |
| BankNo | String | ✅ (khi Receiver = 1) | Mã ngân hàng nhận. Phải khớp tài khoản đã đồng bộ |
| Memo | String | ❌ | Nội dung chuyển tiền. Không truyền → dùng Memo đã đăng ký |
Quy tắc Type
| Receiver | Type hợp lệ |
|---|---|
| 1 (User) | Luôn 1 |
| 2 (Merchant) | Đúng Merchant.Type đã đăng ký |
| 3 (CashPlus) | Luôn 2 |
Phí chi
Người nhận chịu phí chi: SpendAmount = Amount − FeeAmount.
| Lệnh | Phí |
|---|---|
| Realtime cho User | Theo biểu phí realtime |
| Realtime cho Merchant | Theo biểu phí realtime; 0 khi giao dịch được miễn phí chi Merchant |
| Mọi lệnh T+1 | 0 |
Amount không đủ trả phí chi realtime → 125.
Ví dụ Request
{
"RequestId": "CP20250115100501",
"RequestTime": "2025-01-15 10:05:01",
"PartnerCode": "SHOP123",
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0001",
"Receiver": 2,
"Type": 1,
"Amount": 6860,
"Memo": "Thanh toan don hang 1001"
}
Ví dụ Request — lệnh chi User
{
"RequestId": "CP20250115143001",
"RequestTime": "2025-01-15 14:30:01",
"PartnerCode": "SHOP123",
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0002",
"Receiver": 1,
"Type": 1,
"Amount": 7000,
"Code": "USER001",
"AccountNo": "0123******89",
"BankNo": "970416"
}
Thứ tự kiểm tra
Baokim kiểm tra lần lượt. Gặp điều kiện đầu tiên không đạt thì trả lỗi, không tạo lệnh.
| Bước | Điều kiện | Kết quả nếu không đạt |
|---|---|---|
| 1 | Chữ ký hợp lệ | 120 |
| 2 | Tham số đúng định dạng | 102, 110, 138, … |
| 3 | ReferenceId chưa tồn tại với PartnerCode này | Cùng nội dung: trả ResponseCode=200 + lệnh đã có. Khác nội dung: 142 |
| 4 | TransactionId tồn tại và thuộc PartnerCode | 112 |
| 5 | Trước cutoff 23:50:59 ngày T | 141 |
| 6 | TransactionId đã đăng ký số tiền chia sẻ | 133 |
| 7 | Giao dịch được đăng ký qua API v2 | 143 |
| 8 | Người nhận không có lệnh nào đang ở Status 0, 99 hoặc 200 | 134 |
| 9 | Với Receiver = 1: chưa có lệnh User thất bại vì lỗi tài khoản User | 119 |
| 10 | Type hợp lệ theo quy tắc Type | 107 |
| 11 | Amount bằng số đã đăng ký cho người nhận | 136 |
| 12 | Với Receiver = 1: tài khoản khớp tài khoản đã đồng bộ | 103, 104, 111 |
| 13 | Amount > phí chi (lệnh realtime) | 125 |
Response
ghi chú
HTTP 200 - Thành công
Bảng tham số chính
| Tên trường | Kiểu dữ liệu | Bắt buộc | Mô tả |
|---|---|---|---|
| ResponseCode | Integer | ✅ | Kết quả tiếp nhận request. 200 = lệnh đã được tạo (hoặc đã tồn tại) |
| ResponseMessage | String | ✅ | Thông báo |
| Data | Object | ❌ | Thông tin lệnh chi. Chỉ có khi ResponseCode=200 |
Data
| Tên trường | Kiểu dữ liệu | Mô tả |
|---|---|---|
| TransactionId | String | Mã giao dịch thu hộ |
| ReferenceId | String | Mã lệnh chi phía CashPlus |
| TransIdPayment | String | Mã lệnh chi phía Baokim. Không đổi trong suốt vòng đời lệnh |
| Receiver | Integer | Người nhận |
| Type | Integer | Hình thức chi |
| Status | Integer | Kết quả lệnh chi: 0, 99, 200, 11 (xem Mã lỗi) |
| ErrorCode | String | Mã lỗi chi tiết khi Status=11 |
| Retryable | Boolean | Chỉ có khi Status=11. true = được gọi lệnh mới, false = không gọi lại |
| RequestAmount | Integer | Số tiền yêu cầu (= Amount) |
| FeeAmount | Integer | Phí chi |
| SpendAmount | Integer | Số tiền thực chuyển cho người nhận |
| Source | String | Luôn PARTNER với lệnh CashPlus gọi |
Ví dụ Response — lệnh realtime đang xử lý
{
"ResponseCode": 200,
"ResponseMessage": "Thành công",
"Data": {
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0001",
"TransIdPayment": "TP2501151005010001",
"Receiver": 2,
"Type": 1,
"Status": 99,
"ErrorCode": null,
"RequestAmount": 6860,
"FeeAmount": 0,
"SpendAmount": 6860,
"Source": "PARTNER"
}
}
Ví dụ Response — lệnh User thất bại do lỗi tài khoản
{
"ResponseCode": 200,
"ResponseMessage": "Thành công",
"Data": {
"TransactionId": "BK6AB9B10B92C04SZ",
"ReferenceId": "CPSPEND0002",
"TransIdPayment": "TP2501151430010002",
"Receiver": 1,
"Type": 1,
"Status": 11,
"ErrorCode": "118",
"Retryable": false,
"RequestAmount": 7000,
"FeeAmount": 2500,
"SpendAmount": 4500,
"Source": "PARTNER"
}
}
Ví dụ Response — sai số tiền
{
"ResponseCode": 136,
"ResponseMessage": "Số tiền phải bằng số đã đăng ký cho người nhận"
}
Xử lý timeout
Lệnh realtime được Baokim xử lý đồng bộ trước khi trả response, có thể mất tới 30 giây. CashPlus nên đặt timeout khi gọi API này tối thiểu 35 giây.
Nếu CashPlus không nhận được response (timeout, mất kết nối):
- Gọi lại cùng
ReferenceIdvới cùng nội dung (hoặc tra cứu theoReferenceId). Baokim không tạo lệnh trùng. - Chỉ dùng
ReferenceIdmới khi tra cứu trả137(lệnh không tồn tại) và còn trước cutoff.
Error Codes
| Mã lỗi | Mô tả |
|---|---|
| 200 | Lệnh đã được tạo hoặc đã tồn tại (xem Data.Status) |
| 101 | Lỗi trong quá trình xử lý bên Baokim. Gọi lại với cùng ReferenceId |
| 102 | RequestId hoặc RequestTime không hợp lệ (sai định dạng hoặc lệch quá 5 phút) |
| 103 | User Code không hợp lệ (chưa đồng bộ) |
| 104 | Số tài khoản User không khớp tài khoản đã đồng bộ |
| 107 | Type không hợp lệ |
| 110 | Partner Code không hợp lệ |
| 111 | Mã ngân hàng User không khớp tài khoản đã đồng bộ |
| 112 | Transaction ID không hợp lệ |
| 119 | Lệnh User trước đó đã thất bại vì lỗi tài khoản User, không gọi lại |
| 120 | Chữ ký không chính xác |
| 125 | Số tiền không đủ trả phí chi |
| 133 | Chưa đăng ký số tiền chia sẻ |
| 134 | Người nhận đang có lệnh hiệu lực (Status 0, 99 hoặc 200) |
| 136 | Số tiền khác số đã đăng ký cho người nhận |
| 138 | ReferenceId không hợp lệ |
| 141 | Quá thời gian cutoff 23:50:59 ngày giao dịch |
| 142 | ReferenceId đã dùng cho lệnh khác nội dung |
| 143 | Giao dịch đã được đăng ký qua API v1 |
Mã lỗi chi tiết của lệnh (ErrorCode khi Status=11): xem Mã lỗi.