При переходе на онлайн-кассы по требованиям Федерального закона № 54-ФЗ перед разработчиками встает непростая задача: как обеспечить круглосуточную фискализацию чеков при оплатах на сайте без участия живого оператора. Классическая подсистема торгового оборудования в типовых конфигурациях 1С (особенно на базе обычных форм, таких как УТ 10.3 или УПП) рассчитана исключительно на интерактивную работу с пользователем на клиенте. В этой статье разберем ключевые сложности серверной фискализации и рассмотрим несколько проверенных вариантов реализации автоматической пробивки чеков.
Прежде чем приступать к архитектуре решения, проанализируем нормативные требования. При осуществлении расчетов в сети «Интернет» безналичными электронными средствами платежа чек передается клиенту в электронной форме (по СМС или e-mail). При расчетах, исключающих непосредственное взаимодействие продавца и покупателя, кассовый чек должен быть сформирован не позднее рабочего дня, следующего за днем осуществления расчета, но не позднее момента фактической передачи товара покупателю. Это снимает жесткое ограничение фискализации «секунда в секунду» и позволяет закладывать разумные паузы на обслуживание информационной базы.
В типовом интернет-магазине процесс расчетов часто строится по двухчековой схеме:
Главное техническое препятствие серверного пробития чеков регламентным заданием кроется в драйверах кассового оборудования. Библиотеки драйверов (например, FprnM1C82_54FZ.dll) долгое время выпускались исключительно в 32-битном варианте. Если на сервере развернут 64-битный рабочий процесс 1С (ragent.exe, rphost.exe), прямое подключение 32-битной компоненты через вызов ЗагрузитьВнешнююКомпоненту() завершится системной ошибкой несовместимости архитектур.
Кроме того, вся стандартная подсистема «1С:Библиотека подключаемого оборудования» (БПО) и типовые модули (такие как ПодключаемоеОборудованиеУниверсальныйДрайверКлиент и МенеджерОборудованияВызовСервера) исторически спроектированы для клиентского интерфейса и используют модальные диалоги и оповещения.
Наиболее надежный и современный подход, позволяющий полностью уйти от клиентских костылей и проблем с разрядностью, — использование локального веб-сервера кассы (например, встроенного локального Web-сервера современных драйверов производителя или решений класса kkmserver).
В этом случае на сервере, к которому по USB или Ethernet подключена ККТ, в качестве системной службы Windows/Linux разворачивается локальный сервис. Он держит постоянное соединение с кассой и предоставляет локальный REST API, принимающий команды фискализации в формате JSON. Серверная часть 1С работает с кассой обычными HTTP-запросами из регламентного задания или HTTP-сервиса.
Посмотрим на пример формирования и отправки чека из серверного кода 1С с помощью встроенного объекта HTTPСоединение:
ПараметрыПодключения = Новый Структура("Хост, Порт", "127.0.0.1", 5893);
Соединение = Новый HTTPСоединение(ПараметрыПодключения.Хост, ПараметрыПодключения.Порт);
// Формируем структуру данных чека
ЗапросJSON = Новый Структура;
ЗапросJSON.Вставить("Command", "RegisterCheck");
ЗапросJSON.Вставить("NumDevice", 0);
ЗапросJSON.Вставить("TypeCheck", 0); // Продажа
ЗапросJSON.Вставить("IsСheckStrings", Истина);
ЗапросJSON.Вставить("TaxVariant", 1); // Система налогообложения
ЗапросJSON.Вставить("ClientAddress", "client@example.com");
ТаблицаТоваров = Новый Массив;
СтрокаТовара = Новый Структура;
СтрокаТовара.Вставить("Name", "Оплата заказа №12345");
СтрокаТовара.Вставить("Price", 1500.00);
СтрокаТовара.Вставить("Quantity", 1);
СтрокаТовара.Вставить("Amount", 1500.00);
СтрокаТовара.Вставить("Department", 1);
СтрокаТовара.Вставить("Tax", 20); // Ставка НДС
СтрокаТовара.Вставить("SignMethodCalculation", 1); // Предоплата 100%
ТаблицаТоваров.Добавить(СтрокаТовара);
ЗапросJSON.Вставить("CheckStrings", ТаблицаТоваров);
// Сериализация в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ЗапросJSON);
ТелоЗапроса = ЗаписьJSON.Закрыть();
HTTPЗапрос = Новый HTTPЗапрос("/Execute", Новый Соответствие);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8);
HTTPОтвет = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
ОтветСтрока = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
При таком подходе серверная 1С полностью изолирована от физического интерфейса ККТ. Веб-сервер сам следит за стабильностью COM/USB-порта и возвращает номер фискального документа (ФД), фискальный признак (ФПД) и статус смены.
Если конфигурация сильно переписана или используется старая версия платформы, где интеграция через веб-сервер требует слишком больших трудозатрат, чеки можно пробивать через выделенный клиентский сеанс. Разберем по шагам, как построить отказоустойчивую очередь обработки.
ОчередьПечатиЧеков со статусом «К фискализации».Для стабилизации работы сеанса-робота клиент 1С запускают как системную службу Windows (при помощи утилит-оберток для служб) с ключами командной строки, подавляющими модальные диалоги и сообщения об ошибках.
Если необходимо использовать стандартные библиотеки ККТ без сторонних сервисов прямо из серверного контекста 64-битной 1С, применяют механизм межпроцессного взаимодействия Windows COM+:
В этом сценарии Windows создает 32-битный суррогатный процесс dllhost.exe, в котором размещается библиотека драйвера. Серверный 64-битный процесс 1С обращается к компоненте через стандартный вызов Новый COMОбъект(...), а трансляцию вызовов между 64-битной и 32-битной памятью берет на себя операционная система.
Какое бы серверное решение ни было выбрано, помним: физический кассовый аппарат является устройством строго последовательного доступа. Нельзя одновременно отправлять команды на ККТ из нескольких параллельных фоновых заданий, даже если касса подключена по Ethernet. При проектировании серверной фискализации все входящие оплаты обязательно помещаются в единую транзакционную очередь, обработка которой ведется в один поток с использованием исключительных блокировок 1С.