Интеграция с ГИС ЖКХ: SOAP/XML, архитектура проекта, подписание и обработка ошибок

Курс посвящён практической интеграции с ГИС ЖКХ через SOAP/XML: от понимания сервисов и схем данных до построения структуры проекта. Разберём полный жизненный цикл обмена: формирование запросов, подписание, отправка, получение результатов, обработку ошибок и эксплуатационные аспекты.

1. Обзор ГИС ЖКХ и сценарии интеграции

Обзор ГИС ЖКХ и сценарии интеграции

Что такое ГИС ЖКХ и зачем она нужна

ГИС ЖКХ — государственная информационная система, в которой участники сферы ЖКХ публикуют и обмениваются юридически значимой информацией: о домах, помещениях, лицевых счетах, начислениях, оплатах, приборах учёта, договорах управления/ресурсоснабжения, обращениях граждан и других сущностях.

С практической точки зрения интеграция с ГИС ЖКХ нужна, чтобы:

  • снизить ручной ввод и количество ошибок
  • обеспечить своевременную и полную публикацию данных в соответствии с требованиями регулятора
  • синхронизировать данные между внутренними системами (биллинг, CRM, учёт приборов) и государственным контуром
  • построить контролируемый процесс: подтверждение отправки, обработка статусов, разбор ошибок
  • Официальный портал системы: ГИС ЖКХ.

    Кто участвует в обмене данными

    В типовой схеме участвуют:

  • Организации (УО, ТСЖ/ЖСК, РСО, региональные операторы капремонта и ТКО) — поставляют данные и получают результаты обработки.
  • Операторы внутренних систем — пользователи и администраторы биллинга/CRM/учётных систем.
  • ГИС ЖКХ — принимает сообщения, валидирует, обогащает ссылками на справочники, ставит в обработку, возвращает статусы и ошибки.
  • Удостоверяющий центр и сертификаты — обеспечивают криптографическую подпись сообщений (юридическая значимость и целостность).
  • Какие данные обычно интегрируют

    Чтобы дальше говорить о SOAP/XML и проектировании, важно понимать наборы данных, которые чаще всего автоматизируют.

    Справочные и реестровые данные

  • дома, помещения, подъезды, комнаты, общедомовое имущество
  • договоры управления и договоры ресурсоснабжения, привязки к домам
  • лицевые счета, плательщики (в рамках допустимых моделей данных)
  • приборы учёта и их характеристики
  • Операционные данные

  • начисления, перерасчёты, задолженности
  • оплаты и распределение оплат
  • показания приборов учёта
  • работы и услуги, тарифы и нормативы (в зависимости от роли организации)
  • Взаимодействие с гражданами

  • обращения и ответы
  • уведомления, результаты рассмотрения
  • Важно: в реальных проектах почти всегда приходится решать задачу сопоставления идентификаторов между вашей системой и ГИС ЖКХ (например, дом у вас — это house_id=123, а в ГИС — другой идентификатор/уникальный ключ). Это напрямую влияет на архитектуру интеграции.

    Варианты интеграции: от ручной работы к API

    На практике встречаются 3 подхода.

  • Ручной ввод через личный кабинет: подходит для небольших объёмов, но плохо масштабируется и сложен для контроля качества.
  • Полуавтоматический обмен через выгрузки: часть данных готовится автоматически, но загрузка/проверка часто остаётся ручной.
  • Системная интеграция через API: обмен идёт из вашей системы напрямую, с подписанием, получением статусов, автоматической обработкой ошибок.
  • Этот курс посвящён системной интеграции, где обмен обычно строится вокруг:

  • SOAP как протокола взаимодействия
  • XML как формата сообщений
  • XSD-схем как правил структуры данных
  • криптографической подписи исходящих сообщений
  • асинхронной обработки и получения статусов
  • Как выглядит жизненный цикл обмена сообщением

    Один из ключевых источников ошибок в интеграциях — неправильные ожидания о том, как реально движется информация. Часто запрос не означает мгновенного результата: система может принять сообщение, поставить в очередь и только потом обработать.

    Ниже — обобщённый жизненный цикл интеграционного сообщения.

  • Внутренняя система формирует бизнес-событие (например, начисления за месяц готовы к публикации).
  • Интеграционный слой преобразует данные в XML согласно требованиям сервиса.
  • Сообщение подписывается сертификатом (криптография и юридическая значимость).
  • Сообщение отправляется в ГИС ЖКХ по SOAP.
  • ГИС ЖКХ возвращает первичный ответ (например, что сообщение принято) и идентификаторы для отслеживания.
  • Далее система получает итоговый статус обработки (успех или ошибки) и привязывает его к исходной операции.
  • Результат фиксируется в журнале, а при ошибках запускаются корректирующие действия.
  • !Общая схема движения данных и статусов между вашей системой и ГИС ЖКХ

    Типовые сценарии интеграции

    Ниже — сценарии, с которых чаще всего начинают, и что в них важно учитывать.

    Публикация реестров (дома, помещения, договоры)

    Цель: синхронизировать базу объектов и договорные связи.

    Ключевые особенности:

  • критично правильно сопоставить адресные и реестровые сущности
  • нужны механизмы обновления: изменение атрибутов, закрытие/открытие периодов действия
  • важна идемпотентность: повторная отправка не должна создавать дубль
  • Приборы учёта и показания

    Цель: вести актуальные данные по ИПУ/ОДПУ и показаниям.

    Ключевые особенности:

  • наличие строгих правил валидации (форматы, даты, связи с помещением/домом)
  • конфликтные ситуации: показания уже были поданы другим источником, пересечения периодов
  • Начисления, перерасчёты, оплаты

    Цель: публиковать платёжные документы и результаты оплат.

    Ключевые особенности:

  • большие объёмы данных и требование к производительности
  • пакетная отправка и контроль частичных ошибок
  • необходимость согласовать модель данных биллинга и модель ГИС (особенно по услугам и периодам)
  • Обращения граждан и ответы

    Цель: получать обращения из ГИС ЖКХ и отправлять ответы/статусы.

    Ключевые особенности:

  • двусторонний обмен (входящие события тоже надо обрабатывать)
  • контроль сроков и статусов, аудит изменений
  • Универсальная таблица для первичной оценки работ

    | Сценарий | Что автоматизируем | Основной риск | Что закладывать в проект сразу | |---|---|---|---| | Реестры объектов | Дома/помещения/связи | Несовпадение идентификаторов и адресов | Слой сопоставления, справочники, журнал изменений | | Приборы и показания | ПУ и показания | Конфликты периодов и источников | Валидации, правила приоритета, повторные отправки | | Начисления и оплаты | ПД, оплаты | Большие объёмы и частичные ошибки | Пакетирование, ретраи, мониторинг, очереди | | Обращения | Входящие/исходящие сообщения | Пропуск сроков и статусов | Очередь задач, SLA-контроль, аудит |

    Что обязательно учесть ещё до первой строки кода

    Роли и границы ответственности

  • кто является источником истины по каждому типу данных
  • кто отвечает за исправление ошибок: ИТ, расчётчики, специалисты по начислениям, операторы ЛК
  • как принимается решение о повторной отправке и корректировках
  • Контуры и среды

    Как минимум вам понадобятся:

  • среда разработки (локальная/стенд)
  • тестовый контур взаимодействия (если доступен)
  • промышленный контур
  • Даже если технически запросы одинаковые, организационно процессы различаются: доступы, сертификаты, регламенты повторов, окна публикации.

    Наблюдаемость и управляемость интеграции

    Интеграция с ГИС ЖКХ без хорошего журнала быстро превращается в поддержку “по скриншотам”. Минимальный набор того, что нужно логировать:

  • идентификатор исходной операции во внутренней системе
  • идентификатор сообщения/запроса (корреляция)
  • время формирования, подписания, отправки
  • первичный ответ приёма и итоговый статус обработки
  • текст и коды ошибок, если они есть
  • версию схемы/сервиса (если применимо)
  • Какие ошибки встречаются чаще всего (на уровне концепции)

    В следующих статьях мы будем разбирать ошибки технически, но уже сейчас полезно разделить их на классы:

  • транспортные: сеть, TLS, недоступность сервиса
  • безопасность и подпись: неверный сертификат, ошибка криптографии, некорректная подпись
  • структурные: XML не соответствует XSD
  • бизнес-валидации: нарушены правила предметной области (периоды, связи сущностей, недопустимые значения)
  • конкурентные/статусные: объект уже существует, операция недопустима в текущем состоянии, конфликт версий
  • Правильная архитектура интеграции строится так, чтобы каждый класс ошибок:

  • попадал в свою категорию в логах
  • имел понятный сценарий реакции (повторить, исправить данные, сменить сертификат, эскалировать)
  • Как эта статья связана со следующим материалом курса

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

  • как устроены SOAP-сервисы и почему важно читать WSDL и XSD
  • как спроектировать структуру проекта (клиенты сервисов, маппинг, доменная модель, хранилище статусов)
  • как организовать подписание и проверку подписи
  • как построить обработку ошибок и повторные попытки без дублей и потери данных
  • 2. Сервисы ГИС ЖКХ: методы, контракты, ограничения

    Сервисы ГИС ЖКХ: методы, контракты, ограничения

    Зачем разбираться в сервисах, методах и контрактах

    В предыдущей статье мы обсудили сценарии интеграции и жизненный цикл обмена: сформировали данные, подписали, отправили, получили подтверждение приёма, затем дождались итогового статуса обработки.

    Чтобы этот цикл работал стабильно, нужно понимать три вещи:

  • методы сервиса: какие операции доступны и что они делают;
  • контракты: как именно выглядит SOAP/XML, какие поля обязательны, какие справочники и типы данных используются;
  • ограничения: что может пойти не так по объёмам, очередям, статусам, версиям схем и правилам предметной области.
  • Эта статья даёт практическую рамку: как читать контракт (WSDL/XSD), как классифицировать методы, и какие ограничения закладывать в архитектуру интеграционного слоя.

    Из чего состоит “сервис” в SOAP-интеграции

    В SOAP-мире слово сервис обычно означает набор операций, опубликованных в виде контракта.

    Основные артефакты контракта

  • WSDL — описание операций: какие методы доступны, какие сообщения входят/выходят, где endpoint.
  • XSD — схемы данных: строгие правила структуры XML, типы, обязательность полей, форматы.
  • Namespace и версии — пространство имён XML и его изменение при развитии схем.
  • Практический смысл:

  • WSDL отвечает на вопрос “какие методы вызвать и куда”.
  • XSD отвечает на вопрос “как должен выглядеть XML, чтобы его приняли”.
  • Системный эффект: если вы строите интеграцию вокруг WSDL/XSD, вы снижаете вероятность “угадывания” структуры сообщений и получаете воспроизводимую генерацию клиентов и валидацию.

    !Как WSDL и XSD задают правила для SOAP-сообщений

    Как устроено SOAP-сообщение на практике

    SOAP-запрос и SOAP-ответ — это XML-документы с общей “обвязкой”. Внутри почти всегда есть:

  • Envelope — контейнер всего сообщения
  • Header — служебные данные (может быть пустым или обязательным, зависит от контракта)
  • Body — полезная нагрузка, структура которой задаётся XSD
  • Важное архитектурное правило: ваш проект должен хранить и коррелировать не только бизнес-данные, но и “служебную” часть обмена: идентификаторы сообщений, подпись, статусы обработки.

    Типы методов, которые встречаются в интеграции с ГИС ЖКХ

    Названия методов зависят от конкретного сервиса и версии схем, но по смыслу операции обычно укладываются в несколько устойчивых типов.

    Операции публикации и изменения данных

    Это методы, которые “вносят” данные в государственный контур:

  • создание или обновление сущности
  • пакетная загрузка набора сущностей
  • изменение статуса/периода действия (например, закрытие, актуализация)
  • Ключевые свойства:

  • чаще всего асинхронные: первичный ответ означает “принято”, а не “обработано”
  • важна идемпотентность: повтор запроса не должен создавать дубликаты
  • Операции получения статуса обработки

    Поскольку многие операции асинхронные, почти всегда есть отдельный механизм получения результата:

  • запрос статуса по идентификатору (корреляционному ключу)
  • получение протокола обработки и списка ошибок
  • Даже если метод называется иначе, вы проектируете его как часть общего паттерна: отправили → получили идентификатор → опросили/получили результат.

    Операции выгрузки данных из ГИС ЖКХ

    Это методы чтения:

  • запрос реестровых данных
  • запрос справочников
  • выгрузка информации по сущности или периоду
  • Ключевые свойства:

  • часто есть фильтры (период, статус, идентификатор)
  • результат может быть “страничным” или формироваться как отдельная сущность/файл, доступный позже
  • Операции работы со справочниками и классификаторами

    Справочники важны, потому что XSD и бизнес-валидации часто требуют строгое значение из перечня:

  • типы объектов
  • коды оснований, статусов, причин
  • единицы измерения и прочие классификаторы
  • Архитектурно выгодно иметь слой кэширования справочников и контроля их актуальности.

    Асинхронность как “стандартный режим”

    Одна из самых частых ошибок ожиданий: разработчик считает, что раз SOAP-вызов вернул 200 OK, значит данные применены.

    В реальности у многих операций жизненный цикл такой:

  • Отправили SOAP-запрос с данными.
  • Получили первичный ответ: “принято в обработку” и идентификатор.
  • Через некоторое время получили итог: успешно или ошибки.
  • !Типовой асинхронный обмен и получение итогового результата

    Следствие для проекта: нужен журнал обмена и хранилище статусов, иначе вы не сможете управлять публикациями и разбирать инциденты.

    Контрактные требования: что “ломает” интеграцию чаще всего

    Соответствие XSD

    Если тело сообщения не соответствует XSD, система обычно не переходит к бизнес-проверкам.

    Типовые причины:

  • пропущены обязательные элементы
  • неверный формат даты/числа
  • нарушен порядок элементов (для некоторых схем это критично)
  • передано значение, не входящее в допустимый перечень
  • Практика: внедряйте локальную валидацию XML по XSD до отправки. Это дешевле, чем разбор отказов на стороне ГИС ЖКХ.

    Связи сущностей и ссылочные поля

    В интеграциях ЖКХ редко можно отправить “самостоятельную” сущность без ссылок. Почти всегда требуется:

  • идентификатор связанного объекта (дом, помещение, договор)
  • корректный период действия
  • совпадение по справочникам и статусам
  • Отсюда появляется обязательный слой сопоставления идентификаторов между вашей системой и ГИС ЖКХ, о котором мы говорили в обзорной статье.

    Версионирование схем

    Контракт может меняться: добавляются поля, меняются ограничения, появляются новые типы.

    Что закладывать в архитектуру:

  • фиксировать версию схемы/контракта в журнале отправок
  • отделять маппинг данных от транспортного клиента, чтобы обновление XSD не “ломало” весь проект
  • иметь регламент обновления и тестирования на тестовом контуре
  • Ограничения, которые важно учитывать в проектировании

    Ниже — не “точные лимиты”, а классы ограничений, которые встречаются практически всегда и должны быть отражены в архитектуре.

    Ограничения по объёму и пакетированию

  • большие операции (начисления, платёжные документы) должны уходить пакетами
  • при частичных ошибках нужно уметь:
  • - выделить ошибочные элементы - повторить отправку только того, что нужно

    Проектный вывод: реализуйте батчинг и обработку результатов на уровне “элемент внутри пакета”, а не только “пакет целиком”.

    Ограничения по времени и очередям

  • первичный ответ может прийти быстро, а итоговая обработка — занять время
  • повторная отправка “раньше времени” может приводить к конфликтам статусов или дубликатам
  • Проектный вывод: вам нужен контролируемый планировщик повторов и опроса статусов, а также стратегия backoff (увеличение интервала между повторами при отсутствии результата).

    Ограничения по идемпотентности

    Если вы повторяете запрос из-за таймаута, сетевой ошибки или неизвестного статуса, возможны два сценария:

  • система не получила запрос — повтор безопасен
  • система получила запрос, но вы не получили подтверждение — повтор может создать дубль или конфликт
  • Проектный вывод: храните корреляционные идентификаторы, используйте единый ключ операции у себя, и проектируйте повторную отправку как управляемый процесс, а не как “просто ретрай HTTP”.

    Ограничения безопасности: подпись и доступ

    На уровне интеграции обычно сочетаются:

  • защищённый транспорт (TLS)
  • сертификаты и криптография для подписи сообщений
  • Это влияет на архитектуру:

  • ключи и сертификаты должны храниться и использоваться по регламенту
  • операции подписи должны быть повторяемыми и наблюдаемыми (лог: какой сертификат, какой отпечаток, какой идентификатор сообщения)
  • ошибки подписи и ошибки бизнес-валидации должны классифицироваться отдельно
  • Подпись и криптографию мы будем разбирать в следующих материалах курса, но уже здесь важно понимать: часть ограничений “сервисов” лежит не в XML, а в безопасности.

    Как разработчику “читать” сервис и не гадать

    Надёжный рабочий порядок выглядит так:

  • Найти WSDL конкретного сервиса и зафиксировать версию.
  • Определить операции:
  • - что отправляет данные - что возвращает статус - что читает данные
  • Поднять XSD и определить:
  • - обязательные поля - справочные значения и ограничения - ключевые идентификаторы и связи
  • Собрать тестовый запрос минимального размера:
  • - валидный по XSD - с корректными ссылками на сущности
  • Зафиксировать “трассу” обмена в журнале:
  • - request/response - идентификаторы - итоговый статус

    Практический инструментальный минимум:

  • SOAP-клиент для ручных прогонов (например, SoapUI) — чтобы быстро видеть request/response
  • валидатор XML по XSD — чтобы ловить ошибки до отправки
  • централизованный журнал интеграции — чтобы связывать бизнес-операцию с техническим обменом
  • Мини-словарь терминов статьи

  • Метод (операция) — конкретный SOAP-вызов сервиса.
  • Контракт — формальное описание методов и структур данных (WSDL + XSD).
  • Валидация по XSD — проверка, что XML соответствует схеме.
  • Асинхронная обработка — результат операции доступен позже, через статус/протокол.
  • Идемпотентность — повтор запроса не должен приводить к созданию дубликатов или неконсистентному состоянию.
  • Как эта статья связана со следующими темами курса

    Дальше логично перейти от понимания “что такое сервис и контракт” к реализации:

  • как устроить структуру проекта: клиенты, маппинг, хранилище статусов, журнал
  • как организовать подписание SOAP/XML
  • как классифицировать и обрабатывать ошибки: транспортные, контрактные (XSD), бизнесовые, статусные
  • Официальная точка входа в систему: ГИС ЖКХ.

    3. SOAP и XML на практике: WSDL, XSD, namespaces

    SOAP и XML на практике: WSDL, XSD, namespaces

    Как эта тема связана с предыдущими статьями

    В первых двух статьях курса мы договорились о главном:

  • интеграция с ГИС ЖКХ почти всегда строится на SOAP и XML
  • многие операции асинхронные: первичный ответ означает «принято», а итоговый результат приходит позже через статусы/протоколы
  • стабильность интеграции определяется не «угадыванием формата», а следованием контракту: WSDL + XSD и учётом ограничений
  • Эта статья — практическая: как читать WSDL и XSD, как понимать namespaces, и почему от них зависит генерация клиента, сборка XML и последующая валидация.

    Базовые понятия: SOAP, XML, контракт

    SOAP

    SOAP — это формат обмена сообщениями поверх HTTP (обычно), где запрос и ответ — XML-документы в стандартной «обвязке».

    У SOAP есть формальная спецификация. Для справки:

  • SOAP Version 1.2 Part 1: Messaging Framework (W3C)
  • XML

    XML — это текстовый формат, где данные описываются элементами и атрибутами. Он удобен тем, что:

  • хорошо валидируется по схеме
  • поддерживает пространства имён (namespaces)
  • используется в SOAP и цифровой подписи XML
  • Контракт: WSDL + XSD

    Контракт SOAP-сервиса обычно состоит из:

  • WSDL — описание операций, сообщений и endpoint (куда отправлять)
  • XSD — схемы, которые задают строгую структуру XML для полезной нагрузки
  • Спецификация WSDL для справки:

  • Web Services Description Language (WSDL) 1.1 (W3C Note)
  • Спецификация XML Schema для справки:

  • XML Schema Part 1: Structures (W3C)
  • Анатомия SOAP-сообщения

    SOAP-сообщение почти всегда имеет форму:

    Ключевая практическая мысль для проектов ГИС ЖКХ:

  • Body вы строите по XSD
  • Header часто связан с безопасностью и подписанием (обычно это отдельная тема и отдельный слой в проекте)
  • и то, и другое нужно уметь логировать и коррелировать с бизнес-операцией (из предыдущих статей: «жизненный цикл обмена» и «хранилище статусов»)
  • WSDL на практике: что в нём искать разработчику

    WSDL отвечает на вопрос: какие операции есть, какие у них входы/выходы, и куда отправлять запрос.

    Главные разделы WSDL (простая карта)

    Внутри WSDL чаще всего встречаются следующие сущности:

  • definitions — корневой элемент, в нём объявляются пространства имён и общий контекст
  • types — ссылки на XSD или встроенные схемы
  • message — описание сообщений (вход/выход), обычно через ссылки на элементы XSD
  • portType — набор операций (интерфейс)
  • binding — как именно «упаковывать» сообщения (SOAP 1.1/1.2, стиль, транспорт)
  • service / port — конкретный endpoint (URL)
  • Практический алгоритм чтения WSDL:

  • Найдите endpoint: раздел serviceportaddress.
  • Найдите нужную операцию в portType (название метода).
  • Посмотрите, какие сообщения являются input и output.
  • Проверьте, где лежат XSDtypes обычно есть xsd:import/xsd:include).
  • Почему WSDL важен именно в интеграции с ГИС ЖКХ

    На типовом проекте WSDL используется для:

  • генерации клиентского кода (чтобы не писать сериализацию вручную)
  • определения, где заканчивается «ваша логика», и начинается «транспорт»
  • автоматизации тестов контрактов (регрессия при обновлении версий)
  • Если вы интегрируете несколько сервисов ГИС ЖКХ, WSDL помогает дисциплинировать кодовую базу: каждый сервис — отдельный клиент, свои DTO/модели, своя версия контракта.

    !Связь WSDL, XSD и SOAP-сообщений на уровне контракта

    XSD на практике: как схема управляет вашим XML

    XSD отвечает на вопрос: какие элементы допускаются, в каком порядке, какие типы данных, что обязательно, какие ограничения.

    Самые важные конструкции XSD, которые нужно узнавать

  • xsd:element — элемент XML (например, House, Account, RequestHeader)
  • xsd:complexType — сложный тип (набор вложенных элементов)
  • xsd:sequence — порядок элементов (для многих схем он критичен)
  • minOccurs / maxOccurs — обязательность и кратность
  • простые типы (xsd:string, xsd:date, xsd:decimal) и ограничения (enumeration, pattern)
  • Что это значит в практическом смысле:

  • если minOccurs="1", элемент обязателен
  • если maxOccurs="unbounded", элемент может повторяться много раз (и это часто превращается в батчи/пакеты)
  • если задан enumeration, нельзя передать произвольное значение — только из списка
  • Пример: «пакетная» структура как следствие XSD

    Очень типичная ситуация для обменов с ГИС ЖКХ — пакетная отправка. На уровне XSD это выглядит как элемент со списком повторяющихся записей.

    Если XSD задаёт Item как повторяющийся элемент, ваша архитектура (из предыдущей статьи про ограничения) должна уметь:

  • формировать пакет
  • разбирать результат на уровне элементов пакета
  • повторять отправку частично, если протокол вернул ошибки только по части элементов
  • Почему важна локальная валидация по XSD

    Локальная валидация означает: проверить XML по XSD до отправки в ГИС ЖКХ.

    Это даёт:

  • быстрый и дешёвый цикл исправления (ошибка ловится у вас, а не после отправки)
  • чёткую классификацию: контрактная ошибка (XSD) отделяется от бизнес-ошибки (правила предметной области)
  • предсказуемые ретраи: XSD-ошибка не лечится повтором
  • Namespaces: что это такое и почему без них «всё ломается»

    Зачем вообще нужны namespaces

    Namespace (пространство имён) — это способ отличать элементы с одинаковыми названиями, но разным смыслом.

    Пример проблемы без namespaces:

  • и в вашем сообщении, и в чужом контракте может существовать элемент Request
  • XML должен однозначно понимать, к какому «словарю» относится элемент
  • Спецификация для справки:

  • Namespaces in XML 1.0 (Third Edition) (W3C)
  • Как это выглядит в XML

    Namespace задаётся URI и привязывается к префиксу:

    Здесь важно понимать:

  • префикс nsпросто псевдоним, можно назвать иначе (m, p, x)
  • URI urn:example:some-schemaреальный идентификатор пространства имён, и именно он должен совпадать с тем, что ожидает XSD/WSDL
  • Типовые ошибки с namespaces

  • элемент в «не том» namespace: выглядит правильно, но схема считает его чужим
  • забыли объявить xmlns:... и получили ошибку парсинга
  • использовали дефолтный namespace (xmlns="...") и неожиданно «перенесли» в него элементы, которые должны быть без namespace (или наоборот)
  • !Как одинаковый префикс может означать разный namespace URI

    targetNamespace в XSD и почему его нужно проверять

    В XSD почти всегда есть targetNamespace. Он определяет, к какому namespace относятся элементы этой схемы.

    Практическое правило:

  • если вы сериализуете элемент как ns:Something, то ns должен быть привязан к URI, совпадающему с targetNamespace (или с тем namespace, где определён нужный элемент)
  • Это одна из причин, почему ручная сборка XML опасна: визуально XML может быть «красивым», но формально — невалидным.

    Как WSDL, XSD и namespaces влияют на структуру проекта

    Чтобы интеграция с ГИС ЖКХ была управляемой (особенно при обновлениях схем), полезно заранее разделить ответственность в коде.

    Рекомендуемое разбиение слоёв

  • SOAP-клиент
  • - отвечает за отправку запроса и получение ответа - знает endpoint, таймауты, ретраи транспортного уровня
  • Модели контракта (DTO)
  • - классы, сгенерированные или написанные под XSD - отражают namespaces и структуру схем
  • Маппинг домена в контракт
  • - преобразует ваши бизнес-объекты в DTO (и обратно) - здесь живут правила заполнения обязательных полей, справочники, преобразования форматов
  • Валидация
  • - проверка XML по XSD до отправки - классификация ошибок как контрактных
  • Журнал и корреляция
  • - хранит request/response и идентификаторы для асинхронных статусов (из предыдущих статей)

    Почему обновления схем не должны «ломать всё приложение»

    Если у вас смешаны транспорт, маппинг и доменная логика, любое изменение XSD приводит к цепочке правок по всему коду.

    Если же выделены слои, обновление обычно локализуется:

  • меняется DTO/контрактный слой
  • адаптируется маппинг
  • транспорт и журнал обмена остаются стабильными
  • Практический чек-лист разработчика перед первым запросом

  • Зафиксировать версию WSDL и связанные XSD (сохранить в репозитории или артефактном хранилище).
  • Определить endpoint и нужные операции.
  • Проверить targetNamespace в XSD и expected namespaces в WSDL.
  • Собрать минимально валидный запрос:
  • Настроить локальную валидацию по XSD.
  • Включить логирование:
  • исходный XML (или канонический вид, если так требует политика безопасности)
  • первичный ответ
  • корреляционные идентификаторы для опроса статуса
  • Что дальше по курсу

    После того как вы уверенно читаете WSDL/XSD и понимаете namespaces, можно переходить к инженерной части интеграции:

  • проектирование структуры проекта (клиенты, маппинг, журнал, хранилище статусов)
  • подписание SOAP/XML и управление сертификатами
  • обработка ошибок: транспортных, контрактных (XSD), бизнесовых и статусных
  • Для контекста работы с системой:

  • ГИС ЖКХ
  • 4. Структура интеграционного проекта: слои, модули, конфигурация

    Структура интеграционного проекта: слои, модули, конфигурация

    Зачем нужна отдельная архитектура интеграции с ГИС ЖКХ

    В предыдущих статьях мы закрепили, что интеграция с ГИС ЖКХ строится на SOAP/XML, строго следует контракту (WSDL + XSD) и часто работает в асинхронном режиме: запрос может быть принят, но обработан позже со статусом и протоколом.

    Отсюда практический вывод: интеграционный код нельзя делать как «пару методов, которые дергают SOAP». Нужна структура проекта, которая:

  • отделяет транспорт (SOAP) от бизнес-логики и маппинга
  • позволяет обновлять XSD/WSDL без переписывания всего приложения
  • хранит корреляцию запросов и статусов
  • управляет повторами, пакетами и ошибками
  • Эта статья даёт рекомендуемую структуру интеграционного проекта: слои, модули и конфигурация, которые обычно требуются для стабильной работы.

    !Схема слоёв и модулей интеграционного проекта и их зависимостей

    Принципы проектирования, которые упрощают поддержку

    Разделение ответственности

    Проект устойчивее, когда у каждого слоя одна ответственность:

  • транспорт знает, как отправить SOAP и получить ответ
  • контракт знает, как выглядит XML по XSD
  • маппинг знает, как заполнить контракт из ваших данных
  • оркестрация знает, когда отправлять, как ждать статус, когда повторять
  • наблюдаемость знает, что логировать и как связать события
  • Зависимости «внутрь»

    Удобное правило: зависимости идут от внешнего к внутреннему.

  • внутренние слои не должны «знать» про SOAP, WSDL, конкретные библиотеки подписи
  • внешние слои могут знать про внутренние контракты (интерфейсы) и реализовывать их
  • Практический эффект: можно сменить SOAP-библиотеку, способ подписи или механизм очередей, не переписывая бизнес-сценарии.

    Слои проекта

    Ниже — модель слоёв, которая хорошо ложится на интеграцию с ГИС ЖКХ. Названия можно адаптировать, смысл важнее.

    Contract слой

    Это слой контрактных моделей и валидации структуры.

    Обычно включает:

  • DTO/классы, сгенерированные из WSDL/XSD (или написанные вручную, если генерация неудобна)
  • утилиты сериализации/десериализации XML (строго по контракту)
  • валидацию XML по XSD до отправки
  • Зачем выделять отдельно:

  • обновление XSD меняет DTO, но не должно ломать доменную логику
  • ошибки XSD-валидации классифицируются как контрактные и не должны уходить в «повторы»
  • Ссылки на спецификации (для справки по терминологии):

  • SOAP Version 1.2 Part 1: Messaging Framework
  • Web Services Description Language (WSDL) 1.1
  • XML Schema Part 1: Structures
  • Infrastructure слой

    Это реализация технических деталей: сеть, SOAP, подпись, хранилища.

    Типовой состав:

  • SOAP-клиенты по сервисам (endpoint, таймауты, настройки TLS)
  • модуль подписания (XML Signature и/или требования конкретного сервиса)
  • репозитории хранения (журнал запросов/ответов, статусы, сопоставления идентификаторов)
  • планировщик/воркеры (опрос статусов, отправка батчей, ретраи)
  • интеграция с очередью сообщений, если она используется
  • Важно: Infrastructure не должен «решать», что публикуем и когда это считается завершенным — он предоставляет инструменты.

    Domain слой

    Это ядро смысла интеграции. Он описывает операции и их жизненный цикл.

    Здесь удобно хранить:

  • модели интеграционных операций: что отправляем, какой ключ идемпотентности, в каком состоянии
  • классификацию ошибок (транспортная, подпись, контрактная, бизнесовая, статусная)
  • правила идемпотентности и дедупликации
  • доменные события: «отправлено», «принято», «обработано успешно», «ошибка протокола»
  • Domain слой не зависит от SOAP и XML. Он опирается на абстракции.

    Application слой

    Это оркестрация сценариев и «склейка» бизнес-процессов:

  • сценарии публикации (например, «опубликовать начисления за период»)
  • разбиение на батчи
  • вызов подписания и отправки
  • запуск опроса статуса и обработка результата
  • формирование задач на исправление ошибок
  • Application слой знает, как проходит жизненный цикл обмена (из первой статьи курса), и использует Domain-модели и порты к Infrastructure.

    Модули проекта: рекомендуемая разрезка по папкам или пакетам

    Ниже — практический вариант разбиения по модулям. Он подходит как для монорепозитория, так и для нескольких библиотек.

    Модуль giszhkh-contract

  • версии WSDL/XSD, закреплённые в репозитории
  • сгенерированные DTO
  • XSD-валидатор
  • вспомогательные конвертеры типов (даты, перечисления, форматы)
  • Правило: модуль не содержит HTTP/SOAP-кода и не обращается к базам.

    Модуль giszhkh-transport

  • SOAP-клиенты по сервисам
  • общие SOAP-конфигурации (endpoint, timeouts)
  • обработка SOAP Fault и преобразование в типизированные ошибки
  • Правило: модуль не знает про вашу доменную модель начислений, лицевых счетов и т.п.

    Модуль giszhkh-security

  • операции подписи и работа с ключевым материалом
  • абстракция над криптопровайдером
  • аудит: какой сертификат использован, отпечаток, срок действия
  • Замечание: конкретные требования подписи зависят от сервиса и политики безопасности, поэтому этот модуль важно изолировать и тестировать отдельно.

    Модуль integration-domain

  • модели операций, статусов, протоколов
  • интерфейсы-порты (например, SendRequestPort, StatusPollPort, IntegrationJournalPort)
  • классификатор ошибок и правила реакций
  • Модуль integration-application

  • сценарии и use-case’ы
  • батчинг и планирование повторов
  • обработчики результатов (успех, частичная ошибка, критическая ошибка)
  • Модуль integration-storage

  • реализация журналирования (БД)
  • таблицы статусов и корреляции
  • хранение сопоставлений идентификаторов
  • Если хранилище реализовано в Infrastructure, его всё равно полезно выделять отдельно как модуль, потому что схема данных и миграции живут своей жизнью.

    Ключевые технические компоненты внутри проекта

    Журнал обмена и корреляция

    Без журнала интеграция становится неуправляемой: невозможно доказать, что именно отправили, и что вернул сервис.

    Минимальная запись журнала на одну попытку отправки:

  • Идентификатор бизнес-операции у вас (например, billingDocId или jobId).
  • Технический идентификатор сообщения (корреляция).
  • Сервис и операция (название метода).
  • Версия контракта (какой WSDL/XSD использовали).
  • Времена: сформировано, подписано, отправлено, получен первичный ответ.
  • Результат первичного ответа: принято/отказано, коды.
  • Ссылка на сырой запрос/ответ (или защищённое хранилище), с учётом политики безопасности.
  • Отдельно фиксируется итоговый результат асинхронной обработки (успех/ошибки) и протокол.

    Хранилище статусов асинхронной обработки

    Нужна сущность «операция публикации», которая живёт дольше одного HTTP-запроса.

    Типовые статусы (их имена вы задаёте сами, они не обязаны совпадать с терминами ГИС ЖКХ):

  • Draft (подготовлено)
  • Signed (подписано)
  • Sent (запрос отправлен)
  • Accepted (принято в обработку)
  • Processing (ожидаем итог)
  • Success (обработано успешно)
  • Failed (обработано с ошибками)
  • Смысл: любое падение приложения посередине не должно «терять» операцию — после восстановления система должна продолжить с корректного шага.

    Идемпотентность и повторные попытки

    Повторы неизбежны из-за сетевых сбоев и асинхронности. Поэтому в Domain/Application слоях нужен ключ идемпотентности.

    Примеры ключей:

  • для загрузки начислений: orgId + period + batchNumber + sourceDocId
  • для показаний: meterId + readingDate
  • Рекомендация: ключ должен однозначно определять «что именно хотели сделать», и быть стабильным при повторной отправке.

    Батчинг и частичные ошибки

    Если сервис принимает список сущностей, архитектура должна уметь:

  • Разбить исходные данные на батчи по размеру.
  • Отправить батчи независимо.
  • Разобрать протокол так, чтобы понимать ошибки на уровне элемента.
  • Повторять только то, что имеет смысл повторять.
  • Конфигурация: что должно настраиваться без перекомпиляции

    Интеграция почти всегда работает в нескольких контурах (тест/пром) и под разными организациями. Поэтому конфигурация должна быть внешней.

    Группы настроек

  • Настройки подключения:
  • - URL endpoint’ов по сервисам - таймауты - параметры TLS
  • Настройки безопасности:
  • - путь к хранилищу ключей или идентификатор контейнера - алиас сертификата - политики выбора сертификата для организации
  • Настройки сценариев:
  • - размер батча - расписание отправок и опроса статусов - стратегия повторов (количество, задержки)
  • Настройки наблюдаемости:
  • - уровни логирования - маскирование персональных данных - включение/отключение сохранения «сырого» XML

    Версионирование контрактов как часть конфигурации

    Даже если код один, у вас может быть несколько версий XSD/WSDL в эксплуатации (например, переходный период). Практично уметь выбирать версию контракта на уровне конфигурации:

  • «для сервиса X использовать контракт версии V»
  • «валидировать исходящий XML схемой V»
  • Это снижает риск, что срочное обновление схемы «сломает» весь поток.

    Минимальные интерфейсы (порты), которые упрощают тестирование

    Чтобы Application и Domain слои тестировались без реальной ГИС ЖКХ, полезны интерфейсы.

    Пример набора портов:

  • SoapSendPort — отправка подготовленного SOAP-запроса и получение первичного ответа
  • StatusPollPort — запрос статуса по идентификатору
  • SignaturePort — подписать полезную нагрузку или сообщение
  • JournalPort — записать и прочитать журнал обмена
  • IdMappingPort — получить сопоставление ваших идентификаторов с идентификаторами ГИС ЖКХ
  • Тогда в тестах вы подменяете эти порты стабами, а в проде подключаете Infrastructure-реализации.

    Как эта структура помогает обработке ошибок

    Мы ещё будем подробно разбирать обработку ошибок в следующих темах курса, но архитектурно важно подготовить места, где ошибки «живут».

    Разделение по слоям даёт ожидаемое поведение:

  • транспортная ошибка обрабатывается в transport/infrastructure и превращается в тип ошибки Domain уровня
  • контрактная ошибка (XSD) ловится до отправки, фиксируется в журнале и не уходит в повтор
  • бизнес-ошибка приходит в протоколе обработки и требует корректировки исходных данных или сопоставлений
  • ошибка подписи относится к security модулю и обычно требует вмешательства в сертификаты/ключи, а не изменения XML
  • Связь с дальнейшими темами курса

    После того как структура проекта определена, можно двигаться по двум ключевым направлениям:

  • подписание SOAP/XML и управление сертификатами (как отдельный слой и набор ошибок)
  • стратегия обработки ошибок и повторов: транспорт, SOAP Fault, XSD, бизнес-валидации, статусы асинхронной обработки
  • Для общего контекста работы системы:

  • ГИС ЖКХ
  • 5. Движение данных: очереди, идемпотентность, корреляция, статусы

    Движение данных: очереди, идемпотентность, корреляция, статусы

    Зачем отдельно разбирать «движение данных»

    В предыдущих статьях курса мы закрепили три опоры интеграции с ГИС ЖКХ:

  • обмен почти всегда идёт через SOAP/XML и строго по WSDL/XSD
  • многие операции асинхронные: «принято» не равно «успешно обработано»
  • интеграция требует отдельной структуры проекта: клиенты, маппинг, журнал, хранилище статусов
  • Эта статья отвечает на практический вопрос: как сделать так, чтобы данные «доезжали» управляемо, даже если:

  • сервис временно недоступен
  • вы не получили ответ из-за таймаута
  • обработка в ГИС ЖКХ занимает минуты или часы
  • один и тот же пакет случайно отправили дважды
  • Для этого в интеграционном проекте обычно вводят четыре конструкта, которые работают вместе:

  • очереди (и планировщик) для управляемой доставки и повторов
  • идемпотентность для защиты от дублей
  • корреляция для связывания всех технических событий с одной бизнес-операцией
  • статусы для прозрачного жизненного цикла операции и её элементов
  • !Общая схема движения операции от внутренней системы до итогового результата в ГИС ЖКХ

    Очереди и планирование: почему «просто вызвать SOAP» недостаточно

    Что такое очередь в контексте интеграции

    Очередь здесь — это механизм, который хранит задачи на выполнение и отдаёт их воркерам (исполнителям) в нужный момент. Очередь может быть:

  • брокером сообщений (например, RabbitMQ/ActiveMQ)
  • таблицей в базе данных (часто достаточно для старта)
  • специализированным планировщиком фоновых задач
  • Смысл один: интеграция перестаёт зависеть от того, жив ли сейчас внешний сервис, и получает управляемую доставку.

    Зачем очереди именно в ГИС ЖКХ

    Очереди встраиваются почти в каждый сценарий:

  • исходящая отправка: «начисления готовы» → задача на публикацию
  • разбор пакетной загрузки: один батч → много элементарных результатов
  • опрос статусов: «принято» → задача на повторный опрос через интервал
  • повторные попытки: сетевой сбой → задача на повтор по стратегии backoff
  • Если этого нет, появляются две типовые проблемы:

  • потеря операций: приложение упало между «сформировали XML» и «сохранили факт отправки»
  • шторм повторов: при сбое сеть/сервис начинает получать неконтролируемые повторы, а вы — дубли и конфликты
  • Минимальный паттерн: Outbox + воркеры

    На практике удобно мыслить так:

  • Outbox: надёжное хранилище «что нужно отправить» (обычно в БД)
  • Воркер отправки: забирает запись, формирует XML, валидирует, подписывает, отправляет
  • Воркер статусов: периодически опрашивает результат по корреляционным идентификаторам
  • Критичный момент: запись в Outbox создаётся до попытки взаимодействия с ГИС ЖКХ и хранится независимо от жизни процесса.

    Идемпотентность: защита от дублей при повторах

    Что такое идемпотентность простыми словами

    Идемпотентность — это свойство операции, при котором повтор выполнения не меняет результат сверх первого применения.

    В интеграции с ГИС ЖКХ повторы неизбежны, например:

  • вы отправили запрос, но не получили ответ из-за таймаута
  • сервис вернул временную ошибку
  • приложение перезапустилось, а операция была «на границе» отправки
  • Если операция не идемпотентна, повтор превращается в:

  • создание дублей сущностей
  • конфликт «уже существует»
  • несогласованность статусов между вашей системой и ГИС ЖКХ
  • Ключ идемпотентности

    Чтобы повторы стали управляемыми, вводят ключ идемпотентности — стабильный идентификатор «что именно мы хотели сделать».

    Требования к ключу:

  • однозначно описывает бизнес-действие
  • одинаковый при повторной отправке
  • не зависит от технических деталей (время формирования, случайные GUID попытки)
  • Примеры (логика, не стандарт):

  • начисления: orgId + period + batchNumber + internalDocumentId
  • показания: meterId + readingDate
  • обновление объекта: entityType + internalId + version (если вы ведёте версионность)
  • Где реализуется идемпотентность

    Обычно на двух уровнях.

    На уровне вашей системы (обязательно)

  • одна бизнес-операция создаёт одну запись операции в хранилище
  • параллельные исполнители не должны отправлять одно и то же одновременно
  • повтор должен «приклеиваться» к той же операции, а не создавать новую
  • На уровне результата (желательно)

  • если ГИС ЖКХ отвечает «объект уже существует» или «операция уже обработана», вы должны уметь:
  • - распознать это как безопасный повтор - перейти к синхронизации идентификаторов/статуса, а не к бесконечным ретраям

    Практический вывод: идемпотентность — это не «ретраи», а дисциплина хранения факта операции и её ключа.

    Корреляция: как связать запрос, ответ, статус и протокол

    Что такое корреляция

    Корреляция — это связывание всех технических событий вокруг одной операции:

  • ваш внутренний документ или событие
  • сформированный XML
  • попытки отправки
  • первичный SOAP-ответ
  • последующие запросы статуса
  • итоговый протокол обработки
  • Без корреляции вы не сможете ответить на вопросы поддержки и бизнеса:

  • «что именно мы отправили?»
  • «почему в ЛК ГИС ЖКХ не появилось?»
  • «это ошибка сети или ошибка данных?»
  • Практическая модель идентификаторов

    Удобно разделять идентификаторы на три группы.

  • Идентификатор бизнес-операции: стабильный ключ у вас (например, billingDocId, jobId, operationId)
  • Идентификатор попытки: уникален для каждой отправки (например, attemptId)
  • Идентификаторы внешнего контура: то, что возвращает ГИС ЖКХ для отслеживания асинхронной обработки (например, идентификатор сообщения/заявки/квитанции обработки — конкретное имя зависит от сервиса)
  • Важно: даже если сервис возвращает внешний идентификатор, основной якорь корреляции должен быть ваш operationId, потому что он живёт дольше контрактов и версий схем.

    Корреляция в логах

    Для сквозной трассировки (особенно если несколько сервисов и воркеров) полезно внедрить единый correlationId в логи. Если у вас распределённая система, можно ориентироваться на стандарт W3C:

  • W3C Trace Context
  • Даже если вы не внедряете полный distributed tracing, сам принцип полезен: одна операция — один идентификатор в логах, журнале и статусах.

    Статусы: как описать жизненный цикл операции и не потерять «середину»

    Почему статусы нужны всегда

    SOAP-вызов — это момент времени, а интеграционная операция — процесс.

    Процесс может длиться долго и переживать:

  • повторные попытки
  • ожидание асинхронной обработки
  • частичные ошибки внутри пакета
  • ручную корректировку данных и повтор
  • Поэтому статусы — это не «красота», а механизм восстановления и контроля.

    Два уровня статусов: операция и элементы пакета

    В ГИС ЖКХ часто отправляют батчи (списки сущностей). Отсюда возникают два уровня состояния.

  • Статус операции (батча): отправлен ли пакет, принят ли в обработку, получен ли итоговый протокол
  • Статус элемента: успешен ли конкретный дом/ПУ/начисление внутри пакета
  • Если хранить только статус батча, вы теряете управляемость при частичных ошибках: придётся отправлять заново всё или разбирать вручную.

    Пример внутренней машины состояний

    Ниже пример статусов, которые удобно держать у себя. Они не обязаны совпадать с терминологией ГИС ЖКХ, их цель — управляемый процесс.

    | Статус | Что означает | Что должно быть сохранено | Типичная следующая стадия | |---|---|---|---| | Draft | операция создана, но ещё не готова к отправке | ключ идемпотентности, входные данные/ссылки | Validated | | Validated | XML собран и прошёл локальную XSD-валидацию | версия контракта, результат валидации | Signed | | Signed | сообщение подписано | отпечаток сертификата, факт подписи | Sent | | Sent | запрос отправлен | сырой request/response, attemptId | Accepted или RetryScheduled | | Accepted | получен первичный ответ «принято» | внешний идентификатор для статуса | Processing | | Processing | ждём итог обработки | расписание следующего опроса | Success или Failed | | Success | обработано успешно | протокол, внешние идентификаторы сущностей | завершение | | Failed | обработано с ошибками | протокол с ошибками, привязка ошибок к элементам | исправление и повтор |

    !Машина состояний интеграционной операции и места, где возникают повторы и ошибки

    Как статусы связаны с типами ошибок

    Статусы помогают не только «где мы», но и что делать дальше. Типовая связка (по смыслу из предыдущих статей):

  • транспортная ошибка → планировать повтор (RetryScheduled)
  • ошибка подписи → остановить и требовать вмешательства по сертификатам (Failed с типом Security)
  • XSD-ошибка → не повторять, исправлять маппинг/данные (Failed с типом Contract)
  • бизнес-ошибка в протоколе → исправлять предметные данные/сопоставления (Failed с типом Business)
  • Главное правило: ретраи лечат только то, что может исчезнуть само (сеть, временная недоступность), но не лечат структуру XML и бизнес-правила.

    Практическая «минимальная модель данных» для журнала и статусов

    Ниже — минимальный набор сущностей, который обычно нужен, чтобы очереди, идемпотентность и статусы работали вместе.

    Что хранить по операции

  • operationId: внутренний идентификатор
  • idempotencyKey: ключ идемпотентности
  • service и method: какой сервис и операция
  • contractVersion: версия WSDL/XSD
  • status: текущий статус
  • nextRunAt: когда можно/нужно продолжить (для очереди/планировщика)
  • externalTrackingId: идентификатор для опроса статуса (если выдан)
  • Что хранить по попытке отправки

  • attemptId: идентификатор попытки
  • operationId: ссылка на операцию
  • createdAt: время попытки
  • requestXmlRef и responseXmlRef: ссылки на сохранённые request/response (или защищённое хранилище)
  • transportResult: результат транспорта (успешно/таймаут/ошибка TLS)
  • soapFault: если был SOAP Fault
  • Что хранить по элементам батча (если пакетный метод)

  • itemId: элемент внутри пакета
  • operationId: к какому батчу относится
  • sourceEntityId: ваш идентификатор сущности
  • status: успех/ошибка/не обработан
  • errorCode и errorText: если ошибка пришла по элементу
  • Практический эффект: вы можете повторно отправить только элементы со статусом ошибки, а не весь батч.

    Типовой алгоритм движения операции по очередям

    Ниже — базовый сценарий, который удобно реализовывать в Application слое (из статьи про структуру проекта), опираясь на Infrastructure (транспорт/подпись/хранилище).

  • Создать операцию в статусе Draft с idempotencyKey.
  • Поставить операцию в очередь на обработку.
  • Воркер берёт операцию (с блокировкой от параллельного выполнения).
  • Собирает контрактный DTO и сериализует XML.
  • Валидирует XML по XSD.
  • Подписывает сообщение.
  • Отправляет SOAP-запрос.
  • Сохраняет первичный ответ и переводит статус:
  • - в Accepted, если принят и выдан внешний идентификатор - в RetryScheduled, если временная ошибка - в Failed, если неустранимая ошибка
  • Воркер статусов по externalTrackingId запрашивает итог.
  • Разбирает протокол:
  • - обновляет статус операции - при батчах обновляет статусы элементов - формирует задачи на исправление данных при бизнес-ошибках

    Повторы и backoff: как не устроить «само-DDoS»

    При временных сбоях важны два правила.

  • Повторы должны быть ограничены по числу попыток и по времени жизни операции.
  • Интервалы повторов должны расти, если ошибка повторяется (backoff).
  • Пример стратегии без формул:

  • 1-я ошибка: повтор через 30 секунд
  • 2-я ошибка: повтор через 2 минуты
  • 3-я ошибка: повтор через 10 минут
  • далее: перевод в Failed и эскалация, если лимит исчерпан
  • Отдельно стоит разделять:

  • повторы отправки (когда мы не уверены, что запрос дошёл)
  • повторы опроса статуса (когда запрос дошёл и принят, но итог ещё не готов)
  • Это разные очереди/типы задач и разные интервалы.

    Антипаттерны, которые ломают управляемость

  • Нет единого operationId и журнала: разбор инцидентов становится невозможным.
  • Ретраи на XSD-ошибках: система без пользы создаёт нагрузку и шум в логах.
  • Нет блокировки/дедупликации: два воркера отправляют одно и то же, появляются дубли и конфликтные статусы.
  • Храните только статус батча: частичные ошибки превращаются в ручной ад.
  • Не сохраняете первичный ответ: теряете внешний идентификатор и не можете корректно опросить итог.
  • Связь с следующими темами курса

    В этой статье мы описали механику движения интеграционной операции.

    Дальше по курсу логично углубиться в две практические области:

  • подписание SOAP/XML и управление сертификатами как отдельный этап жизненного цикла (и отдельный класс ошибок)
  • обработка ошибок: как классифицировать SOAP Fault, контрактные ошибки, бизнес-валидации и статусные конфликты, и как связывать их со статусами и стратегиями повторов
  • 6. ЭП и подписание сообщений: форматы, хранилища ключей, проверка

    ЭП и подписание сообщений: форматы, хранилища ключей, проверка

    Как это связано с предыдущими темами курса

    Ранее мы разобрали:

  • что интеграция с ГИС ЖКХ строится на SOAP/XML и жёстко следует WSDL/XSD
  • что многие операции асинхронные, и для управляемости нужны журнал, корреляция и статусы
  • как разделять проект на слои и модули, чтобы обновления контрактов и инфраструктуры не ломали бизнес-сценарии
  • Подписание сообщений — следующий обязательный шаг в жизненном цикле операции:

  • сформировали данные и построили XML по XSD
  • провели локальную валидацию
  • подписали (ЭП)
  • отправили по SOAP
  • получили первичный ответ и дальше отслеживаем итоговый статус
  • Если этап подписи спроектирован неправильно, вы будете видеть ошибки, которые не лечатся ретраями: сообщение системно не принимается или считается юридически недостоверным.

    !Место подписи в жизненном цикле интеграционного сообщения

    Что такое электронная подпись в контексте SOAP/XML

    Термины, которые нужно различать

  • Закрытый ключ — секретный ключ, которым выполняют подписание. Его нельзя передавать и нельзя логировать.
  • Сертификат — публичная часть (открытый ключ + сведения о владельце), подписанная удостоверяющим центром. Сертификат можно передавать получателю.
  • Электронная подпись (ЭП) — криптографический результат, который позволяет:
  • - проверить целостность (данные не изменились после подписи) - проверить принадлежность (кто подписал, если доверяем цепочке сертификатов)

    В SOAP/XML интеграциях подпись чаще всего реализуется как XML Signature: это специальный XML-элемент Signature, который содержит информацию о том, что именно подписано и как это проверить.

    Полезные спецификации для понимания формата:

  • XML Signature Syntax and Processing Version 1.1
  • XML Canonicalization 1.1
  • Что именно подписывается

    В реальных SOAP-сервисах возможны варианты:

  • подписывается всё SOAP Body (частый подход: подпись «прикреплена» к полезной нагрузке)
  • подписывается отдельный бизнес-документ внутри Body
  • подписываются части SOAP Header, если по контракту там есть идентификаторы или security-блок
  • Критичная мысль: подпись вычисляется не «по смыслу данных», а по байтовому представлению XML после преобразований. Поэтому любая мелочь — пробелы, порядок атрибутов, namespaces, форматирование — может сломать проверку, если изменения произошли после подписи.

    Форматы подписи и основные режимы XML Signature

    Три режима размещения подписи

  • Enveloped signatureSignature находится внутри подписываемого XML-документа.
  • Enveloping signature — подписываемые данные помещены внутрь Signature.
  • Detached signatureSignature хранится отдельно, а подписываемый фрагмент указывается ссылкой.
  • В интеграциях на SOAP чаще встречаются enveloped и detached варианты.

    Из чего состоит XML Signature (упрощённо)

    Типовая подпись содержит:

  • SignedInfo — описание того, что подписываем:
  • - ссылки Reference на подписываемые фрагменты - алгоритмы преобразования (transforms) - алгоритм хэширования (digest)
  • SignatureValue — собственно значение подписи, вычисленное закрытым ключом
  • KeyInfo — данные для проверки, часто включают сертификат (X509Data)
  • Практический вывод для проекта: для отладки и журнала важно уметь сохранять:

  • какие URI/Id были подписаны
  • какие алгоритмы применены
  • какой сертификат использован (как минимум отпечаток)
  • Но при этом нельзя сохранять в логах закрытый ключ и чувствительные данные без политики маскирования.

    Каноникализация: почему «одинаковый XML» может не проверяться

    Что такое каноникализация

    Каноникализация (C14N) — это приведение XML к стандартизированному виду перед вычислением хэша и подписи.

    Зачем она нужна:

  • XML допускает разное «косметическое» представление (пробелы, переносы строк, порядок атрибутов)
  • без каноникализации два семантически одинаковых документа могут давать разные байты, а значит разные хэши и подписи
  • Спецификация:

  • XML Canonicalization 1.1
  • Типовые причины поломки подписи на практике

  • подпись вычислили, а потом библиотека SOAP заново «отформатировала» XML (pretty print)
  • добавили/изменили namespace-объявления после подписи
  • изменили порядок элементов или атрибутов сериализацией «по-своему»
  • подписали один фрагмент, а реально отправили другой (например, DTO отличается от итогового SOAP)
  • Архитектурное правило: подписывать нужно максимально близко к моменту отправки и именно тот XML, который уйдёт по сети.

    Хранилища ключей: варианты, плюсы и риски

    Что значит «хранить ключ» в интеграционном проекте

    Вам нужно безопасно хранить и использовать:

  • закрытый ключ
  • сертификат(ы)
  • цепочку сертификатов (если требуется проверка цепочки)
  • При этом проект должен поддерживать:

  • несколько организаций и несколько сертификатов
  • ротацию (замену) сертификатов
  • контроль срока действия
  • Файловые контейнеры PKCS#12 (.p12 / .pfx)

    Это распространённый формат «в одном файле»: закрытый ключ + сертификат + цепочка.

    Спецификация:

  • RFC 7292: PKCS #12: Personal Information Exchange Syntax
  • Плюсы:

  • просто подключать в приложении
  • удобно для тестовых контуров
  • Минусы:

  • проблема секретов: файл нужно защищать, пароль нужно хранить в секрет-хранилище
  • есть риск копирования ключа (сложно обеспечить, что он «не утёк»)
  • Рекомендации:

  • хранить пароль в секрет-хранилище, а не в конфиге
  • ограничить права доступа к файлу
  • отделить тестовые ключи от промышленных и от регламента доступа
  • Хранилище сертификатов ОС

    Ключи могут храниться в системном хранилище (зависит от ОС и криптопровайдера), а приложение обращается к ключу по идентификатору.

    Плюсы:

  • удобнее управлять доступами на уровне ОС
  • меньше риск случайного копирования файла
  • Минусы:

  • усложняется переносимость и контейнеризация
  • сложнее воспроизводить окружение в CI
  • Аппаратные модули (HSM) и токены

    Смысл HSM: закрытый ключ физически не покидает устройство. Приложение отправляет запрос «подпиши», получает подпись.

    Плюсы:

  • максимальный контроль над ключом
  • аудит операций подписи
  • Минусы:

  • стоимость, инфраструктура
  • нужно проектировать отказоустойчивость и доступность HSM
  • Сравнение вариантов

    | Вариант | Где ключ | Основной риск | Когда уместно | |---|---|---|---| | PKCS#12 файл | на диске сервера | утечка файла/пароля | пилоты, тест, иногда прод при строгих регламентах | | Хранилище ОС | в контуре ОС/провайдера | зависимость от окружения | прод в контролируемых серверах | | HSM/токен | в устройстве | сложность/стоимость | требования повышенной безопасности |

    Выбор сертификата и многоконтурность

    Почему «один сертификат» почти никогда не заканчивается

    В типовой интеграции встречаются причины иметь несколько сертификатов:

  • разные организации (разные владельцы сертификатов)
  • разные контуры (тест/пром)
  • ротация и перекрывающиеся сроки (старый ещё действует, новый уже введён)
  • Поэтому в проекте нужен реестр ключей/сертификатов и политика выбора:

  • по orgId
  • по целевому контуру
  • по типу операции (если регламент требует)
  • Что фиксировать в журнале интеграции

    Чтобы разбирать инциденты и доказывать, чем подписали, полезно сохранять:

  • отпечаток сертификата (fingerprint)
  • серийный номер сертификата
  • период действия (NotBefore / NotAfter)
  • идентификатор хранилища/контейнера (без секретов)
  • Сами ключевые материалы и пароли в журнал не пишутся.

    Проверка подписи: что проверяем локально и что ожидаем от принимающей стороны

    Две проверки, которые имеют смысл у вас

  • Криптографическая проверка подписи
  • - проверяем, что подпись математически корректна для указанного открытого ключа - это ловит ошибки сериализации, каноникализации и «подписали не то»
  • Проверка сертификата
  • - срок действия - целостность цепочки сертификатов (если у вас есть доверенные корни)

    Базовая спецификация по сертификатам X.509:

  • RFC 5280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile
  • Важно: в некоторых интеграциях вы не сможете полностью воспроизвести логику доверия принимающей стороны (например, из-за внутреннего набора доверенных УЦ). Но криптографическую корректность подписи и срок действия сертификата вы проверить обязаны.

    Почему локальная проверка экономит недели

    Если вы не проверяете подпись у себя, то при отказе сервиса у вас остаётся много гипотез:

  • неправильный алгоритм
  • не тот фрагмент подписали
  • не туда вставили Signature
  • сертификат не тот
  • Локальная проверка резко сужает поле: если локально подпись не проверяется, проблема у вас до отправки.

    Где размещать логику подписи в архитектуре проекта

    В статье про структуру проекта мы выделяли модуль giszhkh-security. Это оптимальное место для:

  • доступа к ключам (файл, ОС, HSM)
  • операций подписи
  • операций локальной проверки
  • аудита использования сертификатов
  • В Application-слое подпись должна выглядеть как вызов понятного интерфейса, например:

  • SignaturePort.sign(xml, policy)
  • SignaturePort.verify(xml)
  • Где policy — набор правил: что подписывать, какой алгоритм, как вставлять Signature, какой сертификат выбирать.

    Типовые ошибки подписи и правильная реакция

    Ошибки, которые не лечатся ретраем

  • неверный сертификат (не тот владелец/контур)
  • истёк срок действия сертификата
  • подпись невалидна из-за изменений XML после подписи
  • неверные transforms/каноникализация
  • Реакция:

  • перевод операции в Failed с типом Security
  • создание задачи на исправление (сертификаты/настройки/пайплайн сериализации)
  • Ошибки, которые могут быть временными

  • недоступно хранилище ключей (сетевой HSM, временная ошибка провайдера)
  • Реакция:

  • планируем повтор с backoff (как для инфраструктурных ошибок), но с ограничением числа попыток
  • Практический чек-лист перед запуском в прод

  • Зафиксировать, какой сертификат используется для каждой организации и контура.
  • Проверить срок действия и регламент ротации.
  • Запретить любое форматирование XML после подписи.
  • Включить локальную проверку подписи до отправки.
  • Настроить журнал: отпечаток сертификата, идентификатор операции, ссылки на request/response.
  • Подготовить сценарий аварии: что делать при истечении сертификата и кто отвечает.
  • Как эта тема связана с обработкой ошибок

    Подпись — отдельный класс отказов, который нужно отделять от:

  • транспортных ошибок (TLS/сеть)
  • контрактных ошибок (XSD)
  • бизнес-ошибок (протокол обработки)
  • В следующем материале логично разбирать обработку ошибок системно: как классифицировать ошибки на каждом шаге (валидация, подпись, отправка, статус), как привязывать их к статусам операции, и как строить корректные ретраи без дублей.

    7. Ошибки и устойчивость: fault-коды, ретраи, мониторинг, аудит

    Ошибки и устойчивость: fault-коды, ретраи, мониторинг, аудит

    Зачем отдельная тема про устойчивость

    В предыдущих статьях мы выстроили «скелет» интеграции с ГИС ЖКХ:

  • SOAP/XML и строгий контракт WSDL/XSD
  • асинхронность: «принято» не равно «успешно обработано»
  • структура проекта: слои, журнал, статусы
  • подписание и проверка подписи
  • Теперь важно сделать систему управляемой в ошибках: понимать, где именно ломается, можно ли повторять, как это увидеть в мониторинге и как доказать, что было отправлено и чем подписано.

    !Жизненный цикл операции и точки возникновения ошибок

    Классификация ошибок: чтобы не лечить «повтором» то, что повтором не лечится

    Правильная классификация нужна для двух вещей:

  • выбрать реакцию: повторять, остановить, отдать на исправление данных
  • корректно отражать статус операции и создавать понятные задачи поддержки
  • Транспортные ошибки

    Это ошибки, при которых вы не смогли надёжно доставить запрос.

  • таймаут HTTP
  • DNS/маршрутизация
  • разрыв соединения
  • временная недоступность узла
  • Обычно такие ошибки потенциально повторяемы, но требуют идемпотентности и ограничений по числу попыток.

    Ошибки TLS и взаимной аутентификации

    Если используется TLS и/или клиентские сертификаты на канале, возможны:

  • недоверенная цепочка сертификатов
  • неверный клиентский сертификат
  • несовместимые параметры TLS
  • Часть таких ошибок устранима только настройками, а не ретраями.

    SOAP Fault

    SOAP Fault означает, что вы дошли до SOAP-уровня, но сервис вернул формальную ошибку.

  • это может быть «контрактно не то вызвали»
  • это может быть «доступ запрещён»
  • это может быть «внутренняя ошибка сервиса»
  • Важно: SOAP Fault сам по себе не говорит, повторять или нет. Решение принимается по типу Fault и сопутствующим деталям.

    Спецификация SOAP 1.2: SOAP Version 1.2 Part 1: Messaging Framework.

    Контрактные ошибки (XSD)

    Это ошибки, которые вы должны ловить до отправки, локальной валидацией XML по XSD:

  • отсутствует обязательный элемент
  • неверный формат значения
  • неверный namespace
  • нарушен порядок элементов, если он задан схемой
  • Главное правило: XSD-ошибка не лечится ретраем. Она лечится исправлением данных или маппинга.

    Ошибки подписи и сертификатов

    Это ошибки, которые возникают на этапе Signed или при проверке у принимающей стороны:

  • истёк срок действия сертификата
  • выбран не тот сертификат (не тот контур или не та организация)
  • подпись невалидна из-за изменения XML после подписи
  • несовместимые алгоритмы и transforms
  • Спецификации для понимания формата: XML Signature Syntax and Processing Version 1.1, XML Canonicalization 1.1.

    Главное правило: ошибки подписи обычно не лечатся ретраем (кроме временной недоступности хранилища ключей).

    Бизнес-ошибки и протокол обработки

    Это ошибки, которые приходят после того, как запрос принят, на этапе Processing:

  • некорректные связи сущностей
  • конфликт периодов
  • объект уже существует (иногда это безопасный повтор, иногда нет)
  • ограничения предметной области
  • Чаще всего они требуют коррекции данных и повторной публикации только проблемных элементов батча.

    SOAP Fault на практике: что извлекать и как логировать

    SOAP Fault может выглядеть по-разному в SOAP 1.1 и SOAP 1.2, но смысл общий: есть код, текст и детали.

    Какие поля Fault важны

  • faultcode или Code: категория ошибки (уровень протокола)
  • faultstring или Reason: человекочитаемое объяснение
  • detail или Detail: машинные детали, иногда с бизнес-кодами
  • Практическое правило для проекта: сохраняйте в журнале минимум код, текст, сырой fault XML (с маскированием чувствительных данных) и связывайте это с operationId.

    Почему важно отличать Fault от «успешного» HTTP

    В SOAP-интеграциях HTTP 200 может прийти вместе с Fault внутри XML. Поэтому критерий «успеха отправки» должен быть таким:

  • получен ответ
  • он распарсен
  • он не является SOAP Fault
  • он содержит ожидаемые поля первичного подтверждения (например, идентификатор для опроса статуса)
  • Матрица реакций: повторять, останавливать, отдавать на исправление

    Ниже — практическая матрица, которую удобно «вшить» в классификатор ошибок доменного слоя.

    | Класс ошибки | Где возникает | Повторять? | Типовая реакция | Что обязательно сохранить | |---|---|---|---|---| | Транспорт | Sent | Да | RetryScheduled с backoff | попытка, таймаут/код, request-id, endpoint | | TLS/сертификаты канала | Sent | Обычно нет | Failed и задача на настройку | ошибка TLS, цепочка доверия, какой cert использовался | | SOAP Fault: временная ошибка сервиса | Sent | Иногда | ограниченный ретрай | сырой Fault, код, корреляция | | SOAP Fault: доступ/контракт | Sent | Нет | Failed и исправление конфигурации/кода | WSDL/XSD версия, операция, Fault | | XSD-валидация | Validated | Нет | Failed и исправление маппинга/данных | результат валидации, какая схема | | Подпись | Signed | Обычно нет | Failed и задача по ключам/подписи | отпечаток сертификата, политика подписи | | Бизнес-ошибка в протоколе | Processing | Нет | корректировка данных, повтор выборочно | протокол, привязка ошибок к элементам |

    Ретраи: как повторять безопасно и не создавать дубли

    Два разных вида повторов

    В интеграции с ГИС ЖКХ важно разделять:

  • ретрай отправки: вы не уверены, дошёл ли запрос, или сервис временно недоступен
  • ретрай опроса статуса: запрос дошёл и принят, но итог обработки ещё не готов
  • Это разные очереди задач, разные лимиты и разные последствия.

    Условия, при которых ретрай допустим

    Ретрай допустим, если одновременно выполнены условия:

  • ошибка потенциально временная (сеть, таймаут, временная недоступность)
  • у операции есть стабильный ключ идемпотентности
  • вы корректно сохраняете факт попытки, чтобы не было параллельных отправок одного и того же
  • Если нет идемпотентности и журнала попыток, ретраи превращаются в генератор дублей.

    Backoff и jitter простыми словами

  • Backoff означает, что интервал между попытками растёт при повторяющихся ошибках: так вы снижаете нагрузку на сервис и на свою систему.
  • Jitter означает небольшую случайную «прибавку/убавку» к интервалу: так много воркеров не пойдут повторять одновременно.
  • Это критично, чтобы не устроить «само-DDoS» при массовом сбое.

    Когда ретраи запрещены

  • XSD-ошибка
  • ошибка подписи из-за формата XML или неверного сертификата
  • SOAP Fault, который явно говорит о неверном вызове, доступе или данных
  • В этих случаях повтор создаёт только шум и нагрузку.

    Ограничения ретраев, которые стоит зафиксировать в конфигурации

  • максимальное число попыток отправки
  • максимальное время жизни операции в статусе ожидания
  • отдельные лимиты для «отправки» и «опроса статуса»
  • политика остановки и эскалации (кому и когда)
  • Мониторинг: что наблюдать, чтобы поддержка работала без «скриншотов»

    Три уровня наблюдаемости

  • логи: отвечают на вопрос что произошло
  • метрики: отвечают на вопрос как часто и насколько плохо
  • трассировка: отвечает на вопрос где именно и сколько времени заняло
  • Если выбирать минимум для старта, то это: структурированные логи + метрики + понятные дашборды.

    Корреляция в логах

    В каждой записи логов и в журнале интеграции должны быть идентификаторы:

  • operationId (ваш стабильный идентификатор операции)
  • attemptId (попытка отправки)
  • externalTrackingId (что вернула ГИС ЖКХ для статуса)
  • Если система распределённая, полезен общий контекст трассировки: W3C Trace Context.

    Минимальный набор метрик

  • количество операций в статусах Draft/Validated/Sent/Accepted/Processing/Failed
  • глубина очереди на отправку и очереди опроса статусов
  • доля успешных операций за период
  • распределение причин ошибок по классам: Transport/Contract/Security/Business
  • среднее и p95 время от Sent до Success (для асинхронной обработки)
  • Алерты и пороги

    Пороги должны быть связаны со смыслом процесса:

  • рост Failed по классу Contract означает регрессию маппинга или смену схем
  • рост Transport означает инфраструктурную проблему
  • рост времени Processing означает задержку на стороне внешней обработки
  • Практический совет: не начинайте с десятков алертов, начните с 5–7 сигналов, но сделайте для них понятные инструкции.

    Аудит: что хранить, чтобы доказать отправку, подпись и результат

    Аудит в интеграции с ГИС ЖКХ — это способность ответить на вопросы:

  • что именно отправили и когда
  • чем подписали
  • что вернул сервис и какой итоговый протокол обработки
  • Что является аудитным следом операции

    Минимальный набор данных, который стоит хранить в журнале интеграции:

  • operationId, service, method, версия контракта
  • отметки времени: сформировано, подписано, отправлено, получен первичный ответ, получен итог
  • ссылки на сырой request и response (часто не прямо в таблице, а как xmlRef в защищённом хранилище)
  • externalTrackingId для асинхронного статуса
  • для подписи: отпечаток сертификата, серийный номер, срок действия сертификата
  • Закрытый ключ, пароли и секреты хранить нельзя.

    Маскирование и хранение XML

    XML может содержать персональные данные. Поэтому почти всегда нужен режим:

  • маскировать чувствительные поля в логах
  • хранить сырые XML в защищённом хранилище с ограничением доступа
  • хранить контрольные суммы или «ссылку на объект» вместо копий в разных местах
  • Неизменяемость и сроки хранения

    Если аудит используется для разборов и доказательств, важно:

  • ограничить право изменения журналов
  • фиксировать, кто и когда просматривал чувствительные записи
  • определить срок хранения, достаточный для поддержки и проверок
  • Практический runbook: как разбирать инцидент по шагам

  • Найти operationId по бизнес-объекту (лицевой счёт, начисление, ПУ).
  • Проверить статус операции и последние попытки.
  • Если ошибка Transport, посмотреть историю ретраев и текущую доступность endpoint.
  • Если SOAP Fault, извлечь код/Reason/Detail и понять, это «временная» или «логическая» ошибка.
  • Если Contract, поднять результат XSD-валидации и версию схемы.
  • Если Security, проверить отпечаток и срок действия сертификата, а также локальную проверку подписи.
  • Если Business/Protocol, открыть протокол обработки и определить, какие элементы батча проблемные.
  • Создать задачу на корректировку данных или настроек и запланировать повтор выборочно.
  • Как эта статья связывает курс в единую систему

  • Из статей про SOAP/WSDL/XSD следует, что контрактные ошибки нужно ловить локально, а не повторять.
  • Из статьи про архитектуру проекта следует, что классификация ошибок и реакции должны жить в Domain/Application слоях, а инфраструктура только поставляет детали.
  • Из статьи про движение данных следует, что ретраи обязаны быть идемпотентными, коррелируемыми и управляемыми статусами.
  • Из статьи про подпись следует, что ошибки Security — отдельный класс, требующий аудита сертификатов и строгого контроля «подписали именно то, что отправили».
  • Следующий практический шаг в реальном проекте — формализовать ваши политики: таблицу реакций на ошибки, конфигурацию ретраев, набор метрик и регламент аудита, чтобы интеграция работала стабильно под нагрузкой и переживала сбои без ручного хаоса.