При интеграции систем на платформе 1С с API программы лояльности «Аэрофлот Бонус» разработчики часто сталкиваются с проблемой: сформированная подпись запроса не совпадает с контрольным примером сервиса. Выясним причину этой проблемы и разберем по шагам правильную реализацию криптографического алгоритма на 1С.
В эталонной реализации сервиса (написанной на языке Python) для подписи запросов используется алгоритм HMAC-SHA1, в котором в качестве ключа выступает MD5-хэш пин-кода партнера, а в качестве данных — конкатенация параметров транзакции:
msg = str(login) + str(nonce) + str(int(round(float(amount) * rate)))
key = pincode_md5
signature = hmac.new(msg=msg, key=key, digestmod=hashlib.sha1).hexdigest()
Рассмотрим подробнее ключевые нюансы, из-за которых результат в 1С может отличаться от контрольного значения:
Строка(Число) форматирует числа с разделителями групп разрядов (например, "1 000" вместо "1000"). Для формирования строки сообщения необходимо использовать Формат(Число, "ЧГ=0").hexdigest() в Python возвращает 32-значную шестнадцатеричную строку в нижнем регистре (hex-lowercase). Если в 1С хэш-сумма пин-кода останется в верхнем регистре, HMAC-SHA1 вернет неверный дайджест.UTF-8 без добавления маркера последовательности байтов (BOM).round() в Python 3 использует банковское округление (к ближайшему четному числу). В 1С по умолчанию используется математическое округление (РежимОкругления.Окр15как20). При расчете итогового значения суммы важно учитывать правила округления на стороне сервиса.Начиная с версии платформы 8.3.10, в 1С доступен встроенный объект ХешированиеДанных с поддержкой вычисления HMAC при передаче секретного ключа вторым параметром конструктора. Разберем реализацию расчетной функции по шагам.
Вычисление MD5-хэша для пин-кода партнера:
Сначала преобразуем строку пин-кода в двоичные данные UTF-8 без BOM и рассчитаем хэш MD5, обязательно приведя результат к нижнему регистру.
Функция ПолучитьMD5Строки(Знач ИсходнаяСтрока)
ДвоичныеДанныеСтроки = ПолучитьДвоичныеДанныеИзСтроки(ИсходнаяСтрока, КодировкаТекста.UTF8, Ложь);
Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
Хеширование.Добавить(ДвоичныеДанныеСтроки);
Возврат НРег(Хеширование.ХешСумма);
КонецФункции
Сборка строки сообщения для подписи:
Сформируем строку сообщения из параметров транзакции с явным отключением группировки разрядов у числовых значений.
Функция СформироватьСообщение(Логин, Nonce, Сумма, Курс)
// Рассчитываем целочисленное значение суммы
РасчетнаяСумма = Окр(Сумма * Курс, 0, РежимОкругления.Окр15как20);
// Форматируем числа без пробелов и разделителей
СтрокаNonce = Формат(Nonce, "ЧГ=0");
СтрокаСуммы = Формат(РасчетнаяСумма, "ЧГ=0");
СтрокаСообщения = СокрЛП(Логин) + СтрокаNonce + СтрокаСуммы;
Возврат СтрокаСообщения;
КонецФункции
Вычисление итоговой подписи HMAC-SHA1:
Инициализируем объект ХешированиеДанных с алгоритмом ХешФункция.SHA1 и передаем двоичные данные MD5-ключа в конструктор.
Функция ПолучитьПодписьАэрофлотБонус(Логин, ПинКод, Nonce, Сумма, Курс) Экспорт
// Шаг 1: Получаем MD5 от пин-кода в нижнем регистре
MD5КлючСтрока = ПолучитьMD5Строки(СокрЛП(ПинКод));
// Шаг 2: Формируем двоичные данные ключа в UTF-8
ДвоичныеДанныеКлюча = ПолучитьДвоичныеДанныеИзСтроки(MD5КлючСтрока, КодировкаТекста.UTF8, Ложь);
// Шаг 3: Собираем строку сообщения и переводим в двоичные данные
СтрокаСообщения = СформироватьСообщение(Логин, Nonce, Сумма, Курс);
ДвоичныеДанныеСообщения = ПолучитьДвоичныеДанныеИзСтроки(СтрокаСообщения, КодировкаТекста.UTF8, Ложь);
// Шаг 4: Вычисляем HMAC-SHA1
ХешированиеHMAC = Новый ХешированиеДанных(ХешФункция.SHA1, ДвоичныеДанныеКлюча);
ХешированиеHMAC.Добавить(ДвоичныеДанныеСообщения);
// Возвращаем хэш в нижнем регистре
Возврат НРег(ХешированиеHMAC.ХешСумма);
КонецФункции
Если конфигурация работает на старых версиях платформы 1С, где объект ХешированиеДанных еще не поддерживал секретные ключи для HMAC, расчет можно выполнить через вызов COM-объектов .NET Framework:
Функция ПолучитьHMACSHA1_COM(Знач СтрокаСообщения, Знач СтрокаКлюча)
Кодировка = Новый COMОбъект("System.Text.UTF8Encoding");
HMAC = Новый COMОбъект("System.Security.Cryptography.HMACSHA1");
БайтыКлюча = Кодировка.GetBytes_4(СтрокаКлюча);
HMAC.Key = БайтыКлюча;
БайтыСообщения = Кодировка.GetBytes_4(СтрокаСообщения);
ХешБайты = HMAC.ComputeHash_2(БайтыСообщения);
// Преобразуем массив байтов в hex-строку
BitConverter = Новый COMОбъект("System.BitConverter");
HexСтрока = BitConverter.ToString(ХешБайты);
HexСтрока = СтрЗаменить(HexСтрока, "-", "");
Возврат НРег(HexСтрока);
КонецФункции
Применение штатных средств платформы с контролем кодировок и отключением разделителей разрядов гарантирует полное совпадение результатов хэширования между 1С и сервисом «Аэрофлот Бонус».