В этой заметке разбираю ошибки 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: у них различается представление полей.
Как проверяю исправленный обработчик
- На обезличенных образцах проверяю извлечение всех трёх полей в формате нужной операции. Отдельно проверяю отсутствие необязательных полей.
- Убеждаюсь, что HTTP-статус и XML-код попадают в разные поля журнала, а пароль не записывается.
- Проверяю остановку повторов для 401, 404 и 406, а также предусмотренное регламентом поведение при 503 и 504.
- После устранения причины выполняю согласованную безопасную операцию. Проверяю не только логический результат GetBlock, но и ожидаемые данные ответа. Пробные запросы не должны создавать, подписывать или оплачивать реальные документы без отдельного разрешения.
Для меня исправление здесь — это не исчезновение красной строки в журнале. Обработчик должен сохранить причину отказа, выбрать допустимое действие и не продолжать отправку там, где её требуется остановить.
Получилось или остались вопросы?
Поделитесь результатом, дополните инструкцию своим опытом или задайте вопрос. Я читаю комментарии и обновляю статьи по реальным случаям.