Интеграция устаревшей платформы 1С:Предприятие 7.7 с современными веб-сервисами часто вызывает сложности. Одной из самых распространенных проблем является несоответствие кодировок. Платформа 7.7 работает с однобайтовой кодировкой (обычно Windows-1251), в то время как современные REST API (включая Wildberries) отдают данные в формате JSON в кодировке UTF-8. В этой статье мы подробно разберем, почему при использовании стандартных методов возникают "кракозябры" и как корректно получить читаемый текст ответа.
Рассмотрим стандартный подход, который используют разработчики при написании HTTP-запросов в 1С 7.7. Обычно для этого применяется OLE-объект WinHttp.WinHttpRequest.5.1. При получении ответа многие обращаются к свойству ResponseText.
В этом кроется корень проблемы:
ResponseText пытается интерпретировать эти байты, используя текущую системную кодовую страницу (CP1251).РђР±РІ).Accept-Charset: windows-1251) обычно не помогает, так как современные API игнорируют эти требования и всегда отвечают в UTF-8.Проанализируем два основных способа решения этой задачи: с использованием внешней компоненты (как было предложено в обсуждении) и с использованием штатных средств Windows.
В обсуждении на форуме участники пришли к выводу, что эффективным методом является использование внешней компоненты, которая позволяет сохранить "сырой" ответ сервера (raw response) напрямую в файл, минуя механизм преобразования строк внутри 1С 7.7.
Компонента curl1c.dll (также известная как "Карлик") — это обертка над популярной библиотекой cURL. Ее преимущество в том, что она позволяет указать тип приемника данных как "Файл". В этом случае байты записываются на диск как есть, без попытки их прочитать как строку.
Разберем рабочий пример кода, который позволяет получить список карточек товаров с Wildberries и сохранить корректный JSON в файл.
Алгоритм действий:
1 (Файл).Пример кода для 1С 7.7:
РезФайл = "e:\out.txt"; // Путь, куда сохраним ответ
АдресЗапроса = "https://content-api.wildberries.ru/content/v2/get/cards/list";
// Формируем тело запроса (JSON)
ТелоЗапр = "{ ""settings"": { ""cursor"": {""limit"": 100 }, ""filter"": {""withPhoto"": -1}}}";
Authorization = "Ваш_Токен_Авторизации";
// Загрузка компоненты
ЗагрузитьВнешнююКомпоненту("curl1c.dll");
Карлик = СоздатьОбъект("Карлик");
// Настройка приемника данных
Приемник = Карлик.Приемник;
Приемник.Тип = 1; // 1 означает запись в файл
Приемник.Данные = РезФайл;
// Настройка параметров запроса
Карлик.УстановитьПараметр("URL", АдресЗапроса);
Карлик.УстановитьПараметр("CUSTOMREQUEST", "POST");
// Важно: для JSON используем Content-Type application/json.
// Хотя в обсуждении упоминался xml, для JSON API это некорректно,
// но сервер может простить ошибку. Лучше писать правильно:
Карлик.УстановитьПараметр("HTTPHEADER", "Content-Type: application/json; charset=UTF-8");
Карлик.УстановитьПараметр("HTTPHEADER", "Authorization: " + Authorization);
// Передача тела запроса
Карлик.Источник.Данные = ТелоЗапр;
// Выполнение
КодВозврата = Карлик.Выполнить();
Если КодВозврата = 0 Тогда
Сообщить("Запрос выполнен успешно. Ответ в файле " + РезФайл);
Иначе
Сообщить("Ошибка выполнения запроса: " + КодВозврата);
КонецЕсли;
После выполнения этого кода у вас на диске появится файл out.txt в кодировке UTF-8, который будет содержать корректные данные. Далее этот файл можно прочитать средствами, понимающими UTF-8, или перекодировать.
Если вы не хотите или не можете использовать сторонние DLL (например, из соображений безопасности или сложности администрирования), задачу можно решить стандартными объектами Windows, доступными через OLE. Этот метод является архитектурно более чистым.
Идея заключается в следующем: мы используем WinHttp, но забираем не ResponseText, а ResponseBody (массив байтов). Затем с помощью объекта ADODB.Stream мы конвертируем этот массив в строку, явно указав кодировку UTF-8.
Разберем реализацию этого метода:
Функция ПолучитьДанныеWB(Адрес, Токен, ТелоJson)
// 1. Отправка запроса
WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("POST", Адрес, 0); // 0 - синхронный режим
WinHttp.SetRequestHeader("Content-Type", "application/json; charset=utf-8");
WinHttp.SetRequestHeader("Authorization", Токен);
// Некоторые API требуют указывать Locale, но это опционально
// WinHttp.SetRequestHeader("locale", "ru");
Попытка
WinHttp.Send(ТелоJson);
Исключение
Сообщить("Ошибка отправки запроса: " + ОписаниеОшибки());
Возврат "";
КонецПопытки;
Если WinHttp.Status <> 200 Тогда
Сообщить("Ошибка сервера: " + WinHttp.Status + " " + WinHttp.StatusText);
// Можно попытаться прочитать текст ошибки тем же способом ниже
КонецЕсли;
// 2. Получение бинарных данных
// Важно использовать именно ResponseBody, а не ResponseText
БинарныйОтвет = WinHttp.ResponseBody;
// 3. Конвертация UTF-8 -> Строка 1С (Windows-1251)
Stream = СоздатьОбъект("ADODB.Stream");
Stream.Type = 1; //adTypeBinary
Stream.Mode = 3; //adModeReadWrite
Stream.Open();
Stream.Write(БинарныйОтвет);
Stream.Position = 0;
Stream.Type = 2; //adTypeText
Stream.Charset = "utf-8"; // Указываем исходную кодировку данных
// Читаем уже раскодированный текст.
// ADO сам преобразует UTF-8 в текущую системную кодировку
ТекстОтвета = Stream.ReadText();
Stream.Close();
Возврат ТекстОтвета;
КонецФункции
Преимущества этого метода:
После того как мы получили строку с правильной кодировкой (любым из способов), возникает задача разобрать JSON (парсинг). Поскольку в 1С 7.7 нет встроенного объекта ЧтениеJSON, удобно использовать MSScriptControl.ScriptControl.
Пример разбора ответа:
ТекстОтвета = ПолучитьДанныеWB(...); // Используем функцию из Способа 2 или читаем файл
ScriptControl = СоздатьОбъект("MSScriptControl.ScriptControl");
ScriptControl.Language = "JScript";
Попытка
// Добавляем код для создания объекта из JSON-строки
// Оборачиваем eval в скобки, чтобы корректно обработать JSON
ОбъектJSON = ScriptControl.Eval("(" + ТекстОтвета + ")");
// Теперь можно обращаться к полям JSON как к свойствам объекта
// Учитывайте структуру ответа WB. Например, cards - это массив.
МассивКарточек = ОбъектJSON.cards;
Количество = МассивКарточек.length;
Для Индекс = 0 По Количество - 1 Цикл
// Получаем конкретную карточку по индексу
Карточка = МассивКарточек.Result(Индекс); // В JScript доступ по индексу через массив[i], но через OLE надежнее методы коллекции, если доступны, или Eval
// Либо через вспомогательную функцию в ScriptControl:
// ScriptControl.ExecuteStatement("var card = obj.cards[" + Индекс + "];");
// Более простой вариант перебора через Enumerator JScript внутри самого скрипта,
// но для простых задач можно вытаскивать поля точечно:
Наименование = ScriptControl.Eval("cards[" + Индекс + "].title");
Артикул = ScriptControl.Eval("cards[" + Индекс + "].vendorCode");
Сообщить("Товар: " + Наименование + ", Артикул: " + Артикул);
КонецЦикла;
Исключение
Сообщить("Ошибка разбора JSON: " + ОписаниеОшибки());
КонецПопытки;
Проблема "кракозябр" при работе с Wildberries API в 1С 7.7 связана исключительно с неверной интерпретацией UTF-8 как ANSI. Решить её можно либо сохранением данных в файл через специализированные компоненты (curl1c), либо использованием связки WinHttp.ResponseBody и ADODB.Stream для корректного декодирования в памяти. Второй способ является более универсальным и не требует установки дополнительного ПО.