Как правильно рассчитать MD5 хеш-сумму и передать её в JSON-запросе в 1С

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

При интеграции 1С с внешними веб-сервисами (интернет-магазины, службы доставки, платежные шлюзы) часто возникает задача формирования POST-запроса, защищенного цифровой подписью. Обычно подпись представляет собой MD5-хеш от тела запроса, объединенного с секретным ключом API. В процессе реализации этой задачи программисты 1С часто сталкиваются с ошибками типизации при записи JSON и несоответствием итоговой контрольной суммы на стороне сервера. В этой статье мы подробно разберем, как правильно подготовить данные, рассчитать хеш и сформировать корректный JSON.

Разбор ошибки: Передано значение недопустимого типа

Первая проблема, с которой мы можем столкнуться, возникает при использовании метода ЗаписатьJSON. Если мы попытаемся передать объект хеширования напрямую в структуру запроса, платформа выдаст ошибку: "Передано значение недопустимого типа". Проанализируем причину ситуации. Объект ХешированиеДанных.ХешСумма возвращает значение типа ДвоичныеДанные, в то время как формат JSON ожидает простую строку (String). 1С не выполняет автоматическое приведение этого сложного объекта к строке Hex-формата внутри метода сериализации.

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

Способ 1: Получение шестнадцатеричной строки (классический метод)

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


ХешированиеДанных = Новый ХешированиеДанных(ХешФункция.MD5);
ХешированиеДанных.Добавить(СтрокаJSON_Запрос + api_ключ);

// Приводим к строке, переводим в нижний регистр и удаляем пробелы
ХешСтрока = СтрЗаменить(НРег(СокрЛП(ХешированиеДанных.ХешСумма)), " ", "");
СтруктураPOST_Запрос.Вставить("sign", ХешСтрока);

Важное замечание: Метод XMLСтрока(ХешированиеДанных.ХешСумма), который иногда предлагают на форумах, в данном случае может работать некорректно. Он предназначен для сериализации в формат Base64, тогда как большинство API требуют именно Hex-представление (шестнадцатеричный код).

Способ 2: Использование современных функций платформы (рекомендуется)

Начиная с версии 8.3.10, в 1С появилась специализированная функция ПолучитьГексадецимальнуюСтрокуИзДвоичныхДанных(). Рассмотрим более надежный и производительный вариант реализации:


ХешированиеДанных = Новый ХешированиеДанных(ХешФункция.MD5);
ХешированиеДанных.Добавить(СтрокаJSON_Запрос + api_ключ);

// Получаем чистую Hex-строку без лишних манипуляций
ХешСтрока = НРег(ПолучитьГексадецимальнуюСтрокуИзДвоичныхДанных(ХешированиеДанных.ХешСумма));
СтруктураPOST_Запрос.Вставить("sign", ХешСтрока);

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

Проблема кодировки при расчете хеша

Выясним еще одну важную причину, по которой сервер может отклонять запрос: несовпадение кодировок. По умолчанию строки в 1С хранятся в формате UTF-16. Если мы просто складываем СтрокаJSON + API_Ключ, метод Добавить() объекта хеширования будет обрабатывать их как UTF-16. Однако 99% внешних систем ожидают, что хеш был вычислен на основе строки в кодировке UTF-8.

Для решения этой проблемы преобразуем строку в двоичные данные перед хешированием:


СтрокаДляПодписи = СтрокаJSON_Запрос + api_ключ;
// Явно указываем кодировку UTF-8
ДанныеДляХеша = ПолучитьДвоичныеДанныеИзСтроки(СтрокаДляПодписи, КодировкаТекста.UTF8, Ложь);

ХешированиеДанных = Новый ХешированиеДанных(ХешФункция.MD5);
ХешированиеДанных.Добавить(ДанныеДляХеша);
Подпись = НРег(ПолучитьГексадецимальнуюСтрокуИзДвоичныхДанных(ХешированиеДанных.ХешСумма));

Формирование сложной структуры JSON

Проанализируем ситуацию, когда необходимо вложить один JSON-объект в другой (Stringified JSON). Часто API требует, чтобы основное тело запроса передавалось в поле request в виде строки, а рядом лежала подпись sign. Посмотрим на правильный алгоритм сборки такого запроса:

  1. Сначала формируем внутреннюю структуру (бизнес-данные: заказы, товары, клиенты).
  2. Сериализуем её в строку JSON.
  3. Используем эту строку для расчета хеша.
  4. Создаем финальную структуру, куда помещаем и строку JSON, и полученный хеш.

Разберем это на практическом примере кода:


// 1. Создаем внутренние данные
СтруктураЗаказа = Новый Структура;
СтруктураЗаказа.Вставить("product_order", "55555");
СтруктураЗаказа.Вставить("contact", "Иванов");

МассивПараметры = Новый Массив;
МассивПараметры.Добавить(СтруктураЗаказа);

ОбъектЗапроса = Новый Структура;
ОбъектЗапроса.Вставить("method", "create");
ОбъектЗапроса.Вставить("parameters", МассивПараметры);

// 2. Сериализуем внутренний объект в компактную строку
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет); // Убираем переносы для точности хеша
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON);
ЗаписатьJSON(ЗаписьJSON, ОбъектЗапроса);
СтрокаВнутреннийJSON = ЗаписьJSON.Закрыть();

// 3. Считаем подпись
ДанныеДляХеша = ПолучитьДвоичныеДанныеИзСтроки(СтрокаВнутреннийJSON + api_ключ, КодировкаТекста.UTF8, Ложь);
Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
Хеширование.Добавить(ДанныеДляХеша);
Подпись = НРег(ПолучитьГексадецимальнуюСтрокуИзДвоичныхДанных(Хеширование.ХешСумма));

// 4. Собираем итоговый пакет для отправки
ИтоговаяСтруктура = Новый Структура;
ИтоговаяСтруктура.Вставить("request", СтрокаВнутреннийJSON);
ИтоговаяСтруктура.Вставить("sign", Подпись);

ЗаписьФинальная = Новый ЗаписьJSON;
ЗаписьФинальная.УстановитьСтроку();
ЗаписатьJSON(ЗаписьФинальная, ИтоговаяСтруктура);
РезультатЗапроса = ЗаписьФинальная.Закрыть();

Управление спецсимволами и форматированием

Важно обратить внимание на параметр ПереносСтрокJSON.Нет. Если при записи JSON платформа 1С добавит символы переноса строки (\r\n) или лишние пробелы для красоты (Pretty print), то MD5-хеш от такой строки будет отличаться от хеша "чистой" строки. Большинство веб-серверов при проверке подписи ожидают именно компактный JSON без лишних пробельных символов.

Также помните, что при вложении готовой строки JSON в поле другой структуры (как в поле request в примере выше), метод ЗаписатьJSON автоматически экранирует кавычки внутри этой строки (превратит " в \"). Это стандартное поведение JSON, и принимающая сторона должна корректно выполнить обратное преобразование (десериализацию).

Соблюдение этих правил — использование UTF-8, правильная конвертация ДвоичныеДанные в Hex-строку и контроль отсутствия лишних пробелов — позволит вам создавать надежные интеграции с любыми внешними системами.

← На главную