Задача: контрагенты в бухгалтерии, продажи — в Битрикс24
Клиент ведёт учёт в 1С:Бухгалтерии предприятия 3.0 с доработанным блоком коммерческих предложений: там живут контрагенты, договоры, контактные лица, номенклатура и сами КП. А отдел продаж работает в Битрикс24 — воронка, компании, контакты, сделки. Пока данные переносили руками, менеджеры видели не тот статус, в CRM плодились дубли контрагентов, а бухгалтерия не знала, на какой стадии сделка.
Нужен был автоматический обмен: контрагент и контактное лицо из 1С должны появляться в Битрикс24 как компания и контакт, коммерческое предложение — как сделка на нужной стадии воронки, а остатки номенклатуры — подтягиваться в карточку товара CRM. Всё это — без переписывания типовой Бухгалтерии, чтобы конфигурация оставалась на поддержке и обновлялась штатно.
Решение: расширение-коннектор поверх типовой конфигурации
Интеграцию собрали как расширение конфигурации (Vendor — ИП Низамов Илья Юрьевич). Типовые объекты не меняли: справочники «Контрагенты», «Контактные лица», «Номенклатура» и документ коммерческого предложения заимствованы в расширение, и к ним добавлен лишь обработчик «после записи». Вся логика обмена вынесена в собственные общие модули по схеме MVC: контроллер (что синхронизируем), модель (как собрать данные объекта для CRM) и ядро (единая обёртка над REST Битрикс24).
- Контроллеры —
ns_Bitrix24Company,ns_Bitrix24Contact,ns_Bitrix24Deal,ns_Bitrix24Product; - Модели —
ns_Bitrix24CompanyModel,ns_Bitrix24DealModelи т.д. (сборка полей объекта); - Ядро —
ns_Bitrix24Core: авторизация, HTTP, дженерик REST-методы; - Служебные регистры — сопоставление ID, очередь изменений, настройки, лог, даты сверки.
Авторизация: OAuth 2.0 к коробочному Битрикс24
Портал у клиента — коробочная версия Битрикс24, поэтому авторизация идёт по полному циклу
OAuth 2.0: запрос authorize отдаёт редирект 302 с параметром
code, затем code обменивается на access_token и
refresh_token через oauth.bitrix.info. Токены и время их жизни
хранятся в регистре настроек, а перед каждым запросом ядро само продлевает истёкший токен.
Функция ИнициализацияПодключения(НастройкаПодключения) Экспорт
// 1. authorize -> редирект 302 с параметром code
Соединение = ПолучитьHTTPСоединение(Перечисления.ns_ТипыHTTPЗапросов.oauth, НастройкаПодключения);
Ответ = Соединение.Получить(ЗапросHTTP_Authorize(НастройкаПодключения));
Если Ответ.КодСостояния <> 302 Тогда Возврат ОбработатьОшибку(...); КонецЕсли;
ПараметрыОтвета = ПолучитьСписокПараметров(Ответ.Заголовки.Получить("Location"));
Код = ПараметрыОтвета.Получить("code");
Cookie = Ответ.Заголовки.Получить("Set-Cookie");
// 2. code -> access_token + refresh_token на oauth.bitrix.info
Ответ = ПолучитьHTTPСоединение(Перечисления.ns_ТипыHTTPЗапросов.token, НастройкаПодключения)
.Получить(ЗапросHTTP_Token(НастройкаПодключения, Код, Cookie));
ДанныеТокена = ПрочитатьJSON(Ответ.ПолучитьТелоКакСтроку());
РегистрыСведений.ns_Settings.RecordSetting(..AccessToken, ДанныеТокена.access_token);
РегистрыСведений.ns_Settings.RecordSetting(..RefreshToken, ДанныеТокена.refresh_token);
РегистрыСведений.ns_Settings.RecordSetting(..RefreshTime, ТекущаяДата() + ДанныеТокена.expires_in);
КонецФункции
// Перед каждым запросом — автопродление истёкшего токена:
Процедура ПроверитьТокен(Настройка)
Если Настройка[..RefreshTime] < ТекущаяДата() Тогда
ОбновитьТокен();
КонецЕсли;
КонецПроцедуры
Единая обёртка над REST Битрикс24
Все вызовы CRM идут через один метод ядра. Он подставляет актуальный токен, разбирает
ответ и различает result и error. Отдельно обрабатывается ситуация,
когда объект в CRM уже удалён («Not found») — тогда сопоставление в регистре очищается, чтобы
1С не била в несуществующий ID. Поверх этого — тонкие дженерик-методы над
<entity>.<method>: Добавить, Обновить,
Получить, Удалить, Список.
Функция ОтправитьЗапрос(МетодREST, Данные = "", ...) Экспорт
Настройка = РегистрыСведений.ns_Settings.GetAListOfSettings();
ПроверитьТокен(Настройка); // авто-refresh
Результат = ОтправитьRESTЗапрос(Настройка, МетодREST, Данные);
Структура = JSONDecode(Результат);
Если Структура.Получить("result") <> Неопределено Тогда
Возврат Структура["result"];
ИначеЕсли Структура.Получить("error") <> Неопределено Тогда
Если СтрНайти(Структура["error_description"], "Not found") > 0 Тогда
РегистрыСведений.ns_DataMapping.ОчиститьСопоставление(Сущность, id); // удалён в CRM
КонецЕсли;
Возврат ОбработатьОшибку("ОтправитьЗапрос", Структура["error_description"]);
КонецЕсли;
КонецФункции
// Дженерик над любым методом CRM:
Функция Добавить(Сущность, Поля) Экспорт
Тело = Новый Соответствие; Тело.Вставить("fields", Поля);
Возврат ОтправитьЗапрос(Строка(Сущность) + ".add", JSONEncode(Тело)); // crm.company.add и т.п.
КонецФункции
Событийная выгрузка через очередь изменений
Обмен не дёргает CRM прямо в момент проведения документа. При записи заимствованного
объекта обработчик «после записи» лишь регистрирует изменение в регистре-очереди
ns_ExchangeBitrix24. Отдельный регламентный процесс разбирает очередь пачкой,
диспетчеризуя объект по типу сущности. Так проведение документа не тормозит на сетевых
запросах, а сбой связи не рушит запись в 1С.
// Заимствованный справочник «Контрагенты» — добавлен обработчик после записи:
&После("ПриЗаписи")
Процедура ns_ПриЗаписи(Отказ)
Если НЕ Отказ Тогда
УстановитьПривилегированныйРежим(Истина);
ns_Bitrix24Server.RegistrationOfChanges(Перечисления.ns_EntitiesBitrix24.crm_company, Ссылка, Ложь);
КонецЕсли;
КонецПроцедуры
// Регламентная обработка очереди — диспетчер по типу объекта:
Процедура ОбменBitrix24() Экспорт
Для Каждого Изменение Из РегистрыСведений.ns_ExchangeBitrix24.ВыбратьИзменения() Цикл
Если ТипЗнч(Изменение.ObjectReference) = Тип("ДокументСсылка.КоммерческоеПредложение") Тогда
ns_Bitrix24Deal.DB_POST(Изменение.ObjectReference); // КП -> сделка
ИначеЕсли Изменение.Entity = Перечисления.ns_EntitiesBitrix24.crm_company Тогда
ns_Bitrix24Company.DB_POST(Изменение.ObjectReference); // контрагент -> компания
ИначеЕсли Изменение.Entity = Перечисления.ns_EntitiesBitrix24.crm_contact Тогда
ns_Bitrix24Contact.DB_POST(Изменение.ObjectReference); // контактное лицо
КонецЕсли;
ns_Bitrix24Core.Pause(); // пауза между вызовами CRM
КонецЦикла;
КонецПроцедуры
Контрагенты и контакты → компании и контакты CRM
Контроллер сущности решает: если для объекта уже есть ID в регистре сопоставления —
делаем update, иначе add. Модель собирает поля для CRM, а полученный
из ответа ID тут же записывается в ns_DataMapping. Один и тот же паттерн работает
для контрагентов (crm.company), контактных лиц (crm.contact) и
номенклатуры (crm.product).
Функция ДобавитьОбновить(ID, СсылкаНаОбъект)
Если ЗначениеЗаполнено(ID) Тогда
Результат = ns_Bitrix24Core.Обновить(ПолучитьСущность(), ID,
ns_Bitrix24CompanyModel.ПолучитьДанныеОбъекта(СсылкаНаОбъект, Истина));
Иначе
Результат = ns_Bitrix24Core.Добавить(ПолучитьСущность(),
ns_Bitrix24CompanyModel.ПолучитьДанныеОбъекта(СсылкаНаОбъект));
КонецЕсли;
// сохраняем сопоставление «ссылка 1С — ID Битрикс24»
ns_Bitrix24CompanyModel.ОбработатьРезультат(Результат, СсылкаНаОбъект);
Возврат Результат;
КонецФункции
Коммерческое предложение → сделка воронки
Самая содержательная часть — маппинг КП на crm.deal. Из документа собираются
заголовок, компания и контакт (через те же контроллеры), тип сделки, а статус КП
переводится в стадию воронки Битрикс24 по справочнику стадий, который коннектор сам
подтягивает из CRM (crm.status + типы сущностей). Прикладные атрибуты КП (номер,
тип, количество продукции, адрес объекта и доставки) уезжают в пользовательские поля сделки
UF_CRM_*.
Данные.Вставить("TITLE", "КП " + Выборка.Номер + " от " + Формат(Выборка.Дата, "ДЛФ=D"));
Данные.Вставить("COMPANY_ID", ns_Bitrix24Company.DB_POST(Выборка.Контрагент)); // контрагент -> компания
СписокКонтактов = Новый Массив;
СписокКонтактов.Добавить(ns_Bitrix24Contact.DB_POST(Выборка.КонтактноеЛицо));
Данные.Вставить("CONTACT_IDS", СписокКонтактов);
Данные.Вставить("TYPE_ID", "SALE");
// Статус КП -> стадия воронки
Если Выборка.Ссылка.ПометкаУдаления Тогда
Данные.Вставить("STAGE_ID", 13); // «Проиграно»
ИначеЕсли ЗначениеЗаполнено(Выборка.Статус) Тогда
Данные.Вставить("STAGE_ID", ns_Bitrix24Status.НайтиСтатусВВоронкеПоСсылке(Выборка.Статус));
Иначе
Данные.Вставить("STAGE_ID", "NEW");
КонецЕсли;
// Прикладные атрибуты -> пользовательские поля сделки
Данные.Вставить("UF_CRM_1563552145", Выборка.Номер); // Номер КП
Данные.Вставить("UF_CRM_1560747914", ПолучитьТипКП(Выборка.ТипКП)); // Тип КП
Данные.Вставить("UF_CRM_1560747580", ПолучитьКоличествоПродукции(Выборка.Ссылка));
Обмен остатками номенклатуры
Для номенклатуры сделали отдельную очередь ns_ExchangeBitrixRemains и свой
проход: остатки не смешиваются с обменом карточек товара и гонятся своим регламентом методом
DB_POST_REMAINS. Так менеджер в CRM видит актуальное наличие, не заглядывая в 1С,
а нагрузка на портал от частого обновления остатков не мешает основному обмену.
Двусторонняя синхронизация и защита от дублей
Обмен работает в обе стороны. Из 1С в CRM — по очереди изменений. Из CRM в 1С — инкрементально:
коннектор запрашивает у Битрикс24 только записи с DATE_MODIFY позже последней
даты сверки (регистр ns_DateVerification), находит объект по
регистру сопоставления ns_DataMapping и создаёт/обновляет документ. Ключевые
приёмы против дублей и зацикливания:
- Регистр сопоставления «ссылка 1С ↔ ID Битрикс24» — один объект никогда не создаётся дважды;
- Даты сверки по каждой сущности — тянем только дельту, а не всю базу;
- Самоочистка сопоставления при ответе «Not found» — если объект удалён в CRM, 1С это замечает и не долбит мёртвый ID;
- Лог и консоль разработчика (
ns_DeveloperConsole) — видно каждый запрос и ответ, обмен диагностируется без отладчика.
Что не меняли и как это переносится
Типовую 1С:Бухгалтерию не трогали — вся интеграция изолирована в расширении, поэтому конфигурация обновляется штатно. Настройки портала (адрес, логин, ключи) вынесены в регистр, а не зашиты в код, так что тот же коннектор переносится на другой портал или базу заменой параметров подключения. Тот же авторский движок мы ставили и на другие конфигурации 1С — меняется только модель сущностей и набор синхронизируемых объектов.
Похожие интеграции 1С ↔ Битрикс24
Этот коннектор — часть линейки наших интеграций Битрикс24 под разные конфигурации:
- 1С:Управление торговлей 10.3 → Битрикс24 CRM — торговый учёт, сделки и товары;
- Битрикс24 для автосервиса — заказ-наряды становятся сделками воронки;
- 1С:ERP → Битрикс24, смарт-процессы — сделки, задачи и crm.item производственного предприятия.
Разбираем такую интеграцию по шагам — от OAuth 2.0 до обмена данными — на курсе «Интеграция 1С и Битрикс24 через расширения». Хотите такую же связку под свою базу — закажите разработку.