Как правильно декодировать строку тела запроса в 1С, чтобы итоговый хэш совпал?

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

В процессе интеграции 1С с внешними системами разработчики часто сталкиваются с ситуацией, когда приходящая строка тела запроса и её контрольный хэш не проходят проверку на стороне 1С. Мы получаем данные, используем стандартный метод РаскодироватьСтроку, вычисляем хэш от результата, но он упорно не совпадает с тем, что прислал отправитель. Рассмотрим подробнее, почему это происходит и как решить проблему «неправильного» декодирования.

Разберем основную причину: Конфликт стандартов RFC

Проанализируем ситуацию: почему одна и та же строка, закодированная для URL, может выглядеть по-разному? Основная причина кроется в существовании нескольких стандартов кодирования. Выясним разницу между ними:

  1. RFC 1738: Этот стандарт часто применяется при передаче данных форм (тип контента application/x-www-form-urlencoded). Его главная особенность — замена символа пробела на знак «плюс» (+).
  2. RFC 3986: Более современный стандарт, который требует, чтобы пробел кодировался строго как %20.

Если внешняя система (например, написанная на PHP или использующая библиотеку cURL) кодирует пробелы как «плюсы», а 1С при использовании метода РаскодироватьСтроку с параметром СпособКодированияСтроки.КодировкаURL ожидает формат %20 (или наоборот), то после декодирования мы получим разные строки. Даже разница в один символ в строке полностью меняет результат хэш-функции.

Проанализируем влияние регистра HEX-последовательностей

Посмотрим на то, как кодируются специальные символы. Стандарт URL-кодирования не жестко регламентирует регистр букв после знака процента. Одна система может выдать %d0%af, а другая — %D0%AF. Хотя для визуального чтения текста это не имеет значения, для алгоритмов, которые могут пытаться считать хэш от промежуточных (еще закодированных) данных или использовать чувствительные к регистру методы преобразования, это станет критической ошибкой.

Выясним роль бинарных данных при расчете хэша

Важно помнить, что хэш (будь то MD5, SHA-1 или SHA-256) всегда считается не от «текста», а от последовательности байтов. Процесс в 1С обычно выглядит так:

Тело запроса (байты) -> Строка (1С) -> РаскодированнаяСтрока (1С) -> Хэш (байты)

На этапе превращения раскодированной строки обратно в байты для расчета хэша 1С использует кодировку (чаще всего UTF-8). Если в исходной строке были спецсимволы, которые 1С интерпретировала некорректно при декодировании, байтовый состав финальной последовательности изменится. Например, если в строке был символ тильды (~), точки (.) или подчеркивания (_), разные версии библиотек кодирования могут либо оставить их «как есть», либо экранировать. Если клиент прислал %7E вместо ~, и 1С не вернула это в исходный символ перед хэшированием, проверка провалится.

Рассмотрим решение 1: Предварительная обработка строки

Если мы выяснили, что клиент присылает данные в стандарте RFC 1738 (где пробел — это «плюс»), а встроенный метод 1С отрабатывает это некорректно, мы можем применить ручную замену перед декодированием. Разберем пример кода:


// Допустим, ДанныеЗапроса - это полученная от клиента строка
СтрокаДляДекодирования = СтрЗаменить(ДанныеЗапроса, "+", "%20");
Результат = РаскодироватьСтроку(СтрокаДляДекодирования, СпособКодированияСтроки.КодировкаURL);

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

Рассмотрим решение 2: Работа с потоками и «чистыми» данными

Чтобы избежать искажений, которые вносит строковый тип 1С (который внутри платформы использует UTF-16), эксперты рекомендуют работать с данными в их исходном бинарном виде. Проанализируем ситуацию с использованием объектов ПотокВПамяти и ЧтениеДанных. Это позволяет контролировать кодировку на каждом этапе:

  1. Получаем тело запроса как ДвоичныеДанные.
  2. Используем ЧтениеДанных, чтобы прочитать поток именно в той кодировке, которую гарантирует отправитель (например, UTF-8 без BOM).
  3. Если необходимо ручное декодирование процентов, выполняем его на уровне байтов или через регулярные выражения, не допуская автоматических преобразований платформы.

Проблема BOM (Byte Order Mark)

Еще один важный момент, который стоит рассмотреть — это наличие символов BOM в начале строки. При получении тела запроса и преобразовании его в строку 1С может неявно добавить или отсечь невидимые символы BOM. Если отправитель считал хэш от данных UTF-8 без BOM, а 1С при обработке добавила эти 2-3 байта в начало, хэши никогда не совпадут. При расчете хэша в 1С всегда явно указывайте кодировку и проверяйте необходимость BOM.

Взаимодействие с клиентом и настройки cURL

Посмотрим на ситуацию со стороны отправителя. Если клиент использует cURL, важно понимать разницу между флагами передачи данных:

Совет: Если у вас есть возможность влиять на сторону отправителя, попросите их использовать --data-binary и передавать данные в заранее согласованной кодировке (UTF-8). Это исключит большинство проблем с неоднозначным декодированием на стороне 1С.

Резюме по исправлению ошибки

Подводя итог, для успешного совпадения хэша нам необходимо:

← На главную