83

Ошибки API ЭТРАН: как читать XML-ответ АСУ–АСУ

В этой заметке разбираю ошибки API ЭТРАН при обмене АСУ–АСУ. Самое важное для диагностики — не потерять тело ответа: короткая запись «404» или «504» ещё не объясняет, что произошло. Сначала я отделяю HTTP-статус от ошибки внутри XML, затем проверяю формат ответа и только после этого решаю, можно ли повторять запрос.

Ниже речь о SOAP-интерфейсе GetBlock, описанном в руководстве программиста 2022 года и комплекте XSD от 27 мая 2022 года. Это разбор конкретного формата обмена, а не утверждение о неизменности API. Для действующего подключения приоритет имеют выданные организации актуальные схемы и регламент. Ошибки браузерного входа и загрузки МЧД по этим кодам расшифровывать нельзя.

Что сохраняю при ошибке API ЭТРАН

Для разбора мне нужны название запроса, время отправки, HTTP-статус, логический результат GetBlock и возвращённое содержимое параметра Text. В описанном интерфейсе Text служит и для передачи команды, и для получения результата. Если журнал сохраняет только признак True или False, из него пропадает объяснение отказа.

Диагностическую копию ответа храню с ограниченным доступом. Перед передачей убираю пароли, персональные данные и коммерческие реквизиты документов. Параметры Login и Password в журнал целиком не записываю. Само подключение и разрешённый состав обмена готовятся отдельно — об этом есть заметка о проекте технических решений для АСУ–АСУ.

Три поля XML, которые нельзя смешивать

В сообщении об ошибке предусмотрены errorCode, errorMessage и errorStatusCode. Первое поле характеризует ошибку обработки, второе содержит пояснение, третье уточняет причину. Например, синтаксис XML и отсутствие прав на документ — разные основания для отказа, даже если приложение показывает пользователю одну общую надпись.

Число из errorStatusCode не является HTTP-статусом только потому, что выглядит знакомо. Значение 504 внутри ответа ЭТРАН имеет собственный смысл. Если же вместо XML пришла HTML-страница шлюза с HTTP 504, это другой случай. Аналогично, HTTP 400 и 500 при загрузке МЧД не следует автоматически сопоставлять с кодами АСУ–АСУ.

Почему обработчик может не увидеть код

В комплекте схем есть два способа размещения этих полей. Отдельный элемент error типа ErrorAnswer использует атрибут value. В базовом типе SimpleAnswer поля объявлены как содержимое элементов. Поэтому перед исправлением обработчика я проверяю тип конкретного ответа, а не ищу один универсальный путь к значению.

Вот два фрагмента, показывающих различие. Это не полные ответы сервера:

<errorStatusCode value="404"/>

<errorStatusCode>404</errorStatusCode>

Чтение только атрибута во втором случае не даст код; чтение только текста в первом — тоже. Кроме того, поля ошибки в SimpleAnswer необязательны. Отсутствующее поле нельзя без проверки остальных данных превращать в «неизвестную ошибку» или объявлять доказательством успешной операции.

Когда прекращаю повторные запросы

Для перечисленных ниже значений errorStatusCode руководство описывает разные действия. Речь именно об XML-ответе ЭТРАН в указанной версии интерфейса.

  • 401 — авторизация. Возможны неверные данные системного пользователя, прекращение или приостановка действия договора ЭОД либо доверенностей. Отправку запросов этого пользователя останавливаю. Сверяю реквизиты с выданными при подключении; если они верны, проверка действия договора и полномочий проводится через подразделение РЖД, оформлявшее ЭОД. В руководстве предусмотрено ручное разрешение возобновления обмена после устранения причины.
  • 404 — данные или права. Код не позволяет выбрать одну из этих причин без дальнейшей проверки. Бессмысленно продолжать тот же запрос с теми же данными пользователя. Проверяю идентификаторы и область разрешённого доступа. Использовать другую учётную запись можно только при наличии у неё законных полномочий, а не для обхода ограничений.
  • 406 — формат запроса. Не отправляю неизменный XML снова. Сверяю его с текущим руководством и схемой именно этой операции, исправляю несовместимые поля или структуру и затем выполняю разрешённую проверку.

Чем отличаются 503 и 504

503 в этом формате означает ошибку связи с внешними сервисами. Руководство предписывает уменьшить частоту запросов данного типа до одного в минуту и сообщить о сбое подразделению ИВЦ или ГВЦ, с которым заключён договор ЭОД. Я передаю название операции, время и обезличенное пояснение ошибки — без пароля и полного документа.

504 означает остановку АС ЭТРАН до указанного времени; планируемое возобновление описывается в тексте ошибки. Обычные запросы нужно заблокировать. В руководстве оставлено исключение для тестирования соединения: не чаще одного раза в минуту, с возобновлением полноценного обмена после успешного ответа.

Эти интервалы относятся к описанному регламенту 2022 года. Если действующий регламент организации задаёт иной порядок, обработчик должен соответствовать ему.

Как проверить связь запросом test

В том же руководстве для проверки связи предусмотрен запрос test. Через настроенное подключение GetBlock передаю в параметре Text следующий XML; это содержимое параметра, а не полный SOAP-конверт:

<test version="1.0">
</test>

Для успешного выполнения описан ответ testReply с элементом version. Его структура в руководстве выглядит так:

<testReply>
  <version value=""/>
</testReply>

Пустой value здесь оставлен из шаблона документации — это не реальный ответ проверенного сервера. В полученном ответе проверяю структуру и значение версии, а не сравниваю XML посимвольно с этим примером.

Успешный testReply подтверждает выполнение тестового запроса, но сам по себе не доказывает доступ к конкретной накладной или справке. Если тест не выполнен, сохраняю фактический ответ либо отсутствие ответа и продолжаю диагностику по нему. Код errorCode=100 в руководстве обозначает внутреннюю ошибку: по одному этому числу нельзя уверенно заключить, что оборвалась сеть.

Почему не зашиваю старый перечень кодов навсегда

Даже внутри рассмотренного комплекта таблица руководства и перечисления в EtranCategories.xsd совпадают не полностью. Например, в таблице errorCode есть 100, а схема перечисляет 1–5. Это повод сверить версии и фактический ответ, а не самовольно исправить схему под удобный вариант.

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

Как проверяю исправленный обработчик

  1. На обезличенных образцах проверяю извлечение всех трёх полей в формате нужной операции. Отдельно проверяю отсутствие необязательных полей.
  2. Убеждаюсь, что HTTP-статус и XML-код попадают в разные поля журнала, а пароль не записывается.
  3. Проверяю остановку повторов для 401, 404 и 406, а также предусмотренное регламентом поведение при 503 и 504.
  4. После устранения причины выполняю согласованную безопасную операцию. Проверяю не только логический результат GetBlock, но и ожидаемые данные ответа. Пробные запросы не должны создавать, подписывать или оплачивать реальные документы без отдельного разрешения.

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

Получилось или остались вопросы?

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

Напишите комментарий

Опишите проблему и укажите, какое решение вы уже проверили. Адрес электронной почты на сайте не публикуется.