Как отправить GET-запрос в 1С для получения access_token API iiko.biz и избежать ошибок 404/400?

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

Приветствуем, коллеги! Многие разработчики 1С сталкиваются с необходимостью интеграции с внешними системами через HTTP-запросы. Сегодня мы рассмотрим распространенную задачу – получение маркера доступа (access token) от API iiko.biz с помощью GET-запроса. На примере реальной проблемы из форума мы выясним, почему возникают ошибки 404 (ресурс не найден) и 400 (неверный запрос), и как правильно сформировать запрос, чтобы успешно получить нужный токен.

Введение в проблему: получение access_token iiko.biz

Наша цель — отправить HTTP GET запрос к API iiko.biz по следующему адресу: /api/0/auth/access_token?user_id={user_id}&user_secret={user_secret}. Параметры user_id (идентификатор клиента) и user_secret (пароль клиента) должны быть переданы в запросе, а в ответ мы ожидаем получить строку с маркером доступа. Однако, при первых попытках зачастую возникают ошибки, такие как 404 или 400. Давайте разберем, почему это происходит и как это исправить.

Анализ первоначальной попытки и выявление ошибок

Рассмотрим исходный код, с которым столкнулся наш коллега на форуме. В нем допущены несколько ключевых ошибок, которые привели к получению кодов состояния 404 и 400.


Сервер = "iiko.biz:9900";
Ресурс = "/api/0/auth/";
Соед = Новый HTTPСоединение(Сервер, ,log , pas, , , Новый ЗащищенноеСоединениеOpenSSL);
Запр = Новый HTTPЗапрос(Ресурс);
Запр.АдресРесурса = Ресурс ;
Запр.Заголовки.Вставить("user_id", log);
Запр.Заголовки.Вставить("user_secret", pas);
ФайлОтвет = ПолучитьИмяВременногоФайла("txt");
Ответ = Соед.Получить(Запр, ФайлОтвет);
Сообщить("Код состояния: " + Строка(Ответ.КодСостояния));
ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.Прочитать(ФайлОтвет, КодировкаТекста.UTF8);
ТекстОтвет = ТекстДок.ПолучитьТекст;
Сообщить(Ответ.КодСостояния);
Сообщить(ТекстОтвет);

Выясним причины, по которым этот код не работает:

  1. Некорректное указание сервера и порта: В первой строке Сервер = "iiko.biz:9900"; порт 9900 включен в имя сервера. Однако, для объекта HTTPСоединение порт должен быть отдельным параметром. Это приводит к тому, что 1С пытается подключиться к серверу с именем "iiko.biz:9900" на стандартном порту, что, вероятно, не соответствует действительности.
  2. Неполный адрес ресурса: Переменная Ресурс = "/api/0/auth/"; не содержит полного пути к методу access_token и, главное, не включает параметры запроса. Корректный путь должен быть /api/0/auth/access_token, а параметры должны быть добавлены после вопросительного знака. Отсутствие access_token в пути ресурса приводит к ошибке 404 (Not Found), так как запрашиваемый ресурс не существует по указанному пути.
  3. Неправильная передача параметров: Параметры user_id и user_secret передаются через заголовки HTTP-запроса (Запр.Заголовки.Вставить(...)). Для GET-запросов, согласно спецификации API iiko.biz, эти параметры должны быть частью строки запроса (query string) в адресе ресурса. Передача их в заголовках вместо строки запроса привела к ошибке 400 (Bad Request) с сообщением от сервера "Wrong user name [] or password []". Сервер просто не находит нужные ему параметры там, где ожидает.
  4. Использование временных файлов: Хотя не является критической ошибкой, но для получения простого строкового ответа (каким и является access token) нет необходимости создавать и читать временные файлы. Мы можем получить тело ответа напрямую в виде строки, что упрощает код и повышает его эффективность.

Корректировка параметров HTTP-соединения

Первым делом, разделим адрес сервера и порт. Метод HTTPСоединение принимает их как отдельные параметры, что обеспечивает правильное установление соединения. Это критически важно для корректной работы.


Сервер = "iiko.biz"; // Только имя сервера
Порт = 9900;       // Порт выносим в отдельную переменную
Соед = Новый HTTPСоединение(Сервер, Порт, , , , , Новый ЗащищенноеСоединениеOpenSSL);

Обратите внимание, что мы также используем объект Новый ЗащищенноеСоединениеOpenSSL, который указывает на использование защищенного HTTPS протокола. Это необходимо, так как мы работаем с защищенным соединением на порту 9900, что является стандартной практикой для безопасного обмена данными с API.

Правильное формирование строки запроса (ресурса)

Ключевой момент – это правильное формирование строки запроса, которая включает полный путь к методу API и все необходимые параметры. Согласно документации API iiko.biz, путь к методу получения токена – /api/0/auth/access_token, а параметры user_id и user_secret должны быть переданы в строке запроса после знака вопроса ?, разделенные амперсандом &.

Сформируем переменную Ресурс следующим образом:


log = "Ваш_User_ID";    // Замените на реальный user_id, предоставленный для API
pas = "Ваш_User_Secret"; // Замените на реальный user_secret (пароль API)

Ресурс = "/api/0/auth/access_token?user_id=" + log + "&user_secret=" + pas;

Важно: URL-кодирование параметров. Если значения user_id или user_secret могут содержать специальные символы (например, пробелы, амперсанды &, знаки вопроса ?, слэши /, диакритические знаки и т.д.), их необходимо предварительно URL-кодировать. Это предотвратит некорректную интерпретацию параметров сервером. Для этого в 1С можно использовать функцию СтроковыеФункцииКлиентСервер.URIКодировать() (если Библиотека стандартных подсистем (БСП) встроена в вашу конфигурацию) или ИнтернетСоединение.URLКодировать(). Например:


logСпецСимволы = "Мой ID с пробелом & символом?"; // Пример параметра со спецсимволами
logЗакодированный = ИнтернетСоединение.URLКодировать(logСпецСимволы, КодировкаТекста.UTF8); // Используем UTF8 для кодировки
// Результат logЗакодированный будет: "Мой%20ID%20с%20пробелом%20%26%20символом%3F"

pasЗакодированный = ИнтернетСоединение.URLКодировать(pas, КодировкаТекста.UTF8);
Ресурс = "/api/0/auth/access_token?user_id=" + logЗакодированный + "&user_secret=" + pasЗакодированный;

Применение URL-кодирования гарантирует, что сервер правильно интерпретирует все части вашего запроса, и вы избежите ошибок, связанных с некорректными символами в URL.

Получение тела ответа напрямую

Чтобы избежать лишней работы с временными файлами, которая может быть неэффективной и требовать дополнительной очистки, мы можем получить тело HTTP-ответа напрямую в виде строки. Для этого используем метод ПолучитьТелоКакСтроку() объекта Ответ.


Ответ = Соед.Получить(Запр);
Результат = Ответ.ПолучитьТелоКакСтроку();
Сообщить(Результат);

Этот подход значительно упрощает код, повышает его производительность и делает его более читаемым при работе с небольшими строковыми ответами, такими как маркер доступа.

Итоговое рабочее решение

Объединив все исправления и лучшие практики, мы получаем следующий рабочий код для отправки GET-запроса и получения маркера доступа. Этот код включает обработку возможных ошибок и демонстрирует правильную структуру запроса.


// Укажите ваши реальные user_id и user_secret для доступа к API iiko.biz
Перем log, pas;
log = "ВАШ_API_USER_ID";    // Замените на реальный идентификатор клиента API
pas = "ВАШ_API_USER_SECRET"; // Замените на реальный пароль клиента API

// Корректируем адрес сервера и порт согласно требованиям iiko.biz
Сервер = "iiko.biz";
Порт = 9900;

// Важно: Кодируем параметры для безопасности, если они могут содержать специальные символы.
// Если функция ИнтернетСоединение.URLКодировать недоступна в вашей версии 1С или конфигурации,
// убедитесь, что ваш user_id и user_secret не содержат специальных символов,
// которые могут нарушить структуру URL.
Попытка
    logЗакодированный = ИнтернетСоединение.URLКодировать(log, КодировкаТекста.UTF8);
    pasЗакодированный = ИнтернетСоединение.URLКодировать(pas, КодировкаТекста.UTF8);
Исключение
    // Если функция недоступна или произошла ошибка кодирования, используем исходные значения
    Сообщить("Внимание: Не удалось URL-кодировать параметры. Убедитесь, что они не содержат спецсимволов.");
    logЗакодированный = log;
    pasЗакодированный = pas;
КонецПопытки;


// Формируем полный адрес ресурса с параметрами, включенными в строку запроса
Ресурс = "/api/0/auth/access_token?user_id=" + logЗакодированный + "&user_secret=" + pasЗакодированный;

// Создаем HTTP-соединение с использованием HTTPS.
// Рекомендуется всегда устанавливать таймаут для предотвращения "зависаний" программы.
// Например, таймаут в 60 секунд:
Соед = Новый HTTPСоединение(Сервер, Порт, , , , 60, Новый ЗащищенноеСоединениеOpenSSL);

// Создаем HTTP-запрос
Запр = Новый HTTPЗапрос(Ресурс);

// Отправляем GET-запрос и получаем ответ с использованием блока Попытка...Исключение
Попытка
    Ответ = Соед.Получить(Запр);

    // Всегда проверяем код состояния HTTP-ответа для определения успешности
    Если Ответ.КодСостояния = 200 Тогда
        Результат = Ответ.ПолучитьТелоКакСтроку();
        Сообщить("Успешный ответ (токен): " + Результат);
        // Здесь можно разобрать JSON-ответ, если токен возвращается в JSON-объекте
        // Например:
        // ЧтениеJSON = Новый ЧтениеJSON;
        // ЧтениеJSON.УстановитьСтроку(Результат);
        // ОбъектJSON = ПрочитатьJSON(ЧтениеJSON);
        // Если ОбъектJSON.Свойство("accessToken") Тогда
        //     МаркерДоступа = ОбъектJSON.accessToken;
        //     Сообщить("Получен маркер доступа: " + МаркерДоступа);
        // КонецЕсли;
    Иначе
        // В случае ошибки, получаем и выводим информацию из тела ответа
        РезультатОшибки = Ответ.ПолучитьТелоКакСтроку();
        Сообщить("Ошибка HTTP при получении токена. Код состояния: " + Строка(Ответ.КодСостояния));
        Сообщить("Текст ошибки от сервера: " + РезультатОшибки);
        // В зависимости от кода состояния, можно реализовать разную логику
        Если Ответ.КодСостояния = 400 Тогда
            Сообщить("Вероятно, неверные user_id или user_secret, либо проблема с их кодированием.");
        ИначеЕсли Ответ.КодСостояния = 404 Тогда
            Сообщить("Проверьте правильность адреса ресурса: " + Ресурс);
        КонецЕсли;
    КонецЕсли;

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

Данный код корректно формирует GET-запрос, передает параметры согласно требованиям API, использует защищенное соединение и включает базовую обработку успешного ответа и различных HTTP-ошибок. Это позволяет не только успешно получить маркер доступа, но и получить полезную информацию для отладки в случае проблем.

Дополнительные рекомендации для надежной работы с API

Для создания более устойчивых, безопасных и поддерживаемых интеграций с внешними API, такими как iiko.biz, рассмотрим следующие важные аспекты, которые выходят за рамки простого получения токена:

1. Таймауты для стабильной работы

Установка таймаута (предельного времени ожидания) для операций с HTTPСоединение является критически важной практикой. Если таймаут не задан, программа может "зависнуть" на неопределенное время в случае проблем с сетью, медленной работой сервера или некорректных настроек прокси/брандмауэра. Это может привести к блокировке потоков выполнения и, в конечном итоге, к сбоям в работе всей системы 1С.

Таймаут в секундах указывается в конструкторе HTTPСоединение. Значение 0 или пустое поле означает отсутствие таймаута, что является ошибкой в большинстве практических сценариев. Мы настоятельно рекомендуем всегда устанавливать разумное значение, например, от 30 до 120 секунд, в зависимости от ожидаемой скорости ответа API.


// Устанавливаем таймаут в 60 секунд, чтобы запрос не "завис"
Соед = Новый HTTPСоединение(Сервер, Порт, , , , 60, Новый ЗащищенноеСоединениеOpenSSL);

2. Кодирование параметров запроса (URL-кодирование)

Как мы уже выяснили, если значения параметров запроса (таких как user_id и user_secret) могут содержать специальные символы (пробелы, амперсанды &, знаки вопроса ?, слэши /, кириллицу и т.д.), их необходимо предварительно URL-кодировать. Это предотвратит некорректную интерпретацию параметров сервером. Некодированные специальные символы могут быть восприняты как часть структуры URL (например, разделители параметров), что приведет к ошибкам в запросе.

В 1С для URL-кодирования мы можем использовать функцию ИнтернетСоединение.URLКодировать(). Она принимает строку для кодирования и необязательный параметр кодировки текста (рекомендуется использовать КодировкаТекста.UTF8).


ИсходныйПараметр = "Мой API-ID с пробелом & символом?";
ЗакодированныйПараметр = ИнтернетСоединение.URLКодировать(ИсходныйПараметр, КодировкаТекста.UTF8);
// Результат ЗакодированныйПараметр будет: "Мой%20API-ID%20с%20пробелом%20%26%20символом%3F"
// Такие значения безопасно включать в строку запроса.

3. Расширенная обработка HTTP-ответов

Помимо кодов 404 (ресурс не найден) и 400 (неверный запрос), существует множество других HTTP-статусов, которые полезно обрабатывать для более надежного и информативного взаимодействия с API. Мы рекомендуем проверять КодСостояния ответа и, в случае неуспешного кода, анализировать тело ответа на наличие дополнительной информации об ошибке, которую сервер может предоставить (как это было с ошибкой "Wrong user name [] or password []").

Основные категории HTTP-статусов:

  1. 1xx (Информационные): Запрос получен, продолжается обработка (например, 100 Continue). Редко встречаются в клиентских запросах API.
  2. 2xx (Успешные): Запрос успешно обработан (например, 200 OK, 201 Created, 204 No Content). Для iiko.biz API успешный ответ на запрос токена должен иметь httpStatusCode: 200.
  3. 3xx (Перенаправление): Целевой ресурс перемещен (например, 301 Moved Permanently, 302 Found). Объект HTTPСоединение в 1С может автоматически следовать некоторым перенаправлениям, но знание этого помогает в отладке, если вы столкнетесь с неожиданным поведением или бесконечными циклами перенаправлений.
  4. 4xx (Клиентские ошибки): Проблема на стороне клиента (например, 401 Unauthorized — необходима аутентификация, 403 Forbidden — доступ запрещен, 404 Not Found — ресурс не существует, 400 Bad Request — некорректный запрос). Это наиболее частые ошибки, которые требуют исправления на вашей стороне.
  5. 5xx (Серверные ошибки): Проблема возникла на стороне сервера (например, 500 Internal Server Error, 503 Service Unavailable). В этом случае, возможно, вам придется просто повторить запрос позже или связаться с поддержкой API.

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

4. Особенности ЗащищенноеСоединениеOpenSSL

Объект ЗащищенноеСоединениеOpenSSL используется для установления HTTPS-соединений, обеспечивая шифрование данных и защиту от перехвата. Если возникают ошибки инициализации SSL-соединения, это может быть связано с несколькими причинами:

  1. Некорректные или отсутствующие сертификаты удостоверяющих центров: На машине, где выполняется код 1С (клиент или сервер), должны быть установлены и доверены корневые сертификаты удостоверяющих центров, которые выдали сертификат для сервера iiko.biz.
  2. Прокси-серверы и SSL-инспекция: В некоторых корпоративных сетях прокси-серверы могут перехватывать и модифицировать SSL-трафик (SSL-инспекция). Это приводит к тому, что 1С видит не оригинальный сертификат сервера, а сертификат прокси, что может вызвать ошибки проверки подлинности. В таких случаях может потребоваться настройка прокси в 1С или добавление сертификата прокси в доверенные.
  3. Версии OpenSSL и TLS протоколов: Убедитесь, что используемая версия платформы 1С:Предприятие поддерживает актуальные версии OpenSSL и TLS протоколов (TLS 1.2, 1.3). Устаревшие версии могут быть несовместимы с современными серверами.

В конструкторе ЗащищенноеСоединениеOpenSSL можно указать СертификатыУдостоверяющихЦентров для явного контроля проверки сертификата сервера, что бывает полезно в специфических корпоративных окружениях с собственной инфраструктурой PKI (Public Key Infrastructure).

5. Важные нюансы iiko.biz API

При работе именно с API iiko.biz необходимо учитывать ряд специфических моментов, которые могут повлиять на успешность ваших интеграций:

  1. Срок действия токена: Полученный маркер доступа в iiko.biz API является временным и действует всего 15 минут. После этого требуется получить новый токен, отправив запрос повторно. Ваша система должна быть спроектирована таким образом, чтобы автоматически обновлять токен, если он истек или был отозван.
  2. API-логин и пароль: user_id и user_secret для API — это отдельный логин и пароль, выданные специально для доступа к API. Их нельзя путать с учетными данными для входа на портал iiko.biz. Использование некорректных учетных данных API приведет к ошибкам аутентификации (например, 400 Bad Request, как мы видели).
  3. Привязка к организации и активность приложения: Даже при успешном получении токена, API-логин должен быть привязан к одной или нескольким организациям в iiko.biz через веб-интерфейс. Также приложение "API Delivery" должно быть активно и подключено к вашей организации, возможно, требуя оплаченной лицензии. Без этого запросы к другим методам API (например, на получение списка организаций или данных продаж) могут возвращать пустой результат или ошибки доступа, даже если токен был получен успешно.
  4. Актуальность API: Важно учитывать, что iiko.biz API, который мы рассматриваем (старая версия), не будет дорабатываться и развиваться в дальнейшем. Для новых интеграций и более широкого функционала рекомендуется использовать iikoCloud API, который предлагает более современные возможности и активно развивается. Этот факт стоит учитывать при планировании долгосрочных решений.

6. Обработка исключений

Всегда используйте блоки Попытка...Исключение...КонецПопытки для перехвата возможных ошибок при выполнении HTTP-запросов. Сетевые операции подвержены множеству внешних факторов: отсутствие сетевого соединения, проблемы с DNS-разрешением, недоступность целевого сервера, ошибки в работе прокси-серверов и многое другое. Корректная обработка исключений сделает ваш код более устойчивым, предотвратит аварийное завершение работы программы и позволит реализовать логику восстановления или уведомления пользователя.


Попытка
    // Ваш HTTP-запрос и обработка ответа
Исключение
    Сообщить("Произошла критическая ошибка при выполнении HTTP-запроса: " + ОписаниеОшибки());
    // Здесь можно добавить логику для записи ошибки в журнал,
    // отправки уведомления администратору, или повторной попытки запроса
КонецПопытки;

7. Использование библиотек

Для более сложной и стандартизированной работы с HTTP(S) и FTP(S) протоколами в 1С можно рассмотреть использование подсистемы "Получение файлов через Интернет" из Библиотеки стандартных подсистем (БСП), если она доступна в вашей конфигурации. БСП предоставляет готовые механизмы для работы с интернет-соединениями, включая:

Использование БСП позволяет значительно сократить объем написанного кода, повысить надежность и унифицировать работу с интернет-ресурсами.

Следуя этим рекомендациям, вы сможете не только успешно получать маркер доступа к API iiko.biz, но и строить более надежные, безопасные и поддерживаемые интеграции на платформе 1С:Предприятие, минимизируя риски возникновения ошибок и упрощая отладку.

← На главную