Как преобразовать GUID в массив байт и закодировать в Base64 в 1С?

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

При интеграции 1С со сторонними веб-сервисами и сайтами (особенно разработанными на платформе Microsoft .NET / C#) часто возникает требование передавать уникальные идентификаторы не обычной строкой вида 08ed0482-a722-4182-b410-e77f3acc34e6, а в виде массива из 16 байт, закодированного в строку Base64.

Если выполнить прямое преобразование шестнадцатеричной строки в двоичные данные, принимающая сторона может не распознать переданный идентификатор. Разберем причины такого поведения и рассмотрим готовые варианты решения задачи.

В чем причина различий: специфика порядка байтов в .NET (Mixed-Endian)

Выясним, почему простое удаление дефисов и преобразование в Base64 не дает ожидаемого внешней системой результата. Стандартный GUID представляет собой 128-битное число (16 байт). Однако формат его сериализации в массив байтов различается:

  1. Стандарт RFC 4122 (сетевой порядок Big-Endian): байты записываются строго слева направо в том порядке, в котором они представлены в шестнадцатеричной строке.
  2. Экосистема Microsoft .NET (Mixed-Endian): при вызове метода Guid.ToByteArray() в .NET первые три компонента структуры записываются в порядке Little-Endian (от младшего байта к старшему), а оставшиеся две — в порядке Big-Endian:
    1. Первый блок (4 байта / 8 символов) разворачивается задом наперед побайтово (байты 1-2-3-4 становятся 4-3-2-1).
    2. Второй блок (2 байта / 4 символа) разворачивается (байты 5-6 становятся 6-5).
    3. Третий блок (2 байта / 4 символа) разворачивается (байты 7-8 становятся 8-7).
    4. Четвертый и пятый блоки (оставшиеся 8 байт) сохраняют свой исходный порядок.

Для того чтобы внешняя система на базе .NET смогла корректно прочитать GUID из строки Base64, нам необходимо выполнить аналогичную перестановку байтов на стороне 1С.

Решение 1: Конвертация GUID в Base64 штатными средствами 1С

Начиная с версии платформы 1С:Предприятие 8.3.10, доступны объекты БуферДвоичныхДанных и методы ПолучитьБуферДвоичныхДанныхИзHexСтроки, ПолучитьBase64СтрокуИзБуфераДвоичныхДанных. Это позволяет выполнить операцию исключительно средствами встроенного языка без создания временных файлов и внешних библиотек.

Разберем по шагам алгоритм преобразования:

  1. Удаляем символы дефиса из строкового представления GUID.
  2. Получаем объект БуферДвоичныхДанных из шестнадцатеричной строки.
  3. Меняем местами байты в первых трех блоках GUID согласно карте инверсии.
  4. Преобразуем полученный буфер в Base64-строку.

Посмотрим на программный код функции:


Функция ГУИД_Из_1С_в_Base64(ГУИД_Из_1С_Строкой) Экспорт
    
    // Очищаем строку GUID от дефисов
    ГУИДБезДефисов = СтрЗаменить(ГУИД_Из_1С_Строкой, "-", "");
    
    // Получаем двоичный буфер из Hex-строки
    БуферДанных = ПолучитьБуферДвоичныхДанныхИзHexСтроки(ГУИДБезДефисов);
    
    // Формируем карту перестановки байтов (индексы от 1)
    КартаИнверсии = Новый Соответствие;
    КартаИнверсии.Вставить(4, 1);
    КартаИнверсии.Вставить(3, 2);
    КартаИнверсии.Вставить(6, 5);
    КартаИнверсии.Вставить(8, 7);
    
    // Инвертируем байты в первых трех сегментах
    Для Каждого КлючИнверсии Из КартаИнверсии Цикл
        ЗначениеПриемника = БуферДанных.Получить(КлючИнверсии.Значение - 1);
        ЗначениеИсточника = БуферДанных.Получить(КлючИнверсии.Ключ - 1);
        
        БуферДанных.Установить(КлючИнверсии.Ключ - 1, ЗначениеПриемника);
        БуферДанных.Установить(КлючИнверсии.Значение - 1, ЗначениеИсточника);
    КонецЦикла;
    
    // Кодируем полученный буфер в Base64
    Возврат ПолучитьBase64СтрокуИзБуфераДвоичныхДанных(БуферДанных);
    
КонецФункции

Решение 2: Обратное преобразование из Base64 в GUID 1С

Если веб-сервис присылает ответ с идентификатором в формате Base64, нам потребуется выполнить обратную операцию для поиска или записи ссылки в базе 1С. Проанализируем реализацию обратной функции:


Функция ГУИД_Из_Base64_В_1С(ГУИД_Base64_Строкой) Экспорт
    
    // Декодируем Base64 в буфер двоичных данных
    БуферДанных = ПолучитьБуферДвоичныхДанныхИзBase64Строки(ГУИД_Base64_Строкой);
    
    // Карта перестановки байтов для возврата в Big-Endian
    КартаИнверсии = Новый Соответствие;
    КартаИнверсии.Вставить(4, 1);
    КартаИнверсии.Вставить(3, 2);
    КартаИнверсии.Вставить(6, 5);
    КартаИнверсии.Вставить(8, 7);
    
    Для Каждого КлючИнверсии Из КартаИнверсии Цикл
        ЗначениеПриемника = БуферДанных.Получить(КлючИнверсии.Ключ - 1);
        ЗначениеИсточника = БуферДанных.Получить(КлючИнверсии.Значение - 1);
        
        БуферДанных.Установить(КлючИнверсии.Ключ - 1, ЗначениеИсточника);
        БуферДанных.Установить(КлючИнверсии.Значение - 1, ЗначениеПриемника);
    КонецЦикла;
    
    // Получаем hex-строку и форматируем ее дефисами
    HexСтрока = ПолучитьHexСтрокуИзБуфераДвоичныхДанных(БуферДанных);
    
    Результат = Сред(HexСтрока, 1, 8) + "-" 
              + Сред(HexСтрока, 9, 4) + "-" 
              + Сред(HexСтрока, 13, 4) + "-" 
              + Сред(HexСтрока, 17, 4) + "-" 
              + Сред(HexСтрока, 21);
    
    Возврат Новый УникальныйИдентификатор(НРег(Результат));
    
КонецФункции

Решение 3: Использование COM-объекта .NET (для сред под управлением Windows)

Рассмотрим альтернативный вариант, который можно применить, если на сервере или клиенте 1С зарегистрирована специальная COM-обертка для вызова методов .NET CLR. В этом случае задача решается прямым вызовом нативных методов System.Guid.Parse и System.Convert.ToBase64String:


// Пример вызова через зарегистрированный COM-мост
NetObject = Новый COMОбъект("NetObjectToIDispatch45");

ТипGuid = NetObject.ПолучитьТип("System.Guid");
ТипConvert = NetObject.ПолучитьТип("System.Convert");

ОбъектGuid = ТипGuid.Parse("08ed0482-a722-4182-b410-e77f3acc34e6");
МассивБайт = ОбъектGuid.ToByteArray();

ИтоговыйGUID = ТипConvert.ToBase64String(МассивБайт);
// Результат: "ggTtCCKngkG0EOd/Osw05g=="

Дополнительно: Формат URL-Safe Base64

При передаче идентификаторов через параметры URL в REST API принимающая сторона может ожидать строку в формате URL-Safe Base64 (без спецсимволов +, / и знаков выравнивания =). В таком случае после выполнения стандартной функции достаточно выполнить простую строковую замену:


Base64Url = СтрЗаменить(СтрЗаменить(Base64Строка, "+", "-"), "/", "_");
Base64Url = СтрЗаменить(Base64Url, "=", "");
← На главную