Разработка веб-сервисов в 1С обычно идет по классическому пути: программист создает объект Web-сервис, определяет его методы, параметры и типы XDTO, а затем платформа автоматически генерирует WSDL-описание. Однако в реальной практике часто встречается обратная задача: клиент (сторонняя система, часто на базе .NET или Java) уже имеет жестко заданный формат запроса и требует, чтобы наш сервис принимал данные именно в таком виде. При попытке реализовать такой «подгон» разработчики часто сталкиваются с неочевидными ошибками, включая самую распространенную — «Ошибка 500».
В этой статье мы подробно разберем, как правильно настроить веб-сервис 1С под существующий SOAP-запрос, проанализируем структуру XML и выясним, какие ограничения платформы 1С могут помешать успешной интеграции.
Рассмотрим пример запроса, который прислал клиент. На первый взгляд он кажется стандартным, но в нем скрыто несколько важных деталей, которые определяют логику настройки 1С:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<requestRootId xmlns="http://schemas.microsoft.com/application-insights">100100</requestRootId>
<requestId xmlns="http://schemas.microsoft.com/application-insights">451289</requestId>
</s:Header>
<s:Body>
<GetPrice xmlns="http://tempuri.org/">
<priceRequest xmlns:a="http://schemas.datacontract.org/2004/07/com.Ordering"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Currency>EUR</a:Currency>
<a:CurReference>12345</a:CurReference>
<a:CurNumber>843</a:CurNumber>
<a:LocationCode>LocationCode1</a:LocationCode>
<a:OrderType>Stock</a:OrderType>
<a:Parts>
<a:Part>
<a:PartNumber>1825005</a:PartNumber>
<a:Quantity>1</a:Quantity>
<a:UnitOfMeasure>Piece</a:UnitOfMeasure>
</a:Part>
</a:Parts>
</priceRequest>
</GetPrice>
</s:Body>
</s:Envelope>
Важные моменты в этом запросе:
<a:Parts> не был закрыт корректно (отсутствовал слеш). Перед началом настройки всегда проверяйте XML на валидность.http://tempuri.org/ для метода и http://schemas.datacontract.org/... для данных. Это типичные пространства имен для сервисов на WCF (.NET). В 1С они должны совпадать символ в символ.Проанализируем ситуацию: чтобы 1С поняла структуру priceRequest, нам необходимо создать XDTO-пакет. Если у вас есть XSD-схема от клиента — это лучший вариант. Если нет, схему придется воссоздать вручную.
При создании пакета URI пространства имен должен быть в точности таким, как в запросе у элементов данных: http://schemas.datacontract.org/2004/07/com.Ordering. Любая опечатка или лишний слеш в конце строки приведет к тому, что 1С не сможет сопоставить входящий XML с типом данных XDTO, и вы получите ошибку десериализации.
Внутри пакета опишем тип объекта priceRequest со всеми свойствами (Currency, CurReference и т.д.). Помните, что для систем на .NET порядок следования полей часто имеет значение (обычно по алфавиту). Если порядок в вашем XDTO-пакете будет отличаться от присланного XML, платформа может выдать ошибку 500.
Теперь перейдем к самому объекту Web-сервис в метаданных 1С:
http://tempuri.org/. Именно в этом пространстве находится сам метод GetPrice.s:Body, то есть GetPrice.priceRequest. В свойстве "Тип значения" выберите созданный ранее тип из XDTO-пакета.Выясним причину, по которой даже при правильной настройке XDTO сервис может возвращать ошибку 500. Проблема кроется в блоке <s:Header>.
Особенности 1С: Платформа 1С при работе со стандартными объектами Web-сервисы нацелена на обработку только содержимого s:Body. Официально 1С крайне ограничена в работе с заголовками.
Если вызывающая сторона (клиент) передает заголовки, 1С может их просто проигнорировать, но если в заголовках установлен атрибут mustUnderstand="1", или если сама структура конверта не соответствует ожиданиям парсера 1С, сервер вернет 500-ю ошибку еще до того, как управление будет передано в ваш программный код.
Рассмотрим варианты решения, если заголовки мешают работе:
Если стандартный Web-сервис 1С не справляется с десериализацией из-за специфических заголовков или структуры XML, мы рекомендуем использовать HTTP-сервисы. В этом случае вы берете на себя роль «ручного» обработчика SOAP-протокола.
Разберем алгоритм работы через HTTP-сервис:
HTTP-сервис с шаблоном пути, имитирующим адрес веб-сервиса.POST получаем тело запроса в виде строки или потока.ЧтениеXML, чтобы распарсить конверт вручную.Пример кода для обработки такого запроса в HTTP-сервисе:
Функция GetPricePost(Запрос)
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
// Пропускаем Envelope и Header, добираемся до Body
Пока Чтение.Прочитать() Цикл
Если Чтение.Имя = "GetPrice" И Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
// Начинаем десериализацию данных из Body с помощью XDTO
ДанныеRequest = ФабрикаXDTO.ПрочитатьXML(Чтение, ФабрикаXDTO.Тип("http://schemas.datacontract.org/2004/07/com.Ordering", "priceRequest"));
Прервать;
КонецЕсли;
КонецЦикла;
// Здесь ваша логика обработки данных
// ...
// Формируем ответ также в формате SOAP-конверта вручную
ТекстОтвета =
"<s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">" +
"<s:Body>...</s:Body>" +
"</s:Envelope>";
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(ТекстОтвета);
Возврат Ответ;
КонецФункции
Если вы все же решили использовать стандартный веб-сервис и получаете 500, проанализируем ситуацию с помощью инструментов диагностики:
EXCP. В файлах логов вы увидите подробный стек ошибки, который возникает внутри платформенного кода 1С при попытке разобрать XML.s:Header). Если без заголовков 1С принимает запрос — причина в них.Подведем итоги нашего разбора. Развертывание сервиса «от запроса» требует ювелирной точности в настройке XDTO-пакетов и пространств имен. Помните, что:
HTTP-сервиса дает вам полный контроль над входящим XML и позволяет обойти любые ограничения платформенного парсера.