Eu tenho sido um tempo muito ocupado com webservices a quem devo chamar com PHP e hoje eu tive que lidar com os cabeçalhos SOAP. A verdade é que é um mundo completamente escuro e eu me encontrei com muitos obstáculos. Vou dizer-lhe onde e como eu resolvi, mas primeiro vamos olhar para alguma teoria.

Os serviços web se tornaram o principal modo de troca de informações entre aplicações, independentemente das plataformas, sistemas operacionais e linguagens de programação. SOAP é um dos protocolos em que são trocados dados e é baseado em XML, de modo que as pesquisas cliente o servidor com um formato XML e recebe a resposta em um outro XML. Para entender o que queremos dizer, vamos olhar para a estrutura de um pedido e resposta SOAP.

Call (pedido):

  1. encoding = "UTF-8" ?> <? Xml version = "1.0" encoding = "UTF-8"?>
  2. xmlns:ns1= "com.xplota.ws" > Xmlns: SOAP-ENV = "http://schemas.xmlsoap.org/soap/envelope/" xmlns: ns1 = <SOAP-ENV:Envelope "com.xplota.ws">
  3. <SOAP-ENV:Header>
  4. <ns1:entity>
  5. <code> 1 </ code>
  6. <desc> </> Desc
  7. </ Ns1:> entidade
  8. <ns1:language>
  9. <code> 1 </ code>
  10. <desc> </> Desc
  11. </ Ns1:> língua
  12. <ns1:userId>
  13. <code> 1 </ code>
  14. <desc> </> Desc
  15. </ Ns1: usuário>
  16. </ SOAP-ENV:> Cabeçalho
  17. <SOAP-ENV:Body>
  18. </ SOAP-ENV: Body>
  19. </ SOAP-ENV: Envelope>

Answer (resposta):

  1. encoding = "utf-8" ?> <? Xml version = "1.0" encoding = "-8" utf?>
  2. xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" > <Novelas: 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 ">
  3. <soap:Header>
  4. > Xmlns = <status "com.xplota.ws">
  5. <code> 0 </ code>
  6. <desc> Ok </ desc>
  7. </ Status>
  8. </ Soap:> Cabeçalho
  9. <soap:Body>
  10. </ Soap: Body>
  11. </ Soap: Envelope>

Como visto na listagem anterior, tanto o pedido ea resposta é composto de dois nós XML, cabeçalho e corpo. O comumente usado é o corpo (que deixei em branco porque não estamos interessados neste momento) e que contêm os parâmetros que são enviadas para o webservice no pedido de retornados na resposta.

Enviando os cabeçalhos de sabão

No presente caso, deve enviar certos parâmetros no cabeçalho e ler a partir daí os códigos de erro potencial se tivesse havido. A transferência, apesar de ser uma estrutura em vez de um parâmetro simples, foi simples, você define uma classe com os parâmetros adequados e é enviada diretamente. O PHP motor SOAP é responsável pela tradução. Considere-se um estudo de caso.

  1. / / Definir os cabeçalhos de classe
  2. classe wsHeader
  3. (
  4. = 0 ; public $ Code = 0;
  5. = ; public $ desc = ";
  6. $code , $desc ) { public function __construct ($ code, $ desc) (
  7. = $code ; $ This -> Code = $ código;
  8. = $desc ; $ This -> Desc = $ desc;
  9. )
  10. )
  11. / / Uma instância do cliente SOAP
  12. ( ) ; Par $ = array ();
  13. SoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; $ Cliente novo SoapClient = ("http://midominio.com/ws?wsdl", $ par);
  14. / / Adicionar os cabeçalhos dos pedidos
  15. ( ) ; $ Headers = array ();
  16. = new SoapHeader ( "com.xplota.ws" , 'entity' , new wsHeader ( 1 , ) ) ; Cabeçalhos $] = new SoapHeader [(com.xplota.ws ", entidade ', wsHeader Novo (1"));
  17. = new SoapHeader ( "com.xplota.ws" , 'language' , new wsHeader ( 1 , ) ) ; Cabeçalhos $] = new SoapHeader [(com.xplota.ws "," linguagem ", wsHeader Novo (1"));
  18. = new SoapHeader ( "com.xplota.ws" , 'userId' , new wsHeader ( 1 , ) ) ; Cabeçalhos $] = new SoapHeader [(com.xplota.ws "," UserID ", wsHeader Novo (1"));
  19. $headers ) ; $ Client - __setSoapHeaders> ($ headers);
  20. / / Iniciar a chamada para o método foi
  21. -> TuMetodo ( $parametros ) ; $ Resultado = $ cliente -> TuMetodo ($ params);

Como você pode ver é bastante simples de entender. Ao adicionar um cabeçalho deve indicar o espaço que pertence ao motor SOAP sabe como tratá-la, é dado um nome e um objeto que o contém.

Com isso, ter resolvido o lado de entrega de nossas cabeças e tem um pedido SOAP como indicado no XML primeiro.

Recebendo cabeçalhos SOAP

Agora que o método em nosso webservice diz com alguns cabeçalhos de outros que sabemos como interpretar a resposta de XML como a segunda lista. Então nós temos um problema muito grande. Não há nenhuma maneira de obter estes títulos, o motor SOAP do PHP retorna apenas o corpo, nunca cabeçalhos.

De acordo com o método manual PHP __soapCall cliente SOAP para definir uma matriz que irá retornar esses cabeçalhos, mas eu não era capaz de executar a invocação de um método de webservice com esta sintaxe, enquanto invoca-los diretamente no cliente (como documentação indica que pode ser feito) eu trabalhei na perfeição. Ou seja, a teoria diz que o primeiro método que eu possa ver os cabeçalhos, mas eu trabalhei quando eu trabalhei no segundo, mas ele retorna os cabeçalhos e não há maneira de recuperá-los.

Após uma longa disputa com SOAP e funções de pesquisa, mas ainda não chegaram a qualquer conclusão, é como se tivesse acontecido com qualquer um, eu não encontrei nada útil. Eu só tinha uma solução, fazer a minha própria classe a partir do original de resposta SOAP para processar o XML manualmente para obter os dados necessários. Dito e feito. Deixe a solução.

Primeiro eu criar o meu próprio tipo de SOAP e eu verificar se posso fazer o que eu quero.

  1. SoapClient { classe XSoapClient estende SoapClient (
  2. $wsdl , $options ) { public function __construct ($ wsdl, $ options) (
  3. , $options ) ; parent:: __construct ($ wsdl, $ options);
  4. )
  5. $request , $location , $action , $version ) { __doRequest função pública ($ pedido, $ local, $ action, $ version) (
  6. $request , $location , $action , $version ) ; $ Resposta = pai: __doRequest ($ pedido, $ local, $ action, $ version);
  7. ; $ Resposta de retorno;
  8. )
  9. )
  10. XSoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; $ Cliente novo XSoapClient = (http://midominio.com/ws?wsdl ", $ par);

Acho que vou ter sorte se eu tentar esse novo cliente SOAP funciona perfeitamente, mas se eu verificar o conteúdo de $ resposta vejo que contém o XML webservice resposta completa. Como você vê a única coisa que muda é que isso aconteceu instanciar o nome da nova classe. Bom começo, se eu jogar minhas cartas bem eu posso obter os cabeçalhos no __doRequest método :) .

Vamos uma vez que este XML para conseguir o que queremos. Graças às funções DOM e XPath em PHP é muito simples. Este é o resultado final do meu cliente SOAP cabeçalhos de recuperação:

  1. SoapClient SoapClient classe estende XSoapClient
  2. (
  3. = array ( ) ; privado responseHeaders $ = array ();
  4. $wsdl , $options ) { public function __construct ($ wsdl, $ options) (
  5. , $options ) ; parent:: __construct ($ wsdl, $ options);
  6. )
  7. $request , $location , $action , $version ) { __doRequest função pública ($ pedido, $ local, $ action, $ version) (
  8. $request , $location , $action , $version ) ; $ Resposta = pai: __doRequest ($ pedido, $ local, $ action, $ version);
  9. DOMDocument; Dom DOMDocument $ = novo;
  10. ( $response , LIBXML_NOWARNING ) ; $ Dom -> resposta ($ loadXML, LIBXML_NOWARNING)
  11. DOMXPath ( $dom ) ; $ Caminho = DOMXPath novo ($ dom);
  12. ( 'soap' , 'http://schemas.xmlsoap.org/soap/envelope/' ) ; $ Caminho - registerNamespace> ("sabão", "http://schemas.xmlsoap.org/soap/envelope/ ');
  13. -> query ( '//soap:Header/*' ) ; $ Xml = $ caminho - consulta> ('/ / soap: Header / *');
  14. = $this -> headers2array ( $xml ) ; $ This -> responseHeaders = $ this - headers2array> ($ xml);
  15. ; $ Resposta de retorno;
  16. )
  17. getResponseHeaders função pública () (
  18. -> responseHeaders ; return $ this - responseHeaders>;
  19. )
  20. $response ) { headers2array função privada ($ resposta) (
  21. ( ) ; $ Headers = array ();
  22. $response as $node ) { foreach ($ resposta quanto $ node) (
  23. $node -> hasChildNodes ( ) ) { if ($ node - hasChildNodes> ()) (
  24. $node -> nodeName ] = $this -> headers2array ( $node -> childNodes ) ; Cabeçalhos [$ -] nodeName> = $ this - headers2array> ($ node - childNodes>);
  25. { Else ()
  26. $node -> nodeName ] = $node -> nodeValue ; Cabeçalhos [$ -] nodeName> = $> - nodeValue nó;
  27. )
  28. )
  29. ; $ Headers de retorno;
  30. )
  31. )
  32. = new XSoapClient ( "http://midominio.com/ws?wsdl" , $par ) ; lang = <pre "php"> $ client = XSoapClient novo (http://midominio.com/ws?wsdl ", $ par);
  33. -> TuMetodo ( $parametros ) ; $ Resultado = $ cliente -> TuMetodo ($ params);
  34. -> getResponseHeaders ( ) ; Soapheaders $ = $ cliente - getResponseHeaders> ();

Problema resolvido e muito elegante. Se alguém sabe como obter os cabeçalhos sem montar toda essa bagunça que você me diga, por favor.

Se você tem revelado útil este artigo ... Compartilhe!