Работа с современными 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 может ошибочно интерпретировать поток байтов как стандартную системную кодировку. В результате происходит необратимая потеря данных: символы, которые не входят в текущую кодовую страницу, заменяются знаками вопроса.
Разберем по шагам, какие инструменты нам понадобятся для корректной обработки данных.
Одним из самых простых решений, как было замечено в обсуждении, является замена стандартного объекта запроса. Объект Msxml2.ServerXMLHTTP зачастую более корректно обрабатывает текстовые потоки в формате XML. Посмотрим на пример кода:
// Создаем объект, оптимизированный для работы с XML по HTTP
WinHttp = СоздатьОбъект("Msxml2.ServerXMLHTTP");
WinHttp.Open("GET", СсылкаНаКвитанцию, 0);
WinHttp.SetRequestHeader("Authorization", "token " + Токен);
WinHttp.Send();
Статус = WinHttp.Status;
Если Статус = 200 Тогда
// Использование ResponseText в этом объекте может сразу вернуть читаемую строку
ТекстОтвета = WinHttp.ResponseText;
Сообщить(ТекстОтвета);
Иначе
Сообщить("Ошибка запроса: " + Статус);
КонецЕсли;
Однако даже этот метод не всегда гарантирует успех, если структура ответа сложная или сервер выдает бинарный поток. В таких случаях нужно переходить к ручному управлению кодировками.
Этот метод считается «золотым стандартом» для 1С 7.7. Вместо того чтобы просить объект запроса интерпретировать текст, мы забираем «сырые» бинарные данные через ResponseBody и передаем их в специальный буфер — ADODB.Stream, где явно указываем нужную нам кодировку UTF-8.
Важный нюанс: Не используйте перебор байтов в цикле для конвертации. Это крайне медленно и неэффективно. Правильно использовать встроенные методы объекта ADODB.Stream. Разберем алгоритм:
WinHttp.ResponseBody).ADODB.Stream с типом Type = 1 (бинарный).Type = 2) и устанавливаем Charset = "utf-8".Рассмотрим реализацию этой функции:
Функция ПреобразоватьИзУТФ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(БинарныйОтвет);
// Теперь ТекстКвитанции содержит нормальный русский текст
Сообщить(ТекстКвитанции);
КонецЕсли;
Поскольку квитанции МДЛП представляют собой 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. Это обеспечивает стопроцентную сохранность кириллических символов и стабильную работу интеграции с системой МДЛП.