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

Quy ước chung

9 phút đọc

Trang này tổng hợp các quy ước kỹ thuật nền tảng áp dụng cho toàn bộ API Ferry. Việc nắm vững các nguyên tắc về định dạng dữ liệu, phân trang con trỏ, sắp xếp và kiểm soát trùng lặp sẽ giúp bạn xây dựng lớp tích hợp tin cậy và hạn chế tối đa lỗi vận hành.

Đường dẫn, phiên bản và dữ liệu gửi lên

Phần tiêu đề “Đường dẫn, phiên bản và dữ liệu gửi lên”

Hệ thống Ferry tuân thủ các chuẩn giao tiếp sau:

Hạng mụcQuy chuẩn kỹ thuậtLưu ý tích hợp
Tiền tố và phiên bản/api/v1/<tài-nguyên>Hiện tại toàn bộ API hoạt động trên phiên bản v1
Giới hạn kích thước payloadTối đa 1 MB cho mỗi yêu cầuVới các đơn hàng đông khách, cần tối ưu payload gửi lên
Cơ chế lọc dữ liệu (whitelist)Tự động loại bỏ các trường không nằm trong định nghĩa schemaGửi sai tên trường sẽ bị bỏ qua âm thầm mà không báo lỗi
Mã lỗi dữ liệu không hợp lệHTTP 422 Unprocessable EntityPhân biệt với mã 400; lỗi 422 cho biết dữ liệu vi phạm ràng buộc
Mã truy vết yêu cầuHeader x-request-idKhuyến nghị sinh mã UUID riêng cho mỗi lệnh gọi để thuận tiện tra soát log
  • Phản hồi được nén tự động, trừ luồng sự kiện; HTTP client cần đọc được nội dung nén.
  • Ngôn ngữ thông điệp được chọn bằng header ngôn ngữ, mặc định là tiếng Việt.
  • Nếu không gửi x-request-id, Ferry tự sinh mã truy vết.
  • x-public, x-internal, x-admin chỉ là nhãn tài liệu OpenAPI; gửi chúng không thay đổi quyền truy cập.
  • Dữ liệu trả về bằng API key có thể thiếu trường dù Dashboard hiển thị đủ và bạn có quyền với bản ghi. Đây có thể là lỗi khai báo trường cho đối tác; báo Ferry, không có cách vượt qua từ phía client.

Phân trang con trỏ kết hợp (composite cursor) là mặc định. Phân trang theo số trang vẫn tồn tại ở một số nhóm đã đánh dấu cũ; dạng này trả cờ còn trang kế và tổng số bản ghi thay vì con trỏ.

Sơ đồ dưới đây cho thấy luồng phân trang theo con trỏ giữa hệ thống đối tác và Ferry:

sequenceDiagram
autonumber
participant Partner as Hệ thống đối tác
participant Ferry as API Ferry
Partner->>Ferry: Gửi yêu cầu trang đầu tiên kèm tham số limit
Ferry-->>Partner: Trả về danh sách dữ liệu kèm con trỏ nextCursor
loop Lặp khi nextCursor còn giá trị
Partner->>Ferry: Gửi yêu cầu trang kế tiếp kèm cursor=nextCursor
Ferry-->>Partner: Trả về trang dữ liệu tiếp theo kèm nextCursor mới
end
Note over Partner,Ferry: Dừng khi nextCursor rỗng hoặc đạt ngưỡng cần lấy

Những quy tắc vận hành cần lưu ý:

  1. Trần số lượng bản ghi (limit): Mặc định mỗi trang trả về 10 bản ghi. Mức tối đa cho phép là 50 bản ghi/trang (riêng bản chuyến dạng HTML tối đa 100). Nếu gửi limit=200, hệ thống vẫn tự động kẹp về 50 bản ghi mà không báo lỗi.
  2. Tính chất con trỏ: Chuỗi nextCursor mã hoá vị trí phân trang dựa trên thứ tự sắp xếp và mã bản ghi. Đối tác chỉ sử dụng lại chuỗi này trong phiên phân trang hiện tại, không lưu trữ con trỏ vào cơ sở dữ liệu để dùng lại sau nhiều ngày.
  3. Xử lý con trỏ lỗi: Nếu truyền con trỏ không hợp lệ, hệ thống sẽ tự động quay trở về trang đầu tiên mà không báo lỗi. Lớp gọi API của bạn cần kiểm tra tránh lặp vô hạn bằng cách giới hạn số trang tối đa.

Hệ thống Ferry áp dụng cơ chế sắp xếp mặc định theo mã bản ghi giảm dần cho toàn bộ các endpoint danh sách.

Nếu giao diện người dùng của bạn cần hiển thị dữ liệu theo thứ tự khác (ví dụ: giá tăng dần hoặc giờ chạy sớm nhất), bạn cần tải đầy đủ danh sách về phía máy chủ của mình và thực hiện sắp xếp cục bộ trước khi hiển thị.

Các endpoint hỗ trợ lọc dữ liệu theo các trường được định nghĩa trước cho từng đối tượng (ví dụ: lọc theo trạng thái booking, khoảng ngày, hoặc mã đối tác). Bạn nên sử dụng các tham số lọc chuẩn được mô tả trên Scalar thay vì dựa vào các tham số tuỳ biến nội bộ.

Bộ lọc động hỗ trợ 13 toán tử: eq, neq, contains, ncontains, gt, gte, lt, lte, in, nin, between, empty, nempty. Các điều kiện nối bằng AND, không hỗ trợ OR. Chỉ lọc được trường nằm trong danh sách cho phép; các nhóm có danh sách này gồm booking, khách hàng, tổ chức, tuyến, giao dịch, người dùng và bến.

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ể được áp dụng, 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.

Hạng mụcĐịnh dạng quy chuẩnHướng dẫn xử lý
Ngày tìm kiếm gửi lênYYYY-MM-DDGửi chuỗi ngày chuẩn theo giờ địa phương Việt Nam (GMT+7)
Mốc thời gian trả vềChuỗi ISO-8601 theo chuẩn UTCPhải chuyển đổi sang múi giờ GMT+7 trước khi hiển thị cho khách hàng
Đơn vị tiền tệViệt Nam Đồng (VND)Kiểu số nguyên, không có phần thập phân

Lỗi phổ biến nhất của các nhà tích hợp là lấy trực tiếp mốc thời gian UTC trong phản hồi API để hiển thị cho khách hàng, dẫn đến giờ tàu chạy bị lệch 7 tiếng so với thực tế.

Dữ liệu không có trường riêng ghi đơn vị tiền tệ hoặc múi giờ nghiệp vụ. Mọi số tiền là VND; ngày trần được hiểu theo giờ địa phương của hãng tàu, không theo múi giờ máy chủ của bạn. Ngày nghiệp vụ đổi lúc nửa đêm giờ Việt Nam.

Ferry không hỗ trợ header khoá chống lặp tự động (idempotency key) cho lệnh tạo booking.

Quy tắc xử lý an toàn cho phía đối tác:

  1. Quản lý mã tham chiếu giao dịch: Hệ sinh thái của bạn cần sinh một mã giao dịch duy nhất cho mỗi đơn hàng của khách.
  2. Kiểm tra trước khi thử lại: Khi gặp lỗi mất kết nối lúc tạo booking, hãy gọi API tra cứu danh sách booking gần nhất để xác minh xem đơn hàng đã được ghi nhận hay chưa trước khi quyết định tạo lại.
  3. Khoá xuất vé nội bộ: Đối với lệnh xác nhận xuất vé, hệ thống Ferry có cơ chế khoá xử lý nội bộ theo từng booking để đảm bảo không bị trừ tiền hoặc xuất vé trùng khi có nhiều lệnh gọi đồng thời trên cùng một mã booking.

Lệnh xác nhận gọi lại khi đang xử lý thường trả lỗi đang xử lý, không trả bản sao kết quả lần trước. Webhook cũng không có khoá chống trùng; đối tác phải tự khử trùng theo mã tài nguyên trong sự kiện. Xem Webhooks.

Khi truy vấn danh sách (chuyến tàu, đơn hàng, giao dịch), phản hồi có thể trả về mảng rỗng [] kèm HTTP 200.

Lưu ý:

  • Danh sách rỗng có thể là do không có dữ liệu thực tế (chuyến đã hết vé hoặc chưa mở bán), nhưng cũng có thể do hệ thống backend gặp sự cố tạm thời khi kết nối cơ sở dữ liệu.
  • Phía đối tác không nên dùng kết quả rỗng của một lần truy vấn đơn lẻ làm căn cứ để tự động xoá dữ liệu đã lưu trong hệ thống của mình. Khi gặp danh sách rỗng bất thường, hãy thử lại sau vài giây hoặc đối chiếu với các truy vấn khác.
Hiểu nhầmThực tếCách xử lý đúng
Yêu cầu sắp xếp chuyến theo giá rẻ nhấtHệ thống luôn trả về sắp xếp theo mã bản ghi giảm dầnTải dữ liệu về và tự sắp xếp trên ứng dụng của bạn
Yêu cầu lấy 200 bản ghi mỗi trangHệ thống tự động kẹp trần tối đa 50 bản ghiSử dụng phân trang con trỏ để duyệt qua các trang kế tiếp
Tự động gọi lại lệnh tạo booking khi mạng chập chờnTạo ra nhiều booking trùng lặp và giữ ghế ảoTra cứu lại danh sách booking trước khi quyết định gọi lại
Hiển thị trực tiếp thời gian trả về từ APIDữ liệu thời gian trả về theo giờ UTCChuyển đổi mốc thời gian sang múi giờ Việt Nam (GMT+7)
Coi mọi mã 422 là lỗi định dạng dữ liệuMã 422 còn dùng cho lỗi nghiệp vụ, số dư và tiến trình đang xử lýĐọc mã lỗi và thông điệp; không tự động gửi lại

Trang này tương ứng với các tham số truy vấn chung xuất hiện trên hầu hết các nhóm của Scalar UI — Ferry VN API:

Tham số trên ScalarÝ nghĩa và quy ước
limitSố lượng bản ghi cần lấy (mặc định 10, tối đa 50)
cursorChuỗi con trỏ lấy từ nextCursor của trang trước để xem trang tiếp theo
x-request-idHeader tuỳ chọn gửi mã định danh truy vết yêu cầu
TrangNội dung nên đọc tiếp
Xác thực bằng API keyQuy chuẩn truyền khoá và xử lý mã lỗi xác thực
Luồng đặt véÁp dụng quy tắc kiểm soát trùng lặp vào quy trình đặt vé
Giá và markupQuy tắc làm tròn tiền tệ và cấu trúc giá vé
Lỗi và cách xử lýChi tiết danh mục mã lỗi và chiến lược thử lại an toàn