Привет! На связи Илья, руководитель проектов, и Артем, TL Laravel в Webest. Расскажем о том, как мы построили обмен между интернет-магазином и 1С. Реализовали двусторонний обмен через очереди, ввели приоритеты для разных типов данных и сделали прозрачный мониторинг в админке Orchid.
Задача, подход и реализация
У нашего клиента два направления: B2C и крупный B2B-блок с отдельным оптовым каталогом, списками компаний и контрагентов. Поскольку продажи идут онлайн, офлайн и через партнеров, остатки постоянно меняются. Все данные изначально хранились в 1С, и соответственно, вся работа сотрудников осуществлялась там же.
Нужно было настроить обмен данными между сайтом и 1С, чтобы данные стабильно выгружались из 1С на сайт и загружались обратно. Мы не использовали штатный функционал, а реализовали обмен напрямую в базу данных через очереди: 1С отдаёт пакет данных сайту, сайт сразу обрабатывает его и записывает в БД.
Так система сама управляет процессами от выгрузки информации на сайт до загрузки новых контрагентов. Это закрыло большую часть рутинной работы сотрудников с контрагентами, заказами, остатками товаров, адресами доставки.
Что в себя включает интеграция с 1C:
двусторонний обмен списками контрагентов;
обмен остатками товара, ценами и номенклатурой в сторону сайта;
обмен деревом каталога (структурой каталога);
двусторонний обмен заказами (можно создать заказ в 1С, он появится на сайте и наоборот);
обмен налогами, типами налогов и налоговыми ставками с привязкой к конкретному товару и стране;
обмен складами в сторону сайта;
обмен типами кошельков, историей бонусного баланса в сторону 1С;
2 вспомогательных обмена: позволяют выгружать на сайт 1) списки клиентов и 2) списки товаров. Эти списки можно далее использовать при настройке акций и рекламных кампаний.
обмен списками желаемого количества товара в сторону 1С (после оформления заказа пользователем на сайте следом в 1C передается список желаемого количества продукции с привязкой к этому пользователю).
Реализовали такие важные функции, как проверку подлинности продукции (клиент вводит код на сайте, система сверяет его с базой) и статистику этих проверок для сотрудников (какой товар, кто и сколько раз проверял, с деталями по API, стране, устройству).

Также добавили сбор данных о желаемом количестве товаров. Клиент в каталоге набирает товар и рядом указывает, сколько бы хотел заказать — это позволяет анализировать спрос на виды продукции со стороны дистрибьюторов.
Логика обмена данными с 1С в Laravel проекте
Общая архитектура обмена
В проекте реализован двусторонний обмен данными между Laravel-приложением и 1С. Вся интеграция построена на принципах асинхронной обработки, надежности и прозрачности для обеих сторон. Система поддерживает как импорт данных из 1С, так и экспорт данных из приложения обратно в 1С.
Ключевые сущности обмена
Пакеты обмена — это логические группы данных, которые передаются между системами. Для каждого обмена (импорт/экспорт) создаются отдельные пакеты.
Объекты обмена — это отдельные сущности (например, пользователи, клиенты, заказы), которые входят в состав пакета. Каждый объект содержит XML-данные и дополнительную информацию (тип, статус, приоритет и т.д.).
Импорт данных из 1С
1С отправляет XML-файл (или архив с XML) на специальный API-эндпоинт Laravel-приложения. После получения файл сохраняется и создается новая запись о пакете импорта. Далее этот файл автоматически ставится в очередь на обработку.
В очереди происходит разбор XML-файла: каждый объект из файла выделяется и сохраняется в отдельную запись в таблице объектов импорта, где фиксируется его тип, XML-данные, приоритет и другие параметры. Таким образом, каждый объект из файла становится отдельной задачей для дальнейшей обработки.
Далее специальная консольная команда, которая запускается по расписанию (обычно каждую минуту), проверяет наличие необработанных пакетов импорта. Если такие есть, она берет их в работу, поочередно обрабатывает каждый объект, вызывая соответствующий метод сервиса импорта для каждого типа объекта. В результате обработки объекты либо создаются/обновляются в основной базе данных приложения, либо получают статус ошибки, если что-то пошло не так.
После обработки всех объектов в пакете система автоматически меняет статус пакета на успешный или ошибочный, в зависимости от результатов.
Структура данных импорта
Система использует две основные таблицы для хранения данных импорта:
import_files — пакеты импорта:
Schema::create('import_files', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable(); // Имя файла
$table->string('path')->nullable(); // Путь к файлу
$table->string('onec_id')->nullable(); // ID пакета в 1С
$table->string('base_onec')->nullable(); // База 1С
$table->integer('priority')->default(10); // Приоритет обработки
$table->integer('status')->default(0); // Статус пакета
$table->timestamps();
});
import_xml_objects — объекты импорта:
Schema::create('import_xml_objects', function (Blueprint $table) {
$table->id();
$table->foreignId('import_file_id') // ID пакета импорта
->constrained()
->onDelete('cascade');
$table->string('name'); // Тип объекта (Users, Clients, etc.)
$table->longText('xml_data'); // XML данные объекта
$table->integer('status')->default(0); // Статус обработки
$table->string('error_text')->nullable(); // Текст ошибки
$table->integer('priority')->default(500); // Приоритет обработки
$table->string('transport_id')->nullable(); // TransportID из 1С
$table->string('date_exchange')->nullable(); // Дата обмена
$table->integer('sql_id')->nullable(); // ID созданной записи в БД
$table->string('onec_id')->nullable(); // ID объекта в 1С
$table->timestamps();
});
Обработка объектов импорта
Команда WriteXmlObjectsToTables обрабатывает объекты импорта каждую минуту:
class WriteXmlObjectsToTables extends Command
{
protected $signature = 'write:xml_objects';
protected $description = 'Обработка и запись в таблицы xml объектов из таблицы import_xml_objects';
public function handle(ImportService $importService)
{
// Поиск файла для обработки
$importFile = ImportFile::where('status', ImportFile::IN_WORK_STATUS)->first();
if (!$importFile) {
$importFile = ImportFile::where('status', ImportFile::NEW_STATUS)
->orderBy('priority')
->first();
if ($importFile) {
$importFile->update(['status' => ImportFile::IN_WORK_STATUS]);
}
}
if ($importFile) {
// Получение необработанных объектов
$xmlObjects = $importFile->xmlObjects()
->where('status', ImportXmlObject::NEW_STATUS)
->orderBy('priority')
->limit(config('one_c.import.object_proc_limit'))
->get();
if ($xmlObjects->isNotEmpty()) {
foreach ($xmlObjects as $xmlObject) {
$methodName = 'import' . $xmlObject->name;
try {
if (method_exists($importService, $methodName)) {
// Обработка объекта через соответствующий метод
$resultData = $importService
->$methodName(new SimpleXMLElement($xmlObject->xml_data));
$xmlObject->update($resultData);
} else {
$xmlObject->update([
'status' => ImportXmlObject::CRITICAL_ERROR_STATUS,
'error_text' => 'Неизвестный xml объект',
]);
}
} catch (\Throwable $th) {
Log::channel('import_1c_error')
->error('Id xml объекта: ' . $xmlObject->id . ', Ошибка: ' . $th->getMessage());
$xmlObject->update([
'status' => ImportXmlObject::CRITICAL_ERROR_STATUS,
'error_text' => $th->getMessage(),
]);
}
}
}
// Проверка завершения обработки пакета
$noNewObjectsInImport = $importFile->xmlObjects()
->where('status', ImportXmlObject::NEW_STATUS)->doesntExist();
if ($noNewObjectsInImport) {
$hasErrors = $importFile->xmlObjects()
->where(fn($q) => $q
->orWhere('status', ImportXmlObject::ERROR_STATUS)
->orWhere('status', ImportXmlObject::CRITICAL_ERROR_STATUS)
)
->exists();
if ($hasErrors) {
$importFile->update(['status' => ImportFile::ERROR_STATUS]);
} else {
$importFile->update(['status' => ImportFile::SUCCESS_STATUS]);
}
}
}
}
}
Экспорт данных в 1С
Экспорт работает по схожему принципу, но инициируется изменениями в данных приложения. На ключевых моделях (например, Клиент, Пользователь, Заказ) установлены наблюдатели (Observers). Каждый раз, когда происходит создание или изменение таких объектов, наблюдатель формирует XML-описание объекта и создает новую запись в таблице объектов экспорта.
Когда 1С запрашивает новые данные для импорта, она обращается к специальному API-эндпоинту. В этот момент приложение формирует новый пакет экспорта, собирая все объекты, которые еще не были переданы в 1С, и объединяет их в один XML-файл. Этот файл возвращается 1С, а все объекты, вошедшие в пакет, получают статус «передано в 1С».
После обработки пакета на стороне 1С, она отправляет обратно файл-ответ с результатами обработки. Приложение разбирает этот файл, обновляет статусы объектов экспорта (например, «успешно обработано» или «ошибка»), чтобы эти объекты не попадали в новые пакеты экспорта.
Структура данных экспорта
export_files — пакеты экспорта:
Schema::create('export_files', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable(); // Имя файла
$table->string('path')->nullable(); // Путь к файлу
$table->integer('status')->default(0); // Статус пакета
$table->timestamps();
});
export_xml_objects — объекты экспорта:
Schema::create('export_xml_objects', function (Blueprint $table) {
$table->id();
$table->foreignId('export_file_id') // ID пакета экспорта
->nullable()
->constrained()
->onDelete('set null');
$table->string('type'); // Тип объекта (Users, Clients, Orders итд)
$table->longText('xml_data'); // XML данные объекта
$table->integer('status')->default(0); // Статус обработки
$table->string('error_text')->nullable(); // Текст ошибки
$table->integer('priority')->default(500); // Приоритет обработки
$table->integer('sql_id')->nullable(); // ID созданной записи в БД
$table->string('onec_id')->nullable(); // ID объекта в 1С
$table->unsignedTinyInteger('error_count')
->default(0); // Количество ошибок при попытках передачи
$table->timestamps();
});
Визуализация обмена в админ-панели Orchid
Вся логика обмена полностью прозрачна для администраторов через раздел «Обмен с 1С» в админ-панели Orchid. В этом разделе реализованы отдельные вкладки для импорта и экспорта, каждая из которых содержит:
1. Список пакетов — отображаются все пакеты обмена (импортные и экспортные), с указанием их статуса, времени создания, количества объектов, ошибок и другой служебной информации. Можно быстро увидеть, какие пакеты были успешно обработаны, а где возникли проблемы.


2. Список объектов — для каждого пакета можно посмотреть все входящие в него объекты. Для каждого объекта отображается его тип, статус обработки, идентификаторы, приоритет, а также текст ошибки (если она возникла).


3. Детализация — при необходимости можно открыть подробную информацию по каждому объекту или пакету, увидеть исходные XML-данные, историю изменений статусов, связанные ошибки.
4. Фильтрация и поиск — реализованы удобные фильтры по статусу, типу объекта, дате создания, что позволяет быстро находить нужную информацию даже при большом объеме данных.
5. Мониторинг статусов — администратор может в реальном времени отслеживать, какие объекты и пакеты находятся в работе, какие успешно обработаны, а какие требуют внимания.
Таким образом, админ-панель Orchid становится полноценным инструментом мониторинга и управления процессом обмена с 1С, позволяя оперативно реагировать на любые сбои или задержки.
Итоги
Все процессы построены на очередях и транзакциях, что исключает потерю данных.
Обработка идет пакетами, что позволяет работать с большими объемами данных.
Легко добавлять новые типы объектов для обмена.
Администратор всегда видит актуальное состояние обмена и может быстро найти причину любой проблемы.
Большинство процессов полностью автоматизированы, участие человека требуется только для мониторинга и анализа ошибок.
Система обмена с 1С в этом Laravel-проекте — это масштабируемый и прозрачный механизм, который обеспечивает синхронизацию данных между двумя системами и облегчает сопровождение интеграции.
Подробнее об управлении разработкой проектов читайте в тг-канале https://t.me/alexeyitru.
Комментарии (8)
Webest
10.09.2025 14:17Классная идея со сбором данных о желаемом количестве товаров, может сильно помочь в планировании продаж.
Zanbatist
10.09.2025 14:17Интересная статья, спасибо! Cразу возник практический вопрос: насколько сложно внедрить подобные практики (например, регулярные выражения для валидации) в уже существующий большой легаси-проект, где кодовая база не всегда идеальна? С чего лучше начать, чтобы не сломать то, что уже работает, и не вызвать сопротивление у команды?
AlexEp Автор
10.09.2025 14:17Спасибо за вопрос! В легаси-проектах главное — не пытаться внедрить всё сразу. Лучше идти маленькими шагами: выбрать один понятный кейс, обернуть его простыми тестами и добавить «мягкую» валидацию (сначала просто логировать ошибки, не ломая процесс).
Так команда видит, что изменения реально помогают, а не мешают. Со временем проверки можно сделать строже и расширить на другие участки кода. Такой постепенный подход снижает риски и сопротивление внутри команды.
Zippy
10.09.2025 14:17на практике - проблема в том что екомер уж боьнот разеый.
Редко удается отобразить данные как есть.
AlexEp Автор
10.09.2025 14:17Да, это так. В e-commerce почти никогда не получается отобразить данные «как есть». Почти всегда нужна прослойка, которая преобразует их под логику сайта и ожидания пользователей - маппинг, адаптеры, иногда даже своя модель каталога.
Isiirk
10.09.2025 14:17Как вы решаете задачу, если объект со ссылкой на другой объект приходит раньше, чем появляется ссылочный объект?
AlexEp Автор
10.09.2025 14:17Если объект ссылается на то, чего ещё нет, мы его не теряем, а сохраняем «в ожидании». Когда связанный объект приезжает, система достраивает связь. Если он так и не появился, то отмечаем ошибку и можно повторно запросить данные. Так порядок прихода уже не критичен.
AlexEp Автор
Если вы тоже сталкиваетесь с задачами интеграции 1С и e-commerce или думаете, как оптимизировать обмен данными в своем проекте, пишите нам.