Интеграция 1С с облачными CRM-системами, такими как amoCRM, является стандартной задачей для автоматизации современного бизнеса. Один из наиболее частых сценариев — получение списка сделок (лидов), которые были изменены или созданы после определенной даты. Это позволяет минимизировать объем передаваемых данных и синхронизировать только актуальную информацию.
В этой статье мы подробно разберем, как решить данную задачу. Сначала мы проанализируем историческое решение, обсуждавшееся на форуме (использование заголовка IF-MODIFIED-SINCE в устаревшем API v2), а затем рассмотрим современный, надежный и поддерживаемый способ реализации этой логики с помощью актуального API v4.
В более ранних версиях 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, Заголовки);
При таком запросе сервер возвращал абсолютно все сделки, игнорируя фильтр. Давайте выясним причину этой проблемы. Здесь крылись сразу две критические ошибки:
Fri, 15 Mar 2019 01:00:00 UTC.Рабочий вариант кода 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 механизм работы кардинально изменился в лучшую сторону. Разработчикам больше не нужно формировать сложные текстовые заголовки даты в формате RFC 1123 / RFC 2822 (такие как Fri, 15 Mar 2019...).
Давайте проанализируем ключевые изменения в API v4:
Authorization: Bearer [Access_Token].filter[updated_at].page).Рассмотрим детально, как написать надежный алгоритм получения измененных сделок на платформе 1С:Предприятие 8.3.
В 1С нет встроенной функции для мгновенного получения Unix Timestamp, но ее легко написать самостоятельно. Unix-время отсчитывается в секундах от даты 01.01.1970 00:00:00. При этом важно переводить дату в универсальное время (UTC), чтобы избежать проблем со смещением часовых поясов.
Создадим вспомогательную функцию:
Функция ДатаВUnixTimestamp(Знач ЛокальнаяДата) Экспорт
УниверсальнаяДата = УниверсальноеВремя(ЛокальнаяДата);
НачалоЭпохи = Дата(1970, 1, 1, 0, 0, 0);
Возврат Цел(УниверсальнаяДата - НачалоЭпохи);
КонецФункции
Поскольку измененных сделок может быть больше лимита в 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;
КонецЦикла;
КонецПроцедуры
В 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С успешно обработает любое количество измененных сделок без потери производительности и риска упереться в лимиты облачного сервера.