Как настроить интеграцию 1С с amoCRM: решаем проблемы с авторизацией, куками и GET/POST запросами

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

Интеграция учетных систем 1С:Предприятие с CRM-платформами — одна из самых частых задач, с которыми сталкивается разработчик. В процессе реализации обмена данными с amoCRM многие начинающие специалисты совершают типовые ошибки, связанные с непониманием протокола HTTP, некорректной передачей параметров в GET-запросах или потерей сессии авторизации.

В этой статье мы подробно разберем, почему возникает ошибка 401 Unauthorized после успешного входа, как правильно передавать параметры запроса в 1С, а также рассмотрим современный и безопасный подход к интеграции с использованием актуального amoCRM API v4 и протокола авторизации OAuth 2.0.

Анализ проблемы: почему сбрасывается авторизация (ошибка 401)

Рассмотрим ситуацию, описанную на форуме. Разработчик успешно отправляет POST-запрос на авторизацию, получает ответ 200 OK с подтверждением успешного входа, но при следующем запросе на получение списка сделок сервер возвращает ошибку 401 - Нет авторизации.

Выясним причину такого поведения системы. Дело в том, что HTTP-протокол по своей природе не хранит состояние (stateless). Сервер «не помнит», кто к нему обращался мгновение назад, если клиент не идентифицирует себя в каждом последующем запросе. В старых версиях API amoCRM для идентификации пользователя использовались сессии и временные файлы Cookies.

При успешном запросе на авторизацию сервер отправляет в заголовках ответа параметр Set-Cookie. Чтобы последующие запросы выполнялись успешно, 1С должна перехватить эту куку и передавать ее в заголовке каждого последующего запроса. Разберем по шагам, как это реализовать в коде 1С.


// 1. Создаем HTTP-соединение
Соединение = Новый HTTPСоединение("subdomain.amocrm.ru",,,,,, Новый ЗащищенноеСоединениеOpenSSL);

// 2. Формируем запрос на авторизацию (Legacy-метод)
ЗапросАвторизации = Новый HTTPЗапрос("/private/api/auth.php?type=json");
ЗапросАвторизации.Заголовки.Вставить("Content-Type", "application/json");

Авторизация = Новый Структура;
Авторизация.Вставить("USER_LOGIN", "my_login");
Авторизация.Вставить("USER_HASH", "my_hash");

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Авторизация);
ТелоЗапроса = ЗаписьJSON.Закрыть();

ЗапросАвторизации.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
ОтветАвторизации = Соединение.ОтправитьДляОбработки(ЗапросАвторизации);

// 3. Получаем и сохраняем Cookie из заголовков ответа
СессионнаяКука = ОтветАвторизации.Заголовки.Получить("Set-Cookie");

Теперь при выполнении любых других операций (например, получение списка лидов) мы обязаны передавать сохраненную куку в заголовках нового запроса:


ЗапросДанных = Новый HTTPЗапрос("/api/v2/leads");
// Передаем сессионную куку обратно на сервер
ЗапросДанных.Заголовки.Вставить("Cookie", СессионнаяКука);

Типичная ошибка: передача тела в GET-запросах (ошибка 400)

Вторая популярная проблема — возникновение ошибки 400 Bad Request при попытке получить данные. Разработчики часто пытаются передавать параметры выборки (например, количество строк limit_rows) в теле GET-запроса через JSON, используя метод ОтправитьДляОбработки().

Проанализируем эту ошибку. Согласно спецификации протокола HTTP, метод GET предназначен исключительно для получения информации с сервера. Он не должен содержать тело запроса. Если передать тело в GET-запросе, сервер либо проигнорирует его, либо вернет ошибку некорректного запроса (400).

Правильный способ передачи параметров для GET-запросов — добавление их непосредственно в строку адреса ресурса (Query Parameters) после знака вопроса ?. Параметры разделяются между собой символом амперсанда &.

Вместо метода ОтправитьДляОбработки() для GET-запросов в 1С необходимо использовать метод Получить() объекта HTTPСоединение.

Посмотрим на пример правильного формирования GET-запроса с параметрами:


// Формируем адрес ресурса с параметрами в URL
ПараметрыЗапроса = "limit_rows=100&limit_offset=0";
АдресРесурса = "/api/v2/leads?" + ПараметрыЗапроса;

Запрос = Новый HTTPЗапрос(АдресРесурса);
Запрос.Заголовки.Вставить("Cookie", СессионнаяКука);

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

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


ПараметрыСтруктура = Новый Структура;
ПараметрыСтруктура.Вставить("limit_rows", "100");
ПараметрыСтруктура.Вставить("limit_offset", "50");

СтрокаПараметров = "";
Для Каждого КлючИЗначение Из ПараметрыСтруктура Цикл
    СтрокаПараметров = СтрокаПараметров + ?(СтрокаПараметров = "", "", "&") + КлючИЗначение.Ключ + "=" + КлючИЗначение.Значение;
КонецЦикла;

Запрос.АдресРесурса = "/api/v2/leads?" + СтрокаПараметров;

Важное обновление: переход на amoCRM API v4 и OAuth 2.0

Критически важно: Описанные выше методы авторизации по USER_HASH и сессионным кукам, а также использование REST API v2 полностью устарели и отключены со стороны amoCRM. Современные интеграции должны использовать исключительно протокол OAuth 2.0 и актуальную версию API v4.

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

  1. Авторизация по токенам: Вместо логина и хэша используются два токена: access_token (короткоживущий токен доступа, действует 24 часа) и refresh_token (токен обновления, действует 3 месяца).
  2. Заголовок авторизации: Куки больше не используются. В каждый запрос необходимо передавать заголовок Authorization со значением Bearer [access_token].
  3. Изменение эндпоинтов: Все запросы к сущностям теперь отправляются на адреса вида /api/v4/leads, /api/v4/contacts и т.д.
  4. Новые параметры пагинации: Параметры limit_rows и limit_offset упразднены. В API v4 для постраничной навигации используются параметры limit (количество записей на страницу, максимум 250) и page (номер страницы).

Реализация авторизации OAuth 2.0 в 1С по шагам

Для начала работы необходимо зарегистрировать интеграцию в личном кабинете amoCRM (раздел "амоМаркет" -> "Установленные" -> "Создать интеграцию"). Вы получите три ключа: ID интеграции (client_id), Секретный ключ (client_secret) и временный Код авторизации (authorization_code).

Разберем, как выполнить первичный обмен кода авторизации на рабочие токены в 1С:


Функция ПолучитьПервичныеТокены(АдресСубдомена, IDИнтеграции, СекретныйКлюч, КодАвторизации, СсылкаДляОбратногоВызова)
    
    Соединение = Новый HTTPСоединение(АдресСубдомена, , , , , 10, Новый ЗащищенноеСоединениеOpenSSL);
    Запрос = Новый HTTPЗапрос("/oauth2/access_token");
    Запрос.Заголовки.Вставить("Content-Type", "application/json");
    
    // Формируем параметры в соответствии с требованиями amoCRM OAuth 2.0
    ПараметрыOAuth = Новый Структура;
    ПараметрыOAuth.Вставить("client_id", IDИнтеграции);
    ПараметрыOAuth.Вставить("client_secret", СекретныйКлюч);
    ПараметрыOAuth.Вставить("grant_type", "authorization_code");
    ПараметрыOAuth.Вставить("code", КодАвторизации);
    ПараметрыOAuth.Вставить("redirect_uri", СсылкаДляОбратногоВызова);
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, ПараметрыOAuth);
    ТелоЗапроса = ЗаписьJSON.Закрыть();
    
    Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
    Попытка
        Ответ = Соединение.ОтправитьДляОбработки(Запрос);
        Если Ответ.КодСостояния = 200 Тогда
            Возврат Ответ.ПолучитьТелоКакСтроку(); // Здесь придут access_token и refresh_token
        Иначе
            ВызватьИсключение "Ошибка авторизации: " + Ответ.ПолучитьТелоКакСтроку();
        КонецЕсли;
    Исключение
        ЗаписатьЛогОшибки(ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
КонецФункции

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


Функция ОбновитьТокены(АдресСубдомена, IDИнтеграции, СекретныйКлюч, ТекущийРефрешТокен)
    
    Соединение = Новый HTTPСоединение(АдресСубдомена, , , , , 10, Новый ЗащищенноеСоединениеOpenSSL);
    Запрос = Новый HTTPЗапрос("/oauth2/access_token");
    Запрос.Заголовки.Вставить("Content-Type", "application/json");
    
    ПараметрыOAuth = Новый Структура;
    ПараметрыOAuth.Вставить("client_id", IDИнтеграции);
    ПараметрыOAuth.Вставить("client_secret", СекретныйКлюч);
    ПараметрыOAuth.Вставить("grant_type", "refresh_token");
    ПараметрыOAuth.Вставить("refresh_token", ТекущийРефрешТокен);
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, ПараметрыOAuth);
    ТелоЗапроса = ЗаписьJSON.Закрыть();
    
    Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
    Ответ = Соединение.ОтправитьДляОбработки(Запрос);
    Если Ответ.КодСостояния = 200 Тогда
        // Обязательно перезаписываем оба токена в 1С, так как старый refresh_token сгорает!
        Возврат Ответ.ПолучитьТелоКакСтроку();
    Иначе
        ВызватьИсключение "Не удалось обновить токен доступа: " + Ответ.ПолучитьТелоКакСтроку();
    КонецЕсли;
    
КонецФункции

Пример работы с API v4: Получение списка сделок

Теперь спроектируем правильный GET-запрос для получения сделок из amoCRM версии API v4 с использованием токена доступа Bearer и новых параметров постраничной навигации.


Процедура ПолучитьСписокСделокV4()
    
    Субдомен = "mycompany.amocrm.ru";
    РабочийТокен = ПолучитьАктуальныйAccessTokenИзБазы(); // Метод получения сохраненного токена
    
    Соединение = Новый HTTPСоединение(Субдомен, , , , , 10, Новый ЗащищенноеСоединениеOpenSSL);
    
    // Запрашиваем 1-ю страницу, лимит 50 сделок
    АдресРесурса = "/api/v4/leads?limit=50&page=1";
    
    Запрос = Новый HTTPЗапрос(АдресРесурса);
    Запрос.Заголовки.Вставить("Authorization", "Bearer " + РабочийТокен);
    Запрос.Заголовки.Вставить("Content-Type", "application/json");
    
    Попытка
        Ответ = Соединение.Получить(Запрос);
        Если Ответ.КодСостояния = 200 Тогда
            СтрокаJSON = Ответ.ПолучитьТелоКакСтроку();
            // Обрабатываем полученный JSON со сделками
            ОбработатьДанныеСделок(СтрокаJSON);
        ИначеЕсли Ответ.КодСостояния = 204 Тогда
            Сообщить("Сделок больше нет (пустая страница).");
        ИначеЕсли Ответ.КодСостояния = 401 Тогда
            Сообщить("Токен истек, требуется обновление!");
            // Вызываем процедуру обновления токенов
        Иначе
            Сообщить("Неизвестная ошибка сервера. Код: " + Ответ.КодСостояния);
        КонецЕсли;
    Исключение
        ВызватьИсключение "Ошибка соединения с amoCRM: " + ОписаниеОшибки();
    КонецПопытки;
    
КонецПроцедуры

Использование универсального метода ВызватьHTTPМетод()

В современной разработке на платформе 1С (начиная с версии 8.3.10) рекомендуется использовать универсальный метод ВызватьHTTPМетод() вместо устаревших специализированных методов. Это особенно актуально при обновлении данных сделок в amoCRM v4, где активно применяется HTTP-метод PATCH (частичное изменение данных).

Рассмотрим пример обновления названия сделки с помощью метода PATCH:


Процедура ОбновитьСделкуV4(IDСделки, НовоеНазвание)
    
    Субдомен = "mycompany.amocrm.ru";
    РабочийТокен = ПолучитьАктуальныйAccessTokenИзБазы();
    
    Соединение = Новый HTTPСоединение(Субдомен, , , , , 10, Новый ЗащищенноеСоединениеOpenSSL);
    
    // Эндпоинт для обновления конкретной сделки
    АдресРесурса = "/api/v4/leads/" + Формат(IDСделки, "ЧГ=0");
    
    Запрос = Новый HTTPЗапрос(АдресРесурса);
    Запрос.Заголовки.Вставить("Authorization", "Bearer " + РабочийТокен);
    Запрос.Заголовки.Вставить("Content-Type", "application/json");
    
    // Формируем структуру изменяемых полей
    ДанныеСделки = Новый Структура;
    ДанныеСделки.Вставить("name", НовоеНазвание);
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, ДанныеСделки);
    ТелоЗапроса = ЗаписьJSON.Закрыть();
    
    Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
    // Используем современный метод ВызватьHTTPМетод для PATCH-запроса
    Ответ = Соединение.ВызватьHTTPМетод("PATCH", Запрос);
    
    Если Ответ.КодСостояния = 200 Тогда
        Сообщить("Сделка успешно обновлена!");
    Иначе
        Сообщить("Не удалось обновить сделку. Код ответа: " + Ответ.КодСостояния);
    КонецЕсли;
    
КонецПроцедуры

Подведем итоги

При интеграции 1С с amoCRM важно соблюдать следующие правила:

  1. Никогда не передавайте параметры отбора в теле GET-запроса. Всегда формируйте строку запроса URL и используйте метод HTTPСоединение.Получить().
  2. Для современных интеграций полностью откажитесь от устаревшей авторизации по сессионным кукам и перейдите на протокол OAuth 2.0.
  3. Не забывайте своевременно обновлять пару токенов (access_token и refresh_token) и перезаписывать их в своей базе данных, так как старый refresh_token аннулируется сервером сразу же после его использования.
  4. Для изменения объектов (лидов, контактов, задач) в API v4 используйте HTTP-метод PATCH с помощью универсального метода платформы 1С ВызватьHTTPМетод().
← На главную