Payment - Thanh Toán & Xuất Vé
API Endpoint: POST /api/v1/services/booking/v1/thanh-toan
📋 Overview
Thanh toán và xuất vé (issue ticket). Chuyển booking từ HOLD (trang_thai: 0) sang ISSUED (trang_thai: 1).
Flow:
HOLD (trang_thai: 0) --[Payment]--> ISSUED (trang_thai: 1)
🔌 API Specification
Endpoint
POST {{base_url}}/api/v1/services/booking/v1/thanh-toan
Headers
{
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer {access_token}"
}
Request Body
{
"ve_id": 68,
"phuong_thuc": "wallet",
"xac_nhan": "y"
}
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
ve_id | number | ✅ Yes | Booking ID (from HOLD response) |
phuong_thuc | string | ✅ Yes | Payment method: "wallet" (F2 wallet) |
xac_nhan | string | ✅ Yes | Confirmation: "y" (yes) |
Payment Methods:
| Value | Description |
|---|---|
"wallet" | F2 wallet (default) |
✅ Success Response
Status: 200 OK
{
"message": "Thanh toán vé thành công",
"data": {
"ve": {
"id": 68,
"uuid": "b31c2b48-aea3-11f0-8b81-86d224031662",
"pnr": "37UQPF",
"trang_thai": 1,
"hang_bay": "VJ",
"so_hieu": "VJ 636",
"hanh_trinh": "SGN - DAD",
"ngay_bay": "25-10-2025 20:20:00",
"nguoi_dai_dien": "NGUYEN VAN TEST",
"tong_hanh_khach": 1,
"ho_ten_booker": "TRAN THI BOOKER",
"email_1": "test@example.com",
"email_2": "booker@example.com",
"gia_net": 1436400,
"thue": 97000,
"ngay_book": "22-10-2025 00:31:00",
"ngay_het_han": "22-10-2025 04:31:00",
"updated_at": "22-10-2025 00:33:09"
},
"chang_bay": [...],
"hanh_khach": [...]
},
"status": "success",
"code": 200
}
Key Response Fields:
| Field | Type | Description |
|---|---|---|
data.ve.trang_thai | number | Status: 1 = ISSUED (ticket issued) |
data.ve.pnr | string | PNR - Booking reference |
data.ve.ngay_xuat | string | Issue date (when ticket was issued) |
data.ve.updated_at | string | Last update timestamp |
💡 Example: cURL
curl -X POST "{{base_url}}/api/v1/services/booking/v1/thanh-toan" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {access_token}" \
-d '{
"ve_id": 68,
"phuong_thuc": "wallet",
"xac_nhan": "y"
}'
Response:
{
"message": "Thanh toán vé thành công",
"data": {
"ve": {
"id": 68,
"pnr": "37UQPF",
"trang_thai": 1,
"gia_net": 1436400
}
},
"status": "success"
}
⚠️ Important Notes
1. Booking Must Be HOLD
// Before payment
"trang_thai": 0 // HOLD
// After payment
"trang_thai": 1 // ISSUED
Only HOLD bookings can be paid.
2. Payment Method
Current version only supports:
"phuong_thuc": "wallet" // F2 wallet
3. Confirmation Required
"xac_nhan": "y" // Must be "y" (yes)
4. Total Amount
Payment amount is automatically calculated from booking:
- Ticket price (
gia_net) - Services (baggage, food)
- Seat selection
No need to specify amount in request.
5. After Payment
Once ISSUED (trang_thai: 1):
- Ticket cannot be cancelled
- Can only VOID (within 24 hours) or REFUND
- Services/seats cannot be modified (on some routes)
🐛 Common Issues
Booking Not Found
Response:
{
"message": "Không tìm thấy vé",
"status": "error"
}
Solution: Verify ve_id is correct
Already Issued
Response:
{
"message": "Vé đã được xuất",
"status": "error"
}
Cause: Booking already paid (trang_thai: 1)
Insufficient Balance
Response:
{
"message": "Số dư không đủ",
"status": "error"
}
Cause: F2 wallet balance < booking total amount
Booking Expired
Response:
{
"message": "Vé đã hết hạn thanh toán",
"status": "error"
}
Cause: Current time > ngay_het_han (payment deadline)
Solution: Create new booking
📊 Booking State Transitions
| From State | Action | To State |
|---|---|---|
| HOLD (0) | Payment | ISSUED (1) |
| ISSUED (1) | - | Cannot change |
Note: ISSUED tickets cannot return to HOLD state.
🔗 Related Operations
After payment, you can:
- Get Booking Details →
../manage-booking/GET-DETAILS.md - List Bookings →
../manage-booking/LIST-BOOKINGS.md
Note: Some manage booking operations (add services, update journey) may have restrictions after ticket is issued.
📝 Notes
- Simple API: Only 3 fields required (
ve_id,phuong_thuc,xac_nhan) - Automatic amount calculation (ticket + services + seats)
- Changes
trang_thaifrom0(HOLD) to1(ISSUED) - Uses F2 wallet balance
- Cannot be reversed (only VOID/REFUND possible)
- Payment deadline usually +4 hours from booking time