预订流程
预订引擎的典型流程:获取 token,按客人搜索的日期和入住人数列出房型,应用所选价格及优惠券(如有),完成支付步骤,最后通过 BookingPushRQ 将预订写入 HMS。本指南结合真实的请求和响应逐步讲解每个环节。
/external/public/login/external/online/roomTypecoupon/search · stock/packagespayment/type/{type}channel/booking1. 获取 token#
在服务器启动时或 token 过期时登录一次,并将 token 与酒店 ID 一起保存。详见身份验证。
2. 列出房型#
使用客人搜索表单中的值请求房型列表。如有儿童同行,请发送其年龄;儿童价格按年龄计算。
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"响应中的每个房型应展示以下内容:
| 字段 | 界面展示 |
|---|---|
name, images[], detail, roomFeatures[] | 房型卡片 |
roomCount | 剩余房间数。为 0 表示“不可售”,原因见 roomRestrictionMessage。 |
accommodationTypes[].title | 餐食选项(含早餐、半膳…) |
accommodationTypes[].prices{} | 价格选项:标准价与不可退款价 |
prices 对象的键格式为 "<persons>-<1|0>"。后缀 1 表示标准(可退款)价格,0 表示不可退款价格;不可退款选项带有 nonRefundable: "[NR]"。按房间计价(priceType: 1)时,无论入住人数多少,键均为 1-1 / 1-0。
{
"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. 优惠券与套餐#
如果客人输入了优惠码,请先验证,然后在您一方应用折扣:
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"
}
}change 为 0 时,rate 是百分比折扣(10%);为 1 时是固定金额(以酒店币种计 10.00)。将折扣应用到房费上,并在预订中发送折后总额。
如需销售附加服务,请展示套餐列表。客人选择的套餐以 extras[] 放入预订,套餐的 id 填在 stockID 中。应用优惠券和套餐后的总额写入预订的 Total。
4. 支付步骤#
列出酒店接受的支付方式,并根据客人的选择继续。方式 10(在线支付)会发起支付会话,并将客人转交给支付服务商;支付完成后,客人返回您的 returnUrl。所有支付方式的说明见支付流程指南。
5. 推送预订#
支付结果确定后,将预订写入 HMS。ID 是您生成的唯一编号,请将同一编号告知客人。房型和餐食类型 ID 取自房型列表。
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, // 您的唯一预订编号
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, // 您的唯一预订编号
'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 是该预订在 HMS 中的 ID,请与您自己的记录一起保存。预订会显示在后台的“Online”渠道下,HMS 会根据酒店的设置向客人发送确认邮件。
多间客房#
同一房型和餐食类型售出多间房时,每间房都是一个独立的 RoomStays 项;第一间的 NumberOfUnits 为 "1",第二间为 "2",依此类推。不同房型同样各为独立的项。预订的 Total 为所有房间和附加服务的合计。
修改与取消#
使用相同的 ID 将预订再次发送到同一端点:
type: "Modify"— 日期、房间或客人信息有变更。请发送预订当前状态的完整内容;HMS 会用它替换现有记录。type: "Cancel"— 预订已取消。其中的房间也要带上type: "Cancel"。
常见错误#
- 长时间缓存房型列表。房态和价格随时变化;请在客人进入支付步骤前刷新列表。
- 发送的
childCount与childAges[]的长度不一致:服务器以年龄列表为准,并会静默修改儿童数。 - 在
roomTypeID/ratePlanID中发送您自己的 ID,而不是房型列表中的 ID:将返回 Could not register.。 - 对 9 以外的支付方式发送
PaymentCard:卡数据会被不必要地传输到 HMS。 - 网络错误后使用不同的
ID重试:这会产生重复预订。请使用相同的ID重试。