Как правильно получить и обработать кириллицу в кодировке UTF-8 при работе с API МДЛП в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Работа с современными REST API, такими как система маркировки МДЛП (Честный ЗНАК), в среде 1С:Предприятие 7.7 часто сопровождается трудностями. Основная проблема заключается в том, что платформа 7.7 была создана задолго до повсеместного внедрения Unicode и «из коробки» работает только с кодировкой Windows-1251 (ANSI). В то же время все современные веб-сервисы обмениваются данными исключительно в UTF-8.

Типичная ситуация: программист отправляет запрос через WinHttp.WinHttpRequest.5.1, получает ответ (например, квитанцию об обработке документа), но вместо русских букв видит знаки вопроса «??????» или нечитаемые символы («кракозябры»). Рассмотрим подробнее, почему это происходит и как правильно решить проблему несколькими способами.

Выясняем причину: почему появляются знаки вопроса?

Проанализируем механизм работы объекта WinHttpRequest. Когда мы обращаемся к свойству ResponseText(), объект пытается самостоятельно определить кодировку ответа. Если сервер в HTTP-заголовках явно не указал charset=utf-8 (а МДЛП часто возвращает квитанции как application/octet-stream), WinHttp может ошибочно интерпретировать поток байтов как стандартную системную кодировку. В результате происходит необратимая потеря данных: символы, которые не входят в текущую кодовую страницу, заменяются знаками вопроса.

Разберем по шагам, какие инструменты нам понадобятся для корректной обработки данных.

Способ 1. Использование объекта Msxml2.ServerXMLHTTP

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


// Создаем объект, оптимизированный для работы с XML по HTTP
WinHttp = СоздатьОбъект("Msxml2.ServerXMLHTTP"); 
 WinHttp.Open("GET", СсылкаНаКвитанцию, 0);
 WinHttp.SetRequestHeader("Authorization", "token " + Токен);
 WinHttp.Send();

 Статус = WinHttp.Status;
 Если Статус = 200 Тогда
     // Использование ResponseText в этом объекте может сразу вернуть читаемую строку
     ТекстОтвета = WinHttp.ResponseText;
     Сообщить(ТекстОтвета);
 Иначе
     Сообщить("Ошибка запроса: " + Статус);
 КонецЕсли;

Однако даже этот метод не всегда гарантирует успех, если структура ответа сложная или сервер выдает бинарный поток. В таких случаях нужно переходить к ручному управлению кодировками.

Способ 2. Использование ADODB.Stream для перекодировки

Этот метод считается «золотым стандартом» для 1С 7.7. Вместо того чтобы просить объект запроса интерпретировать текст, мы забираем «сырые» бинарные данные через ResponseBody и передаем их в специальный буфер — ADODB.Stream, где явно указываем нужную нам кодировку UTF-8.

Важный нюанс: Не используйте перебор байтов в цикле для конвертации. Это крайне медленно и неэффективно. Правильно использовать встроенные методы объекта ADODB.Stream. Разберем алгоритм:

  1. Получаем данные от сервера в бинарном виде (WinHttp.ResponseBody).
  2. Загружаем их в ADODB.Stream с типом Type = 1 (бинарный).
  3. Меняем режим стрима на текстовый (Type = 2) и устанавливаем Charset = "utf-8".
  4. Считываем готовый текст в кодировке Windows-1251, которую понимает 1С 7.7.

Рассмотрим реализацию этой функции:


Функция ПреобразоватьИзУТФ8(БинарныеДанные)
    Стрим = СоздатьОбъект("ADODB.Stream");
    Стрим.Type = 1; // Устанавливаем бинарный режим
    Стрим.Open();
    Стрим.Write(БинарныеДанные); // Записываем ResponseBody
    
    Стрим.Position = 0; // Возвращаемся в начало
    Стрим.Type = 2;     // Переключаемся в текстовый режим
    Стрим.Charset = "utf-8"; // Указываем исходную кодировку
    
    Результат = Стрим.ReadText(); // Получаем строку в ANSI
    Стрим.Close();
    Возврат Результат;
КонецФункции

Теперь основной код получения квитанции будет выглядеть так:


WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
 WinHttp.Open("GET", СсылкаКвит, 0);
 WinHttp.SetRequestHeader("Authorization", "token " + токен);
 WinHttp.Send();

 Если WinHttp.Status = 200 Тогда
     // Получаем именно Body (бинарные данные), а не Text
     БинарныйОтвет = WinHttp.ResponseBody;
     ТекстКвитанции = ПреобразоватьИзУТФ8(БинарныйОтвет);
     
     // Теперь ТекстКвитанции содержит нормальный русский текст
     Сообщить(ТекстКвитанции);
 КонецЕсли;

Способ 3. Прямая загрузка в DOMDocument

Поскольку квитанции МДЛП представляют собой XML-документы, мы можем воспользоваться тем фактом, что парсер MSXML умеет самостоятельно определять кодировку, если в начале файла есть декларация encoding="UTF-8". Мы можем передать бинарные данные напрямую в объект DOMDocument, минуя строковые переменные 1С.

Проанализируем следующий пример:


WinHttp = СоздатьОбъект("Msxml2.ServerXMLHTTP");
 WinHttp.Open("GET", СсылкаКвит, 0);
 WinHttp.Send();

 Если WinHttp.Status = 200 Тогда
     ДокXML = СоздатьОбъект("Msxml2.DOMDocument");
     // Загружаем данные напрямую из свойства responseXML или responseBody
     ДокXML.load(WinHttp.responseBody); 
     
     // Теперь можно работать с узлами XML, кириллица будет корректной
     УзелКоммент = ДокXML.selectSingleNode("//operation_comment");
     Если ПустоеЗначение(УзелКоммент) = 0 Тогда
         Сообщить("Результат: " + УзелКоммент.text);
     КонецЕсли;
 КонецЕсли;

Рекомендации и важные замечания

1. Проверка заголовков: Всегда проверяйте, что возвращает сервер. Если в ответе указано Content-Type: application/octet-stream, WinHttpRequest.ResponseText почти наверняка исказит кириллицу. Используйте только бинарное чтение. 2. Обработка ошибок авторизации: В коде обязательно предусматривайте обработку статуса 401. Токены МДЛП имеют свойство истекать, и в этом случае вместо квитанции вы получите JSON с текстом ошибки. 3. Сохранение на диск: Если вам нужно сохранить полученную квитанцию в файл для последующего анализа, используйте метод SaveToFile объекта ADODB.Stream. Это позволит сохранить файл именно в UTF-8 (если нужно для внешних программ) или перекодировать его «на лету» в Windows-1251 для чтения в текстовом редакторе.

Подводя итог, можно сказать, что проблема «вопросиков» в 1С 7.7 при работе с API решается отказом от использования метода ResponseText в пользу ResponseBody с последующей обработкой через ADODB.Stream или MSXML.DOMDocument. Это обеспечивает стопроцентную сохранность кириллических символов и стабильную работу интеграции с системой МДЛП.

← На главную