В процессе эксплуатации торговых точек на базе 1С 7.7 часто возникает критическая проблема: пользователи намеренно или случайно изменяют системное время на компьютере. Это приводит к серьезным последствиям, например, к открытию смены фискального регистратора (ФР) в "будущем". В такой ситуации пробить чеки текущей датой становится невозможно до тех пор, пока реальное время не "догонит" время открытия смены в памяти ФР. Чтобы избежать подобных инцидентов, нам необходимо научиться получать эталонное время из интернета и программно контролировать его корректность.
Разберем подробно несколько эффективных способов решения этой задачи: от использования системных утилит Windows до написания программного кода внутри 1С.
Самый простой и надежный способ — задействовать встроенную службу времени Windows. Мы можем выполнить запрос к публичным NTP-серверам (например, pool.ntp.org), чтобы получить информацию о разнице между системным и эталонным временем. Проанализируем команду, которая позволяет получить срез данных:
// Пример команды для командной строки или вызова через КомандаСистемы()
w32tm /stripchart /computer:pool.ntp.org /samples:1 /dataonly
Разберем параметры этой команды:
/stripchart — выводит график (или данные) разницы во времени./computer:pool.ntp.org — адрес сервера точного времени./samples:1 — количество запросов (нам достаточно одного для проверки)./dataonly — возвращает только числовые данные без лишнего текста.В 1С 7.7 результат выполнения можно перенаправить в текстовый файл и считать его. Рассмотрим, как это реализовать:
Процедура ПроверитьВремяЧерезNTP()
ИмяФайла = "time_check.txt";
КомандаСистемы("w32tm /stripchart /computer:pool.ntp.org /samples:1 /dataonly > " + ИмяФайла);
Текст = СоздатьОбъект("Текст");
Текст.Открыть(ИмяФайла);
Если Текст.КоличествоСтрок() > 0 Тогда
// Анализируем строку с результатом
Результат = Текст.ПолучитьСтроку(Текст.КоличествоСтрок());
Сообщить("Результат проверки времени: " + Результат);
КонецЕсли;
КонецПроцедуры
Для того чтобы сопоставить время из интернета (которое обычно передается в формате UTC/GMT) с локальным временем компьютера, нам нужно точно знать текущий часовой пояс. В 1С 7.7 нет встроенной функции ЧасовойПоясСеанса, поэтому мы воспользуемся механизмом WMI (Windows Management Instrumentation) через MSScriptControl.
Рассмотрим пример функции, которая возвращает смещение локального времени от GMT в часах:
Функция ПолучитьСмещениеВремениWMI()
Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.Language = "vbscript";
Скрипт.AddCode("
|function GetGMTOffset()
| set Service = GetObject(""winmgmts:\\.\root\cimv2"")
| set colTimeZone = Service.ExecQuery(""Select * from Win32_TimeZone"")
| for each objTimeZone In colTimeZone
| GetGMTOffset = objTimeZone.Bias / 60
| exit for
| next
|end function
|");
Сдвиг = Скрипт.Run("GetGMTOffset");
Возврат Сдвиг;
КонецФункции
Этот код позволяет нам понять, на сколько часов системное время должно отличаться от эталонного времени Гринвича. Объект Win32_TimeZone и его свойство Bias возвращают смещение в минутах, которое мы делим на 60 для получения часов.
Иногда порт 123 (UDP), необходимый для NTP, закрыт системными администраторами или провайдером. В этом случае мы можем прибегнуть к хитрости: отправить HTTP-запрос к любому крупному веб-серверу и прочитать заголовок Date, который всегда содержит точное время сервера в формате GMT.
Выясним, как реализовать это через объект MSXML2.XMLHTTP:
Функция ПолучитьВремяЧерезHTTP()
Http = СоздатьОбъект("MSXML2.XMLHTTP");
Http.Open("GET", "https://google.com", 0);
Http.Send();
// Получаем заголовок ответа
ДатаСтрокой = Http.getResponseHeader("Date");
// Пример строки: "Mon, 21 Aug 2023 12:00:00 GMT"
Сообщить("Время по GMT из заголовка HTTP: " + ДатаСтрокой);
Возврат ДатаСтрокой;
КонецФункции
Важный момент: полученную строку необходимо распарсить, чтобы перевести ее в формат даты 1С. Это обеспечит независимость от настроек системных часов пользователя.
Чтобы окончательно исключить ошибку "Смена открыта в будущем", мы должны программно сравнивать время компьютера с внутренним временем кассового аппарата перед открытием чека или смены. Проанализируем алгоритм проверки:
GetDeviceMetrics или GetStatus в зависимости от модели).ТекущееВремя().Пример логики на языке 1С 7.7 (псевдокод драйвера):
ФР.Password = 30; // Пароль администратора ФР
ФР.GetStatus();
ВремяФР = ФР.Time; // Получаем время из ФР
ВремяПК = ТекущееВремя();
Если Макс(ВремяФР, ВремяПК) - Мин(ВремяФР, ВремяПК) > "00:05:00" Тогда
Предупреждение("ВНИМАНИЕ! Время на компьютере расходится с временем в кассе!");
СтатусВозврата(0); // Блокируем дальнейшее действие
КонецЕсли;
Программные методы — это хорошо, но первопричину (возможность изменения времени пользователем) нужно устранять административно. Рассмотрим шаги, которые следует предпринять системному администратору:
secpol.msc (Локальная политика безопасности) в разделе Локальные политики -> Назначение прав пользователя найдите параметр "Изменение системного времени". Удалите оттуда всех, кроме администраторов и службы LOCAL SERVICE.w32tm /resync при каждом включении компьютера или раз в час.Используя комбинацию этих методов, мы создадим надежную систему контроля времени, которая исключит простои в работе торговой точки из-за некорректных данных в фискальном регистраторе.