- Nhà phát triển
- Đặt vé: vòng đời một booking
Đặt vé: vòng đời một booking
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.
Trước khi bắt đầu
Phần tiêu đề “Trước khi bắt đầu”| Đ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ác | Xác thực bằng API key |
| Thông tin chuyến và chỗ ngồi | Cần mã chuyến, ngày đi và vị trí ghế đã chọn | Tra 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ức | Tài khoản của bạn và toàn chuỗi cấp trên phải đủ hạn mức thanh toán | Tiề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ỗi | Sự kiện gửi ra |
Trình tự các bước thực hiện
Phần tiêu đề “Trình tự các bước thực hiện”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 endBảng dưới đây tóm tắt các thao tác theo từng bước:
| Bước | Hệ thống của bạn | Phía Ferry | Lưu ý đối tác |
|---|---|---|---|
| 1 | Tra cứu chuyến và ghế trống | Trả 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 |
| 2 | Gọi lệnh tạo booking | Tạo bản ghi booking và gắn hạn thanh toán | Nhận mã booking và trạng thái Đã gửi yêu cầu (2) |
| 3 | Kiểm tra số dư và hạn thanh toán | Theo dõi thời hạn thanh toán được cấp | Đảm bảo số dư khả dụng đủ chi trả giá NET |
| 4 | Gọ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 |
| 5 | Poll trạng thái booking | Trả trạng thái cập nhật mới nhất của đơn | Tiếp tục poll định kỳ cho đến khi đạt trạng thái cuối |
| 6 | Tải tệp vé và gửi khách | Cung cấp liên kết tải vé điện tử đã phát hành | Thực hiện khi booking chuyển sang trạng thái 10 |
Vòng đời trạng thái booking
Phần tiêu đề “Vòng đời trạng thái booking”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 |
|---|---|---|
| 0 | Nhá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. |
| 6 | Xuất vé lỗi | Hã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. |
| 8 | Hết hạn | Mọ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ủy | Yê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ủy | Booking đã hủy hoàn tất; tiền hoàn trả về tài khoản đại lý. |
| 16 | Hủy do tàu không chạy | Hã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. |
Trạng thái thanh toán của booking
Phần tiêu đề “Trạng thái thanh toán của booking”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ỏ.
Giới hạn và các bất biến nghiệp vụ
Phần tiêu đề “Giới hạn và các bất biến nghiệp vụ”Phạm vi giữ chỗ
Phần tiêu đề “Phạm vi giữ chỗ”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:
- 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.
- 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é. - 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 của booking
Phần tiêu đề “Hạn thanh toán của booking”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:
- Tuyệt đối không gửi ngay lệnh tạo mới.
- 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.
- 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é.
- 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.
Tác vụ tự động đối chiếu đơn treo
Phần tiêu đề “Tác vụ tự động đối chiếu đơn treo”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ố
limittrong các lệnh danh sách bị kẹp tối đa ở mức 50 bản ghi/trang. Nếu gửilimit=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_idgiả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.
Lỗi thường gặp và cách xử lý
Phần tiêu đề “Lỗi thường gặp và cách xử lý”| Triệu chứng | Nguyên nhân khả dĩ | Hướng xử lý | Có nên thử lại |
|---|---|---|---|
| Nhận mã 422 khi tạo booking | Thiế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ại | Có, sau khi sửa dữ liệu |
| Mất kết nối khi tạo booking | Mạng gián đoạn hoặc xử lý kéo dài | Tra cứu booking theo số điện thoại và chuyến trước khi tạo lại | Khô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ày | Chờ vài phút rồi gọi API đọc trạng thái booking | Chờ rồi đọc lại trạng thái |
| Lỗi giới hạn tần suất xác nhận | Gọi xác nhận quá 5 lần trong vòng 60 giây | Tạm dừng và chờ hết cửa sổ 60 giây | Có, 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ức | Có, 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ãng | Kiể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ận | Có, nếu lỗi cho phép thử lại |
Tra cứu trên Scalar
Phần tiêu đề “Tra cứu trên Scalar”Để 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 xem | Nhó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 đơn | Customers |
| Tra cứu chi tiết từng chặng đơn trong booking | Orders |
Xem hướng dẫn đăng nhập và điền khóa API tại Tham chiếu API.
Đọc tiếp
Phần tiêu đề “Đọc tiếp”| Trang | Nội dung liên quan |
|---|---|
| Tra chuyến và chỗ trống | Cách tìm chuyến và lấy sơ đồ ghế trước khi đặt vé |
| Giá vé và markup nhiều cấp | Cơ 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àng | Chi tiết quy trình xử lý xuất vé điện tử |
| Huỷ vé và hoàn tiền | Quy 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 |