Как в 1С получить токен авторизации OAuth 2.0 для API Allegro?

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

При работе с внешними API, такими как Allegro, часто требуется получить токен доступа по протоколу OAuth 2.0. Стандартный способ — это Basic-авторизация с использованием `client_id` и `client_secret`. Однако при реализации этого механизма в 1С можно столкнуться с рядом неочевидных проблем, приводящих к ошибкам `unauthorized` или `400 Bad request`. Давайте разберем по шагам, как правильно составить и отправить запрос на получение токена, и какие "подводные камни" есть в платформе 1С.

Шаг 1. Анализ проблемы: почему сервер возвращает ошибку?

Исходная задача — отправить POST-запрос на адрес `https://allegro.pl/auth/oauth/token` с типом авторизации `grant_type=client_credentials`. Для этого требуется передать специальный заголовок `Authorization`. В первоначальном коде были допущены ошибки, которые приводили к ответу от сервера `{"error":"unauthorized","error_description":"There is no client authentication...`}. Это прямо указывает на то, что сервер не смог распознать или принять наши учетные данные.

Проанализируем основные причины таких ошибок:

  1. Неправильное формирование заголовка `Authorization`.
  2. Особенности кодирования строки в Base64 в среде 1С.
  3. Использование неверного HTTP-метода (GET вместо POST).
  4. Некорректная инициализация объекта `HTTPСоединение`.

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

Шаг 2. Правильное формирование заголовка Basic-авторизации

Согласно стандарту, заголовок для Basic-авторизации должен иметь строго определенный формат: `Authorization: Basic <credentials>`. Где `<credentials>` — это строка `client_id:client_secret`, закодированная в Base64.

Важнейший момент — это правильное кодирование. В 1С для этого используется функция `Base64Строка()`. Однако у этой функции есть особенность: она может добавлять в итоговую строку символы переноса строки (`ПС`) и возврата каретки (`ВК`) для форматирования длинных строк. Такие символы недопустимы в HTTP-заголовках и приводят к ошибке авторизации.

Решение — принудительно удалить эти символы из результата кодирования.

Посмотрим на пример кода, который правильно формирует строку для заголовка:


// Ваши учетные данные для API
ID = "138a7e371a3546dc8a9f10df7185883e";
Secret = "dHWawkVqaN9GEfNeOFYTTFLr0fgC5LOWgFnibRV99HYAeWgHvrpKgfgXojS3MEzJ";

// 1. Объединяем ID и Secret через двоеточие
СтрокаДляКодирования = ID + ":" + Secret;

// 2. Получаем двоичные данные из строки
ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(СтрокаДляКодирования);

// 3. Кодируем в Base64
СтрокаАвторизацииBase64 = Base64Строка(ДвоичныеДанные);

// 4. ОЧИЩАЕМ результат от символов переноса строки. Это критически важный шаг!
СтрокаАвторизацииBase64 = СтрЗаменить(СтрокаАвторизацииBase64, Символы.ПС, "");
СтрокаАвторизацииBase64 = СтрЗаменить(СтрокаАвторизацииBase64, Символы.ВК, "");

// 5. Формируем итоговое значение для заголовка
Авторизация = "Basic " + СтрокаАвторизацииBase64;

Теперь в переменной Авторизация содержится корректная строка, которую сервер сможет успешно декодировать.

Шаг 3. Корректная настройка HTTP-запроса

Разобравшись с заголовком, нужно правильно настроить сам HTTP-запрос. Здесь есть два ключевых момента.

Во-первых, используем правильный HTTP-метод. Получение токена OAuth — это операция создания нового ресурса (токена), поэтому по спецификации должен использоваться метод POST. В 1С для этого предназначен метод ОтправитьДляОбработки() объекта HTTPСоединение. Использование метода Получить() (GET) приведет к ошибке `400 Bad request`, так как сервер не ожидает GET-запрос на этот эндпоинт.

Во-вторых, не дублируем авторизацию. При создании объекта HTTPСоединение есть параметры для указания пользователя и пароля. Если вы их заполните, 1С сама попытается сформировать заголовок Basic-авторизации. Но поскольку мы формируем заголовок `Authorization` вручную, передавать учетные данные в конструктор HTTPСоединение не нужно. Это может привести к конфликту и непредсказуемому поведению.

Правильная инициализация соединения выглядит так:


// Создаем соединение, не передавая логин и пароль в конструктор
HTTPСоединение = Новый HTTPСоединение("allegro.pl.allegrosandbox.pl", 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());

Шаг 4. Итоговый код для получения токена

Теперь соберем все части вместе в единый работающий пример. Этот код выполняет авторизацию на тестовом сервере Allegro и выводит в сообщения полученный токен или текст ошибки.


Процедура ПолучитьТокенAllegro()

    // 1. Ваши учетные данные
    ID = "138a7e371a3546dc8a9f10df7185883e";
    Secret = "dHWawkVqaN9GEfNeOFYTTFLr0fgC5LOWgFnibRV99HYAeWgHvrpKgfgXojS3MEzJ";

    // 2. Формируем заголовок авторизации
    // Объединяем, получаем двоичные данные, кодируем в Base64
    Авторизация = "Basic " + Base64Строка(ПолучитьДвоичныеДанныеИзСтроки(ID + ":" + Secret));
    // Обязательно очищаем от символов переноса строки!
    Авторизация = СтрЗаменить(Авторизация, Символы.ПС, "");
    Авторизация = СтрЗаменить(Авторизация, Символы.ВК, "");

    // 3. Устанавливаем соединение
    // Используем хост песочницы. Порт 443 для HTTPS. Логин и пароль не указываем.
    Попытка
        HTTPСоединение = Новый HTTPСоединение("allegro.pl.allegrosandbox.pl", 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
    Исключение
        Сообщить("Не удалось установить защищенное соединение: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

    // 4. Готовим заголовки запроса
    Заголовки = Новый Соответствие;
    Заголовки.Вставить("Authorization", Авторизация);
    // Можно также добавить другие заголовки, если требует API
    // Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");

    // 5. Создаем HTTP-запрос
    // Параметр grant_type передаем прямо в строке запроса
    АдресРесурса = "/auth/oauth/token?grant_type=client_credentials";
    HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);

    // 6. Отправляем POST-запрос
    Попытка
        HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);

        // 7. Анализируем ответ
        Если HTTPОтвет.КодСостояния = 200 Тогда
            Сообщить("Токен успешно получен!");
            Сообщить(HTTPОтвет.ПолучитьТелоКакСтроку());
        Иначе
            Сообщить("Ошибка при получении токена. Код состояния: " + HTTPОтвет.КодСостояния);
            Сообщить(HTTPОтвет.ПолучитьТелоКакСтроку());
        КонецЕсли;

    Исключение
        Сообщить("Ошибка при выполнении HTTP-запроса: " + ОписаниеОшибки());
    КонецПопытки;

КонецПроцедуры

Выполнив этот код, вы получите JSON-ответ с токеном доступа, который можно использовать для дальнейших запросов к API Allegro. Таким образом, ключ к решению проблемы лежал в деталях: правильном кодировании в Base64 без лишних символов и использовании корректного метода HTTP-запроса.

← На главную