WSDL - 使用WS-Security身份验证使用Web服务 - Delphi

时间:2015-03-18 17:58:23

标签: web-services delphi soap wsdl ws-security

我正在做一个电子发票项目,它使用WSDL肥皂连接到服务下一个链接Link Wsdl Service

所以我使用Delphi的 WSDL Importer 来生成要连接的类。

我使用该服务的代码

procedure TForm1.Button1Click(Sender: TObject);
var
  tBillServ : billService;
  tSendB    : sendBill;
  ByteA     : TByteDynArray;
  tSendBResp: sendBillResponse;
begin
  tSendB:=sendBill.Create;
  tSendBResp:=sendBillResponse.Create;
  tSendB.fileName:='Demo.zip';
  SetLength(ByteA,2);
  ByteA[0]:=10;
  ByteA[1]:=20;
  tSendB.contentFile:=ByteA;
  tSendBResp:=tBillServ.sendBill(tSendB);
end;

我提交的数据只是针对来自服务器的响应的试用版,但是我出现了一条错误消息,正在查找但找不到任何可以帮助我的内容。

如果需要WS-Security连接来更改使用WSDL Importer生成的类的编程?

我遇到了大麻烦,因为他们无法找到解决问题的方法。

我希望我可以提供帮助,对不起我的英语,我使用谷歌翻译

2 个答案:

答案 0 :(得分:1)

上周我遇到了同样的问题。我正在使用Delphi 2010。

首先:我无法设法实现功能齐全的TSOAPHeader后代。我能达到的最远的是要么得到" wsse:"标头节点中的前缀或正确声明wsse命名空间。但它们是相互排斥的:(。

我打赌你试图调用你的webservice方法时得到以下消息:"没有WS-Security标题"。对吗?

添加WS-Security标头的实际工作方式是构建完整的标头节点并在OnBeforeExecute()中添加以下代码:

// Load a copy of the XML in a separate TXMLDocument
XMLDocument.LoadFromStream(SOAPRequest);<br> 
{ Build your complete proper WS-Security header node here)<br>
// Insert the header<br>
XMLDocument.DocumentElement.ChildNodes.Insert(0, SoapHeader);<br>
// THIS LINE IS MANDATORY, AS WE WISH TO OVERWITE THE REQUEST, NOT APPEND TO IT !!!<br>
SOAPRequest.Seek(0, soFromBeginning);<br>
// Overwrite the request<br>
XMLDocument.SaveToStream(SOAPRequest);

然后,释放你的XMLDocument,进行清理等等......它应该可以工作。

答案 1 :(得分:0)

我通过创建此功能解决了这个问题

function GetbillService(UseWSDL: Boolean; Addr: string;var HTTPRIO: THTTPRIO): billService;
 const
  defWSDL = 'https://www.sunat.gob.pe:443/ol-ti-itcpgem-beta/billService?wsdl';
  defURL  = 'https://www.sunat.gob.pe:443/ol-ti-itcpgem-beta/billService';
  defSvc  = 'billService';
  defPrt  = 'BillServicePort';
 var
  RIO: THTTPRIO;
 begin
  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 billService);
    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;

我以这种方式使用它

tBillServ:=GetbillService(True,'',HTTPRIO1);
tSendB:=sendBill.Create;
tSendBResp:=sendBillResponse.Create;
tSendB.fileName:='20100066603-01-F001-1.ZIP';
tSendB.contentFile:=FIleToByteArray('D:\E-Billing\20100066603-01-F001-1.ZIP');
tSendBResp:=tBillServ.sendBill(tSendB);

建立连接但似乎安全标头不正确 需要具备以下特点

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body xmlns:NS1="http://service.sunat.gob.pe" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:NS2="urn:billService1"><NS1:sendBill><parameters href="#1"/></NS1:sendBill><NS2:sendBill id="1" xsi:type="NS2:sendBill"><fileName xsi:type="xsd:string">20100066603-01-F001-1.ZIP</fileName><contentFile xsi:type="xsd:base64Binary">UEsDBBQA.....DAwNBgAAAAAB
    AAEAawAAAD0MAAAAAA==</contentFile></NS2:sendBill></SOAP-ENV:Body></SOAP-ENV:Envelope>

但它似乎是

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SOAP-ENV:Body>
        <sendBill xmlns="http://service.sunat.gob.pe">
            <parameters>
                <fileName>20100066603-01-F001-1.ZIP</fileName>
                <contentFile>UEsDBB.....NjY2MDMtA==</contentFile>
</parameters></sendBill></SOAP-ENV:Body></SOAP-ENV:Envelope>

我尝试使用正确的参数手动发送xml,但即便如此,我得到的安全标头错误

procedure TForm1.HTTPRIO1BeforeExecute(const MethodName: string;
  SOAPRequest: TStream);
var
 Str:String;
 outs:TStream;
begin
  Str:= {Code XML};
  outs:=TStringStream.Create(Str);
  SOAPRequest:=outs;
end;

查看有关添加UsernameToken的WSSE.pas的信息,但我的实现不明确