2012-01-31 89 views
4

幾乎我所有的開發經驗都在桌面應用程序中。我目前使用的是Delphi 2010,我需要編寫一個SOAP客戶端來訪問加州EDD維護的用於處理工資數據的Web服務。我放棄了Delphi WSDL Importer,因爲幕後幕後發生的事情太多了,我似乎無法取得任何進展。我下載了Fiddler2並一直使用它來查看我一直在寫給網絡的內容。我發現這個過程發佈,我覺得我現在正在某個地方。發佈數據並獲得SOAP客戶端的響應

//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; 

我改變了內容類型,因爲原來似乎永遠不會返回。

我一直在呼籲這樣的:

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)存在,並且響應它是可用的。當我發佈時,我可能會因爲附加Web服務名稱而出現404錯誤。在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時,這是工作,我可能需要合併,爲了得到它的工作。

我在正確的方向前進?

從安地列斯的過程並沒有說明如何檢索響應。我如何檢索回覆?

回答

1

我想我取得一些進展。我將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; 

,我現在在提琴手得到兩個結果,一個成功的,一個不是。

成功之一:

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> 

我通過我的代碼加強,看着提琴手反應。當我跨過HTTPSendRequest行時,兩條消息都出現了。在我的按鈕單擊事件中,我將函數的結果分配給一個備忘錄控件,但我得到的是一堆指示不可打印字符的正方形。

難道我得到的結果表明,該過程是好的,但內容是壞?

難道這仍然是一個問題,因爲你不能訪問一個WebService這種方式?

我怎樣才能解密結果或當我到達權利過程中會自動此發生?

0

我現在已經做了更多的研究,買了一本關於web服務"Teach Yourself Web Services"的好書(謝謝你根植於Nook),並且簡單地與我在其網站服務的人嘗試使用。所以我認爲我已經回答了一些我一直在問的問題,我會在這裏總結一下,以防其他人開始採用相同的方式。如果您發現我錯誤地陳述了某些事情,並且您可以糾正或改進它,如果您花時間進行改進,我將不勝感激。

在顯示Web服務使用HTTP的圖形中,這意味着如果您使用的組件可以向網站發出請求,您也可以使用它創建Web服務客戶端。

您應該馬上安裝Fiddler2。您將從中獲得的反饋對取得進展至關重要。

WSDL文件可能有助於創建Web服務客戶端,但可能不會。我使用Delphi WSDL導入器的經驗是,它沒有完成任務。 Web服務上的Wikipedia article在Big Web Services上有一節指出WSDL文件不是必需的,但可以幫助自動化Web服務客戶端的設計。如果它沒有幫助,請不要使用它。您不需要使用HTTPRIO組件來訪問Web服務。您可以使用WinInet單元,其中包含一些代碼,這些代碼是我從某些StackOverflow貼子剽竊的。

WSDL文件中引用的模式不必在所示的位置存在。從技術上講,這些是URI而不是URL(標識符而不是位置)。

當自動生成不起作用時,手動編寫web服務客戶端可能是自動生成的可接受替代方案。此外,像許多黑盒解決方案一樣,它只在工作時纔有效。當它不起作用時,可能沒有其他選擇。此外,您將學習更多,並更好地控制輸出。

如果您使用上面的PostWebData例程,使用SSL發送您的請求似乎是自動的。獲得答覆也包括在這個例程中。

獲得我從Web服務獲得的兩個響應似乎表明我的過程很好,但是我的內容很糟糕。我現在必須查看實際的SOAP信封並提供可接受的數據才能進入下一步。

如果結果在我完成下一步時未解密,那麼我將不得不做更多的研究。

我希望這有助於其他人試圖在Web服務中找到他或她的方式。