Как выполнить авторизацию в Diadoc API из 1С, используя HTTP-запросы?

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

При работе с внешними сервисами, такими как Диадок (поможет обработка автоматического получения документов из Диадок), из среды 1С часто возникает необходимость прямого взаимодействия через API. Стандартные библиотеки могут быть ограничены (например, работать через COM), что подталкивает разработчиков к реализации HTTP-запросов напрямую. Рассмотрим подробнее, как наладить авторизацию в Diadoc API из 1С, выясним типичные ошибки и предоставим работающие примеры кода.

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

Начальная попытка и анализ ошибок

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


&НаСервере
Процедура Команда1НаСервере()
     //получить авторизационный токен
    СерверApi = "diadoc-api.kontur.ru";
    АдресРесурса = "/Authenticate HTTP/1.1";
    
    ИмяФайлаОтвета = ПолучитьИмяВременногоФайла();
    
    ssl = Новый ЗащищенноеСоединениеOpenSSL();
    СоединениеХТТП = Новый HTTPСоединение(СерверApi,443,,,,100,ssl);
     ТексЗапросХТТП = "/Authenticate HTTP/1.1"; // Дублирование и неверный формат
    
    Заголовки = Новый Соответствие();
    Заголовки.Вставить("Authorization", "DiadocAuth ddauth_api_client_id="+"***********************************");
    Заголовки.Вставить("Content-Length", "1252"); // Потенциально неверное значение
    Заголовки.Вставить("Connection", "Keep-Alive");
    ЗапросАвторизованный = Новый HTTPЗапрос(ТексЗапросХТТП, Заголовки);
    
    HTTPОтвет = СоединениеХТТП.Получить(ЗапросАвторизованный, ИмяФайлаОтвета); // Использование Получить вместо Отправить
    СтрокаОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
    КодСостояния = HTTPОтвет.КодСостояния;
    
КонецПроцедуры

При выполнении этого кода мы можем столкнуться с несколькими проблемами, например, "превышение ожидания" или ошибкой 400 Bad Request. Давайте разберем, почему это происходит:

  1. Неверный формат АдресРесурса и ТексЗапросХТТП: В исходном коде указано "/Authenticate HTTP/1.1". Это явная ошибка. АдресРесурса должен содержать только путь к целевому ресурсу, без указания протокола HTTP и его версии. Корректное значение должно быть просто "/Authenticate" или "/V3/Authenticate", в зависимости от версии API.
  2. Некорректное значение Content-Length: Заголовок Content-Length указывает на размер тела запроса в байтах. Если мы выполняем запрос методом GET или POST без тела запроса (что возможно при некоторых схемах авторизации, когда логин/пароль передаются в URL или используются другие механизмы), Content-Length должен быть равен 0. Если же тело запроса содержит данные (например, логин и пароль в формате JSON), то Content-Length должен точно соответствовать длине этих данных. Неправильное значение приводит к ошибке 400 Bad Request.
  3. Использование метода Получить для запроса авторизации: Метод Authenticate в Diadoc API чаще всего ожидается как POST-запрос, особенно если логин и пароль передаются в теле запроса или используются другие сложные схемы авторизации. Метод HTTPСоединение.Получить() обычно соответствует GET-запросу, что может быть некорректно для авторизации. Правильнее использовать HTTPСоединение.Отправить() или HTTPСоединение.ОтправитьДляОбработки() для отправки POST-запроса.
  4. Таймаут (превышение ожидания): Эта проблема может быть вызвана несколькими факторами:
    • Сетевые проблемы: Блокировка порта 443 или отсутствие доступа к diadoc-api.kontur.ru из вашей сети.
    • Неправильный АдресРесурса: Если сервер не может найти запрошенный ресурс из-за некорректного URL, он может просто не отвечать, что приведет к таймауту.
    • Некорректно сформированный запрос: Некоторые серверы могут просто игнорировать запросы, которые не соответствуют их ожиданиям, вызывая таймаут.
  5. Отсутствие Content-Type: Если вы отправляете тело запроса (например, JSON с логином и паролем), необходимо также установить заголовок Content-Type, например, application/json.

Корректная реализация авторизации в Diadoc API

Для успешной авторизации нам потребуется учесть следующие ключевые моменты: правильный адрес ресурса, корректные заголовки (включая Authorization и Content-Length), использование защищенного соединения и подходящий метод HTTP-запроса. Рассмотрим работающий пример, который был актуален и показал свою эффективность.

Прежде всего, давайте подготовим необходимые данные для авторизации. Нам понадобится логин и пароль от аккаунта Диадок, а также ключ разработчика (ddauth_api_client_id). Ключ разработчика — это уникальный идентификатор интегратора, который необходимо получить, оставив заявку на странице интеграции Диадока. Без этого ключа авторизация будет невозможна (вы получите ошибку 401 Unauthorized).

Ниже представлен пример кода, который демонстрирует один из способов авторизации в Диадоке по логину и паролю. Этот код использует метод /Authenticate и передает логин и пароль как параметры URL, что подразумевает пустой тело запроса и Content-Length: 0.


&НаСервере
Процедура АвторизацияDiadocНаСервере()
     ЛогинНаСайтДиадок = "ВашЛогин"; // Замените на реальный логин
    ПарольНаСайтДиадок = "ВашПароль"; // Замените на реальный пароль
    КлючРазработчика = "***********************************"; // Ваш ключ разработчика

    АдресРесурса = "/Authenticate?login=" + ЛогинНаСайтДиадок + "&password=" + ПарольНаСайтДиадок;
    АдресСайта = "diadoc-api.kontur.ru";
    
    HTTPЗапрос2 = Новый HTTPЗапрос;
    
    // Добавляем заголовки. Обратите внимание на формат и состав.
    HTTPЗапрос2.Заголовки.Вставить("Host", АдресСайта);
    HTTPЗапрос2.Заголовки.Вставить("Content-Length", 0); // Важно: 0, так как логин/пароль в URL, а не в теле
    HTTPЗапрос2.Заголовки.Вставить("Authorization", "DiadocAuth ddauth_api_client_id=" + КлючРазработчика);
    // Для метода Authenticate с параметрами в URL, HTTP-метод по умолчанию может быть GET.
    // Однако, для Authenticate чаще ожидается POST. Укажем это явно в заголовках.
    // Если метод Authenticate принимает параметры в URL для GET-запроса, 
    // этот заголовок может быть излишним или неверным.
    // Для POST-запроса с пустым телом, "POST /Authenticate?..." будет корректно.
    HTTPЗапрос2.Заголовки.Вставить("X-HTTP-Method-Override", "POST"); 

    HTTPЗапрос2.АдресРесурса = АдресРесурса; // Устанавливаем корректный АдресРесурса
    
    Соединение1 = Новый HTTPСоединение(АдресСайта, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL(), Ложь); 
    ФайлРезультата = ПолучитьИмяВременногоФайла();
    
    Попытка
        // Для отправки запроса и получения файла ответа.
        Соединение1.ОтправитьДляОбработки(HTTPЗапрос2, ФайлРезультата);
        
        Ответ = Новый ТекстовыйДокумент();
        Ответ.Прочитать(ФайлРезультата, КодировкаТекста.UTF8);
        СтрокаОтвета = Ответ.ПолучитьТекст();
        
        // Здесь СтрокаОтвета будет содержать авторизационный токен
        Сообщить("Авторизация прошла успешно. Токен: " + СтрокаОтвета);
    Исключение
        Сообщить("Ошибка авторизации: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Давайте подробно разберем каждый шаг этого решения:

  1. ЛогинНаСайтДиадок, ПарольНаСайтДиадок, КлючРазработчика: Это ваши учетные данные и ключ, которые необходимо подставить. Ключ разработчика является критически важным для каждого запроса к API Диадок. Он подтверждает вашу "идентификацию" как интегратора.
  2. АдресРесурса = "/Authenticate?login=" + ЛогинНаСайтДиадок + "&password=" + ПарольНаСайтДиадок;: Здесь формируется полный путь к ресурсу авторизации. Мы используем метод Authenticate и передаем логин и пароль в виде параметров URL. Это один из устаревших, но рабочих способов авторизации в Диадоке.
  3. АдресСайта = "diadoc-api.kontur.ru";: Доменное имя API-сервера Диадока.
  4. HTTPЗапрос2 = Новый HTTPЗапрос;: Создаем объект для формирования HTTP-запроса.
  5. Заголовки запроса:
    • HTTPЗапрос2.Заголовки.Вставить("Host", АдресСайта);: Заголовок Host обязателен для HTTP/1.1 и указывает на доменное имя сервера.
    • HTTPЗапрос2.Заголовки.Вставить("Content-Length", 0);: Это очень важный момент. Поскольку мы передаем логин и пароль в строке запроса (URL), а не в теле запроса, тело запроса является пустым. Следовательно, его длина равна 0. Неправильное значение Content-Length — частая причина ошибок 400 Bad Request.
    • HTTPЗапрос2.Заголовки.Вставить("Authorization", "DiadocAuth ddauth_api_client_id=" + КлючРазработчика);: Этот заголовок содержит наш ключ разработчика. DiadocAuth — это тип авторизации, используемый Диадоком для идентификации клиента API.
    • HTTPЗапрос2.Заголовки.Вставить("X-HTTP-Method-Override", "POST");: Этот заголовок не является стандартным HTTP-заголовком, но иногда используется для "переопределения" метода HTTP, когда, например, клиентская библиотека не позволяет явно указать POST для запроса с URL-параметрами, но сервер ожидает POST. В данном контексте он может быть полезен, если Authenticate всегда ожидается как POST. Настоятельно рекомендуем свериться с актуальной документацией Диадока, поскольку методы авторизации могут меняться.
  6. HTTPЗапрос2.АдресРесурса = АдресРесурса;: Присваиваем сформированный адрес ресурса объекту HTTP-запроса.
  7. Соединение1 = Новый HTTPСоединение(АдресСайта, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL(), Ложь);: Создаем защищенное HTTP-соединение с сервером Диадока.
    • АдресСайта: домен.
    • 443: стандартный порт для HTTPS.
    • Новый ЗащищенноеСоединениеOpenSSL(): объект, обеспечивающий использование SSL/TLS для защищенного соединения. Это крайне важно, так как мы передаем конфиденциальные данные.
    • Ложь в конце: параметр УстановитьТаймаутСервера, который здесь отключен (используется значение по умолчанию). Если возникают таймауты, возможно, стоит явно установить больший таймаут.
  8. ФайлРезультата = ПолучитьИмяВременногоФайла();: Мы будем получать ответ от сервера в виде файла, поэтому создаем временный файл.
  9. Соединение1.ОтправитьДляОбработки(HTTPЗапрос2, ФайлРезультата);: Отправляем сформированный HTTP-запрос и сохраняем ответ сервера во временный файл. Это более гибкий метод по сравнению с Получить, позволяющий контролировать тип запроса и тело.
  10. Обработка ответа:
    • Ответ = Новый ТекстовыйДокумент();: Создаем объект для чтения текстового содержимого.
    • Ответ.Прочитать(ФайлРезультата, КодировкаТекста.UTF8);: Читаем содержимое файла ответа.
    • СтрокаОтвета = Ответ.ПолучитьТекст();: Получаем текстовое содержимое, которое должно представлять собой авторизационный токен.

Альтернативные методы авторизации и важные нюансы

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

Актуальные методы авторизации

На текущий момент Диадок поддерживает две основные схемы авторизации:

  1. OpenID Connect: Это рекомендуемый и более современный способ аутентификации. Он подразумевает взаимодействие с OpenID Провайдером, который выдает токен доступа (access_token). Этот токен затем используется в заголовке Authorization с типом Bearer (например, Authorization: Bearer <access_token>). Для настройки интеграции через OpenID Connect требуется зарегистрировать приложение, получить client_id и client_secret в Кабинете интегратора, а затем реализовать один из потоков получения токена (например, Authorization Code Flow или Device Authorization Flow). Время жизни токена ограничено, и его необходимо обновлять. Этот метод требует более сложной реализации, но является более безопасным и гибким.
  2. Методы Диадока: Этот способ является устаревшим и не рекомендуется к использованию для новых интеграций, однако он все еще поддерживается и был предметом обсуждения в нашей теме. Он включает в себя получение авторизационного токена напрямую через метод Authenticate (V3).

Авторизация с помощью методов Диадока (устаревший способ Authenticate (V3))

Рассмотрим различные подходы к использованию метода Authenticate (V3), который мы обсуждали:

Общие ошибки и их причины

Рассмотрим типичные ошибки, с которыми вы можете столкнуться при интеграции, и их возможные причины:

  1. Таймаут (превышение ожидания):

    Как мы уже упоминали, это может быть связано с сетевыми проблемами (фаерволы, прокси), неправильным адресом ресурса или некорректно сформированным запросом, который сервер не может обработать, и просто "висит", ожидая корректных данных.

  2. Ошибка 400 Bad Request:

    Указывает на то, что данные в запросе имеют неверный формат или отсутствуют обязательные параметры. Это часто происходит из-за:

    • Некорректного Content-Length: Его значение должно точно соответствовать длине тела запроса. Если тела нет, то 0.
    • Ошибок в JSON-теле запроса: Неправильный синтаксис JSON.
    • Неправильного АдресРесурса: Опечатки или неверный путь.
    • Отсутствия Content-Type: Если отправляете JSON, но не указали Content-Type: application/json.
  3. Ошибка 401 Unauthorized:

    Возникает, если в запросе отсутствует HTTP-заголовок Authorization, или в нем нет параметра ddauth_api_client_id, или переданный ключ разработчика не зарегистрирован в Диадоке, или истек срок его действия. Убедитесь, что ваш ключ разработчика активен и правильно указан в заголовке.

  4. Ошибка "Invalid scope" при OpenID Connect:

    Указывает на то, что в запросе на получение ссылки для выдачи разрешений указаны некорректные области доступа (scope). Это специфично для OpenID Connect и не относится к устаревшим методам Authenticate.

Рекомендации по интеграции с Diadoc API

Чтобы обеспечить стабильную и надежную интеграцию с Diadoc API, мы рекомендуем придерживаться следующих практик. Для этой задачи есть инструменты для отладки кода и выполнения запросов.

  1. Всегда обращайтесь к официальной документации: Для получения самой актуальной и подробной информации по методам и параметрам всегда используйте официальную документацию Диадок API на developer.kontur.ru. API постоянно развивается, и методы могут меняться.
  2. Используйте рекомендуемый способ авторизации: Если вы создаете новую интеграцию, рассмотрите возможность использования OpenID Connect. Несмотря на более сложную первоначальную настройку, этот метод является более современным, безопасным и поддерживаемым.
  3. Тщательно проверяйте HTTP-запросы: При формировании HTTP-запросов внимательно проверяйте все заголовки (Authorization, Content-Type, Content-Length) и структуру тела запроса в соответствии с выбранным методом аутентификации и форматом данных (JSON/protobuf). Неверный заголовок или тело могут быть причиной большинства проблем.
  4. Диагностика ошибок: В случае возникновения ошибок, коды состояния HTTP (400, 401, 405, 500) и сообщения об ошибках в теле ответа могут помочь в диагностике проблемы — для этого подойдёт обработка для анализа HTTP-запросов в реальном времени. Всегда логируйте эти данные.
  5. Используйте тестовый ключ разработчика: Для тестирования интеграции можно использовать тестовый ключ разработчика, который предоставляется бесплатно на ограниченный срок. Это позволит отладить код без влияния на рабочие данные.
  6. Готовые решения для 1С: Диадок предлагает готовые решения для интеграции с 1С, включая модуль для 1С и AddIn компоненту — есть готовый модуль реализации юридически значимого ЭДО в 1С. Эти решения могут значительно упростить работу с API, так как содержат уже реализованные механизмы аутентификации, работы с криптографией и обработку документов. Если есть возможность, используйте их.

Надеемся, что этот подробный анализ и примеры кода помогут вам успешно наладить авторизацию в Diadoc API из 1С и избежать распространенных ошибок. Ваша внимательность к деталям HTTP-запросов и следование актуальной документации будут ключом к успешной интеграции. Для решения последующих прикладных задач по отправке документов также можно использовать готовую обработку для выгрузки счетов-фактур и УПД в XML для Диадока.

← На главную