Как получить измененные сделки из amoCRM в 1С через HTTP-запрос?

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

Интеграция 1С с облачными CRM-системами, такими как amoCRM, является стандартной задачей для автоматизации современного бизнеса. Один из наиболее частых сценариев — получение списка сделок (лидов), которые были изменены или созданы после определенной даты. Это позволяет минимизировать объем передаваемых данных и синхронизировать только актуальную информацию.

В этой статье мы подробно разберем, как решить данную задачу. Сначала мы проанализируем историческое решение, обсуждавшееся на форуме (использование заголовка IF-MODIFIED-SINCE в устаревшем API v2), а затем рассмотрим современный, надежный и поддерживаемый способ реализации этой логики с помощью актуального API v4.

Исторический контекст: Использование заголовка IF-MODIFIED-SINCE в API v2

В более ранних версиях API amoCRM (в частности, v2) для получения сущностей, измененных позже определенной даты, разработчики предлагали использовать стандартный HTTP-заголовок IF-MODIFIED-SINCE. Этот заголовок передает серверу время последнего обновления в текстовом формате. Если сущность изменилась после указанной даты, сервер возвращает ее в ответе.

Разберем ситуацию, с которой столкнулся автор темы на форуме. Код в 1С выглядел следующим образом:


Заголовки = Новый Соответствие;                                 
ЗначениеЗаголовка = "Fri, 01 Mar 2019 12:00:00";
Заголовки.Вставить("IF-MODIFIED-SINCE", ЗначениеЗаголовка);
HTTPЗапрос = Новый HTTPЗапрос("/private/api/v2/json/leads/list?&USER_LOGIN="+USER_LOGIN+"&USER_HASH="+USER_HASH, Заголовки);

При таком запросе сервер возвращал абсолютно все сделки, игнорируя фильтр. Давайте выясним причину этой проблемы. Здесь крылись сразу две критические ошибки:

  1. Неверная временная зона (таймзона): Сервер amoCRM ожидает дату строго в формате UTC. Если передать локальное время без указания смещения или суффикса UTC, сервер может не распознать заголовок и вернуть весь массив данных. Правильный формат строки даты выглядит так: Fri, 15 Mar 2019 01:00:00 UTC.
  2. Проблема интерпретации объема данных: Получив в ответ большой массив данных (например, 500 сделок), разработчик предположил, что фильтрация не сработала и вернулись вообще все сделки из базы. Однако на активных порталах за несколько дней может измениться несколько тысяч сделок. После сокращения интервала до пары часов запрос вернул корректные 77 записей, что подтвердило работоспособность механизма.

Рабочий вариант кода 1С для исторической версии API v2 выглядит следующим образом:


Заголовки = Новый Соответствие; 
Заголовки.Вставить("IF-MODIFIED-SINCE", "Fri, 15 Mar 2019 01:00:00 UTC");

ПутьКРесурсу = "/private/api/v2/json/leads/list?&USER_LOGIN=" + USER_LOGIN + "&USER_HASH=" + USER_HASH;
HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу, Заголовки);

Важное предупреждение: Использование API v2 и авторизации по связке USER_LOGIN и USER_HASH на текущий момент полностью прекращено и не поддерживается со стороны amoCRM. Попытка выполнить такой запрос в современной системе вернет ошибку авторизации. Ниже мы разберем актуальный и безопасный подход.

Современное решение: Фильтрация по дате изменения в API v4

В актуальной версии API v4 механизм работы кардинально изменился в лучшую сторону. Разработчикам больше не нужно формировать сложные текстовые заголовки даты в формате RFC 1123 / RFC 2822 (такие как Fri, 15 Mar 2019...).

Давайте проанализируем ключевые изменения в API v4:

Реализация интеграции на 1С (API v4) по шагам

Рассмотрим детально, как написать надежный алгоритм получения измененных сделок на платформе 1С:Предприятие 8.3.

Шаг 1: Конвертация даты 1С в Unix Timestamp

В 1С нет встроенной функции для мгновенного получения Unix Timestamp, но ее легко написать самостоятельно. Unix-время отсчитывается в секундах от даты 01.01.1970 00:00:00. При этом важно переводить дату в универсальное время (UTC), чтобы избежать проблем со смещением часовых поясов.

Создадим вспомогательную функцию:


Функция ДатаВUnixTimestamp(Знач ЛокальнаяДата) Экспорт
    УниверсальнаяДата = УниверсальноеВремя(ЛокальнаяДата);
    НачалоЭпохи = Дата(1970, 1, 1, 0, 0, 0);
    Возврат Цел(УниверсальнаяДата - НачалоЭпохи);
КонецФункции

Шаг 2: Выполнение HTTP-запроса с фильтрацией и пагинацией

Поскольку измененных сделок может быть больше лимита в 250 штук, мы должны организовать цикл. Будем запрашивать данные постранично, увеличивая параметр page на единицу на каждой итерации, пока сервер не вернет пустой результат (HTTP-статус 204 No Content или пустой JSON-массив).

Давайте посмотрим на пример реализации такого цикла в 1С:


Процедура ПолучитьИзмененныеСделки(ДатаСреза, ИмяСервера, ТокенДоступа)
    
    // Переводим дату 1С в формат Unix Timestamp
    TimestampСреза = ДатаВUnixTimestamp(ДатаСреза);
    
    // Настраиваем HTTP-соединение
    // Используем защищенное соединение OpenSSL, так как amoCRM работает по HTTPS
    ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
    HTTPСоединение = Новый HTTPСоединение(ИмяСервера, 443,,,,, ЗащищенноеСоединение);
    
    // Формируем базовые заголовки для авторизации и формата данных
    Заголовки = Новый Соответствие;
    Заголовки.Вставить("Authorization", "Bearer " + ТокенДоступа);
    Заголовки.Вставить("Content-Type", "application/json");
    
    НомерСтраницы = 1;
    КоличествоСделокВЗапросе = 250;
    
    Пока Истина Цикл
        
        // Формируем параметры фильтрации в строке запроса
        // Запрашиваем сделки, у которых дата изменения (updated_at) больше или равна нашей дате среза [from]
        ПараметрыЗапроса = СтрШаблон("filter[updated_at][from]=%1&limit=%2&page=%3", 
            Формат(TimestampСреза, "ЧГ=0"), 
            Формат(КоличествоСделокВЗапросе, "ЧГ=0"), 
            Формат(НомерСтраницы, "ЧГ=0"));
            
        АдресРесурса = "/api/v4/leads?" + ПараметрыЗапроса;
        
        HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
        
        Попытка
            HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
        Исключение
            ЗаписьЖурналаРегистрации("ИнтеграцияamoCRM", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
            ВызватьИсключение "Ошибка соединения с сервером amoCRM.";
        КонецПопытки;
        
        // Код 204 означает, что данных больше нет (пустая страница)
        Если HTTPОтвет.КодСостояния = 204 Тогда
            Прервать;
        КонецЕсли;
        
        Если HTTPОтвет.КодСостояния <> 200 Тогда
            СообщениеОбОшибке = СтрШаблон("Ошибка сервера amoCRM. Код ответа: %1. Текст: %2", 
                HTTPОтвет.КодСостояния, 
                HTTPОтвет.ПолучитьТелоКакСтроку());
            ЗаписьЖурналаРегистрации("ИнтеграцияamoCRM", УровеньЖурналаРегистрации.Предупреждение,,, СообщениеОбОшибке);
            Прервать;
        КонецЕсли;
        
        // Обрабатываем полученный JSON
        ТелоОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
        ОбработатьСтраницуСделок(ТелоОтвета);
        
        // Переходим к следующей странице
        НомерСтраницы = НомерСтраницы + 1;
        
    КонецЦикла;
    
КонецПроцедуры

Шаг 3: Разбор JSON-ответа

В API v4 amoCRM возвращает данные в расширенном формате HAL JSON. Это означает, что массив сущностей находится в специальном объекте _embedded. Напишем процедуру для разбора этого формата в 1С с помощью стандартных средств платформы (ЧтениеJSON):


Процедура ОбработатьСтраницуСделок(Знач СтрокаJSON)
    
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(СтрокаJSON);
    
    ДанныеОтвета = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();
    
    // Проверяем наличие структуры _embedded и массива сделок (leads)
    Если ТипЗнч(ДанныеОтвета) = Тип("Соответствие") Или ТипЗнч(ДанныеОтвета) = Тип("Структура") Тогда
        
        Если ДанныеОтвета.Свойство("_embedded") Тогда
            ВложенныеДанные = ДанныеОтвета["_embedded"];
            
            Если ВложенныеДанные.Свойство("leads") Тогда
                МассивСделок = ВложенныеДанные["leads"];
                
                Для Каждого Сделка Из МассивСделок Цикл
                    // Здесь реализуется логика обновления данных в 1С
                    // Например, поиск по ID сделки и перезапись реквизитов
                    IDСделки = Сделка["id"];
                    ИмяСделки = Сделка["name"];
                    ДатаИзмененияUnix = Сделка["updated_at"];
                    
                    // Переводим Unix Timestamp обратно в дату 1С для записи в информационную базу
                    ДатаИзменения1С = Дата(1970, 1, 1, 0, 0, 0) + ДатаИзмененияUnix + СмещениеКлиента(ТекущаяДата());
                    
                    // Дополнительная обработка...
                КонецЦикла;
                
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

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

Мы подробно разобрали, как эволюционировал процесс работы с датами изменений в интеграциях между 1С и amoCRM. Использование заголовка IF-MODIFIED-SINCE являлось стандартом для API v2, но требовало ювелирной точности при сборке текстовой строки даты с явным указанием зоны UTC. Любая ошибка в символе приводила к тому, что фильтр игнорировался.

Переход на API v4 упростил задачу: теперь мы фильтруем сделки с помощью интуитивного параметра запроса filter[updated_at][from] и передаем дату в формате простых секунд (Unix Timestamp). Построение правильного постраничного обхода гарантирует, что ваша система 1С успешно обработает любое количество измененных сделок без потери производительности и риска упереться в лимиты облачного сервера.

← На главную