Интеграция с АТОЛ Онлайн для 1С-Битрикс
АТОЛ Онлайн — один из крупнейших операторов фискальных данных (ОФД) в России, предоставляющий облачную кассу для интернет-магазинов. Если сайт работает на 1С-Битрикс и принимает онлайн-платежи от физических лиц, закон 54-ФЗ обязывает применять ККТ и передавать чеки в ОФД. АТОЛ Онлайн закрывает эту задачу без покупки физической кассы.
Как АТОЛ Онлайн вписывается в цепочку
Стандартная цепочка при оплате с фискализацией через АТОЛ:
- Покупатель оплачивает заказ — платёжный агрегатор (ЮКасса, Тинькофф и др.) проводит транзакцию
- Платёжный агрегатор отправляет уведомление в Битрикс об успешной оплате
- Битрикс (или модуль АТОЛ) отправляет запрос в АТОЛ Онлайн на фискализацию чека
- АТОЛ Онлайн регистрирует чек на облачной кассе и передаёт его в ОФД
- Покупатель получает электронный чек на email или по SMS
- АТОЛ возвращает фискальные данные (номер чека, ФН, ФП) в Битрикс
Ключевой момент: АТОЛ работает асинхронно. Запрос на создание чека отправляется, но ответ о результате приходит через webhook или при повторном запросе статуса.
Официальный модуль АТОЛ для Битрикс
АТОЛ предоставляет официальный модуль atol.kkt54 для 1С-Битрикс. Устанавливается через Маркетплейс или вручную.
После установки настраивается в Магазин → Настройки → АТОЛ Онлайн:
| Параметр | Откуда взять |
|---|---|
| Login | Личный кабинет АТОЛ Онлайн |
| Password | Там же |
| Group Code | Идентификатор группы касс |
| INN | ИНН организации |
| Payment Address | URL сайта (как зарегистрирован в АТОЛ) |
| Callback URL | https://shop.ru/local/api/atol-callback.php |
Структура запроса на создание чека
// Отправка чека прихода в АТОЛ
class AtolClient
{
private string $token;
private const API = 'https://online.atol.ru/possystem/v4/';
public function getToken(): void
{
$resp = $this->post('getToken', [
'login' => ATOL_LOGIN,
'pass' => ATOL_PASSWORD,
]);
$this->token = $resp['token'];
}
public function sendReceipt(array $order): array
{
$items = [];
foreach ($order['basket'] as $item) {
$items[] = [
'name' => mb_substr($item['name'], 0, 128), // ограничение АТОЛ
'price' => (float)$item['price'],
'quantity' => (float)$item['quantity'],
'sum' => round($item['price'] * $item['quantity'], 2),
'payment_method'=> 'full_payment',
'payment_object'=> 'commodity',
'vat' => ['type' => 'none'], // или 'vat20', 'vat10'
];
}
if ($order['delivery_price'] > 0) {
$items[] = [
'name' => 'Доставка',
'price' => (float)$order['delivery_price'],
'quantity' => 1.0,
'sum' => (float)$order['delivery_price'],
'payment_method' => 'full_payment',
'payment_object' => 'service',
'vat' => ['type' => 'none'],
];
}
$payload = [
'external_id' => 'BX-' . $order['id'] . '-' . time(),
'receipt' => [
'client' => [
'email' => $order['buyer_email'],
'phone' => $order['buyer_phone'] ?? null,
],
'company' => [
'email' => ATOL_COMPANY_EMAIL,
'sno' => 'osn', // система налогообложения: osn|usn_income|usn_income_outcome|envd|esn|patent
'inn' => ATOL_INN,
'payment_address' => ATOL_PAYMENT_ADDRESS,
],
'items' => $items,
'payments' => [
[
'type' => 1, // 1=электронный, 0=наличные
'sum' => (float)$order['total'],
],
],
'total' => (float)$order['total'],
],
'service' => [
'callback_url' => ATOL_CALLBACK_URL,
],
'timestamp' => date('d.m.Y H:i:s'),
];
return $this->post(ATOL_GROUP_CODE . '/sell', $payload);
}
private function post(string $endpoint, array $data): array
{
$ch = curl_init(self::API . $endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json; charset=utf-8',
'Token: ' . $this->token,
],
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true) ?? [];
}
}
Критичные тонкости при реализации
Сумма позиций должна точно совпадать с total — АТОЛ проверяет это на своей стороне. Расхождение в 1 копейку вызывает ошибку. Типичная проблема при округлении: сумма трёх позиций по 33.33 руб. = 99.99, а total = 100.00. Решение — последней позиции присваивать сумму по остатку.
Наименование позиции — максимум 128 символов. Длинные названия нужно обрезать, но так, чтобы сохранился смысл.
Номенклатурный код (поле nomenclature_code) — с 2024 года обязателен для маркированных товаров (одежда, обувь, парфюмерия, молочная продукция и другие категории). Код берётся из системы «Честный ЗНАК».
Асинхронность — ответ POST /sell содержит только uuid задачи. Фактический результат фискализации приходит в callback. Необходимо хранить uuid и обрабатывать callback.
Обработчик callback от АТОЛ
// local/api/atol-callback.php
$body = json_decode(file_get_contents('php://input'), true);
$uuid = $body['uuid'] ?? '';
$status = $body['status'] ?? ''; // 'done' | 'fail'
if ($status === 'done') {
$fiscalData = $body['payload']['fiscal_receipt_number'] ?? '';
$fnNumber = $body['payload']['fn_number'] ?? '';
$fnDocument = $body['payload']['fiscal_document_number'] ?? '';
// Сохраняем фискальные данные в заказ
saveAtolReceiptData($uuid, [
'fiscal_number' => $fiscalData,
'fn' => $fnNumber,
'fd' => $fnDocument,
'status' => 'done',
]);
} elseif ($status === 'fail') {
$error = $body['payload']['message'] ?? 'Unknown error';
logAtolError($uuid, $error);
// Ставим задачу в очередь на повтор
scheduleAtolRetry($uuid);
}
http_response_code(200);
echo 'OK';
Чек возврата
При возврате средств в АТОЛ нужно отправить чек возврата через метод /sell_refund (полный) или /sell_correction (корректировка). Структура идентична исходному чеку, но endpoint другой:
// Чек полного возврата
$atol->post(ATOL_GROUP_CODE . '/sell_refund', $payload);
// Чек частичного возврата — только возвращаемые позиции
// total и items содержат только возвращаемую часть
Кейс: магазин с 50+ SKU маркированного товара
Магазин одежды подключил АТОЛ Онлайн в 2023 году. Первоначально интеграция работала корректно, но после расширения ассортимента начались ошибки: часть позиций не имела номенклатурного кода из «Честного ЗНАКА».
Решение: при добавлении товара в каталог добавили обязательное поле «Код маркировки» (UF_MARKING_CODE). В момент отправки чека в АТОЛ — валидация наличия кода для маркированных категорий. Если код отсутствует — заказ переходит в статус «Требует проверки» и менеджер вводит код вручную перед фискализацией.
Это задержало автоматическую фискализацию для части заказов, но исключило штрафы за нарушение требований маркировки.
Сроки
| Задача | Срок |
|---|---|
| Установка и настройка официального модуля | 1–2 дня |
| Кастомная интеграция через API АТОЛ | 3–5 дней |
| Обработчик callback + очередь повторов | 1–2 дня |
| Чеки возврата | 1–2 дня |
| Тестирование в тестовой среде АТОЛ | 1–2 дня |







