Начать проект с нами
Стать частью команды
Соцсети

WebRequest вместо аренды облачной кассы: как подключили АТОЛ к Битрикс своими силами

Кейс
2 января 2026
WebRequest вместо аренды облачной кассы: как подключили АТОЛ к Битрикс своими силами
Вячеслав Кречетов
Вячеслав Кречетов

CEO

С задачей по кассе мы столкнулись не потому, что старая интеграция внезапно перестала работать. Наоборот, в целом она работала нормально. Проблема появилась после изменений в требованиях к составу данных, которые должны попадать в чек.

У клиента уже была настроена связка Битрикс + физическая касса АТОЛ. Менять оборудование и тем более переводить всё на облачную кассу не хотелось. Во-первых, это дополнительные расходы. Во-вторых, существующая схема устраивала клиента и не было особого смысла менять её целиком ради одной задачи.

Поэтому сначала посмотрели, что вообще умеет сама касса и какие варианты интеграции предоставляет АТОЛ. В документации нашли WebRequest — HTTP-интерфейс, через который можно передавать кассовые команды непосредственно устройству.

На этом и решили попробовать построить свою интеграцию.

Почему именно WebRequest

Идея здесь довольно простая: Битрикс формирует данные чека, а дальше вместо штатного обработчика мы передаем их в АТОЛ через WebRequest.

То есть архитектура получается примерно такая:

Битрикс → собственный обработчик → ATOL WebRequest → касса.

Никакой отдельной облачной кассы между магазином и физическим устройством в этой схеме нет.

Через WebRequest можно отправлять не только чеки. Есть команды для работы со сменой и проверки состояния кассы. Это пригодилось, потому что хотелось сделать не просто «отправку JSON», а полноценный кассовый обработчик для Битрикс.

В нашем случае были нужны в первую очередь:

  • отправка чеков;
  • открытие смены;
  • закрытие смены;
  • проверка состояния смены;
  • проверка результата выполнения задания;
  • работа с UUID операций.

На бумаге всё это выглядело достаточно просто. На практике больше всего времени ушло не на HTTP-запрос, а на то, чтобы правильно состыковать жизненный цикл кассовой операции Битрикс с асинхронной моделью АТОЛ.

Сначала разбирались с Битрикс

Первое, что стало понятно после изучения модуля «Кассы»: просто перехватить создание чека и отправить его в WebRequest не получится.

У Битрикс есть собственная модель кассовых обработчиков. Система ожидает от них определенный набор методов и определенное поведение. Поэтому пошли по более правильному пути — сделали собственный обработчик на базе стандартного класса кассы.

В качестве основы используется Bitrix\Sale\Cashbox\Cashbox. Дальше уже нужно было связать методы этого класса с форматом запросов АТОЛ.

Получилась достаточно обычная прослойка: снаружи она выглядит для Битрикс как касса, внутри занимается подготовкой данных и отправкой заданий в WebRequest.

Регистрация обработчика

Для начала обработчик нужно зарегистрировать в Битрикс. Для этого используется событие onGetCustomCashboxHandlers.

AddEventHandler('sale', 'onGetCustomCashboxHandlers', function() {
return [
    'redramka_webrequest' => RedramkaWebRequestHandler::class
];
});

После этого новый обработчик появляется среди доступных вариантов кассы.

Дальше уже начинается самое интересное — нужно было разобраться, какие данные Битрикс передает обработчику и в каком виде АТОЛ ожидает получить эти же данные.

Формирование чека

Битрикс внутри уже знает практически всё необходимое для чека: товары, количество, цену, скидки, способ оплаты и остальные данные заказа.

Поэтому не стали собирать чек заново с нуля. Логика формирования запроса была вынесена в отдельный метод, а дальше результат преобразовывался в структуру, которую понимает WebRequest.

Если упростить код до самой сути, отправка выглядит примерно так:

public function sendCheck(Check $check)
{
$uuid = Uuid::generate();
$query = $this->buildCheckQuery($check);

$payload = [
    'uuid' => $uuid,
    'request' => [$query],
];

$this->sendToAtol($payload);

return new EventResult(EventResult::SUCCESS);
}

Это не полный код обработчика, а только схема работы. В реальной реализации вокруг неё еще есть подготовка данных, обработка ответа и работа со статусом задания.

Отдельно пришлось внимательно пройтись по составу позиций и платежей. В таких интеграциях проблема часто возникает не на уровне самого запроса, а из-за какого-нибудь поля, которое в одной системе называется одним образом, а в другой имеет совершенно другую структуру.

Самый неожиданный момент — чек не готов сразу

Вот здесь как раз пришлось немного изменить первоначальный подход.

Поначалу логика казалась очевидной: отправили запрос — получили ответ — считаем, что чек пробит.

Но WebRequest работает асинхронно.

Когда АТОЛ принимает запрос, это еще не означает, что касса уже закончила операцию. В ответ мы получаем идентификатор задания, а дальше нужно проверять его состояние.

В упрощенном виде процесс выглядит так:

  1. Битрикс формирует чек.
  2. Создается UUID.
  3. Задание отправляется в WebRequest.
  4. АТОЛ принимает его.
  5. Касса обрабатывает задание.
  6. По UUID можно получить результат.

Из-за этого нельзя бездумно воспринимать любой успешный HTTP-ответ как успешную фискализацию.

И это, пожалуй, главный момент всей интеграции.

Зачем нужен UUID

UUID используется как идентификатор конкретного задания. Его нужно сохранять, потому что именно по нему потом можно понять, что произошло с операцией.

Это особенно важно при проблемах с сетью.

Представим ситуацию: Битрикс отправил чек, АТОЛ его получил, но соединение оборвалось до того, как магазин получил ответ. Если в этот момент просто повторить отправку, можно получить уже две операции вместо одной.

Поэтому логика должна быть другой: сначала попытаться определить состояние уже созданного задания, и только после этого принимать решение о повторной отправке.

Для меня это был один из тех моментов, которые хорошо выглядят в простой схеме на бумаге, но становятся важными сразу после первого реального сбоя.

Открытие и закрытие смены

С чеками разобрались, но оставался еще один обязательный кусок — управление сменой.

Для открытия смены в WebRequest передается соответствующая команда. Например:

{
"uuid": "...",
"request": [
    {
        "type": "openShift",
        "operator": {
            "name": "Иванов",
            "vatin": "1234567890"
        }
    }
]
}

Закрытие выполняется аналогичным образом:

{
"uuid": "...",
"request": [
    {
        "type": "closeShift",
        "operator": {
            "name": "Иванов",
            "vatin": "1234567890"
        }
    }
]
}

Кроме самих команд, добавили проверку состояния смены. Это позволяет не пытаться отправлять кассовую операцию в ситуацию, когда касса находится в неподходящем состоянии.

В итоге перед отправкой чека можно проверить состояние кассы, а после отправки — отдельно контролировать результат задания.

Что оказалось важнее самого API

Если смотреть только на документацию WebRequest, задача кажется довольно прямолинейной: сформировать JSON и отправить HTTP-запрос.

Но в реальной интеграции проблемные места находятся немного в другом.

Во-первых, нужно учитывать очередь. Физическая касса не может обрабатывать бесконечное количество операций одновременно.

Во-вторых, нельзя путать принятие задания с его выполнением.

В-третьих, нужно продумать поведение при обрыве соединения. Именно здесь UUID становится действительно полезным, а не просто обязательным полем запроса.

И еще один момент — сетевое окружение. WebRequest предъявляет свои требования к адресу, с которого идут запросы, поэтому при переносе проекта или изменении инфраструктуры это тоже необходимо учитывать.

Что получилось в итоге

В результате оставили существующую физическую кассу и не стали добавлять к проекту еще один облачный сервис.

Со стороны Битрикс появился собственный кассовый обработчик. Он получает данные стандартным для Битрикс способом, преобразует их в формат АТОЛ и передает задания через WebRequest.

При этом отдельно обрабатываются смены, UUID и статусы операций.

В итоге получили:

  • интеграцию Битрикс с физической кассой АТОЛ;
  • возможность передавать необходимые данные в чек;
  • работу без аренды отдельной облачной кассы;
  • контроль над логикой интеграции на своей стороне;
  • возможность менять обработчик под конкретный проект.

При этом я бы не сказал, что это какой-то универсальный способ заменить облачную кассу. У решения есть свои ограничения, и перед внедрением их нужно учитывать.

Но для проекта, где уже есть физическая касса АТОЛ и требуется связать её с Битрикс, WebRequest оказался вполне рабочим вариантом.

Главный вывод для нас оказался довольно простым: сложность здесь не в том, чтобы отправить JSON по HTTP. Самое важное — правильно связать две разные модели работы. Битрикс считает, что у него есть кассовая операция, а АТОЛ сначала принимает задание, потом ставит его в очередь и только после этого выполняет.

Если учитывать эту разницу изначально, интеграция получается вполне управляемой.