جریان تأیید مهمان

این راهنما نحوه استفاده از فهرست مهمانان مقیم در پورتال ورود (captive portal) را توضیح می‌دهد: تطبیق آنچه مهمان وارد می‌کند با فهرست، زمان پایان نشست وای‌فای، تناوب به‌روزرسانی فهرست و فیلدهایی که باید برای سوابق قانون 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) {
  // "Room number and surname did not match" — count failed attempts, throttle after 5
}

مقدار unique رکورد منطبق، هویت کاربر هات‌اسپات است. وقتی همان مهمان از دستگاه دوم وارد می‌شود، به‌جای ساختن حساب جدید از حسابی که به این مقدار پیوند خورده است استفاده کنید و محدودیت تعداد دستگاه را روی همان حساب اعمال کنید.

مدت نشست#

checkout تاریخ برنامه‌ریزی‌شده چک‌اوت است و به ساعت 00:00 (UTC) همان روز اشاره می‌کند؛ ساعت روز را ندارد. اگر نشست را تا همان لحظه باز کنید، مهمان صبح روز خروج دسترسی‌اش را از دست می‌دهد. پایان نشست را با افزودن ساعت چک‌اوت هتل به این تاریخ محاسبه کنید:

پایان نشست
const CHECKOUT_TIME = "12:00";                       // the hotel’s check-out time
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 تغییر می‌کند؛ این فیلد را هنگام همگام‌سازی مقایسه کنید و پایان نشست را به‌روز کنید. برای چک‌اوت‌های دیرهنگام، امن‌تر است تا زمانی که مهمان در فهرست است دسترسی را باز نگه دارید.

همگام‌سازی دوره‌ای#

فهرست یک تصویر لحظه‌ای است و اعلان تغییر (وب‌هوک) وجود ندارد. فهرست را در فواصل ثابت دریافت کنید و آن را بر اساس unique با فهرست قبلی مقایسه کنید:

  • فاصله زمانی: برای بیشتر هتل‌ها 5 دقیقه کافی است. اگر انتظار می‌رود مهمانان درست هنگام چک‌این آنلاین شوند، می‌توانید آن را تا 1 تا 2 دقیقه کاهش دهید؛ کمتر از 1 دقیقه نکنید.
  • unique جدید: حساب را آماده کنید؛ مهمان در اولین ورود به پورتال تطبیق داده می‌شود.
  • unique حذف‌شده: مهمان چک‌اوت کرده یا رزرو لغو شده است. نشست را پایان دهید و حساب را ببندید.
  • unique یکسان، roomName یا checkout متفاوت: تغییر اتاق یا تمدید اقامت. حساب را به‌روز کنید.
  • درخواست ناموفق: در صورت تایم‌اوت، 401 یا 5xx، آخرین فهرست موفق را نگه دارید؛ هرگز بر اساس پاسخ خطا حساب‌ها را نبندید.
حلقه همگام‌سازی
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: keep the old list
  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);                // checked out
  }
  for (const [id, g] of next) {
    const old = prev.get(id);
    if (!old) await openAccount(g);                           // new guest
    else if (old.checkout !== g.checkout || old.roomName !== g.roomName) await updateAccount(g);
  }
  return next;
}

چند مهمان در یک اتاق#

هر مهمان در یک اتاق رکورد جداگانه‌ای است: rezervasyon_id مشترک است و unique متفاوت. حساب‌ها را به‌ازای هر مهمان باز کنید نه هر اتاق، تا هر مهمان دستگاه، نشست و سابقه قانون 5651 مخصوص خود را داشته باشد. جست‌وجو با شماره اتاق + نام خانوادگی ممکن است برای مهمانانی با نام خانوادگی یکسان (یک خانواده) بیش از یک رکورد برگرداند؛ به‌جای برداشتن اولین نتیجه، با نام کوچک یا تاریخ تولد ابهام را برطرف کنید یا برای آن‌ها یک حساب مشترک باز کنید.

سوابق قانون 5651#

تکلیف نگهداری لاگ‌های دسترسی طبق قانون 5651 بر عهده سیستم هات‌اسپات است؛ HMS فقط داده‌های هویتی را فراهم می‌کند. هنگام باز شدن نشست، فیلدهای زیر را همراه با آدرس MAC/IP و مهر زمانی ذخیره کنید: unique، rezervasyon_id، firstName، lastName، identityNumber، birthDate، roomName، checkin، checkout. وقتی مهمان از فهرست حذف شود، HMS دیگر این اطلاعات را ارائه نمی‌دهد؛ سابقه را در سمت خودتان نگه دارید.

آخرین به‌روزرسانی: 21 سپتامبر 2026اشتباهی دیدید؟ به ما اطلاع دهید