Как распарсить текстовый лог Сбербанка с фрагментами XML в 1С

Программист 1С v8.3 (Управляемые формы) Управленческий учет Финансы и профессиональные услуги
← На главную

При интеграции с сервисами Сбербанка (например, P2P или эквайринг) разработчики часто сталкиваются с тем, что штатные утилиты обмена записывают результаты своей работы не в чистый XML-файл, а в текстовый лог. В таком файле служебная информация (дата, тип операции, разделители) перемешана с телом XML-запросов и ответов. Прямое использование объекта ЧтениеXML для такого файла невозможно, так как он не является валидным XML-документом с единым корнем.

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

Анализ структуры файла лога

Проанализируем типичную структуру лога, которую предоставляет Сбербанк. Обычно она выглядит следующим образом:

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

Метод 1: Построчное чтение и поиск маркеров

Рассмотрим наиболее надежный способ — чтение файла как текстового документа с поиском ключевых слов. Этот метод позволяет нам точно определить, где начинается и заканчивается XML-блок.

Для реализации этого метода используем объект ТекстовыйДокумент или ЧтениеТекста. Разберем пример кода, который выделяет XML-ответ из лога:


// Создаем объект для чтения файла
ТекстЛога = Новый ЧтениеТекста("C:\Logs\sber_log.txt", КодировкаТекста.UTF8);

СтрокаЛога = ТекстЛога.ПрочитатьСтроку();
НайденоНачалоXML = Ложь;
СтрокаXML = "";

Пока СтрокаЛога <> Неопределено Цикл
    
    // Если находим маркер ответа, начинаем собирать XML
    Если Найти(СтрокаЛога, ">>> ответ") > 0 Тогда
        НайденоНачалоXML = Истина;
        СтрокаЛога = ТекстЛога.ПрочитатьСтроку(); // Переходим к следующей строке, где начинается XML
    КонецЕсли;
    
    Если НайденоНачалоXML Тогда
        // Проверяем, не начался ли следующий блок лога (разделитель)
        Если Найти(СтрокаЛога, "***") > 0 Тогда
            НайденоНачалоXML = Ложь;
            // Здесь можно вызвать процедуру парсинга накопленной строки СтрокаXML
            РаспарситьБлокXML(СтрокаXML);
            СтрокаXML = "";
        Иначе
            СтрокаXML = СтрокаXML + СтрокаЛога;
        КонецЕсли;
    КонецЕсли;
    
    СтрокаЛога = ТекстЛога.ПрочитатьСтроку();
КонецЦикла;

Метод 2: Использование регулярных выражений (RegExp)

Если файл лога небольшой, мы можем прочитать его целиком в память и извлечь все блоки soap:Envelope с помощью регулярных выражений. Это более современный и лаконичный подход.

Выясним причину, почему регулярные выражения эффективны: они позволяют игнорировать текстовый "мусор" между тегами и сразу получать массив чистых XML-строк. Проанализируем пример кода:


// Читаем весь файл в строку
ТекстФайла = ПолучитьТекстИзФайла("C:\Logs\sber_log.txt");

RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;

// Шаблон ищет всё содержимое между тегами soap:Envelope
RegExp.Pattern = "(<soap:Envelope.*?</soap:Envelope>)";

Matches = RegExp.Execute(ТекстФайла);

Для Каждого Match Из Matches Цикл
    ТекущийXML = Match.Value;
    РаспарситьБлокXML(ТекущийXML);
КонецЦикла;

Парсинг извлеченного XML-блока

Когда мы выделили фрагмент XML в отдельную строку, мы можем использовать стандартный объект ЧтениеXML. Обратите внимание, что в логах Сбера данные часто передаются в виде атрибутов узлов.

Разберем, как прочитать данные из узла return, используя метод ПрочитатьАтрибут():


Процедура РаспарситьБлокXML(Знач ВходящаяСтрока)
    
    Чтение = Новый ЧтениеXML;
    Чтение.УстановитьСтроку(ВходящаяСтрока);
    
    Пока Чтение.Прочитать() Цикл
        
        // Нас интересует узел "return" (или "ns1:return")
        Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.ЛокальноеИмя = "return" Тогда
            
            // Получаем данные через атрибуты
            ИдентификаторЗаказа = Чтение.ПолучитьАтрибут("orderId");
            КодОшибки = Чтение.ПолучитьАтрибут("errorCode");
            ТекстОшибки = Чтение.ПолучитьАтрибут("errorMessage");
            
            Сообщить("Заказ: " + ИдентификаторЗаказа + ", Статус: " + ТекстОшибки);
            
        ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.ЛокальноеИмя = "formUrl" Тогда
            
            // Если данные внутри тега, читаем содержимое
            СсылкаНаОплату = Чтение.ПрочитатьСодержимоеКакСтроку();
            Сообщить("Ссылка: " + СсылкаНаОплату);
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Важные нюансы интеграции со Сбербанком

При работе с логами и API Сбера (платформа RBS) следует учитывать несколько критических моментов:

  1. Пространства имен (Namespaces): В логах часто встречаются префиксы soap: или ns1:. При использовании ЧтениеXML лучше ориентироваться на ЛокальноеИмя, чтобы избежать проблем с изменением префиксов в будущем.
  2. Кодировка: Логи Сбера обычно пишутся в UTF-8 без метки BOM. При чтении файла в 1С обязательно указывайте кодировку явно, иначе кириллица в сообщениях об ошибках (поле errorMessage) будет нечитаемой.
  3. Интерпретация статусов: Проанализируем типичные коды. Например, orderStatus="6" означает окончательный отказ в платеже, а actionCode="-2007" указывает на технический отказ со стороны банка. Успешный платеж обычно имеет статус 2.
  4. Данные 3D-Secure: В ответах может приходить поле paReq. Это длинная строка в формате Base64. Если вы парсите лог вручную, убедитесь, что не обрезаете ее, так как она необходима для перенаправления пользователя на страницу подтверждения банка.

Использование Фабрики XDTO (Альтернативный способ)

Если у вас есть XML-схема (XSD), предоставленная Сбербанком, процесс можно значительно упростить. Мы можем создать пакет XDTO в конфигурации и читать извлеченные строки одной командой:


// Предположим, схема загружена в пакет "SberPay"
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ИзвлеченнаяСтрокаXML);
ОбъектОтвета = ФабрикаXDTO.ПрочитатьXML(Чтение, ФабрикаXDTO.Тип("http://engine.paymentgate.ru/webservices/merchant", "registerOrderResponse"));

// Теперь данные доступны как свойства объекта
Сообщить(ОбъектОтвета.return.errorCode);

Посмотрим на ситуацию практически: использование ЧтениеXML в связке с простым строковым поиском маркеров является самым быстрым в реализации и устойчивым к изменениям форматов способом для разбора логов "на лету".

← На главную