Имя: Пароль:
1C
1С v8
1С SOAP веб-сервис / проблема отправки XML
0 maratz5
 
23.10.18
15:13
Всем доброго дня. Уже писал пост на эту тему.

Имеется сторонний SOAP веб-сервис. Вот выдержка из описания:

"API cистемы «****-Информ» представляет собой SOAP веб сервис, взаимодействие с которым осуществляется по протоколу HTTP или HTTPS. Пользователю предоставляется пара [логин, пароль], с помощью которых можно пользоваться сервисом."

У этого веб-сервиса есть метод:

GetServiceInfo -
Возвращает информацию обо всех источниках, доступных пользователю, реквизитах поиска и наборах идентифицирующих свойств. Также возвращает примерное время ответа от источника в секундах. Вызывается без параметров.

Через программу SOAPUI мне удалось подрубиться к этому сервису и даже получаю отклики по этому методу.

Проблема возникла на стороне 1С: не знаю как синтаксически подрубиться.

Вот имеющийся код:

"ИмяПользователя = "****";
Пароль = "****";
    
ЗащищенноеСоединениеOpenSSL = Новый ЗащищенноеСоединениеOpenSSL(Новый СертификатКлиентаWindows(), Новый СертификатыУдостоверяющихЦентровWindows);
ИмяВебСервиса  = "http://ws.prima-inform.ru/PrimaService.asmx?wsdl";;;
WSОпределение = Новый WSОпределения(ИмяВебСервиса, ИмяПользователя, Пароль,,,ЗащищенноеСоединениеOpenSSL);

ВСДанные       = WSОпределение.Сервисы[0];
Прокси         = Новый WSПрокси(WSОпределение, ВСДанные.URIПространстваИмен, ВСДанные.Имя, ВСДанные.ТочкиПодключения[0].Имя,,,ЗащищенноеСоединениеOpenSSL);
    
Прокси.Пользователь = ИмяПользователя;
Прокси.Пароль         = Пароль;
    
ЗапросТип = Прокси.ФабрикаXDTO.Тип("http://ws.****-inform.ru/";, "GetServiceInfo");
Запрос = Прокси.ФабрикаXDTO.Создать(ЗапросТип);

Ответ = Прокси.GetServiceInfo();


В последней строчке кода выходит ошибка с кучей непонятной 1С-ку с небольшим стажем работы иероглифами.

Подскажите, может я не так подрубаюсь к сервису?

В инете инфы не нашел достаточной, а если и нашел, то не смог додуматься.
1 palsergeich
 
23.10.18
15:17
(0) Так по диагонали вроде написано все верно. Хотелось бы ошибку увидеть.
2 palsergeich
 
23.10.18
15:17
Может имелось ввиду Ответ = Прокси.GetServiceInfo(Запрос);
3 maratz5
 
23.10.18
15:19
(2) Да, верно. Там запрос передается. Выглядит так:
Прокси.GetServiceInfo(Запрос);
4 maratz5
 
23.10.18
15:20
Вот текст ошибки:

{ВнешняяОбработка.PrimaSOAP.Форма.Форма.Форма(48)}: Ошибка при вызове метода контекста (GetServiceInfo)
    Ответ = Прокси.GetServiceInfo(Запрос);
по причине:
При вызове веб-сервиса произошла ошибка. Ошибка вызова операции сервиса:  {http://ws.prima-inform.ru/}:PrimaService:GetServiceInfo()
по причине:
При вызове веб-сервиса произошла ошибка. Ошибка SOAP сервера:  System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.AggregateException: One or more errors occurred. ---> System.Reflection.TargetException: Non-static method requires a target.
   at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.ReflectionEvaluator.VisitMethodCall(MethodCallExpression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.EvaluateSubtree(Expression subtree)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
   at MongoDB.Driver.Linq.Processors.PartialEvaluator.Visit(Expression node)
   at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate[TDocument](Expression`1 predicate, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry)
   at MongoDB.Driver.MongoCollectionImpl`1.CreateFindOperation[TProjection](FilterDefinition`1 filter, FindOptions`2 options)
   at MongoDB.Driver.MongoCollectionImpl`1.FindAsync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass43_0`1.<FindAsync>b__0(IClientSessionHandle session)
   at MongoDB.Driver.MongoCollectionImpl`1.<UsingImplicitSessionAsync>d__101`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at MongoDB.Driver.IAsyncCursorSourceExtensions.<FirstOrDefaultAsync>d__5`1.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Prima.Utils.Mongo.Mongo`1.Find(Expression`1 expression)
   at Prima.Core.Repositories.Repository.GetUserId(String username, String password) in D:\Projects\Prima-Inform\prima.Web\Prima.Core.Repositories\Repository.cs:line 158
   at Prima.Api.Ws2.PrimaService._tryAuth() in D:\Projects\Prima-Inform\prima.Web\Prima.Api.Ws2\PrimaService.asmx.cs:line 66
   at Prima.Api.Ws2.PrimaService.tryAuth() in D:\Projects\Prima-Inform\prima.Web\Prima.Api.Ws2\PrimaService.asmx.cs:line 86
   at Prima.Api.Ws2.PrimaService.GetServiceInfo() in D:\Projects\Prima-Inform\prima.Web\Prima.Api.Ws2\PrimaService.asmx.cs:line 95
   --- End of inner exception stack trace ---
Код ошибки: Server
Техническая информация:
<detail xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"; xmlns:xsd="http://www.w3.org/2001/XMLSchema"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>;
5 maratz5
 
23.10.18
15:23
(1) прикрепил текст ошибки
6 palsergeich
 
23.10.18
15:23
(2) Вы не заполнили этот объектЕсли посмотреть на него в SOAPUI то видно что ждется заполнение полей
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; xmlns:ws="http://ws.prima-inform.ru/">;
   <soapenv:Header>
      <ws:AuthHeader>
         <!--Optional:-->
         <ws:Username>?</ws:Username>
         <!--Optional:-->
         <ws:Password>?</ws:Password>
         <!--Optional:-->
         <ws:PartnerId>?</ws:PartnerId>
      </ws:AuthHeader>
   </soapenv:Header>
   <soapenv:Body>
      <ws:GetServiceInfo/>
   </soapenv:Body>
</soapenv:Envelope>
7 maratz5
 
23.10.18
15:25
(6) в SOAP UI я заполнял Username и Password. А в 1С - ке же я заполняю имя пользователя и пароль, разве не то? Как быть тогда?
8 palsergeich
 
23.10.18
15:26
ТО есть сам запрос без параметров, но требуются заполнение вот этой штуки
   <soapenv:Header>

      <ws:AuthHeader>

         <!--Optional:-->

         <ws:Username>?</ws:Username>

         <!--Optional:-->

         <ws:Password>?</ws:Password>

         <!--Optional:-->

         <ws:PartnerId>?</ws:PartnerId>

      </ws:AuthHeader>

   </soapenv:Header>
Если честно - не помню как с soapenv:Header работать
9 Cyberhawk
 
23.10.18
15:28
Если платформенные заголовки, что вокруг конверта, тебя не устраивают, то забудь про использование объектной модели работы с веб-сервисом из 1С. Делай на хттп-запросах.
10 maratz5
 
23.10.18
15:48
(8) Спасибо и на этом. Буду смотреть, как заполнять этот блок
11 maratz5
 
26.10.18
13:21
(9) В общем все получилось, использовал HTTP соединение и HTTP запросы. Все вроде бы хорошо отрабатывает, ответ приходит, как в SOAP UI.

Другой вопрос:

У этого сервиса есть метод "GetFullReport", вот выдержка из инструкции:

"Строит отчет по запросу. Метод можно выполнять, когда хотя бы один из источников уже обработал запрос. В отличие от GetReport данный метод возвращает ответ в более структурированном виде, также проводится некоторый анализ данных, в результате которого фильтруются нерелевантные записи. Структуру такого ответа см. в разделе Структуры отчета -> Структура отчета GetFullReport."

На входе у этого метода следующие параметры:

- requestId (Идентификатор запроса)
- format (Формат отчета. В данном методе формат может принимать только следующие значения: Xml, Json, Pdf).

В SOAP UI формирую следующий XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; xmlns:ws="http://ws.prima-inform.ru/">;
   <soapenv:Header>
      <ws:AuthHeader>
         <!--Optional:-->
         <ws:Username>***</ws:Username>
         <!--Optional:-->
         <ws:Password>***</ws:Password>
         <!--Optional:-->
         <ws:PartnerId>?</ws:PartnerId>
      </ws:AuthHeader>
   </soapenv:Header>
   <soapenv:Body>
      <ws:GetFullReport>
         <ws:requestId>d2601e0b-ebfb-4c9a-9095-29d53e6a2c5c</ws:requestId>
         <ws:format>3</ws:format>
      </ws:GetFullReport>
   </soapenv:Body>
</soapenv:Envelope>



В ответ приходит:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xmlns:xsd="http://www.w3.org/2001/XMLSchema">;
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Client</faultcode>
         <faultstring>System.Web.Services.Protocols.SoapException: Server was unable to read request. ---> System.InvalidOperationException:
         There is an error in XML document (15, 34). ---> System.InvalidOperationException: Instance validation error: '3' is not a valid value for ReportFormat.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read20_ReportFormat(String s)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read49_GetFullReport()
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
   --- End of inner exception stack trace ---
   at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
   at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()</faultstring>
         <detail/>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

В чем может быть проблема? Обращаться к разработчикам сервиса?
12 eklmn
 
гуру
26.10.18
13:24
'3' is not a valid value for ReportFormat
и
- format (Формат отчета. В данном методе формат может принимать только следующие значения: Xml, Json, Pdf

найди отличия
13 maratz5
 
26.10.18
18:36
(12) да пробовал я и так "xml", та же ошибка. Видимо ругается на формат. Блин, может SOAP UI ограничен в возможностях или что еще может быть?
14 runoff_runoff
 
26.10.18
18:50
а helloWorld() работает?
15 palsergeich
 
26.10.18
21:55
(11) Заголовки в запросе ставишь?
Сервисы крайне чувствительны к заголовку Content-type, а при прямых запросах он автоматом не ставится
16 maratz5
 
29.10.18
16:11
(15) Content-Type: text/xml;charset=UTF-8
Ставлю такой. Все равно ошибка.
17 dezss
 
29.10.18
16:19
(13)
<s:enumeration value="Html"/>
<s:enumeration value="Pdf"/>
<s:enumeration value="Rtf"/>
<s:enumeration value="Json"/>
<s:enumeration value="Xml"/>
<s:enumeration value="Zip"/>

А ты кавычки ставил, когда формат передавал?
18 dezss
 
29.10.18
16:20
(17) + т.к. смотрю, что 3 у тебя без кавычек
19 maratz5
 
30.10.18
10:27
(17) Ставил кавычки - ошибка та же.
Очень странно, сейчас попробовал без кавычек отправить - пришел ответ тот который нужен. Очень странно. На тот момент, когда у меня была эта ошибка, я работал с одним логином и паролем, недавно у него срок истек. Сейчас попросил админов вебсервиса дать мне снова доступ к нему, теперь же все получается. Может быть такое, что у меня права были ограничены что???
20 maratz5
 
30.10.18
10:32
Друзья!
Ответ от веб сервиса приходит, только вот в нем содержится
одна очень длинная строка:

"PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8TWFpbkluZm8geG1sbnM6eHNkPSJodHRwOi8vd3d3LnczLm9yZy8yMDAx....."

Это я так понимаю двоичные данные или что? И как их преобразовать в XML?
21 maratz5
 
30.10.18
10:44
(20) разобрался, нужно строку преобразовать в двоичные данные через Base64Значение, а потом можно через метод Записать() сохранить в xml.
А как можно не записывая в файл получить СтрокуXML?
22 maratz5
 
30.10.18
10:51
(21) Тоже разобрался:

ПолучитьСтрокуИзДвоичныхДанных(Base64Значение(СтрокаДвоичныеДанные_XML))

Всем спасибо.
23 CentrForward
 
30.10.18
11:32
(11) Автор, покажи, пожалуйста, как реализовал через HTTPСоединение и HTTP-запросы. Чтоб уж тема завершенная была. Интересно.
24 maratz5
 
30.10.18
12:01
(23) Вот пример кода, в котором вызываю метод "GetServiceInfo", стандартный метод, возвращающий ответ в виде XML об общей информации:

    Хост = "ws.prima-inform.ru";
    
    HTTPСоединение = Новый HTTPСоединение(Хост, , ИмяПользователя, Пароль, , 100, Новый ЗащищенноеСоединениеOpenSSL());    
    
    ЗаголовокЗапросаHTTP = Новый Соответствие();
    ЗаголовокЗапросаHTTP.Вставить("Content-Type", "text/xml;charset=UTF-8");
    ЗаголовокЗапросаHTTP.Вставить("soapAction", "http://ws.prima-inform.ru/GetServiceInfo";);
    
    HTTPЗапрос = Новый HTTPЗапрос("/PrimaService.asmx?", ЗаголовокЗапросаHTTP);  
            
    СтрокаXML = "
    |<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/""; xmlns:ws=""http://ws.prima-inform.ru/"">;
    |   <soapenv:Header>
    |      <ws:AuthHeader>
    |         <!--Optional:-->
    |         <ws:Username>*****</ws:Username>
    |         <!--Optional:-->
    |         <ws:Password>*****</ws:Password>
    |         <!--Optional:-->
    |         <ws:PartnerId>?</ws:PartnerId>
    |      </ws:AuthHeader>
    |   </soapenv:Header>
    |   <soapenv:Body>
    |      <ws:GetServiceInfo/>
    |   </soapenv:Body>
    |</soapenv:Envelope>";
    
    HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаXML);
    
    Результат = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
    
    Ответ = Результат.ПолучитьТелоКакСтроку();



В переменной "Ответ" как раз таки будет XML в виде строки
25 CentrForward
 
30.10.18
12:13
(24) Спасибо!