Как работает обмен Битрикс с 1С. Часть 1
Эта вводная часть об устройстве обмена между 1С-Битрикс и 1С, настройке, ошибках и отладке. Информация взята из онлайн-вебинара, автор которого Гелейшев Павел. Всего планируется несколько частей, т.к. объем материала достаточно большой.
Существует 5 типов обмена:
- Импорт каталога (в т.ч. остатки и цены) из 1С в Битрикс
- Экспорт каталога из Битрикс в 1С
- Обмен документами (заказы, оплаты, отгрузки)
- Обмен пользовательскими справочниками
- Обмен контрагентами
Импорт товаров из Битрикс в 1С используется единоразово, когда к уже существующему сайту подключают пустую 1С. Так же редко используются обмен справочниками и контрагентами, поэтому для начала рассмотрим импорт каталога и обмен документами.
Версии модулей
Старые версии обмена. (ниже 4.x)
- не требуют отдельной установки в 1С;
- у них ограниченный функционал по сравнению с новыми модулями;
- компания 1С-Битрикс официально уже не поддерживает данные модули и заявляет о их неработоспособности, но на практике данные модули еще встречаются и, хоть как, но работают.
Новые версии обмена. (4.x, 5.x, 6.x, 7.x)
- устанавливаются отдельно в 1С;
- умеют автоматически обновляться;
- под каждую версию 1С необходим свой модуль обмена.
Документация по модулям: https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=131&CHAPTER_ID=06315&LE...
Инициализация обмена
Обмен, какого бы типа он не был, всегда инициализирует 1С. Сайт не имеет доступа к 1С и никак не может к ней обратиться.
Точка входа:
/bitrix/admin/1c_exchange.php (для импорта каталога - /bitrix/admin/1c_import.php)
По умолчанию, если ничего не кастомизировано, все свои запросы 1С отправляет именно по этому адресу.
Рассмотрим по шагам как происходит обмен информацией (на примере обмена каталогом).
Шаг 1: авторизация
Для начала 1Ске необходимо авторизоваться на сайте, для этого она отправляет get запрос на страницу:
/bitrix/admin/1c_exchange.php?type=catalog&mode=checkauth
Где параметр type зависит от типа обмена: catalog - для обмена товарами, sale - для обмена документами. Параметр mode равный checkauth это как раз и есть попытка авторизоваться.
Вместе с этим, методом post 1Cка отправляет логин и пароль пользователя сайта под которым она авторизуется. Этого пользователя специально добавляют на сайте для 1С. Чаще всего его делают администратором с полными правами. Но будет правильнее ограничивать данного пользователя в правах и помещать его в отдельную группу, предоставляя только те права, которые необходимы для обмена. Логин и пароль пользователя вносится в 1С, в настройки модуля обмена.
На запрос авторизации, сайт отвечает строкой вида:
success PHPSESSID kLv28pH4X0XpW91T4wg28YeY7DwZZXnz
sessid=7f8ec88162e001fdccabfdd202653fc6 timestamp=1614319624
Где success означает что авторизация прошла успешно. Если вместо success будет fail, либо что-то еще, то 1С выдаст ошибку и обмен прекратится. Параметр sessid это идентификатор сессии, значение которого 1C будет добавлять в каждый следующий запрос обмена. Так сайт понимает, что полученные запросы именно от этой 1Ски и запоминает последнюю операцию обмена.
Шаг 2: инициализация
На этом шаге 1С делает запрос на страницу
/bitrix/admin/1c_exchange.php?type=catalog&mode=init&sessid=7f8ec88162e001fdccabfdd202653fc6&version=2.10
Где в параметре mode передаётся init, а в sessid передаётся значение идентификатора сессии, полученное на прошлом шаге. Помимо этого в параметре version указывается версия схемы обмена. На данный момент самая последняя версия это 2.10. Версия передаётся из-за того, что в разных модулях для 1С, схема обмена реализована с отличиями, поэтому сайту необходимо понимать по какой схеме будет происходить обмен.
Получив запрос на инициализацию, сайт очищает все папки с файлами от предыдущего обмена и отвечает 1Ске строкой с настройками обмена:
zip=yes file_limit=204800
Параметр zip равный yes, что означает у сайта есть библиотека для работы с zip архивом. 1С в данном случае будет отправлять файлы в zip архивах. Это экономит время для передачи файлов. В противном случае (zip=no) 1С будет отправлять XML файлы в открытом виде.
В параметре file_limit сайт указывает максимальный размер одного файла. Значение этого параметра задаётся в настройках обмена на сайте. В случае если файл будет большего размера, то 1С разобьёт его на несколько частей и будет передавать его, соответственно, за несколько запросов. Это необходимо для того что бы не сработало ограничение по размеру файлов загружаемых на сервер сайта.
Шаг 3: отправка файла
1С методом post отправляет тело файла по адресу:
/bitrix/admin/1c_exchange.php?type=catalog&mode=file&filename=1c_catalog.xml&sessid=7f8ec88162e001fdccabfdd202653fc6
Параметр mode устанавливается в значение file, а в параметре filename передаётся имя файла. Сайт сохраняет загружаемые файлы в папку /upload/1c_catalog/ (для обмена товарами), либо /upload/1c_exchange/ (для обмена заказами). Имя файла берется из параметра filename, т.е. именно 1С задает название файла обмена под которым сайт сохраняет его у себя.
Запрос на отправку файлов может повторяться несколько раз, например в случае если файл был разбит 1Ской на несколько частей. На каждый запрос сайт отвечает строкой:
success
Если в ответе будет что-то другое, то обмен прервётся с ошибкой.
После того как файл будет получен полностью, начинается сам процесс импорта.
Шаг 4: начало обмена
Для этого 1С отправляет запрос на страницу:
/bitrix/admin/1c_exchange.php?type=catalog&mode=import&filename=1c_catalog.xml&sessid=7f8ec88162e001fdccabfdd202653fc6
Где для параметра mode указывает значение import и повторно в параметре filename указывает имя файла.
В это время сайт находит нужный файл с указанным именем у себя в папке обмена и начинает импорт. Импорт выполняется в несколько шагов. На процесс импорта 1С уже никак не влияет, она лишь отправляет запросы повторно с mode=import до тех пока пока операция импорта не завершится. В ответ на каждый запрос она получает строку вида:
progress Временные таблицы созданы.
progress Файл импорта прочитан.
progress Обработано 1 из 1 элементов.
Если в строке есть значение progress, то 1С повторяет запрос и будет повторять до тех пор пока не получит ответ:
success Импорт успешно завершен.
Сам процесс импорта несколько необычен в 1С-Битрикс. Скрипт импорта не работает с xml напрямую (с помощью стандартных библиотек php), а создает в базе данных пустую таблицу b_xml_tree (предварительно очистив) и, построчно считывая xml файл импорта, заносит данные в созданную таблицу. После того как файл будет полностью перенесён во временную таблицу, скрипт импорта начинает обрабатывать данные и вносить изменения в БД сайта (например создаёт группы, товары и т.п.)
После того, как импорт файла будет завершён, запускается процесс деактивации разделов и элементов каталога.
Шаг 5: деактивация
Для того что бы файл импорта не разрастался, в выгрузку из 1С добавляют только доступные товары, которые должны быть на сайте, соответственно сайт должен убрать все неактуальные товары.
Процесс деактивации отличается в разных версиях модуля обмена:
-
в старых версиях деактивация происходила на 4-ем шаге (в момент импорта xml, настройки хранились на сайте),
-
в последних версиях деактивация происходит на отдельном шаге (настройки уже хранятся в 1С)
Деактивация происходит только при полном обмене. Для деактивации 1С отправляет запрос на страницу:
/bitrix/admin/1c_exchange.php?type=catalog&mode=deactivate×tamp=1614319624&sessid=7f8ec88162e001fdccabfdd202653fc6
Где параметр mode равен deactivate, а так же указывается timestamp, значение которого 1С получала на первом шаге. timestamp это время начала обмена, по нему сайт ищет все товары, у которых время модификации меньше чем значение в timestamp и деактивирует их. Логика такая: все товары, которые были изменены после времени начала обмена - считаются что они были в xml импорта, а все остальные - нет.
Тут есть особенность, если в момент импорта каталога какие-либо товары были изменены (администратором, скриптом выполняющимся на cron и т.п.), то 1С-Битрикс не поймет, были они в импорте или нет. Такие товары не будут деактивированы, даже если их не было в обмене. Это особенно актуально для больших сайтов, где обмен выполняется очень долго.
При использовании нового модуля обмена, деактивация зависит только от настроек в 1С, настройки в 1С-Битрикс не работают.
Обмен заказами
Обмен заказами (выгрузка из 1С на сайт) идёт по той же самой схеме. Только в параметр mode передаётся значение sale, а сохранение файла происходит в папку /upload/1c_exchange/.
Для экспорта заказов в 1С используется запрос:
/bitrix/admin/1c_exchange.php?type=sale&mode=query&sessid=f5b5d96716e0afb60beec6f1455972d4
В ответ сайт отдаёт XML с заказами, которые были как-либо изменены с даты последнего обмена. Для этого сайт записывает дату и время последнего обмена. Время сохраняется в таблицу b_option, строка last_export_time_committed_/bitrix/admin/1c_excha.
При последующих запросах сайт отдаёт все заказы, в которых дата и время изменения новей, чем дата последнего обмена.
Например, если по какой-либо причине не выгрузился определённый заказ, то достаточно зайти в редактирование этого заказа и нажать "Сохранить". Тогда у заказа изменится дата редактирования и при следующем обмене он попадёт в выгрузку.
Так же можно сбросить время в last_export_time_committed, тогда в xml попадут все заказы. Пример кода для сброса:
\Bitrix\Main\Config\Option::set("sale", "last_export_time_committed_/bitrix/admin/1c_excha", "");
Если обмен завершается с ошибкой
Например при запросе:
/bitrix/admin/1c_exchange.php?type=catalog&mode=import&filename=1c_catalog.xml&sessid=7f8ec88162e091fdccabfdd202653fc6
1C ожидает получить строку, например:
progress Файл импорта прочитан.
А получает: "DB query error"
В этом случае обмен закончится с ошибкой, и для того чтобы понять в чем именно дело необходимо смотреть логи обмена. 1С логирует весь процесс обмена. Путь для хранения лога настраивается внутри модуля 1С.
Так же есть галочка "Выгружать лог на сайт", в этом случае, после окончания обмена, 1С отправит логи на сайт. Но проблема в том, что если сайт при обмене падает с ошибкой, то логи 1С отправить не сможет.
Пример лога обмена 1С
В лог записываются, как действия самой 1С (например "Формирование пакета для общих данных для товаров"), так и то, что возвращает сайт (например "Процесс выполнения обмена: Временные таблицы удалены"). Для того, чтобы сайт возвращал более полные данные по ошибке, а не заглушку "DB query error", необходимо включить режим вывода расширенных ошибок:
$DBDebug = true; // в dbconn.php exception_handling - debug => true // в .settings.php
После этого необходимо повторить обмен. В логах уже будет описана конкретная ошибка, например:
Table 'sv22.b_xml_tree' doesn't exist
...
Сan't create table 'b_xml_tree' (errno: -1)
...
MySQL Query Error: create table b_xml_tree_import_1c
Ошибка по таблице b_xml_tree возникает из-за того, что скорее всего было запущено несколько обменов одновременно. В битрикс процесс устроен так, что может идти одновременно только один обмен, т.к. запись происходит в таблицу b_xml_tree, которая очищается вначале каждого обмена. Т.е. при запуске второго обмена, таблица очистится и первый процесс обмена получит ошибку, т.к. таблицы уже не существует.
Очень часто это возникает из-за того, что подключают дополнительно тестовую 1С и забывают в ней отключить периодический обмен. И две 1С (боевая и тестовая) одновременно шлют запросы на обмен.
Так же случается, если настроен автоматический обмен по расписанию и примерно в это же время запускается ручной обмен.
В зависимости от настроек в 1С, даже при получении ошибки, 1С может попытаться продолжить процесс обмена. Но результат такого обмена непредсказуем, поэтому если в логе есть ошибки, то с ними необходимо разбираться.
Бонус для дочитавших
Когда необходимо посмотреть что же конкретно присылает 1С в xml, приходится запрашивать файлы выгрузки (1С хранит их локально), но это долго и неудобно.
Для решения этой задачи есть волшебная константа:
define("BX_CATALOG_IMPORT_1C_PRESERVE", true); // в dbconn.php
После её установки битрикс перестаёт удалять файлы обмена и сохраняет их в папки
/upload/1c_catalog0/
/upload/1c_catalog1/
...
/upluad/1c_catalogNNN/
Важно! После отладки обязательно убирайте константу, иначе место на сервере быстро закончится.
Есть вопросы или нашли ошибку? Напишите комментарий (можно без регистрации), отвечать стараюсь быстро.