客人验证流程

本指南说明如何在认证门户中使用在住客人名单:如何将客人输入的信息与名单匹配、Wi-Fi 会话应何时结束、名单应多久刷新一次,以及为土耳其第 5651 号法律日志应保留哪些字段。

认证门户上应询问什么#

由于名单同时提供房间和身份信息,最常见的形式是房间号 + 姓氏。仅凭房间号是不够的:任何知道隔壁房间号的人都能登录。其他可选方式有房间号 + 身份证/护照号姓氏 + 出生日期;后者可作为证件号码为空的客人的备用方式。

匹配规则#

将客人输入的内容与名单中的值进行比较之前,先对双方进行规范化处理:

  • 房间号:去除首尾空白并转换为大写。roomName 是字符串(可能是 "104""A-12""Villa 3");不要将其转换为数字,也不要去掉前导零。
  • 姓氏:转换为大写(注意土耳其语的 i → İ 映射),并将连续空格合并为一个。名单中的值通常取自证件,为大写。
  • 证件号码:去除空格并转换为大写。土耳其公民身份证号为 11 位数字;护照号由字母和数字混合组成。
  • 出生日期:名单中为 DD.MM.YYYY 格式;如果您的表单采用其他格式,请进行转换。
匹配
const norm = (s) => String(s ?? "")
  .replace(/\s+/g, " ")
  .trim()
  .toLocaleUpperCase("tr-TR");

function findGuest(list, room, lastName) {
  return list.find((g) =>
    norm(g.roomName) === norm(room) && norm(g.lastName) === norm(lastName)
  ) || null;
}

const guest = findGuest(data.otelde, form.room, form.lastName);
if (!guest) {
  // "房间号与姓氏不匹配" — 统计失败次数, 5 次后限流
}

匹配记录的 unique 值即热点用户的身份标识。同一位客人从第二台设备登录时,请沿用与该值关联的账户,而不是新建账户,并在该账户上执行设备数量限制。

会话时长#

checkout 是计划退房日期,指向当天的 00:00(UTC),不含具体时刻。如果会话只开放到这一时刻,客人在离店当天早上就会失去访问权限。请在该日期上加上酒店的退房时间来计算会话结束时间:

会话结束时间
const CHECKOUT_TIME = "12:00";                       // 酒店的退房时间
const day = new Date(guest.checkout * 1000)
  .toLocaleDateString("en-CA", { timeZone: "UTC" });   // "2026-09-10"
const sessionEnd = new Date(`${day}T${CHECKOUT_TIME}:00+03:00`);

如果客人在退房时间之前离店,就会从名单中消失;请在下一次同步时关闭其账户。如果住宿延长,checkout 会发生变化;请在同步时比较该字段并更新会话结束时间。对于延迟退房的情况,只要客人仍在名单中就保持访问权限,这样更稳妥。

定期同步#

名单只是一个快照,没有变更通知(webhook)。请按固定间隔获取名单,并按 unique 与上一份名单进行比对:

  • 间隔:对大多数酒店来说 5 分钟足够。如果希望客人一办理入住就能上网,可以缩短到 1–2 分钟;但不要低于 1 分钟。
  • 新出现的 unique预先准备账户;客人首次在认证门户登录时完成匹配。
  • 消失的 unique客人已退房或预订已取消。结束会话并关闭账户。
  • unique 相同,但 roomNamecheckout 不同:换房或续住。更新账户。
  • 请求失败:遇到超时、4015xx 时,保留上一次成功获取的名单;切勿根据错误响应关闭账户。
同步循环
async function sync(prev) {
  const res = await fetch(BASE + "/public/json/customer/inhotel", {
    method: "POST",
    headers: { "ApiKey": process.env.HMS_API_KEY, "HotelCode": HOTEL_CODE }
  });
  if (!res.ok) return prev;                                   // 401 / 5xx: 保留旧名单
  const { success, otelde } = await res.json();
  if (success !== 1) return prev;

  const next = new Map(otelde.map((g) => [g.unique, g]));
  for (const [id] of prev) {
    if (!next.has(id)) await closeAccount(id);                // 已退房
  }
  for (const [id, g] of next) {
    const old = prev.get(id);
    if (!old) await openAccount(g);                           // 新客人
    else if (old.checkout !== g.checkout || old.roomName !== g.roomName) await updateAccount(g);
  }
  return next;
}

一个房间住多位客人#

同一房间内的每位客人都是一条独立记录:rezervasyon_id 相同,unique 不同。请按客人而不是按房间开通账户,使每位客人拥有各自的设备、会话和第 5651 号法律日志记录。对于同姓的客人(例如一家人),按房间号 + 姓氏查询可能返回多条记录;此时不要直接取第一条匹配结果,而应通过名字或出生日期加以区分,或为他们开通一个共享账户。

第 5651 号法律日志#

按土耳其第 5651 号法律留存访问日志的义务由热点系统承担,HMS 只提供身份数据。会话开启时,请将以下字段与 MAC/IP 地址和时间戳一起保存:uniquerezervasyon_idfirstNamelastNameidentityNumberbirthDateroomNamecheckincheckout。客人从名单中消失后,HMS 将不再提供这些信息,因此请在您一方保留记录。

最后更新: 2026年9月21日发现错误?请告诉我们