Luồng đặt phòng
Luồng điển hình của một công cụ đặt phòng: lấy token, liệt kê phòng cho ngày và số khách mà khách đã tìm, áp dụng mức giá đã chọn và mã giảm giá (nếu có), hoàn tất bước thanh toán, rồi ghi đặt phòng vào HMS bằng BookingPushRQ. Hướng dẫn này đi qua từng bước với yêu cầu và phản hồi thực tế.
/external/public/login/external/online/roomTypecoupon/search · stock/packagespayment/type/{type}channel/booking1. Lấy token#
Đăng nhập một lần khi máy chủ của bạn khởi động hoặc khi token hết hạn, và lưu token cùng với ID khách sạn. Chi tiết: Xác thực.
2. Liệt kê phòng#
Yêu cầu danh sách phòng với các giá trị từ form tìm kiếm của khách. Nếu có trẻ em đi cùng, hãy gửi tuổi của trẻ; giá cho trẻ em được tính theo độ tuổi.
curl "https://test.hms.gen.tr/external/online/roomType" \
-H "Authorization: Bearer $HMS_TOKEN" \
-d "hotelID=1000" -d "startDate=2026-08-18" -d "endDate=2026-08-20" \
-d "adultCount=2" -d "childCount=1" -d "childAges[]=7" -d "language=en"Những gì cần hiển thị cho mỗi loại phòng trong phản hồi:
| Trường | Trên màn hình |
|---|---|
name, images[], detail, roomFeatures[] | Thẻ phòng |
roomCount | Số phòng còn lại. 0 nghĩa là “không mở bán” — lý do nằm trong roomRestrictionMessage. |
accommodationTypes[].title | Lựa chọn gói ăn (Bao gồm bữa sáng, Bao gồm bữa sáng và tối…) |
accommodationTypes[].prices{} | Lựa chọn giá: tiêu chuẩn và không hoàn tiền |
Khóa của đối tượng prices có dạng "<persons>-<1|0>". Hậu tố 1 là giá tiêu chuẩn (được hoàn tiền), 0 là giá không hoàn tiền; lựa chọn không hoàn tiền có nonRefundable: "[NR]". Với giá theo phòng (priceType: 1), khóa là 1-1 / 1-0 bất kể số khách.
{
"2-1": {
"total": 2,
"title": 2,
"nonRefundable": "",
"price": "1930.00",
"currency": "TRY",
"id": "2/2",
"prices": [
{
"price": "965.00",
"tarih": "18.08.2026"
},
{
"price": "965.00",
"tarih": "19.08.2026"
}
]
},
"2-0": {
"total": 2,
"title": 2,
"nonRefundable": "[NR]",
"price": "1737.00",
"currency": "TRY",
"id": "2-0/2",
"prices": [
{
"price": "868.50",
"tarih": "18.08.2026"
},
{
"price": "868.50",
"tarih": "19.08.2026"
}
]
}
}3. Mã giảm giá và gói dịch vụ#
Nếu khách nhập mã giảm giá, hãy kiểm tra mã và áp dụng mức giảm ở phía bạn:
curl "https://test.hms.gen.tr/external/online/coupon/search" \
-H "Authorization: Bearer $HMS_TOKEN" \
-d "hotelID=1000" -d "coupon=SUMMER2026"{
"success": true,
"cupon": {
"id": 12,
"change": 0,
"rate": "10.00"
}
}Khi change là 0, rate là mức giảm theo phần trăm (10%); khi là 1, đó là số tiền cố định (10.00 theo đơn vị tiền tệ của khách sạn). Áp dụng mức giảm vào tiền phòng và gửi các tổng tiền đã giảm trong đặt phòng.
Để bán dịch vụ bổ sung, hãy hiển thị danh sách gói dịch vụ. Các gói được chọn được đưa vào đặt phòng dưới dạng extras[], với id của gói trong stockID. Tổng tiền sau khi áp dụng mã giảm giá và gói dịch vụ được ghi vào Total của đặt phòng.
4. Bước thanh toán#
Liệt kê các hình thức thanh toán mà khách sạn chấp nhận và xử lý tiếp theo lựa chọn của khách. Với hình thức 10 (thanh toán trực tuyến), một phiên thanh toán được khởi tạo và khách được chuyển sang nhà cung cấp; sau khi thanh toán, khách quay lại returnUrl của bạn. Tất cả các hình thức được trình bày trong hướng dẫn Luồng thanh toán.
5. Gửi đặt phòng#
Khi đã có kết quả thanh toán, hãy ghi đặt phòng vào HMS. ID là mã duy nhất do bạn tạo; hãy cung cấp cùng mã này cho khách. ID loại phòng và gói ăn lấy từ danh sách phòng.
curl -X POST "https://test.hms.gen.tr/external/online/channel/booking" \
-H "Authorization: Bearer $HMS_TOKEN" \
-H "Content-Type: application/json" \
-d @booking.jsonconst booking = {
hotelID: "1000",
ID: orderNo, // mã đặt phòng duy nhất của bạn
type: "Book",
createDateTime: new Date().toISOString(),
checkinDate: "2026-08-18",
checkoutDate: "2026-08-20",
RoomStays: [{
roomTypeID: "2", roomName: "Standard Room",
ratePlanID: "2", ratePlanName: "Bed & Breakfast",
type: "Book", NumberOfUnits: "1",
checkinDate: "2026-08-18", checkoutDate: "2026-08-20",
GuestCount: { adult: 2, child: 1 },
PerDayRates: { currency: "TRY", PerDayRate: [
{ stayDate: "2026-08-18", baseRate: "965.00", hotelServiceFees: "0" },
{ stayDate: "2026-08-19", baseRate: "965.00", hotelServiceFees: "0" }
]},
Total: { amountAfterTaxes: "1930.00", amountOfTaxes: "175.45", currency: "TRY" }
}],
PrimaryGuests: [{ name: "Ayşe", surname: "Demir", PhoneNumber: "+905551112233", email: "[email protected]", CountryCode: "TR" }],
ChildGuests: [{ age: 7 }],
SpecialRequest: [{ text: "Late check-in, around 23:00." }],
extras: [],
Total: { amountAfterTaxes: "1930.00", amountOfTaxes: "175.45", extraTotal: "0.00", currency: "TRY" }
};
const res = await fetch("https://test.hms.gen.tr/external/online/channel/booking", {
method: "POST",
headers: { "Authorization": `Bearer ${process.env.HMS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({ BookingPushRQ: { Bookings: [booking] } })
});
const { BookingPushRS } = await res.json();
if (BookingPushRS.Error) throw new Error(BookingPushRS.Error);
const hmsId = BookingPushRS.BookingConfirmNumbers[0].HMS_ID;$booking = [
'hotelID' => '1000',
'ID' => $orderNo, // mã đặt phòng duy nhất của bạn
'type' => 'Book',
'createDateTime' => date('c'),
'checkinDate' => '2026-08-18',
'checkoutDate' => '2026-08-20',
'RoomStays' => [[
'roomTypeID' => '2', 'roomName' => 'Standard Room',
'ratePlanID' => '2', 'ratePlanName' => 'Bed & Breakfast',
'type' => 'Book', 'NumberOfUnits' => '1',
'checkinDate' => '2026-08-18', 'checkoutDate' => '2026-08-20',
'GuestCount' => ['adult' => 2, 'child' => 1],
'PerDayRates' => ['currency' => 'TRY', 'PerDayRate' => [
['stayDate' => '2026-08-18', 'baseRate' => '965.00', 'hotelServiceFees' => '0'],
['stayDate' => '2026-08-19', 'baseRate' => '965.00', 'hotelServiceFees' => '0'],
]],
'Total' => ['amountAfterTaxes' => '1930.00', 'amountOfTaxes' => '175.45', 'currency' => 'TRY'],
]],
'PrimaryGuests' => [['name' => 'Ayşe', 'surname' => 'Demir', 'PhoneNumber' => '+905551112233', 'email' => '[email protected]', 'CountryCode' => 'TR']],
'ChildGuests' => [['age' => 7]],
'SpecialRequest' => [['text' => 'Late check-in, around 23:00.']],
'extras' => [],
'Total' => ['amountAfterTaxes' => '1930.00', 'amountOfTaxes' => '175.45', 'extraTotal' => '0.00', 'currency' => 'TRY'],
];
$ch = curl_init('https://test.hms.gen.tr/external/online/channel/booking');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('HMS_TOKEN'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['BookingPushRQ' => ['Bookings' => [$booking]]]),
]);
$rs = json_decode(curl_exec($ch), true)['BookingPushRS'];
if (isset($rs['Error'])) {
throw new RuntimeException($rs['Error']);
}
$hmsId = $rs['BookingConfirmNumbers'][0]['HMS_ID'];{
"BookingPushRS": {
"Success": true,
"BookingConfirmNumbers": [
{
"confirmTime": 1755500000,
"bookingID": 48213,
"bookingType": "Book",
"HMS_ID": 48213
}
]
}
}HMS_ID là ID của đặt phòng trong HMS; hãy lưu giá trị này cùng với bản ghi của bạn. Đặt phòng xuất hiện trong bảng quản trị dưới kênh “Online”, và HMS gửi email xác nhận cho khách theo cài đặt của khách sạn.
Nhiều phòng#
Khi bán nhiều phòng cùng loại phòng và gói ăn, mỗi phòng là một mục RoomStays riêng; NumberOfUnits là "1" cho phòng thứ nhất, "2" cho phòng thứ hai, v.v. Các loại phòng khác nhau cũng là các mục riêng. Total của đặt phòng là tổng của tất cả các phòng và dịch vụ bổ sung.
Sửa đổi và hủy#
Gửi lại đặt phòng đến cùng endpoint với cùng ID:
type: "Modify"— ngày, phòng hoặc thông tin khách đã thay đổi. Hãy gửi toàn bộ đặt phòng ở trạng thái hiện tại; HMS sẽ thay thế bản ghi hiện có bằng dữ liệu này.type: "Cancel"— đặt phòng đã bị hủy. Các phòng cũng mangtype: "Cancel".
Lỗi thường gặp#
- Lưu danh sách phòng vào bộ nhớ đệm quá lâu. Phòng trống và giá thay đổi liên tục; hãy làm mới danh sách trước khi khách vào bước thanh toán.
- Gửi
childCountkhác với độ dài củachildAges[]: máy chủ tin vào danh sách tuổi và tự động thay đổi số trẻ em mà không báo. - Gửi ID của riêng bạn làm
roomTypeID/ratePlanIDthay vì ID từ danh sách phòng: API sẽ trả về Could not register. - Gửi
PaymentCardvới các hình thức thanh toán khác 9: dữ liệu thẻ bị truyền đến HMS một cách không cần thiết. - Thử lại sau lỗi mạng với một
IDkhác: việc này tạo ra đặt phòng trùng lặp. Hãy thử lại với cùngID.