Bỏ qua để đến nội dung

Đặt vé: vòng đời một booking

13 phút đọc

Luồng đặt vé là nghiệp vụ trọng tâm trong tích hợp đối tác, gồm hai giai đoạn chính: tạo booking để ghi nhận thông tin hành khách và xác nhận xuất vé để trừ tiền và đặt chỗ thực tế lên hệ thống hãng tàu. Ferry không có bước giữ chỗ tạm độc lập trên hãng tàu; chỗ chỉ thực sự thuộc về khách khi vé được xác nhận xuất thành công.

Điều kiệnÝ nghĩa nghiệp vụTài liệu tham khảo
Khóa API hợp lệToàn bộ các lệnh tạo và quản lý booking yêu cầu xác thực đối tácXác thực bằng API key
Thông tin chuyến và chỗ ngồiCần mã chuyến, ngày đi và vị trí ghế đã chọnTra chuyến và chỗ trống
Nắm rõ giá NET đại lýSố tiền sẽ bị trừ thực tế khi xác nhận xuất véGiá vé và markup nhiều cấp
Số dư khả dụng của tổ chứcTài khoản của bạn và toàn chuỗi cấp trên phải đủ hạn mức thanh toánTiền: số dư, hạn mức và công nợ
Cấu hình webhook (khuyến nghị)Đăng ký URL nhận thông báo khi vé xuất thành công hoặc lỗiSự kiện gửi ra

Sơ đồ dưới đây cho thấy chuỗi tương tác khi tạo và xác nhận xuất vé một booking:

sequenceDiagram
participant A as "Hệ thống của bạn"
participant B as "Ferry API"
participant M as "Hệ thống tài chính"
participant O as "Hệ thống hãng tàu"
A->>B: "Tạo booking mới (POST /bookings)"
B-->>A: "Mã booking, trạng thái Đã gửi yêu cầu (2)"
Note over A,B: "Đã tạo đơn, chưa trừ tiền, hạn thanh toán được kích hoạt"
A->>B: "Xác nhận xuất vé (POST /bookings/confirmToIssue/{id})"
B->>M: "Kiểm tra số dư và hạn mức chuỗi tổ chức"
alt Không đủ tiền
M-->>B: "Số dư không đủ"
B-->>A: "Lỗi số dư, booking giữ nguyên trạng thái 2"
else Đủ tiền
M-->>B: "Giữ tiền theo giá NET đại lý"
B->>O: "Gửi yêu cầu xuất vé sang hãng tàu"
alt Hãng xuất vé thành công
O-->>B: "Mã vé điện tử của hãng"
B-->>A: "Booking chuyển sang Đã có vé (10)"
else Hãng từ chối hoặc lỗi
O-->>B: "Thông báo lỗi xuất vé"
B-->>A: "Booking chuyển sang Xuất vé lỗi (6), hoàn tiền"
end
end

Bảng dưới đây tóm tắt các thao tác theo từng bước:

BướcHệ thống của bạnPhía FerryLưu ý đối tác
1Tra cứu chuyến và ghế trốngTrả thông tin chuyến và trạng thái sơ đồ ghếKiểm tra lại ghế ngay trước khi tạo đơn
2Gọi lệnh tạo bookingTạo bản ghi booking và gắn hạn thanh toánNhận mã booking và trạng thái Đã gửi yêu cầu (2)
3Kiểm tra số dư và hạn thanh toánTheo dõi thời hạn thanh toán được cấpĐảm bảo số dư khả dụng đủ chi trả giá NET
4Gọi lệnh xác nhận xuất véKhóa đơn, giữ tiền và gọi hãng xuất véLệnh có thể mất vài phút tùy độ phản hồi của hãng
5Poll trạng thái bookingTrả trạng thái cập nhật mới nhất của đơnTiếp tục poll định kỳ cho đến khi đạt trạng thái cuối
6Tải tệp vé và gửi kháchCung cấp liên kết tải vé điện tử đã phát hànhThực hiện khi booking chuyển sang trạng thái 10

Trạng thái nghiệp vụ của booking phản ánh tiến trình xử lý đơn hàng từ lúc khởi tạo đến khi hoàn tất hoặc hủy bỏ.

Sơ đồ dưới đây minh họa các bước chuyển trạng thái của một booking:

stateDiagram-v2
state "Nháp (0)" as s0
state "Đã gửi yêu cầu (2)" as s2
state "Xuất vé lỗi (6)" as s6
state "Hết hạn (8)" as s8
state "Đã có vé (10)" as s10
state "Đang yêu cầu huỷ (12)" as s12
state "Đã huỷ (14)" as s14
state "Huỷ do tàu không chạy (16)" as s16
[*] --> s0
s0 --> s2: Lệnh tạo booking
s2 --> s10: Xác nhận xuất vé thành công
s2 --> s6: Hãng báo lỗi khi xuất vé
s2 --> s8: Mọi đơn thuộc booking bị huỷ
s2 --> s14: Hủy trước khi xuất vé
s10 --> s12: Tạo yêu cầu hủy vé
s12 --> s14: Duyệt hủy vé hoàn tất
s10 --> s16: Hãng thông báo tàu hủy chuyến
s8 --> [*]
s14 --> [*]
s16 --> [*]

Ý nghĩa các trạng thái booking:

MãTrạng tháiÝ nghĩa và hành động tiếp theo
0NhápĐơn nháp nội bộ, không xuất hiện ở tầng tích hợp đối tác.
2Đã gửi yêu cầuĐã tạo đơn thành công, ghế được đánh dấu trong Ferry; chờ xác nhận xuất vé trước hạn.
6Xuất vé lỗiHãng từ chối xuất vé hoặc lỗi đường truyền; tiền được hoàn, bạn có thể gọi xuất vé lại.
8Hết hạnMọi order thuộc booking đã bị huỷ; chỗ được nhả. Tạo booking mới nếu khách còn nhu cầu.
10Đã có véVé đã được xuất thành công trên hệ thống hãng; tải tệp vé gửi hành khách.
12Đang yêu cầu hủyYêu cầu hủy vé đang chờ duyệt theo chính sách; xem Hủy vé và hoàn tiền.
14Đã hủyBooking đã hủy hoàn tất; tiền hoàn trả về tài khoản đại lý.
16Hủy do tàu không chạyHãng tàu hủy chuyến vì thời tiết hoặc kỹ thuật; hỗ trợ khách đổi hoặc hoàn tiền.

Song song với trạng thái đơn, mỗi booking có một trục trạng thái thanh toán riêng:

Sơ đồ dưới đây biểu diễn các trạng thái thanh toán của booking:

stateDiagram-v2
state "Chưa trả (1)" as p1
state "Trả thiếu (3)" as p3
state "Đã trả (4)" as p4
state "Đã trả bằng nợ (5)" as p5
state "Đã hoàn (18)" as p18
state "Đã huỷ (30)" as p30
[*] --> p1
p1 --> p4: Xác nhận xuất vé thành công
p1 --> p3: Khách thanh toán thiếu
p3 --> p4: Bổ sung đủ phần thiếu
p1 --> p5: Được cấp trên cho nợ
p5 --> p4: Khách tất toán nợ
p4 --> p18: Hoàn tiền sau khi hủy vé
p1 --> p30: Hủy booking khi chưa trả tiền
p4 --> p30: Hủy booking sau khi đã thanh toán
  • Chưa trả (1): Trạng thái mặc định ngay sau khi tạo booking mới.
  • Trả thiếu (3): Thanh toán một phần qua ngân hàng; bước xác nhận xuất vé không tạo ra trạng thái này.
  • Đã trả (4): Đã trừ tiền thành công khi xác nhận xuất vé hoặc khách thanh toán đủ nợ.
  • Đã trả bằng nợ (5): Tổ chức cấp trên cho phép ghi nhận công nợ để xuất vé trước. Bước chuyển từ trạng thái 5 sang 4 diễn ra tự động trong hệ thống khi nợ được thanh toán, không cần lệnh gọi can thiệp từ đối tác.
  • Đã hoàn (18): Tiền đã được hoàn lại sau khi quy trình duyệt hủy vé kết thúc.
  • Đã hủy (30): Giao dịch thanh toán của booking bị hủy bỏ.

Ferry không giữ chỗ tạm thời trên hệ thống của hãng tàu trong thời gian khách điền thông tin:

  1. Khi tạo booking (trạng thái 2), Ferry chỉ đánh dấu ghế trong sơ đồ ghế nội bộ của Ferry nhằm ngăn các khách khác trong cùng hệ thống chọn trùng.
  2. Hệ thống hãng tàu và các đại lý trực tiếp khác của hãng vẫn có thể bán mất ghế đó cho đến khi lệnh xác nhận xuất vé của bạn gửi sang hãng thành công. Một số hãng tàu (như SuperDong) có mã lỗi chuyên biệt (UnavailableSeats) trả về khi ghế bị đại lý khác chiếm mất giữa bước tạo đơn và bước xác nhận xuất vé.
  3. Chỗ chỉ chắc chắn thuộc về hành khách khi booking chuyển sang trạng thái Đã có vé (10).

Bạn đặt vé bằng nhóm booking, không bằng nhóm đơn

Phần tiêu đề “Bạn đặt vé bằng nhóm booking, không bằng nhóm đơn”

Mỗi booking có thể bao gồm một hoặc nhiều đơn hàng con (orders) tương ứng với từng chặng di chuyển. Tuy nhiên ở tầng API đối tác, nhóm /orders chỉ hỗ trợ thao tác đọc (tra cứu danh sách và xem chi tiết chặng đơn). Con đường duy nhất để phát hành vé là tạo đơn qua /bookings và xác nhận xuất vé qua /bookings/confirmToIssue/{id}.

Hạn thanh toán (payment_expired_at) được tính ngay khi tạo booking theo công thức: thời điểm tạo + giá trị nhỏ hơn giữa (a) cấu hình hạn thanh toán của tổ chức bạn (tính bằng giờ rồi đổi ra phút), và (b) số phút còn lại tới giờ khởi hành sớm nhất trong các chặng.

Lưu ý quan trọng: nếu tổ chức của bạn chưa được thiết lập cấu hình hạn thanh toán, giá trị mặc định sẽ tính thời hạn kéo dài tới sát giờ tàu khởi hành. Bạn có thể lọc danh sách booking theo khoảng hạn thanh toán bằng hai tham số: payment_expired_at_from và payment_expired_at_to.

Tác vụ nền xử lý booking quá hạn còn chưa trả tiền mà không gửi thông báo trước cho đối tác. Muốn nhắc khách, bạn phải đọc payment_expired_at và tự đặt lịch.

Xử lý timeout khi tạo booking (không có Idempotency)

Phần tiêu đề “Xử lý timeout khi tạo booking (không có Idempotency)”

Ferry không hỗ trợ header chống lặp (Idempotency Key) cho lệnh tạo booking. Nếu gửi lệnh POST /bookings hai lần, hệ thống sẽ tạo thành hai booking riêng biệt với hai mã khác nhau.

Quy trình xử lý khi gặp timeout hoặc đứt kết nối:

  1. Tuyệt đối không gửi ngay lệnh tạo mới.
  2. Gọi API liệt kê danh sách booking, lọc theo số điện thoại khách hàng, mã chuyến và ngày đi.
  3. Nếu tìm thấy booking khớp dữ liệu vừa gửi, sử dụng mã booking đó để tiếp tục gọi lệnh xác nhận xuất vé.
  4. Chỉ gửi lệnh tạo mới nếu chắc chắn đơn chưa được ghi nhận trong hệ thống.

Khóa xử lý và giới hạn tần suất gọi lại

Phần tiêu đề “Khóa xử lý và giới hạn tần suất gọi lại”

Khi bạn gọi lệnh xác nhận xuất vé:

  • Ferry kích hoạt một khóa xuất vé nội bộ trong tối đa 600 giây nhằm chống xử lý trùng lặp trên cùng một booking (khóa thanh toán có thời hạn 180 giây). Nếu bạn gọi lại trong lúc tiến trình đang chạy, hệ thống sẽ trả về lỗi HTTP 422 (“đang xử lý”).
  • Có giới hạn mềm tối đa 5 lần gọi xác nhận trong vòng 60 giây cho mỗi booking. Khi vượt quá giới hạn này, hệ thống trả về lỗi nghiệp vụ (HTTP 422), không phải mã lỗi 429.
  • Với một số hãng tàu, quá trình xuất vé có thể kéo dài 5–8 phút. Bạn nên đặt thời gian chờ (timeout) phía client đủ dài hoặc chuyển sang cơ chế kiểm tra định kỳ (polling) trạng thái booking. Webhook chỉ có thời gian chờ tối đa 2 giây và không gửi lại khi thất bại, do đó polling là nguồn dữ liệu chuẩn xác nhất để xác nhận kết quả cuối cùng.

Lần xác nhận gọi lại trong lúc đang xử lý không trả bản sao kết quả lần đầu. Kênh đẩy thời gian thực cần JWT người dùng đăng nhập, nên không thay thế polling cho tích hợp bằng API key.

Nếu booking đã trừ tiền mà chưa nhận được phản hồi vé từ hãng tàu, tác vụ đối chiếu nền của Ferry sẽ tự động kiểm tra lại với hãng và cập nhật trạng thái booking sang Đã có vé (10) sau vài phút. Trong tình huống này, đối tác không nên vội vã tạo đơn thay thế hoặc yêu cầu hủy ngay.

Các giới hạn phân trang và xử lý lỗi cần lưu ý

Phần tiêu đề “Các giới hạn phân trang và xử lý lỗi cần lưu ý”
  • Kẹp trần số lượng bản ghi: Tham số limit trong các lệnh danh sách bị kẹp tối đa ở mức 50 bản ghi/trang. Nếu gửi limit=100, hệ thống vẫn tự động trả về tối đa 50 bản ghi mà không báo lỗi.
  • Sắp xếp mặc định: Tham số sắp xếp chỉ có tác dụng với trường _id; mọi yêu cầu sắp xếp theo các trường khác sẽ bị bỏ qua và tự động thay bằng _id giảm dần.
  • Danh sách rỗng có thể là lỗi hệ thống: Khi cơ sở dữ liệu hoặc dịch vụ phân quyền gặp trục trặc, API liệt kê có thể bọc lỗi và trả về mảng rỗng [] kèm HTTP 200 thay vì trả lỗi 5xx. Đối tác cần đặt cảnh báo khi truy vấn vốn luôn có dữ liệu bỗng nhiên trả về rỗng.
  • Xuất vé hỏng một phần (partial issue): Với booking khứ hồi hoặc nhiều chặng, nếu chỉ một chặng xuất vé thành công và chặng khác bị lỗi, hệ thống sẽ hoàn tiền cho các chặng thất bại và chuyển booking sang trạng thái đặc thù; không mặc định toàn bộ đơn đều cùng thành công hoặc cùng thất bại.
  • Cổng chặn thử lại của trạng thái mã 6 đã gỡ: Khi booking ở trạng thái Xuất vé lỗi (6), cổng chặn thử lại đã được dỡ bỏ nên bạn hoàn toàn có thể kiểm tra lại thông tin và gọi lại lệnh xác nhận xuất vé.

Nhóm liệt kê booking trả cảnh báo sắp ngừng dùng. Bộ lọc động vẫn có thể áp dụng theo danh sách trường cho phép, nhưng chưa có nhóm thay thế ở tầng đối tác; không xây logic phụ thuộc vào bộ lọc này. Xem Quy ước chung.

Bốn hãng tàu chưa hỗ trợ xuất vé tự động

Phần tiêu đề “Bốn hãng tàu chưa hỗ trợ xuất vé tự động”

Hiện có bốn hãng tàu trong danh mục chưa mở cổng xuất vé tự động qua API: Bình An Hà Tiên, Thạnh Thới, Hàng Châu Tourist và Saigon WaterGo. Booking thuộc các hãng này vẫn tạo được nhưng lệnh xác nhận xuất vé sẽ báo lỗi. Xem thêm tại Xuất vé và đơn hàng.

Triệu chứngNguyên nhân khả dĩHướng xử lýCó nên thử lại
Nhận mã 422 khi tạo bookingThiếu trường bắt buộc hoặc dữ liệu hành khách không đúng định dạngĐọc thông báo lỗi trong response, chuẩn hóa dữ liệu rồi gửi lạiCó, sau khi sửa dữ liệu
Mất kết nối khi tạo bookingMạng gián đoạn hoặc xử lý kéo dàiTra cứu booking theo số điện thoại và chuyến trước khi tạo lạiKhông tạo mới ngay
Nhận mã 422 đang xử lý xuất véKhóa xuất vé đang được giữ cho booking nàyChờ vài phút rồi gọi API đọc trạng thái bookingChờ rồi đọc lại trạng thái
Lỗi giới hạn tần suất xác nhậnGọi xác nhận quá 5 lần trong vòng 60 giâyTạm dừng và chờ hết cửa sổ 60 giâyCó, sau khi chờ
Lỗi không đủ số dư khi xuất véSố dư hoặc hạn mức tín dụng của bạn hoặc cấp trên không đủNạp tiền vào tài khoản hoặc liên hệ cấp trên để nâng hạn mứcCó, sau khi nạp đủ tiền
Trạng thái Xuất vé lỗi (mã 6)Hãng tàu từ chối đơn hoặc lỗi cổng kết nối hãngKiểm tra thông điệp lỗi của hãng; sửa thông tin và gọi lại xác nhậnCó, nếu lỗi cho phép thử lại

Để tra cứu lược đồ tham số chi tiết và thử nghiệm gọi trực tiếp, mở giao diện Scalar UI theo các nhóm nghiệp vụ:

Nội dung cần xemNhóm trên Scalar
Tạo booking mới, xác nhận xuất vé, xem chi tiết và tải tệp véBookings
Quản lý thông tin hành khách gắn với đơnCustomers
Tra cứu chi tiết từng chặng đơn trong bookingOrders

Xem hướng dẫn đăng nhập và điền khóa API tại Tham chiếu API.

TrangNội dung liên quan
Tra chuyến và chỗ trốngCách tìm chuyến và lấy sơ đồ ghế trước khi đặt vé
Giá vé và markup nhiều cấpCơ chế phân bổ giá NET và phụ phí theo tổ chức
Tiền: số dư, hạn mức và công nợCơ chế trừ tiền và đối soát biến động số dư
Xuất vé và đơn hàngChi tiết quy trình xử lý xuất vé điện tử
Huỷ vé và hoàn tiềnQuy trình tạo yêu cầu hủy vé và chính sách hoàn tiền
Sự kiện gửi raĐăng ký webhook để nhận thông báo trạng thái đơn tức thời