Интеграционная прослойка на Golang и 1С 8.3: HTTP-сервисы для CRUD «Клиентов» и приём JSON из RabbitMQ

07.10.26

Интеграция - WEB-интеграция

Пошагово связываем middleware на Go с 1С:Предприятие 8.3 через два HTTP-сервиса: CRUD по справочнику «Клиенты» и POST-приём JSON из RabbitMQ. Разбираем публикацию, net/http, идемпотентность и чтение через OData.

В этой части цикла настраиваем обмен с 1С через два опубликованных НТТР-сервиса: CRUD по логическому справочнику «Клиенты» и приём JSON из RabbitMQ. Прослойка middleware на Golang не опрашивает базу по таймеру: изменения идут по HTTP, события из очереди попадают в ту же информационную базу отдельным POST в платформу 1С:Предприятие 8.3.

 

Где в цикле middleware стоят два НТТР-сервиса 1С

RabbitMQ и контейнер прослойки уже подняты в частях 1–4; здесь только URL вида /hs/… и контракт JSON к справочнику. К НТТР-сервисам платформы подходим там, где внешней системе нужен предсказуемый контракт, а очередь должна доставлять события в ту же базу без постоянного СОМ-соединения и регламентных файлов на шару.

Логическая модель для всех каналов одна: справочник «Клиенты» с реквизитами Идентификатор (строка или UUID по вашему правилу), Имя, Тип, Майл. Прослойка в режиме «1С» ходит в первый сервис методами GET, POST и DELETE. Consumer RabbitMQ в Go (или НТТР-мост брокера, если вы его используете) отправляет JSON клиента методом POST во второй сервис. Оба сервиса пишут в один справочник, поэтому запись из очереди должна появиться в выборке первого сервиса.

На поддерживаемой типовой конфигурации тот же приём переносят в расширение: справочник-аналог или дополнительные реквизиты, НТТР-сервисы только в расширении, публикация с включённым расширением. Объекты не должны конфликтовать с основной конфигурацией по имени - тогда снимать базу с поддержки для эксперимента не требуется.

 

НТТР-сервис CRUD: JSON, GET, POST, DELETE и отбор без пометки удаления

В конфигураторе 8.3 создайте объект «НТТР-сервис», задайте корневой URL (например, clients) и шаблоны. Каждый шаблон связывается с НТТР-методом и экспортной функцией сервисного общего модуля (сервер, вызов сервера, без клиентских вызовов). Имена функций платформа подставляет сама, если вы указали их в свойствах шаблона; ниже - схема, которую я обычно повторяю на стенде.

  • GET /list - ClientsListGET(Запрос) - массив клиентов без пометки удаления.
  • GET /item/{id} - ClientsItemGET(Запрос) - один клиент по Идентификатору из URL.
  • POST /item - ClientsItemPOST(Запрос) - создание или обновление по телу JSON.
  • DELETE /item/{id} - ClientsItemDELETE(Запрос) - удаление по идентификатору из URL.

Контракт ответа для списка - массив объектов JSON с полями идентификатора, имени, типа и почты. POST принимает JSON в теле: если элемент с таким Идентификатором уже есть, обновляем реквизиты (в JSON поле «Имя» пишем в Наименование справочника), иначе создаём элемент. DELETE в эталоне физически удаляет элемент; если у вас принята только пометка удаления, GET обязан исключать такие строки тем же правилом, что и запрос списка.

Ответ собираю через HTTPСервисОтвет: код 200 для успешного чтения, 201 для создания, 400 при кривом JSON, 404 если идентификатор не найден, 500 только когда ошибка записи не связана с входными данными. В теле ответа - короткий JSON с полем error, чтобы прослойка на Golang отличила 404 от 500.

Перед записью проверяю Идентификатор и обязательные поля на сервере, без УстановитьПривилегированныйРежим(Истина) без явной причины. Запись от имени пользователя публикации сохраняет RLS и права так, как настроено в роли.

Для ГЕТ-списка отбираю только элементы без пометки удаления.

ВЫБРАТЬ
    Клиенты.Идентификатор КАК Идентификатор,
    Клиенты.Наименование КАК Имя,
    Клиенты.Тип КАК Тип,
    Клиенты.Майл КАК Майл
ИЗ
    Справочник.Клиенты КАК Клиенты
ГДЕ
    НЕ Клиенты.ПометкаУдаления
    И НЕ Клиенты.ЭтоГруппа

Результат запроса сериализую в JSON и отдаю в теле ответа. Если в выборку попадёт помеченный элемент, прослойка и автоматические проверки разойдутся с учётом - это первое, что я проверяю после правки отбора.

Фрагмент обработчика списка (идентификатор из URL для других шаблонов берётся из Запрос.ПараметрыURL):

Функция ClientsListGET(Запрос)

 ЗапросДанных = Новый Запрос;
 ЗапросДанных.Текст =
 "ВЫБРАТЬ
 | Клиенты.Идентификатор,
 | Клиенты.Наименование КАК Имя,
 | Клиенты.Тип,
 | Клиенты.Майл
 |ИЗ
 | Справочник.Клиенты КАК Клиенты
 |ГДЕ
 | НЕ Клиенты.ПометкаУдаления
 | И НЕ Клиенты.ЭтоГруппа";

 Выборка = ЗапросДанных.Выполнить().Выбрать();
 Массив = Новый Массив;
 Пока Выборка.Следующий() Цикл
 Массив.Добавить(СтрокаКлиентаВСтруктуру(Выборка));
 КонецЦикла;

 Возврат ОтветJSON(200, ЗаписатьJSONКлиентов(Массив));

КонецФункции

POST оборачиваю в одну транзакцию: прочитал JSON, нашёл ссылку по Идентификатору, записал объект, зафиксировал. При повторной доставке того же JSON из RabbitMQ срабатывает идемпотентность: обновление вместо второго элемента с тем же ключом. Тело разбираю через ЧтениеJSON; пустой Идентификатор отсекаю до транзакции.

Функция ClientsItemPOST(Запрос)

 Тело = Запрос.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
 Данные = ПрочитатьJSONКлиента(Тело);
 Если Не ЗначениеЗаполнено(Данные.Идентификатор) Тогда
 Возврат ОтветJSON(400, "{\"error\":\"empty id\"}");
 КонецЕсли;

 НачатьТранзакцию();
 Попытка
 Элемент = НайтиИлиСоздатьКлиентаПоИдентификатору(Данные.Идентификатор);
 ЗаполнитьРеквизитыКлиента(Элемент, Данные);
 Элемент.Записать();
 ЗафиксироватьТранзакцию();
 Код =?(Элемент.ЭтоНовый(), 201, 200);
 Возврат ОтветJSON(Код, ЗаписатьJSONКлиента(Элемент));
 Исключение
 ОтменитьТранзакцию();
 Возврат ОтветJSON(500, "{\"error\":\"write failed\"}");
 КонецПопытки;

КонецФункции

DELETE по идентификатору из шаблона URL:

Функция ClientsItemDELETE(Запрос)

 Ид = Запрос.ПараметрыURL.Получить("id");
 Ссылка = Справочники.Клиенты.НайтиПоРеквизиту("Идентификатор", Ид);
 Если Не ЗначениеЗаполнено(Ссылка) Тогда
 Возврат ОтветJSON(404, "{\"error\":\"not found\"}");
 КонецЕсли;

 Объект = Ссылка.ПолучитьОбъект();
 Объект.Удалить();
 Возврат ОтветJSON(200, "{\"ok\":true}");

КонецФункции

Одинаковую запись в справочник из CRUD и из приёмника очереди удобнее вынести в общий серверный модуль (поиск по Идентификатору, валидация, транзакция), а в НТТР-модулях оставить только разбор запроса и выбор кода ответа - иначе два сервиса быстро разъедутся при правке.

Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(ТелоJSON, КодировкаТекста.UTF8);

Тестовое тело для Postman и для сообщения в RabbitMQ (один и тот же JSON): {"Идентификатор":"client-1","Имя":"Demo","Тип":"B2B","Майл":"demo@example.local"}.

 

Публикация на IIS, Apache или встроенном веб-сервере и первые запросы снаружи

НТТР-сервис заработает для middleware только после публикации информационной базы на веб-сервере. В материалах цикла фигурировал IIS; на актуальных стендах часто встречаются Apache или встроенный НТТР-сервис платформы (зависит от релиза 8.3.x и политики ИБ). Сначала публикация ИБ с НТТР-сервисами, затем сверка default.vrd, затем пробный GET с той же учёткой, что у Go.

В default.vrd смотрю, что корневой URL сервиса совпадает с конфигуратором и что база доступна по виртуальному каталогу интегратора. 404 снаружи чаще всего означает неверный путь после /hs/ или опечатку в имени сервиса. 401 на POST из RabbitMQ обычно связан с аутентификацией: Basic или Windows там, где это включено на сайте.

Учётную запись публикации выделяю отдельно, с правами только на справочник «Клиенты». Пароль храним в секретах прослойки, не в репозитории.

Ниже - чек-лист из пяти проверок без повторения установки IIS. Пошаговые инструкции по публикации на IIS и Apache ищите на Infostart по тегам «публикация» и «НТТР-сервис» - здесь только контрольные точки для интегратора.

  1. GET …/hs/clients/list - 200 и JСОН-массив (может быть пустым).
  2. POST …/hs/clients/item с тестовым JSON - 201 или 200.
  3. GET …/hs/clients/item/client-1 - та же запись.
  4. DELETE …/hs/clients/item/client-1 - 200, повторный GET - 404.
  5. Тот же URL и заголовок Authorization, что пропишете в consumer RabbitMQ.

На Apache проверяю права на каталог публикации и прокси перед платформой. Встроенный веб-сервер удобен на стенде; для POST с другого хоста смотрю firewall и совпадение URL в consumer с ручным тестом.

 

Режим «1С» в прослойке на Golang: net/http и слабые места примера

В конфигурации middleware задаём режим работы «1С» и базовый URL опубликованного СРУД-сервиса (схема, хост, порт, виртуальный каталог, /hs/clients/ и хвост шаблона). Пример фрагмента конфига (имена переменных у вас могут отличаться): ONEC_MODE=1c, ONEC_BASE_URL=https://stand.example/local/hs/clients, ONEC_USER=integration, ONEC_PASSWORD=… из секрета, не из git.

Дальше сценарий прямой: GET …/list - список; DELETE …/item/{id} - удаление; POST …/item с телом JSON - изменение или добавление; в конфигураторе или повторным GET убеждаемся, что база 1С изменилась.

На стороне Go достаточно стандартного net/http. GET списка - http.Get с разбором тела через json.Decoder. POST с JSON - http.Post с bytes.NewReader и Content-Type. DELETE и POST с параметрами в query удобнее через http.NewRequest.

client:= &http.Client{Timeout: 30 * time.Second}
req, err:= http.NewRequest(http.MethodDelete, baseURL+"/item/"+id, nil)
if err!= nil {
    return err
}
req.SetBasicAuth(user, pass)
resp, err:= client.Do(req)
if err!= nil {
    return err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
    body, _:= io.ReadAll(resp.Body)
    return fmt.Errorf("delete %s: %d %s", id, resp.StatusCode, string(body))
}
return nil

Ниже - тот же вызов с http.Client{ Timeout: … } и разбором resp.Body при StatusCode от 400 и выше: переиспользуемый клиент, явная проверка кода, чтение тела для лога middleware. На этом этапе связка уже работает при верных URL и авторизации, если не игнорировать код ответа.

Список клиентов разбираю в слайс структур Go с полями под JСОН-контракт 1С. После DELETE проверяю, что элемент исчез из следующего GET.

 

Второй НТТР-сервис: POST из RabbitMQ в справочник

Постоянный опрос 1С из Go не нужен: входящие сообщения очереди направляем HTTP POST в платформу. Второй НТТР-сервис делаю минимальным: GET - короткий статус для мониторинга, POST - JSON клиента с теми же полями, что в CRUD.

  • GET /ping - QueuePingGET(Запрос) - текст или JSON «ok».
  • POST /ingest - QueueIngestPOST(Запрос) - вызов общего модуля записи клиента.

Обработчик POST вызывает ту же процедуру записи, что и CRUD: разбор JSON, поиск по Идентификатору, одна транзакция. При ошибке валидации возвращаю 400 с телом {"error":"…"}. Consumer RabbitMQ при 400 обычно не делает бесконечный requeue: сообщение уходит в dead-letter или отдельную очередь разбора, иначе poison message зациклит очередь. При 5xx или обрыве сети - nack с requeue в пределах лимита повторов.

Типовая схема на middleware: consumer подписан на очередь (имя, exchange и routing key задаёте вы при настройке брокера в частях 1–4), при доставке формирует POST на /hs/queue/ingest с тем же JSON. Альтернатива - плагины и НТТР-мост брокера; меньше кода в Go, зато отдельная настройка durability и таймаутов. Если запись в 1С дольше таймаута HTTP, сообщение может уйти в повтор - идемпотентность по Идентификатору на сервере 1С обязательна.

Имя второго сервиса и корневой URL держу отдельно от CRUD, чтобы права на РОСТ-приём ограничить технической учёткой очереди, а к полному CRUD допускать только прослойку администрирования.

Для очереди включаю durable queue и persistent messages, на consumer - manual ack после успешного HTTP 200 или 201 от 1С.

Тестовое сообщение можно отправить из любой конфигурации-отправителя, если она уже публикует JSON в ту же очередь (тот же exchange и routing key, что у consumer). В тестовой базе 1С смотрим элемент справочника и точку останова в модуле НТТР-сервиса - отладка идёт как у обычного серверного кода, без клиентского сеанса.

 

Согласованность: очередь, СРУД-сервис и прослойка видят одни данные

После POST из RabbitMQ выполняю GET через первый сервис и запрос списка из middleware. Например, в очереди "id":" client-1 ", а в 1С строка без пробелов - в GET пусто; то же с регистром идентификатора.

Отладку НТТР-сервиса веду в конфигураторе: точка останова в функции шаблона, повтор POST из Postman или consumer с одним сообщением. Логи веб-сервера (IIS или Apache) покажут, дошёл ли запрос до платформы, если внутри 1С обработчик не вызвался. Имеет смысл писать отказ валидации в журнал регистрации короткой записью с идентификатором из JSON - без паролей и без полного тела сообщения.

Конфликт двух одновременных POST с одним Идентификатором решается последней успешной транзакцией; если это критично, добавляют версию записи или блокировку в прикладном коде - в базовом эталоне достаточно идемпотентности по ключу.

Когда запись прошла цепочку RabbitMQ - HTTP POST - справочник, её должно быть видно и в режиме «1С» прослойки. Это проверка, что два сервиса не разъехались по правилам отбора и записи.

 

OData для чтения и репозиторий конфигурации как приложение

Дополнение к кастомному CRUD - чтение того же справочника через стандартный OData. В Go формирую URL к набору по метаданным публикации, например /odata/standard.odata/Catalog_Клиенты?$filter=DeletionMark eq false&$select=Ref_Key,Description,Идентификатор,Тип,Майл - точные имена полей смотрите в $metadata, в типовых публикациях наименование часто идёт как Description.

type ODataClient struct {
    RefKey       string `json:"Ref_Key"`
    Description  string `json:"Description"`
    ExternalID   string `json:"Идентификатор"`
    ClientType   string `json:"Тип"`
    Email        string `json:"Майл"`
    DeletionMark bool   `json:"DeletionMark"`
}

Теги структуры сверяю с ответом $metadata, а не копирую вслепую. OData удобен для отчётного чтения и сверки; изменения и приём из очереди отправляю в НТТР-сервис CRUD или приёмник, где действуют ваши правила валидации и отбор без пометки удаления.

Полный текст модулей НТТР-сервисов и прослойки вынесен в репозиторий Connector_1C_Enterprise на GitHub (автор dmitry-msk777). Я опираюсь на него как на эталон конфигурации и Го-кода, но контракт API и порядок публикации всё равно нужно повторить у себя на стенде 8.3.x.

 

Когда так делать нельзя

Ограничения: суточные файлы, документы вместо справочника, жёсткая ИБ без DMZ - тогда схему с открытым POST не применяют.

Если запись должна выполняться только через проведение документов с контролем остатков, прямой POST в справочник из очереди обойдёт прикладную логику - нужен другой контур (документ, обработка, регламентное задание).

Если политика ИБ запрещает внешний POST в базу без WAF, mTLS и централизованного журнала, публикацию НТТР-сервисов на открытый URL без этих мер лучше не использовать.

Вступайте в нашу телеграмм-группу Инфостарт

1С:Предприятие 8.3 HTTP-сервис Golang RabbitMQ JSON интеграция middleware HTTP-сервис 1С Golang middleware RabbitMQ JSON CRUD справочник OData публикация IIS

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

WEB-интеграция Разработчик Аналитик 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Оптовая торговля, дистрибуция, логистика ИТ-компания Платные (руб)

Модуль "Экспортер" — это расширение для 1С, предназначенное для автоматизации процессов выгрузки данных. Оно позволяет эффективно извлекать, преобразовывать и передавать данные из систем 1С в интеграционную платформу Spot2D. Подсистема упрощает настройку, снижает количество ручных операций и обеспечивает удобный контроль данных.

17568 руб.

20.12.2024    7750    35    4    

35

Сайты и интернет-магазины WEB-интеграция Системный администратор Разработчик Пользователь 1С:Предприятие 8 1C:Бухгалтерия 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM / LOGICSTARS. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM / LOGICSTAR разных брендов в одной информационной базе в ручном и автоматическом режиме.

42700 руб.

03.08.2020    25816    42    26    

30

WEB-интеграция Системный администратор Разработчик Пользователь 1С:Предприятие 8 1C:Бухгалтерия 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена по API между конфигурацией 1С:Альфа-Авто 6 и порталом LogicStar. Позволяет работать с несколькими обменами LogicStars разных брендов (CHERY, OMODA, JAECOO, EXEED, TENET) в одной информационной базе в ручном и автоматическом режиме. Поддерживается выгрузка заказ-нарядов, реализаций товаров и товарных остатков.

20740 руб.

13.05.2025    3074    6    0    

8

WEB-интеграция Разработчик Пользователь 1С:Предприятие 8 1C:Бухгалтерия Управленческий учет Платные (руб)

Хорошая основа вашего решения импорта данных статистики Яндекс.Метрики в информационную базу 1С. Получение счетчиков, запрос статистики, получение данных - все в одной обработке.

5094 руб.

21.06.2022    11405    12    0    

12

WEB-интеграция Загрузка и выгрузка в Excel Разработчик Пользователь 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Розница 3.0 Розничная и сетевая торговля (FMCG) Россия Платные (руб)

Расширение освободит вас от необходимости вручную обновлять информацию о товарах в группах ВКонтакте. Достаточно задать правила один раз, и система автоматически формирует файлы yml для дальнейшей загрузки в группы в ВК. Вы сможете легко выбирать, какие товары публиковать, создавая гибкие критерии отбора. Например, можно добавить важные для покупателей параметры: цвет, размер или другие характеристики.

12200 руб.

29.08.2025    3750    7    8    

9
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. amiralnar 9 07.10.26 10:13 Сейчас в теме
Откуда этот перепост?

Где части 1-4?


"RabbitMQ и контейнер прослойки уже подняты в частях 1–4"
Для отправки сообщения требуется регистрация/авторизация