【问题标题】:Posting Data and Getting Response for SOAP Client为 SOAP 客户端发布数据并获得响应
【发布时间】:2012-02-22 19:10:25
【问题描述】:

我几乎所有的开发经验都来自桌面应用程序。我目前正在使用 Delphi 2010,我需要编写一个 SOAP 客户端来访问加利福尼亚 EDD 维护的用于以电子方式处理工资单数据的 Web 服务。我放弃了 Delphi WSDL Importer,因为幕后发生了太多事情,我似乎无法取得任何进展。我下载了 Fiddler2 并一直使用它来查看我在网上写的内容。我找到了这个发帖程序,我觉得我现在已经到了某个地方。

//from StackOverflow Andreas Rejbrand 06/04/2012
procedure WebPostData(const UserAgent: string; const Server: string; const Resource: string; const Data: AnsiString); overload;
    var
      hInet: HINTERNET;
      hHTTP: HINTERNET;
      hReq: HINTERNET;
    const
      accept: packed array[0..1] of LPWSTR = (PChar('*/*'), nil);
      header: string = 'Content-Type: text/plain';
    begin
      hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
      try
        hHTTP := InternetConnect(hInet, PChar(Server), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 1);
        try
          hReq := HttpOpenRequest(hHTTP, PChar('POST'), PChar(Resource), nil, nil, @accept, 0, 1);
          try
            if not HttpSendRequest(hReq, PChar(header), length(header), PChar(Data), length(Data)) then
              raise Exception.Create('HttpOpenRequest failed. ' + SysErrorMessage(GetLastError));
          finally
            InternetCloseHandle(hReq);
          end;
        finally
          InternetCloseHandle(hHTTP);
        end;
      finally
        InternetCloseHandle(hInet);
      end;
    end;

我更改了 Content-Type,因为原来的似乎永远不会返回。

我一直这样称呼它:

procedure TForm1.Button1Click(Sender: TObject);
var sl: TStringList;
    s: String;
begin
  sl := TStringList.Create;
  sl.LoadFromFile('C:\Documents and Settings\Jack\Desktop\My Reading\FSET Development\Ping.xml');
  s := sl.Text;
  sl.Free;
  WebPostData('BNWebSvc', 'FSETTESTPROD.EDD.CA.GOV','fsetservice', s);
end;

在我的浏览器中,主机 (FSETTESTPROD.EDD.CA.GOV) 存在并响应它可用。当我发布时,我收到 404 错误,可能是因为附加了 Web 服务名称。在 Fiddler2 中,输出如下所示:

POST http://FSETTESTPROD.EDD.CA.GOV/fsetservice HTTP/1.1
Accept: */*
Content-Type: text/plain
User-Agent: BNWebSvc
Host: FSETTESTPROD.EDD.CA.GOV
Content-Length: 2190
Pragma: no-cache
Cookie: __utma=158387685.1851397844.1321382260.1321382260.1321382260.1; __utmz=158387685.1321382260.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=calif%20edd%20eft%20payroll%20processor%20batch%20processing

<?xml version="1.0" encoding="utf-8"?>
<log>
  <inputMessage utc="3/2/2007 10:45:44 PM" messageId="urn:uuid:c07c9aef-28db-4843-8dfc-c5b4d3dc363b">
    <processingStep description="Unprocessed message">
      <soap:Envelope xmlns:xop="http://www.w3.org/2004/08/xop/include" 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" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <soap:Header>
          <wsa:Action>//edd.ca.gov/Ping</wsa:Action>
          <wsa:MessageID>urn:uuid:c07c9aef-28db-4843-8dfc-c5b4d3dc363b</wsa:MessageID>
          <wsa:ReplyTo>
            <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
          </wsa:ReplyTo>
          <wsa:To>http://localhost:3031/EDD.DMRC.FSET.WebServices/FsetService.asmx</wsa:To>
          <wsse:Security soap:mustUnderstand="1">
            <wsu:Timestamp wsu:Id="Timestamp-0983e8c1-e822-4648-8066-33839f54a6a0">
              <wsu:Created>2007-03-02T22:45:41Z</wsu:Created>
              <wsu:Expires>2007-03-02T22:50:41Z</wsu:Expires>
            </wsu:Timestamp>
            <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-0d55d82c-d16d-4c0e-826b-21bf7c805a0f">
              <wsse:Username>MyUserName</wsse:Username>
              <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MyPassword</wsse:Password>
              <wsse:Nonce>w6dgDz1DMzKntFsFdEcjhw==</wsse:Nonce>
              <wsu:Created>2007-03-02T22:45:41Z</wsu:Created>
            </wsse:UsernameToken>
          </wsse:Security>
        </soap:Header>
        <soap:Body>
          <Ping xmlns="http://edd.ca.gov/">
          </Ping>
        </soap:Body>
      </soap:Envelope>
    </processingStep>
  </inputMessage>
</log>

当它工作时,我需要使用 HTTPS 发送它,我可能需要合并它以使其工作。

我的方向正确吗?

Andreas 的程序没有说明如何检索响应。如何检索响应?

【问题讨论】:

    标签: delphi soap wininet


    【解决方案1】:

    我现在做了更多的研究,买了一本不错的关于网络服务的书"Teach Yourself Web Services"(感谢你扎根 Nook),并与我正在尝试使用其网络服务的代理机构的某个人进行了简短的交谈。所以我想我对我一直在问的问题有一些答案,我会在这里总结它们,以防其他人开始走同样的路。如果您发现我说错了什么,并且您可以更正或改进它,如果您能花时间输入您的改进,我将不胜感激。

    在显示 Web 服务基于 HTTP 的图形中,这意味着如果您正在使用可以向网站发出请求的组件,您可能还可以使用它来创建 Web 服务客户端。

    您应该马上安装Fiddler2。您将从中获得的反馈对于取得进展至关重要。

    WSDL 文件可能有助于创建 Web 服务客户端,但可能没有。我对 Delphi WSDL 导入器的体验是它的工作并不完整。关于 Web 服务的 Wikipedia article 有一个关于大 Web 服务的部分指出 WSDL 文件不是必需的,但可以帮助自动化 Web 服务客户端的设计。如果没有帮助,请不要使用它。

    您无需使用 HTTPRIO 组件即可访问 Web 服务。您可以将 WinInet 单元与上面我从一些 StackOverflow 帖子中抄袭的一些代码一起使用。

    WSDL 文件中引用的模式不必存在于所示位置。从技术上讲,这些是 URI 而不是 URL(标识符而不是位置)。

    当自动生成不起作用时,手动编写 Web 服务客户端可能是一种可接受的替代自动生成的方法。此外,就像许多黑盒解决方案一样,它只有在有效时才有效。当它不起作用时,可能没有其他选择。此外,您将了解更多信息并更好地控制输出。

    如果您使用上面的 PostWebData 例程,使用 SSL 发送您的请求似乎是自动的。获取响应也包含在此例程中。

    我从 Web 服务获得的两个响应似乎表明我的流程很好,但我的内容很糟糕。我现在必须查看实际的 SOAP 信封并提供可接受的数据以进行下一步。

    如果我完成下一步时结果没有解密,那么我将不得不做更多的研究。

    我希望这对尝试在 Web 服务中找到自己的方式的其他人有所帮助。

    【讨论】:

      【解决方案2】:

      我认为我正在取得一些进展。我将 WebPostData 更改为一个函数,并从其他地方复制了一些代码以使用 SSL 并返回结果。现在看起来像这样:

      function WebPostData(const UserAgent: string; const Server: string; const Resource: string; const Data: AnsiString): String;
      var
        hInet: HINTERNET;
        hHTTP: HINTERNET;
        hReq: HINTERNET;
        BufStream: TMemoryStream;
        BytesRead: Cardinal;
        aBuffer     : Array[0..4096] of Char;
        flags       : DWord;
      const
        accept: packed array[0..1] of LPWSTR = (PChar('*/*'), nil);
        header: string = 'Content-Type: text/plain';
      begin
        hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
        try
          hHTTP := InternetConnect(hInet, PChar(Server), INTERNET_DEFAULT_HTTPS_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 1);
          try
            flags := INTERNET_FLAG_SECURE or INTERNET_FLAG_KEEP_CONNECTION;
            hReq := HttpOpenRequest(hHTTP, PChar('POST'), PChar(Resource), nil, nil, @accept, flags, 1);
            try
              if not HttpSendRequest(hReq, PChar(header), length(header), PChar(Data), length(Data)) then begin
                raise Exception.Create('HttpOpenRequest failed. ' + SysErrorMessage(GetLastError));
              end else begin
                 BufStream := TMemoryStream.Create;
                  try
                    while InternetReadFile(hReq, @aBuffer, SizeOf(aBuffer), BytesRead) do
                    begin
                      if (BytesRead = 0) then Break;
                      BufStream.Write(aBuffer, BytesRead);
                    end;
      
                    aBuffer[0] := #0;
                    BufStream.Write(aBuffer, 1);
                    Result := PChar(BufStream.Memory);
                  finally
                    BufStream.Free;
                  end;
              end;
            finally
              InternetCloseHandle(hReq);
            end;
          finally
            InternetCloseHandle(hHTTP);
          end;
        finally
          InternetCloseHandle(hInet);
        end;
      end;
      

      我现在在 Fiddler 中得到了两个结果,一个成功,一个失败。

      成功者:

      CONNECT fsettestprod.edd.ca.gov:443 HTTP/1.0
      User-Agent: BNWebSvc
      Host: FSETTESTPROD.EDD.CA.GOV:443
      Content-Length: 0
      Connection: Keep-Alive
      Pragma: no-cache
      
      A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
      
      Major Version: 3
      Minor Version: 1
      Random: 4F 28 1F 92 96 EA 2C 64 91 59 12 84 D1 F3 F8 ED BA 89 A5 44 94 D6 50 E0 CF 9B FA 12 5F 57 AD EB
      SessionID: empty
      Ciphers: 
          [0004]  SSL_RSA_WITH_RC4_128_MD5
          [0005]  SSL_RSA_WITH_RC4_128_SHA
          [000A]  SSL_RSA_WITH_3DES_EDE_SHA
          [0009]  SSL_RSA_WITH_DES_SHA
          [0064]  TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
          [0062]  TLS_RSA_EXPORT1024_WITH_DES_SHA
          [0003]  SSL_RSA_EXPORT_WITH_RC4_40_MD5
          [0006]  SSL_RSA_EXPORT_WITH_RC2_40_MD5
          [0013]  SSL_DHE_DSS_WITH_3DES_EDE_SHA
          [0012]  SSL_DHE_DSS_WITH_DES_SHA
          [0063]  TLS_DHE_DSS_EXPORT1024_WITH_DES_SHA  
      

      还有失败的:

      POST https://FSETTESTPROD.EDD.CA.GOV/fsetservice HTTP/1.1
      Accept: */*
      Content-Type: text/plain
      User-Agent: BNWebSvc
      Host: FSETTESTPROD.EDD.CA.GOV
      Content-Length: 2190
      Connection: Keep-Alive
      Cache-Control: no-cache
      Cookie: __utma=158387685.1851397844.1321382260.1321382260.1321382260.1; __utmz=158387685.1321382260.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=calif%20edd%20eft%20payroll%20processor%20batch%20processing
      
      <?xml version="1.0" encoding="utf-8"?>
      <log>
        <inputMessage utc="3/2/2007 10:45:44 PM" messageId="urn:uuid:c07c9aef-28db-4843-8dfc-c5b4d3dc363b">
          <processingStep description="Unprocessed message">
            <soap:Envelope xmlns:xop="http://www.w3.org/2004/08/xop/include" 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" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
              <soap:Header>
                <wsa:Action>//edd.ca.gov/Ping</wsa:Action>
                <wsa:MessageID>urn:uuid:c07c9aef-28db-4843-8dfc-c5b4d3dc363b</wsa:MessageID>
                <wsa:ReplyTo>
                  <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
                </wsa:ReplyTo>
                <wsa:To>http://localhost:3031/EDD.DMRC.FSET.WebServices/FsetService.asmx</wsa:To>
                <wsse:Security soap:mustUnderstand="1">
                  <wsu:Timestamp wsu:Id="Timestamp-0983e8c1-e822-4648-8066-33839f54a6a0">
                    <wsu:Created>2007-03-02T22:45:41Z</wsu:Created>
                    <wsu:Expires>2007-03-02T22:50:41Z</wsu:Expires>
                  </wsu:Timestamp>
                  <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-0d55d82c-d16d-4c0e-826b-21bf7c805a0f">
                    <wsse:Username>***MyUserName***</wsse:Username>
                    <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">***MyPassword***</wsse:Password>
                    <wsse:Nonce>w6dgDz1DMzKntFsFdEcjhw==</wsse:Nonce>
                    <wsu:Created>2007-03-02T22:45:41Z</wsu:Created>
                  </wsse:UsernameToken>
                </wsse:Security>
              </soap:Header>
              <soap:Body>
                <Ping xmlns="http://edd.ca.gov/">
                </Ping>
              </soap:Body>
            </soap:Envelope>
          </processingStep>
        </inputMessage>
      </log>
      

      我单步调试了我的代码并观察了 Fiddler 的反应。当我跨过 HTTPSendRequest 行时,两条消息都出现了。在我的按钮单击事件中,我将函数的结果分配给了一个备忘录控件,但我得到的只是一堆表示不可打印字符的方块。

      我得到的结果是否表明过程很好但内容很糟糕?

      这是否仍然是一个问题,因为您无法以这种方式访问​​ WebService?

      我怎样才能解密结果,或者当我得到正确的过程时这会自动发生吗?

      【讨论】:

        猜你喜欢
        • 2015-02-25
        • 2017-03-19
        • 2015-05-22
        • 1970-01-01
        • 1970-01-01
        • 2021-01-18
        • 2019-05-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多