Форум программистов, компьютерный форум, киберфорум
Delphi: Сети
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.63/91: Рейтинг темы: голосов - 91, средняя оценка - 4.63
0 / 0 / 0
Регистрация: 06.02.2015
Сообщений: 2
1

SOAP клиент для web-сервиса npchk.nalog.ru

06.02.2015, 13:19. Показов 17973. Ответов 4

Всем привет.

Возникла необходимость написать клиент для сервиса http://npchk.nalog.ru.
WSDL сервиса - http://npchk.nalog.ru/FNSNDSCAWS?wsdl
XSD-схемы: запрос - http://npchk.nalog.ru:80/FNSNDSCAWS?xsd=1
ответ - http://npchk.nalog.ru:80/FNSNDSCAWS?xsd=2

В программе SoapUI запрос выглядит следующим образом:
Кликните здесь для просмотра всего текста

XML
1
2
3
4
5
6
7
8
9
10
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:req="http://ws.unisoft/FNSNDSCAWS/Request">
   <soapenv:Header/>
   <soapenv:Body>
      <req:NdsRequest>
         <!--1 to 10000 repetitions:-->
         <req:NP INN="525202471833"/>
         <req:NP INN="525202471834"/>
      </req:NdsRequest>
   </soapenv:Body>
</soapenv:Envelope>

Ответ:
Кликните здесь для просмотра всего текста

XML
1
2
3
4
5
6
7
8
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <NdsResponse DTActFL="04.02.2015" DTActUL="04.02.2015" xmlns="http://ws.unisoft/FNSNDSCAWS/Response">
         <NP INN="525202471833" State="2"/>
         <NP INN="525202471834" State="4"/>
      </NdsResponse>
   </S:Body>
</S:Envelope>


Суть в том, что в запросе можно отправить ИНН и получить ответ, зарегистрирован этот ИНН или нет. Как видно в примере для каждого ИНН добавляется State со значением от 0 до 4.

Использую Delphi 7.
WSDL-importer сгенерировал такой код:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : [url]http://npchk.nalog.ru:80/FNSNDSCAWS?wsdl[/url]
// Encoding : UTF-8
// Version  : 1.0
// (06.02.2015 11:31:58 - 1.33.2.5)
// ************************************************************************ //
 
unit FNSNDSCAWS;
 
interface
 
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;
 
type
 
  // ************************************************************************ //
  // The following types, referred to in the WSDL document are not being represented
  // in this file. They are either aliases[@] of other types represented or were referred
  // to but never[!] declared in the document. The types from the latter category
  // typically map to predefined/known XML or Borland types; however, they could also 
  // indicate incorrect WSDL documents that failed to declare or import a schema type.
  // ************************************************************************ //
  // !:NdsRequest      - "http://ws.unisoft/FNSNDSCAWS/Request"
  // !:NdsResponse     - "http://ws.unisoft/FNSNDSCAWS/Response"
 
 
  // ************************************************************************ //
  // Namespace : [url]http://ws.unisoft[/url]
  // soapAction: NdsRequest
  // transport : [url]http://schemas.xmlsoap.org/soap/http[/url]
  // binding   : FNSNDSCAWSBinding
  // service   : FNSNDSCAWS
  // port      : FNSNDSCAWS_Port
  // URL       : [url]http://npchk.nalog.ru:80/FNSNDSCAWS[/url]
  // ************************************************************************ //
  FNSNDSCAWS_Port = interface(IInvokable)
  ['{4F17B962-874C-C8B5-315F-940BBF480736}']
    function  NdsRequest(const np_in: NdsRequest): NdsResponse; stdcall;
  end;
 
function GetFNSNDSCAWS_Port(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): FNSNDSCAWS_Port;
 
 
implementation
 
function GetFNSNDSCAWS_Port(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): FNSNDSCAWS_Port;
const
  defWSDL = 'http://npchk.nalog.ru:80/FNSNDSCAWS?wsdl';
  defURL  = 'http://npchk.nalog.ru:80/FNSNDSCAWS';
  defSvc  = 'FNSNDSCAWS';
  defPrt  = 'FNSNDSCAWS_Port';
var
  RIO: THTTPRIO;
begin
  Result := nil;
  if (Addr = '') then
  begin
    if UseWSDL then
      Addr := defWSDL
    else
      Addr := defURL;
  end;
  if HTTPRIO = nil then
    RIO := THTTPRIO.Create(nil)
  else
    RIO := HTTPRIO;
  try
    Result := (RIO as FNSNDSCAWS_Port);
    if UseWSDL then
    begin
      RIO.WSDLLocation := Addr;
      RIO.Service := defSvc;
      RIO.Port := defPrt;
    end else
      RIO.URL := Addr;
  finally
    if (Result = nil) and (HTTPRIO = nil) then
      RIO.Free;
  end;
end;
 
 
initialization
  InvRegistry.RegisterInterface(TypeInfo(FNSNDSCAWS_Port), 'http://ws.unisoft', 'UTF-8');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(FNSNDSCAWS_Port), 'NdsRequest');
  InvRegistry.RegisterInvokeOptions(TypeInfo(FNSNDSCAWS_Port), ioLiteral);
 
end.
Для функции, отправляющей запрос, тип входного параметра назван NdsRequest, выходного - NdsResponse.
Как я понимаю, мне нужно описать эти типы. Они должны быть наследниками от TRemotable.
Примерно так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
  TNdsRequest = class(TRemotable)
  public
      constructor Create(XMLNode: IXMLNode);
      function ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter:
                            IObjConverter; const Name, URI: InvString; ObjConvOpts:
                            TObjectConvertOptions; out RefID: InvString): IXMLNode; override;
  private
      fXMLNode: IXMLNode;
  end;
 
  TNdsResponse = class(TRemotable);
Реализация конструктора и метода ObjectToSOAP:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
constructor TNdsRequest.Create(XMLNode: IXMLNode);
begin
    fXMLNode := XMLNode;
end;
 
function TNdsRequest.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter:
                            IObjConverter; const Name, URI: InvString; ObjConvOpts:
                            TObjectConvertOptions; out RefID: InvString): IXMLNode;
begin
    RootNode := fXMLNode.ChildNodes.FindNode('NdsRequest');
    ParentNode := RootNode.ChildNodes.FindNode('NP');
 
    ObjConvOpts := ObjConvOpts + [ocoDontPrefixNode];
 
    Result := inherited ObjectToSOAP(RootNode, ParentNode, ObjConverter, 'State', 'http://ws.unisoft', ObjConvOpts, RefID);
end;
Ещё нарыл, что нужно зарегистрировать класс как-то так
Delphi
1
RemClassRegistry.RegisterXSInfo(TypeInfo(TNdsRequest), 'http://ws.unisoft', 'NdsRequest');
Теперь модуль принял такой вид:
Кликните здесь для просмотра всего текста

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : [url]http://npchk.nalog.ru:80/FNSNDSCAWS?wsdl[/url]
// Encoding : UTF-8
// Version  : 1.0
// (06.02.2015 11:31:58 - 1.33.2.5)
// ************************************************************************ //
 
unit FNSNDSCAWS;
 
interface
 
uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns, XMLIntf;
 
type
 
  // ************************************************************************ //
  // The following types, referred to in the WSDL document are not being represented
  // in this file. They are either aliases[@] of other types represented or were referred
  // to but never[!] declared in the document. The types from the latter category
  // typically map to predefined/known XML or Borland types; however, they could also 
  // indicate incorrect WSDL documents that failed to declare or import a schema type.
  // ************************************************************************ //
  // !:NdsRequest      - "http://ws.unisoft/FNSNDSCAWS/Request"
  // !:NdsResponse     - "http://ws.unisoft/FNSNDSCAWS/Response"
 
 
  // ************************************************************************ //
  // Namespace : [url]http://ws.unisoft[/url]
  // soapAction: NdsRequest
  // transport : [url]http://schemas.xmlsoap.org/soap/http[/url]
  // binding   : FNSNDSCAWSBinding
  // service   : FNSNDSCAWS
  // port      : FNSNDSCAWS_Port
  // URL       : [url]http://npchk.nalog.ru:80/FNSNDSCAWS[/url]
  // ************************************************************************ //
 
  TNdsRequest = class(TRemotable)
  public
      constructor Create(XMLNode: IXMLNode);
      function ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter:
                            IObjConverter; const Name, URI: InvString; ObjConvOpts:
                            TObjectConvertOptions; out RefID: InvString): IXMLNode; override;
  private
      fXMLNode: IXMLNode;
  end;
 
  TNdsResponse = class(TRemotable);
 
  FNSNDSCAWS_Port = interface(IInvokable)
  ['{4F17B962-874C-C8B5-315F-940BBF480736}']
    function  NdsRequest(const np_in: TNdsRequest): TNdsResponse; stdcall;
  end;
 
function GetFNSNDSCAWS_Port(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): FNSNDSCAWS_Port;
 
implementation
 
constructor TNdsRequest.Create(XMLNode: IXMLNode);
begin
    fXMLNode := XMLNode;
end;
 
function TNdsRequest.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter:
                            IObjConverter; const Name, URI: InvString; ObjConvOpts:
                            TObjectConvertOptions; out RefID: InvString): IXMLNode;
begin
    RootNode := fXMLNode.ChildNodes.FindNode('NdsRequest');
    ParentNode := RootNode.ChildNodes.FindNode('NP');
 
    ObjConvOpts := ObjConvOpts + [ocoDontPrefixNode];
 
    Result := inherited ObjectToSOAP(RootNode, ParentNode, ObjConverter, 'State', 'http://ws.unisoft', ObjConvOpts, RefID);
end;
 
function GetFNSNDSCAWS_Port(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): FNSNDSCAWS_Port;
const
  defWSDL = 'http://npchk.nalog.ru:80/FNSNDSCAWS?wsdl';
  defURL  = 'http://npchk.nalog.ru:80/FNSNDSCAWS';
  defSvc  = 'FNSNDSCAWS';
  defPrt  = 'FNSNDSCAWS_Port';
var
  RIO: THTTPRIO;
begin
  Result := nil;
  if (Addr = '') then
  begin
    if UseWSDL then
      Addr := defWSDL
    else
      Addr := defURL;
  end;
  if HTTPRIO = nil then
    RIO := THTTPRIO.Create(nil)
  else
    RIO := HTTPRIO;
  try
    Result := (RIO as FNSNDSCAWS_Port);
    if UseWSDL then
    begin
      RIO.WSDLLocation := Addr;
      RIO.Service := defSvc;
      RIO.Port := defPrt;
    end else
      RIO.URL := Addr;
  finally
    if (Result = nil) and (HTTPRIO = nil) then
      RIO.Free;
  end;
end;
 
initialization
  InvRegistry.RegisterInterface(TypeInfo(FNSNDSCAWS_Port), 'http://ws.unisoft', 'UTF-8');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(FNSNDSCAWS_Port), 'NdsRequest');
  InvRegistry.RegisterInvokeOptions(TypeInfo(FNSNDSCAWS_Port), ioLiteral);
  RemClassRegistry.RegisterXSInfo(TypeInfo(TNdsRequest), 'http://ws.unisoft', 'NdsRequest');
end.

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

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, SOAPHTTPClient, XMLDoc, XMLIntf;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    MyRio: THTTPRIO;
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
uses FNSNDSCAWS;
 
procedure TForm1.Button1Click(Sender: TObject);
var xmlDoc: TXMLDocument;
    Request: IXMLNode;
    NdsRequest: TNdsRequest;
begin
    xmlDoc := TXMLDocument.Create(Application);
    xmlDoc.FileName := 'D:\request.xml';
    xmlDoc.Active := true;
 
    Request := xmlDoc.ChildNodes.FindNode('Data');
 
    myRIO := THTTPRIO.Create(nil);
 
    GetFNSNDSCAWS_Port(true, '', myRIO);
 
    NdsRequest := TNdsRequest.Create(Request);
 
    (myRIO as FNSNDSCAWS_Port).NdsRequest(NdsRequest);
 
    xmlDoc.Free;
end;
 
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    MyRio.Free;
end;
 
end.

Файл request.xml:
Кликните здесь для просмотра всего текста

XML
1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<Data>
<NdsRequest>
<NP INN="525202471833"/>
<NP INN="525202471834"/>
</NdsRequest>
</Data>


В итоге получаю ошибку: Project Wsdl.exe raised exception class ERemotableException with message 'org.xml.sax.SAXParseException; cvc-elt.1.a: Cannot find the declaration of element 'np_in'.'.
Элемент np_in встречается в описании wsdl http://npchk.nalog.ru/FNSNDSCAWS?wsdl.

Помогите мне разобраться что к чему. Что я делаю не так?
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.02.2015, 13:19
Ответы с готовыми решениями:

SOAP клиент для web-сервиса
Здравствуйте. Подобно этой теме https://www.cyberforum.ru/delphi-networks/thread1369524.html ...

WCF клиент для Web-сервиса
Доброе время суток! Пытаюсь создать клиента для Web-сервиса по wsdl. Заголовок и часть аттрибутов...

SOAP получение данных с web-сервиса
Есть код: &lt;?php $client = new...

Отображение xml из SOAP web-сервиса
Добрый день! Подскажите есть web-сервис, написанный по технологии SOAP, необходимо создать php...

4
13073 / 5858 / 1706
Регистрация: 19.09.2009
Сообщений: 8,807
10.02.2015, 02:04 2
Лучший ответ Сообщение было отмечено Cyberg как решение

Решение

В данном случае SOAP ответ веб-службы не имеет сложной структуры. Поэтому можно вручную обработать вызовы на уровне HTTP протокола. Затем, разобрать XML код SOAP ответа и получить нужные данные. Для работы с HTTP протоколом можно воспользоваться компонентами Indy из палитры Delphi.

Если в SoapUI прослушать HTTP трафик при обращении к службе, увидим следующее:
Код
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "POST /FNSNDSCAWS HTTP/1.1[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "Accept-Encoding: gzip,deflate[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "Content-Type: text/xml;charset=UTF-8[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "SOAPAction: "NdsRequest"[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "Content-Length: 398[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "Host: npchk.nalog.ru:80[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "Connection: Keep-Alive[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "User-Agent: Apache-HttpClient/4.1.1 (java 1.5)[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:req="http://ws.unisoft/FNSNDSCAWS/Request">[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "  <soapenv:Header/>[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "  <soapenv:Body>[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "    <req:NdsRequest>[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "      <!--1 to 10000 repetitions:-->[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "      <!-- <req:NP INN="?" KPP="?" DT="?"/> -->[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "      <req:NP INN="525202471833"/>[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "      <req:NP INN="525202471834"/>[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "    </req:NdsRequest>[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "  </soapenv:Body>[\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:>> "</soapenv:Envelope>"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "HTTP/1.1 200 OK[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "Server: nginx/1.6.0[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "Date: Mon, 09 Feb 2015 21:43:10 GMT[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "Content-Type: text/xml;charset=utf-8[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "Content-Length: 315[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "Connection: keep-alive[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "[\r][\n]"
Tue Feb 10 02:43:14 GST 2015:DEBUG:<< "<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><NdsResponse xmlns="http://ws.unisoft/FNSNDSCAWS/Response" DTActFL="09.02.2015" DTActUL="09.02.2015"><NP INN="525202471833" State="2"/><NP INN="525202471834" State="4"/></NdsResponse></S:Body></S:Envelope>"
Здесь видно, какие HTTP заголовки используются при взаимодействии. Такие же заголовки будем формировать в коде на Delphi.

Такое взаимодействие можно организовать следующим образом.
На форму надо положить:
Delphi
1
2
3
4
5
    IdHTTP1: TIdHTTP;
    XMLDocument1: TXMLDocument;
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
Для кнопки Button1 создать обработчик события OnClick. В Memo1 вводится XML код SOAP запроса:
Memo1.Text:
Код
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:req="http://ws.unisoft/FNSNDSCAWS/Request">
  <soapenv:Header/>
  <soapenv:Body>
    <req:NdsRequest>
      <!--1 to 10000 repetitions:-->
      <!-- <req:NP INN="?" KPP="?" DT="?"/> -->
      <req:NP INN="525202471833"/>
      <req:NP INN="525202471834"/>
    </req:NdsRequest>
  </soapenv:Body>
</soapenv:Envelope>
В Memo2 выводятся результаты обработки ответа веб-службы.
Код модуля:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdHTTP, xmldom, XMLIntf, msxmldom, XMLDoc;
 
type
  TForm1 = class(TForm)
    IdHTTP1: TIdHTTP;
    XMLDocument1: TXMLDocument;
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.Button1Click(Sender: TObject);
var
  //Переменные, используемые в коде взаимодействия с веб-службой.
  SUtf8 : UTF8String; //type UTF8String = AnsiString.
  MsReq, MsResp, Ms : TMemoryStream; //Байтовые потоки с данными SOAP запроса и SOAP ответа.
 
  //Переменные, используемые при анализе XML данных SOAP ответа веб-службы.
  S : String;
  i, j : Integer;
  INode, IAttr : IXMLNode;
  IList : IXMLNodeList;
begin
  //----------------------------------------
  //1. Подготовка.
  //----------------------------------------
 
  //Очистка и инициализация.
  IdHTTP1.Request.Clear;
  IdHTTP1.Response.Clear;
  Ms     := nil;
  MsReq  := nil;
  MsResp := nil;
  Memo2.Clear;
 
  try
    //Содержание SOAP запроса берём из Memo1.
    S := Trim(Memo1.Text);
    {
    Memo1.Text:
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:req="http://ws.unisoft/FNSNDSCAWS/Request">
      <soapenv:Header/>
      <soapenv:Body>
        <req:NdsRequest>
          <!--1 to 10000 repetitions:-->
          <!-- <req:NP INN="?" KPP="?" DT="?"/> -->
          <req:NP INN="525202471833"/>
          <req:NP INN="525202471834"/>
        </req:NdsRequest>
      </soapenv:Body>
    </soapenv:Envelope>
    }
    //Перекодируем текст в UTF-8 кодировку.
    SUtf8 := Utf8Encode(S);
    //Запись SOAP запроса в байтовый поток.
    MsReq := TMemoryStream.Create;
    MsReq.Write(SUtf8[1], Length(SUtf8));
 
    //Формируем заголовок HTTP запроса.
    IdHTTP1.ProtocolVersion := pv1_1;
    IdHTTP1.Request.CustomHeaders.Add('Accept-Encoding: gzip,deflate');
    IdHTTP1.Request.ContentType := 'text/xml;charset=UTF-8';
    IdHTTP1.Request.CustomHeaders.Add('SOAPAction: "NdsRequest"');
    IdHTTP1.Request.Connection := 'Keep-Alive';
    IdHTTP1.Request.ProcessHeaders;
 
    //Создаём байтовый поток для записи ответа веб-службы.
    MsResp := TMemoryStream.Create;
 
    //----------------------------------------
    //2. Взаимодействие с веб-службой.
    //----------------------------------------
 
    //Посылаем запрос веб-службе и получаем от неё ответ.
    MsReq.Position := 0; //Потоковый указатель устанавливаем на начало потока.
    IdHTTP1.Post('http://npchk.nalog.ru:80/FNSNDSCAWS', MsReq, MsResp);
 
    //----------------------------------------
    //3. Анализ ответа веб-службы.
    //----------------------------------------
 
    {Печатаем в Memo XML код SOAP ответа. Для этого сначала данные потока-ответа
    переписываем в строку UTF-8, а затем выполняем преобразование текста в ANSI
    или UNICODE кодировку в зависимости от версии Delphi.}
    //Запись данных ответа в строку UTF-8.
    SetLength(SUtf8, MsResp.Size);
    MsResp.Position := 0; //Потоковый указатель устанавливаем на начало потока.
    MsResp.Read(SUtf8[1], Length(SUtf8));
    //Перекодируем текст в ANSI или UNICODE кодировку, в зависимости от версии Delphi.
    S := Utf8Decode(SUtf8);
    //Форматируем полученный XML код и показываем его в Memo.
    Memo2.Lines.Add('----------');
    Memo2.Lines.Add('Ответ веб-службы:');
    Memo2.Lines.Add( Trim(FormatXMLData(S)) );
 
    //Теперь анализируем ответ веб-службы. Для этого можно воспользоваться экземпляром
    //TXMLDocument. Или можно с помощью действий со стоками извлечь нужные данные.
 
    //Обработка с помощью экземпляра TXMLDocument.
 
    //Загружаем XML данные в XML документ.
    MsResp.Position := 0;
    XMLDocument1.LoadFromStream(MsResp, xetUTF_8);
    {Настраиваем XML документ.
    -[doNodeAutoCreate] - запрет на автоматическое создание узлов при попытке чтения.
    -[doAutoSave] - запрет на автоматическое сохранение изменений при закрытии документа.}
    XMLDocument1.Options := XMLDocument1.Options - [doNodeAutoCreate, doAutoSave];
    XMLDocument1.Active := True; //Включаем разбор DOM модели.
 
    //Извлекаем из XML сведения о контрагентах и распечатываем их в Memo2.
    Memo2.Lines.Add('----------');
    Memo2.Lines.Add('Сведения о контрагентах:');
    //Элемент документа <S:Envelope>.
    INode := XMLDocument1.DocumentElement;
    //Первый вложенный элемент <S:Body>.
    INode := INode.ChildNodes.FindNode('S:Body');
    {Далее, в следствии какого-то бага, наверное, по вызову FindNode('NdsResponse')
    элемент <NdsResponse> не обнаруживается. :-) В связи с этим пришлось
    действовать через вызов Get(). Будем считать, что для <S:Body> первым
    вложенным элементом является элемент <NdsResponse>.}
    //Получаем список элементов, которые вложены в <NdsResponse> .
    IList := INode.ChildNodes.Get(0).ChildNodes;
    Memo2.Lines.Add('Количество элементов: ' + IntToStr(IList.Count));
    for i := 0 to IList.Count - 1 do //Перебор элементов списка.
    begin
      INode := IList.Get(i); //Очередной элемент.
      S := '<' + INode.NodeName + '>: ';
      for j := 0 to INode.AttributeNodes.Count - 1 do //Перебор атрибутов.
      begin
        IAttr := INode.AttributeNodes.Get(j); //Очередной атрибут.
        if j > 0 then
          S := S + '; ';
        S := S + IAttr.NodeName + '="' + IAttr.NodeValue + '"';
      end;
      Memo2.Lines.Add(S);
    end;
  finally
    FreeAndNil(Ms);
    FreeAndNil(MsReq);
    FreeAndNil(MsResp);
  end;
end;
 
end.
1
Миниатюры
SOAP клиент для web-сервиса npchk.nalog.ru  
Вложения
Тип файла: 7z WebService-FNSNDSCAWS-01.7z (228.7 Кб, 177 просмотров)
0 / 0 / 0
Регистрация: 06.02.2015
Сообщений: 2
10.02.2015, 11:14  [ТС] 3
Спасибо. Всё замечательно работает. По началу не рассматривал возможность работы через Indy. Однажды только делал на нём отправку/приём почты.
0
13073 / 5858 / 1706
Регистрация: 19.09.2009
Сообщений: 8,807
10.02.2015, 11:20 4
Да - иногда проще через Indy сделать, чем возиться с импортом WSDL и прочими этапами. В моём предыдущем посте, в коде - там лишняя переменная потока Ms - надо убрать её.
0
0 / 0 / 0
Регистрация: 31.03.2016
Сообщений: 2
31.03.2016, 14:19 5
Дорогие друзья, я решаю подобную задачу в Turbo Delphi
и он подчеркивает красным строку "IdHTTP1.Request.ProcessHeaders;"
с сообщением 'IdHTTP1Request' does not contain member named 'ProcessHeaders'

при этом вылетает ошибка на строке "MsResp.Read(SUtf8[1], Length(SUtf8));"
с сообщением "XML document must have a top level element line:0"

помогите,пожалуйста. скажите, как быть?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
31.03.2016, 14:19

Выбор средств разработки для web-сервиса
Приветствую всех! Не знал где задать свой вопрос, решил тут) я web-программированием практически не...

Как задать параметр для web-сервиса?
Имеется web-сервис (не WCF!) service.svc. Аяксом посылаю к нему post-запрос. Получаю ошибку: ...

Что лучше выбрать для создания Web сервиса?
WCF или Core Web API?

Нужен web программист для реализация проекта сервиса грузоперевозок
Необходимо реализовать проект на подобие http://perevezi.ru/ или http://www.vezetvsem.info/ ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.