При интеграции платформы 1С с облачной CRM-системой amoCRM разработчики часто сталкиваются с необходимостью выгрузки больших массивов данных. Одной из базовых задач является получение полного списка контактов. Однако стандартные методы API накладывают жесткие ограничения на количество элементов, возвращаемых за один HTTP-запрос. Если попытаться получить все контакты напрямую, система вернет лишь начальную порцию данных.
В данной статье мы подробно разберем, как обойти это ограничение, проанализируем типичные ошибки разработчиков на примере обсуждения с форума, а также рассмотрим современный и правильный способ реализации постраничной навигации (пагинации) в 1С для актуальной версии amoCRM API v4.
Обратимся к ситуации, описанной в ветке форума. Разработчик пытался использовать устаревший метод API v2 /private/api/v2/json/contacts/list и столкнулся с системным ограничением в 500 элементов. В ходе обсуждения был предложен правильный путь решения — использование параметров limit_rows (размер порции) и limit_offset (сдвиг выборки).
Однако автор темы допустил критическую ошибку в логике, предположив следующее: если limit_rows не может быть больше 500, то и limit_offset должен принимать значения строго от 1 до 500. Проанализируем, почему этот вывод неверен.
Параметр limit_rows определяет, сколько элементов вернет сервер за один раз (размер страницы). А параметр limit_offset указывает, с какого по счету элемента (начиная с нуля) нужно начать выборку. Таким образом, смещение может принимать абсолютно любые значения, кратные размеру страницы.
Выясним причину на простом примере. Предположим, у нас в базе amoCRM содержится 1500 контактов. Чтобы выгрузить их все с шагом в 500 элементов, нам необходимо выполнить три последовательных запроса в цикле:
limit_rows = 500 и limit_offset = 0. Сервер возвращает контакты с 1 по 500.limit_rows = 500 и limit_offset = 500. Сервер возвращает контакты с 501 по 1000.limit_rows = 500 и limit_offset = 1000. Сервер возвращает контакты с 1001 по 1500.Этот цикл должен продолжаться до тех пор, пока сервер не вернет пустой массив данных, что будет означать окончание списка контактов.
Важно учитывать, что код из примера на форуме использует устаревший протокол авторизации по ключам USER_LOGIN и USER_HASH, а также устаревшую ветку API v2. На сегодняшний день поддержка старых версий API полностью прекращена разработчиками amoCRM. Авторизация теперь осуществляется по протоколу OAuth 2.0 с использованием токенов доступа (access_token), передаваемых в заголовках HTTP-запроса.
В актуальной версии API v4 механизм постраничной навигации претерпел существенные изменения:
limit_rows и limit_offset теперь используются более интуитивные параметры limit (количество элементов на страницу) и page (номер страницы)._links, который значительно упрощает переход по страницам.Посмотрим, как выглядит структура ссылки на следующую страницу в формате HAL JSON, возвращаемом сервером amoCRM:
{
"_links": {
"self": {
"href": "https://example.amocrm.ru/api/v4/contacts?limit=250&page=1"
},
"next": {
"href": "https://example.amocrm.ru/api/v4/contacts?limit=250&page=2"
}
},
"_embedded": {
"contacts": [
{ "id": 123, "name": "Иван Иванов" }
]
}
}
Благодаря наличию объекта _links.next.href, нам больше не нужно вручную рассчитывать смещения или номера страниц в коде 1С. Достаточно парсить полученный JSON-ответ, извлекать адрес следующей страницы и выполнять по нему запрос. Если свойство next отсутствует в структуре _links, это означает, что мы достигли конца списка.
Рассмотрим подробнее программный код на языке 1С для получения всех контактов с использованием API v4. Мы будем выполнять запросы в цикле, проверять код состояния ответа и анализировать структуру JSON для перехода на следующую страницу.
&НаСервере
Процедура ПолучитьВсеКонтактыИзAmoCRM()
// Настройки подключения к вашему аккаунту amoCRM
АдресРесурса = "example.amocrm.ru"; // Укажите субдомен вашей организации
ТокенДоступа = "ВАШ_ACCESS_TOKEN"; // Актуальный OAuth access_token
// Начальный путь для запроса первой страницы
ТекущийПуть = "/api/v4/contacts?limit=250&page=1";
Соединение = Новый HTTPСоединение(АдресРесурса, 443,,,,, Новый ЗащищенноеСоединениеOpenSSL());
СистематическийЦикл = Истина;
НомерСтраницы = 1;
Пока СистематическийЦикл Цикл
Запрос = Новый HTTPЗапрос(ТекущийПуть);
Запрос.Заголовки.Вставить("Authorization", "Bearer " + ТокенДоступа);
Запрос.Заголовки.Вставить("Content-Type", "application/json");
Попытка
Ответ = Соединение.Получить(Запрос);
Исключение
ЗаписьЖурналаРегистрации("amoCRM.Интеграция", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
Прервать;
КонецПопытки;
КодСостояния = Ответ.КодСостояния;
// Если контакты закончились, сервер возвращает код HTTP 204 No Content
Если КодСостояния = 204 Тогда
ЗаписьЖурналаРегистрации("amoCRM.Интеграция", УровеньЖурналаРегистрации.Информация,,, "Все контакты успешно загружены.");
Прервать;
ИначеЕсли КодСостояния <> 200 Тогда
ЗаписьЖурналаРегистрации("amoCRM.Интеграция", УровеньЖурналаРегистрации.Предупреждение,,, "Неожиданный ответ сервера: " + КодСостояния);
Прервать;
КонецЕсли;
// Чтение и парсинг полученных данных
ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоОтвета);
ДанныеОтвета = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Обрабатываем контакты из текущей выборки
Если ДанныеОтвета.Свойство("_embedded") И ДанныеОтвета._embedded.Свойство("contacts") Тогда
МассивКонтактов = ДанныеОтвета._embedded.contacts;
Для Каждого Контакт Из МассивКонтактов Цикл
// Здесь выполняется логика обработки конкретного контакта
ИмяКонтакта = Контакт.name;
IDКонтакта = Контакт.id;
КонецЦикла;
КонецЕсли;
// Проверяем наличие следующей страницы через объект _links
ЕстьСледующаяСтраница = Ложь;
Если ДанныеОтвета.Свойство("_links") И ДанныеОтвета._links.Свойство("next") Тогда
ПолныйАдресСледующей = ДанныеОтвета._links.next.href;
// Извлекаем относительный путь из полного URL
ПозицияПути = Найти(ПолныйАдресСледующей, "/api/v4/");
Если ПозицияПути > 0 Тогда
ТекущийПуть = Сред(ПолныйАдресСледующей, ПозицияПути);
ЕстьСледующаяСтраница = Истина;
КонецЕсли;
КонецЕсли;
// Если следующей страницы нет - завершаем цикл выгрузки
Если Не ЕстьСледующаяСтраница Тогда
Прервать;
КонецЕсли;
// Применяем задержку для обхода лимитов на количество запросов в секунду
ПриостановитьВыполнениеПотока(0.2);
НомерСтраницы = НомерСтраницы + 1;
КонецЦикла;
КонецПроцедуры
Для корректного разбора структуры JSON мы используем встроенные в платформу 1С объекты ЧтениеJSON и функцию ПрочитатьJSON(). Это позволяет транслировать строки JSON в стандартное дерево значений, соответствия и структуры платформы 1С, обеспечивая обращение к параметрам через точку (например, ДанныеОтвета._links.next.href).
При написании подобных циклических алгоритмов в 1С крайне важно учитывать системные ограничения платформы amoCRM на частоту запросов. В amoCRM установлено ограничение: не более 7 запросов в секунду для одной интеграции.
Если база содержит тысячи контактов, и цикл в 1С будет выполняться без пауз, вы мгновенно исчерпаете этот лимит. В ответ на ваши запросы сервер начнет возвращать ошибку с кодом 429 Too Many Requests, а сессия интеграции может быть временно заблокирована.
Чтобы избежать этой проблемы, мы принудительно замедляем выполнение цикла 1С между запросами страниц. В коде выше мы применили процедуру ПриостановитьВыполнениеПотока(). Посмотрим, как ее можно реализовать в 1С:
Процедура ПриостановитьВыполнениеПотока(Секунды)
// Для платформы 1С v8.3.15 и выше доступен штатный метод приостановки
Попытка
ПриостановитьВыполнение(Секунды);
Исключение
// Альтернативный метод задержки для старых версий платформы через Wscript.Shell
Попытка
WshShell = Новый COMОбъект("Wscript.Shell");
WshShell.Run("ping -n " + Строка(Секунды + 1) + " 127.0.0.1", 0, Истина);
Исключение
// Резервный пустой цикл, если COM-объект недоступен
НачалоПаузы = ТекущаяДата();
Пока ТекущаяДата() - НачалоПаузы < Секунды Цикл
// Холостой ход
КонецЦикла;
КонецПопытки;
КонецПопытки;
КонецПроцедуры
Оптимальный интервал задержки между запросами страниц составляет около 150–200 миллисекунд (0.2 секунды). Это гарантирует стабильную загрузку тысяч контактов без риска блокировки сессии со стороны amoCRM.
Используя предложенные методики пагинации и контроля лимитов, мы можем построить надежный и отказоустойчивый мост интеграции между 1С и amoCRM, обеспечивающий корректную синхронизацию списков любой длины.