Польза
Синхронизация с 1С/МойСклад

Синхронизация с 1С/МойСклад. Выгрузка заказов.

06 апреля 2020 года
Битрикс, , МойСклад, выгрузка, заказы, синхронизация.

При выгрузке заказов используется точка входа:
/bitrix/admin/1c_exchange.php. Точку входа можно (а иногда — необходимо) кастомизировать, в видео показан пример кастомизации. В примере для кастомизированных файлов используется папка /local/, что соответствует рекомендациям Битрикса.

Процедура забора заказов

При заборе заказов, адрес точки входа вызывается клиентом (1С, МойСклад) с параметром запроса type = sale и сигнал доходит до компонента bitrix:sale.export.1c, в котором происходит основная обработка запроса и подготовка ответа.

Все ответы представляют собой вывод в тело документа (в том числе трансляция тела собранного xml-документа), поведение внутри компонента зависит от параметра запроса mode.

В целом последовательность действий выглядит так:

1. Клиент запрашивает авторизацию.

Параметры запроса:
type=sale,
mode=checkauth.

Цель: получить идентификатор сессии.

Пример ответа сайта на запрос:
success
PHPSESSID
e50e721862288529b8073d4d4198e5ee
sessid=5e14d5c9f509631932efd8d7f3bc6fa2

2. Клиент запрашивает xml-документ

Параметры запроса:
type=sale
mode=query,
sessid=номер_сессии_полученный_на_предыдущем_шаге

Цель: получить xml, в котором содержится информация о заказах.

3. Клиент присылает уведомление об успешном завершении процедуры

Параметры запроса:
type=sale,
mode=success,
sessid=номер_сессии

Пример класса-хелпера

В видео использовался класс для накапливания логов.

Код класса
(файл: /bitrix/php_interface/include/AlexeyGfi/Sale1CExportHelper.php)

namespace AlexeyGfi;


use Bitrix\Main\Context;
use Bitrix\Main\Diag\Debug;

class Sale1CExportHelper
{

    public static function stepLog(&$data = null): void
    {

        if (!$data) {
            return;
        }

        $xmlFileInAnswer = false;

        // Если ответ содержит внутри xml-документ
        if (strpos($data, ' date('Y-m-d H:i:s'),
                'headers' => self::getHeaders(),
                'request' => $context->getRequest()->toArray(),
                'IP' => $context->getServer()->get('REMOTE_ADDR'),
                'innerSessid' => bitrix_sessid(),
                'answer' => $xmlFileInAnswer
                    ?: "\n============>\n" . $data
            ],
            '',
            '/upload/exchange_log/catalog_sync.log'
        );
    }

    protected static function getHeaders()
    {
        // Ключи, которые нам из заголовков не нужны
        $skipKeys = [
            'host', 'x-forwarded-proto',
            'x-forwarded-port', 'connection',
            'accept', 'cache-control',
            'pragma'
        ];

        $headersList = array_filter(
            Context::getCurrent()->getRequest()->getHeaders()->toArray(),
            static function ($key) use ($skipKeys) {
                return !\in_array($key, $skipKeys, true);
            }, ARRAY_FILTER_USE_KEY);

        return array_reduce(
            $headersList,
            static function ($carry, $item) {
                $carry[$item['name']] = implode(', ', $item['values']);
                return $carry;
            }, []);

    }

}

Код регистрации класса в автоподгрузчик:
(файл: /bitrix/php_interface/init.php)

\Bitrix\Main\Loader::registerAutoLoadClasses(
    null, [
    '\AlexeyGfi\Sale1CExportHelper' =>
        '/bitrix/php_interface/include/AlexeyGfi/Sale1CExportHelper.php'
]);

Пример использование лог-хелпера:
(файл: /bitrix/php_interface/init.php)

// Пример 1.
// Фиксируем в логе метку по ходу движения сигнала
//
// Метод хелпера принимает указатель,
// потому инициализируем переменную
$stepInfo = 'query enter';
\AlexeyGfi\Sale1CExportHelper::stepLog($stepInfo);

// Пример 2.
// Отдаём собранный контент:
\AlexeyGfi\Sale1CExportHelper::stepLog($contents);
            

Вспомогательные параметры

Главный движок, который формирует список отгружаемых заказов: метод $export::ExportOrders2Xml, который размещён в файле component.php компонента bitrix:sale.export.1c. Метод получает на вход кроме прочего массив $filter с параметрами для фильтрации и параметр $nTopCount. Модифицируя данные параметры нам представляется возможность повлиять на выгрузку со стороны Битрикса.

Смещение даты

$filter['>=DATE_UPDATE'] — параметр фильтрации, который инициализируется из параметра'last_export_time_committed_' . $curPage модуля sale. Модифицируя значение данного параметра мы можем повлиять на временную метку, от которой будет отталкиваться следующая выгрузка. Полезно при тестировании или если нужно откатиться на какое-то время назад и повторить выгрузку каких-то заказов.

Размер порции выгрузки

$nTopCount — ограничение размера выгрузки, то есть максимальное количество заказов, которые будут отгружены за один запрос. Параметр с нужной настройкой следует проинициализировать до вызова $export::ExportOrders2Xml(...). В видео продемонстрирован пример ограничения размера выгрузки пятью заказами.

Обсуждение статьи 2

Написать
Аноним
пример файла хелпера покоцанный. явно чегото там не хватает
Ответить
Павел
В хелпере остуствует часть метода stepLog.

Я дописал метод. Публикую сюда.

public static function stepLog(&$data = null): void
{

if (!$data) {
return;
}

$xmlFileInAnswer = false;

// Если ответ содержит внутри xml-документ
if (strpos($data, '<?xml version') !== false) {
$xmlFileInAnswer = '/upload/exchange_log' . 'xml_' . date('Y-m-d_H-i-s') . 'xml';

$fp = fopen($_SERVER['DOCUMENT_ROOT'] . $xmlFileInAnswer, 'wb');
fwrite($fp, $data);
fclose($fp);
}

$context = Context::getCurrent();

Dubug::writeToFile(
[
'date' => date('Y-m-d H:i:s'),
'headers' => self::getHeaders(),
'request' => $context->getRequest()->toArray(),
'IP' => $context->getServer()->get('REMOTE_ADDR'),
'innerSessid' => bitrix_sessid(),
'answer' => $xmlFileInAnswer ?: "\n============>\n" . $data
],
'',
'/upload/exchange_log/catalog_sync.log'
);
}
Ответить
Написать