В процессе интеграции 1С с внешними системами разработчики часто сталкиваются с ситуацией, когда приходящая строка тела запроса и её контрольный хэш не проходят проверку на стороне 1С. Мы получаем данные, используем стандартный метод РаскодироватьСтроку, вычисляем хэш от результата, но он упорно не совпадает с тем, что прислал отправитель. Рассмотрим подробнее, почему это происходит и как решить проблему «неправильного» декодирования.
Проанализируем ситуацию: почему одна и та же строка, закодированная для URL, может выглядеть по-разному? Основная причина кроется в существовании нескольких стандартов кодирования. Выясним разницу между ними:
application/x-www-form-urlencoded). Его главная особенность — замена символа пробела на знак «плюс» (+).%20.Если внешняя система (например, написанная на PHP или использующая библиотеку cURL) кодирует пробелы как «плюсы», а 1С при использовании метода РаскодироватьСтроку с параметром СпособКодированияСтроки.КодировкаURL ожидает формат %20 (или наоборот), то после декодирования мы получим разные строки. Даже разница в один символ в строке полностью меняет результат хэш-функции.
Посмотрим на то, как кодируются специальные символы. Стандарт URL-кодирования не жестко регламентирует регистр букв после знака процента. Одна система может выдать %d0%af, а другая — %D0%AF. Хотя для визуального чтения текста это не имеет значения, для алгоритмов, которые могут пытаться считать хэш от промежуточных (еще закодированных) данных или использовать чувствительные к регистру методы преобразования, это станет критической ошибкой.
Важно помнить, что хэш (будь то MD5, SHA-1 или SHA-256) всегда считается не от «текста», а от последовательности байтов. Процесс в 1С обычно выглядит так:
Тело запроса (байты) -> Строка (1С) -> РаскодированнаяСтрока (1С) -> Хэш (байты)
На этапе превращения раскодированной строки обратно в байты для расчета хэша 1С использует кодировку (чаще всего UTF-8). Если в исходной строке были спецсимволы, которые 1С интерпретировала некорректно при декодировании, байтовый состав финальной последовательности изменится. Например, если в строке был символ тильды (~), точки (.) или подчеркивания (_), разные версии библиотек кодирования могут либо оставить их «как есть», либо экранировать. Если клиент прислал %7E вместо ~, и 1С не вернула это в исходный символ перед хэшированием, проверка провалится.
Если мы выяснили, что клиент присылает данные в стандарте RFC 1738 (где пробел — это «плюс»), а встроенный метод 1С отрабатывает это некорректно, мы можем применить ручную замену перед декодированием. Разберем пример кода:
// Допустим, ДанныеЗапроса - это полученная от клиента строка
СтрокаДляДекодирования = СтрЗаменить(ДанныеЗапроса, "+", "%20");
Результат = РаскодироватьСтроку(СтрокаДляДекодирования, СпособКодированияСтроки.КодировкаURL);
Этот простой шаг часто решает проблему расхождения хэшей, если разница заключалась только в обработке пробелов.
Чтобы избежать искажений, которые вносит строковый тип 1С (который внутри платформы использует UTF-16), эксперты рекомендуют работать с данными в их исходном бинарном виде. Проанализируем ситуацию с использованием объектов ПотокВПамяти и ЧтениеДанных. Это позволяет контролировать кодировку на каждом этапе:
ДвоичныеДанные.ЧтениеДанных, чтобы прочитать поток именно в той кодировке, которую гарантирует отправитель (например, UTF-8 без BOM).Еще один важный момент, который стоит рассмотреть — это наличие символов BOM в начале строки. При получении тела запроса и преобразовании его в строку 1С может неявно добавить или отсечь невидимые символы BOM. Если отправитель считал хэш от данных UTF-8 без BOM, а 1С при обработке добавила эти 2-3 байта в начало, хэши никогда не совпадут. При расчете хэша в 1С всегда явно указывайте кодировку и проверяйте необходимость BOM.
Посмотрим на ситуацию со стороны отправителя. Если клиент использует cURL, важно понимать разницу между флагами передачи данных:
-d (--data) автоматически кодирует данные, заменяя пробелы на «плюс».--data-binary отправляет данные «как есть», без модификаций.Совет: Если у вас есть возможность влиять на сторону отправителя, попросите их использовать --data-binary и передавать данные в заранее согласованной кодировке (UTF-8). Это исключит большинство проблем с неоднозначным декодированием на стороне 1С.
Подводя итог, для успешного совпадения хэша нам необходимо:
РаскодироватьСтроку не справляется.