Jump to content
Roberto Marinho

[Resolvido] Soap PHP - Elemento não encontrado no response de um request.

Recommended Posts

Boa tarde a todos.

Estou tentando pegar os elementos do response de um request Soap, porém, não consigo acessar um determinado elemento.

Esse elemento me apresenta 2 complicadores.

 

1. Ele aparece no TCPDUMP do response, mas não importa o método que eu use, não consigo acessa-lo ou manipulá-lo.

2. Ele está duplicado.

 

Response

<?xml version="1.0" encoding="utf-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <ns1:getUserMSISDNResponse xmlns:ns1="http://www.csapi.org/schema/parlayx/sicoweb/v1_0/local">
            <ns1:MSISDN>5599999999999</ns1:MSISDN>
            <ns1:IMEISV>000000000000000</ns1:IMEISV>
            <ns1:extendInfos>
                <name>userType</name>
                <value>0</value>
            </ns1:extendInfos>
            <ns1:extendInfos>
                <name>profile</name>
                <value>0</value>
            </ns1:extendInfos>
        </ns1:getUserMSISDNResponse>
    </soapenv:Body>
</soapenv:Envelope>

O MSISDN e o IMEISV eu consigo obter sem problemas, mas o que está dentro das duas "extendInfos" eu não consigo.

 

Ja usei foreach, mas no maximo eu consigo um array com os MSISDN e o IMEISV.

 

Alguém tem alguma idéia de como me ajudar? 

 

Obrigado.

Edited by Gabriel Heming
adicionar marcação de código

Share this post


Link to post
Share on other sites

De que forma você está consumindo o webservice? Pois, a forma de recuperar o valor depende da forma de acesso.

Share this post


Link to post
Share on other sites
11 minutos atrás, Gabriel Heming disse:

De que forma você está consumindo o webservice? Pois, a forma de recuperar o valor depende da forma de acesso.

Olá Gabriel.

 

Estou chamando esse web service usando a classe SoapClient do PHP.

Segue o código.

 

<?php
$url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$parts = parse_url($url);
parse_str($parts['query'], $query);
$rc = $query['ReasonCode'];

$client = new SoapClient('wsdl/xyz.wsdl');

if ($rc == 0000){

	$spid = "xxxxxx"; 
	$password = "xxxxxxxxx";
	$timestamp = date('YmdHis'); 
	$md5 = md5($spid.$password.$timestamp); 

	$auth = new stdClass(); 
	$auth ->spId = $spid; 
	$auth ->spPassword = $md5; 
	$auth ->serviceId = "xxxxxxxxx";
	$auth ->timeStamp = $timestamp;
	$header = new SoapHeader('http://www.xyz.com/schema/osg/common/v2_1','RequestSOAPHeader',$auth,false); 

	$function = 'getUserMSISDN';
 
	$body= array('getUserMSISDNRequest' => array( 
			'USERTOKEN' => $query['UserToken']
			));
	$endpoint = array('location' => 'http://xxx.xxx.xxx.xxx:8080/xyz/xyz_service'); 
	$client->__setSoapHeaders($header);
	$result = $client->__soapCall($function, $body, $endpoint);
	$resMsisdn = $result->MSISDN;
	$resImei = $result->IMEISV;
			
	echo "<center><h1><br><br><font face='arial' color='white'>Success!!!</font></h1></center>";
	echo "<center><h1><font face='arial' color='white'>Mobile MSISDN: ".$resMsisdn."</font></h1></center>";
	echo "<center><h1><font face='arial' color='white'>Mobile IMEI: ".$resImei."</font></h1></center>";

?>

 

E mais uma vez, muito obrigado pela atenção.

Share this post


Link to post
Share on other sites

Adicione o seguinte trecho de código após a chamada do método e traga-nos o resultado:

var_dump($result);

 

Só um adendo, é possível chamar o nome da função diretamente (sem utilizar o __soapCall), o que eu acredito ser mais semâtico.

Ou seja:

$result = $client->getUserMSISDN($body, $endpoint);

 

Share this post


Link to post
Share on other sites
2 horas atrás, Gabriel Heming disse:

Adicione o seguinte trecho de código após a chamada do método e traga-nos o resultado:


var_dump($result);

 

Olá, Gabriel.

 

o resultado apresentado disso foi:

 

object(stdClass)#4(2) {["MSISDN"] => string(13)"xxxxxxxxxxxxx" ["IMEISV"] => string(15)"xxxxxxxxxxxxxxx"}

 

Eu acho isso particularmente estranho, pois no TCPDUMP vejo que o response tem mais dois campos. Os "extendInfos" que eu citei no meu primeiro post. Seria algum problema com o WSDL, talvez?

 

2 horas atrás, Gabriel Heming disse:

Só um adendo, é possível chamar o nome da função diretamente (sem utilizar o __soapCall), o que eu acredito ser mais semâtico.

Ou seja:


$result = $client->getUserMSISDN($body, $endpoint);

 

 

Cetamente testarei isso mais tarde. Fica bem mais limpo e fácil de entender o código.

 

Muito obrigado por toda a sua ajuda até aqui!

Share this post


Link to post
Share on other sites

Eu desconheço o TCPDUMP, ai não posso afirmar. Também não sei dizer se é um problema do WSDL, pois, nunca vi isso ocorrer.

 

Em casos de SOAP, o mais indicado é testar no SoapUI. Teste no SoapUI e veja se os campos irão aparecer corretamente.

Share this post


Link to post
Share on other sites

Também, na chamada do SoapClient, adicione os seguintes parâmetros nas opções:

$client = new SoapClient(
    'wsdl/wyx.wsdl',
    [
        // Stuff for development. 
        'trace' => 1, 
        'exceptions' => true,
        'cache_wsdl' => WSDL_CACHE_NONE, 
        'features' => SOAP_SINGLE_ELEMENT_ARRAYS
    ]
);

Dessa forma, você terá algumas configurações preparadas para desenvolvimento. Quando entrar em produção, você pode remover as opções de cache e a trace (se não fizer uso de trace).

Share this post


Link to post
Share on other sites

Boa noite.

 

Olha... esse enigma do response ta me tirando o sono, euheuhe!!!

Mas vamos lá.

 

Primeiro um esclarecimento.

O TCPDUMP é um sniffer de rede. Com ele eu capturo o trágego de rede em um arquivo que depois eu posso ler em softwares como o Wireshark. Fazer análise de tráfego, ver como estão os pacotes e também as mensagens HTTP. Assim é que vejo como os pacotes vão e vem entre os servidores que uso.

 

Voltando ao cerne.

 

Testei no SoapUI (Nesse caso é bem chato pois o sistema que estou testando exige que eu faça o fluxo acessando por uma conexão móvel da minha operadora de celular). Tive a resposta esperada e com os parâmetros que eu gostaria de pegar no response aparecendo.

 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <ns1:getUserMSISDNResponse xmlns:ns1="http://www.csapi.org/schema/parlayx/sicoweb/v1_0/local">
         <ns1:MSISDN>55xxxxxxxxxx</ns1:MSISDN>
         <ns1:IMEISV>xxxxxxxxxxxxxxx</ns1:IMEISV>
         <ns1:extendInfos>
            <name>userType</name>
            <value>x</value>
         </ns1:extendInfos>
         <ns1:extendInfos>
            <name>profile</name>
            <value>x</value>
         </ns1:extendInfos>
      </ns1:getUserMSISDNResponse>
   </soapenv:Body>
</soapenv:Envelope>

 

Temos o body, sob o body temos o getUserMSISDNResponse.

No nível mais a baico do getUserMSISDNResponse temo mais 3 elementos.

1 - MSISDN

2 - IMEISV

3 - extendInfos (Esse aparece 2x)

 

MSISDN e IMEISV aparecem para mim sem o menor esforço.

Os 2 extendInfos é que não importa o que eu faça, eu não consigo pegar.

 

Esses dois extendInfos só aparecem pra mim de uma forma, usando "__getLastResponse".

Mas ainda assim aparece de modo bem impróprio.

Eu alimento uma variável com o "__getLastResponse". Usando um var_dump nessa variável, eu vejo o response inteiro, inclusive com os elementos repetidos que nao vejo no momento em que o response chega.

Se eu uso um print_r, consigo apenas uma string contendo todos os valores de dentro das tags e sem separação alguma.

 

Estou vendo que a minha solução final vai ser uma gambiarra manipulando essa string. Ao menos os tamanhos e posições dessa string não mudam.

 

Share this post


Link to post
Share on other sites

Isso está bem estranho mesmo. Consegue nos postar o WSDL do web service? Ao menos as partes desse método, junto com os retornos? Qual a sua versão de PHP?

Share this post


Link to post
Share on other sites

Bom dia, Gabriel.

 

Eu não posso postar o WSDL na íntegra, e não sou experiente nessa coisa toda de Soap e WSDL.

Acho que o que você me pede é isso aqui:

 

<xsd:element name="getUserMSISDNRequest" type="osg_sicoweb_local_xsd:getUserMSISDNRequest"/>
			<xsd:complexType name="getUserMSISDNRequest">
				<xsd:sequence>
					<xsd:element name="USERTOKEN"
						type="xsd:string" maxOccurs="1" minOccurs="1">
						<xsd:annotation>
							<xsd:documentation></xsd:documentation>
						</xsd:annotation>
					</xsd:element>
				</xsd:sequence>
			</xsd:complexType>
		
			<xsd:element name="getUserMSISDNResponse" type="osg_sicoweb_local_xsd:getUserMSISDNResponse"/>
			<xsd:complexType name="getUserMSISDNResponse">
				<xsd:sequence>
					<xsd:element name="MSISDN" type="xsd:string"/>
					<xsd:element name="IMEISV" type="xsd:string"/>
				</xsd:sequence>
			</xsd:complexType>

 

Eu estou usando PHP Version 7.0.27-0+deb9u1 rodando junto com Apache 2.0 em Debian 9.

Share this post


Link to post
Share on other sites

A parte em especial que eu quero é o types, especificamente a definição do tipo de retorno. Vou lhe dar um exemplo.

 

O método a seguinte é denominado SalesOrderHistory, a operação está definida pelo Operation.

<wsdl:operation name="SalesOrderHistory">
    <wsdl:input message="tns:IService_SalesOrderHistory_InputMessage"/>
    <wsdl:output message="tns:IService_SalesOrderHistory_OutputMessage"/>
</wsdl:operation>

O name do elemebto Operation será o nome do método que você consome.

 

No Operation, tem a mensagem de entrada e de saída. Eu gostaria a de saída (output). Através do do atributo message, você deve localizar o elemento message:

<wsdl:message name="IService_SalesOrderHistory_OutputMessage">
    <wsdl:part name="parameters" element="SalesOrderHistoryResponse"/>
</wsdl:message>

Já na message, você irá buscar o tipo de retorno, que está definido no atributo element. O element estará definido em types. Nesse caso, você terá que localizar cada nó inferior, pois, podem existir N nós:

<xs:element name="SalesOrderHistoryResponse">
    <xs:complexType>
        <xs:sequence>
            <xs:element minOccurs="0" name="SalesOrderHistoryResult" nillable="true" type="SalesOrderHistory"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Toda vez que existir um tipo elemente (como é o caso de SalesOrderHistoryResult que referencia SalesOrderHistory). Você terá que buscar o novo element:

<xs:complexType name="SalesOrderHistory">
    <xs:sequence>
        <xs:element minOccurs="0" name="SalesOrderList" nillable="true" type="ArrayOfSalesOrder"/>
    </xs:sequence>
</xs:complexType>

E assim por diante.

 

Share this post


Link to post
Share on other sites

Gabriel.

 

Consegui!!!!

 

Tentando atender ao seu pedido de postar aqui o método e o response contidos no WSDL, acabei tendo a "iluminação" de que estava faltando a declaração do "extendInfos" no response.

 

De "orelhada" eu adicionei este campo no response e voilá! Ele agora aparece no response.

<xsd:element name="extendInfos" type="osg_sicoweb_xsd:NameParameter"/>

 

Agora vou tentar extrair esses valores para variáveis e manipulá-los.

 

Muito obrigado pela sua ajuda e principalmente pela paciência!

Share this post


Link to post
Share on other sites

Logo imaginei que fosse isso. Pois, a biblioteca SOAP interpreta o WSDL e faz um match com o que veio na definição. Se veio algum valor a mais, ele é excluído.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By Anonicah
      Olá preciso de ajuda com esse exercício. Montei até a parte de formulário + validação de javascrip no dreamweaver mas buguei com o resto. O que eu fiz:
       

      <html>
      <head>
      <title> Formulário CPF validado com Java Script </title>
          
          <script language="javascript" type="text/javascript">
      function validar() {
      var cpf = form1.cpf.value;
          
      if (cpf == "") {
      alert('Preencha o campo com seu cpf');
      form1.cpf.focus();
      return false;
      }
          
      }
      </script>
          
          
      </head>
      <body>
      <form name="form1" action="enviar.php" method="post">
      CPF:
      <input name="cpf" type="text"><br /><br />
      <input type="submit"  onclick="return validar()">
      </form>
      </body>
      </html>
       
       
      EXERCÍCIO
      Criar um formulário simples em html com um único campo CPF;
      Fazer uma validação em javascript antes de fazer o post;
      Consumir o WS https://bi.vidaclass.com.br/utils para consultar informações do CPF enviado pelo form;
      Do retorno obtido exibir na tela:
      Nome, email, telefone
      Se tem compra em saude: Sim | Não
      Quantas compras: (5) ex.
      Se tem farma: Sim | Não
      Se tem dependente: Sim | Não
      Qtd. de dependentes: (2) ex.

      Obtem o token para consumir os endpoints;
      https://bi.vidaclass.com.br/auth
      {
          "company_id": 1,
          "username": "webmaster@vidaclass.com.br",
          "password": "Teste20170705"
      }
      Endpoint para consultar o CPF
      https://bi.vidaclass.com.br/utils
      {
          "action": 4,
          "key": {
              "cpf": 25383193820
          }
      }
    • By Luciano Marques
      Então pessoal é o seguinte: Estou tendo problemas para impedir acesso simultâneo no meu projeto. Foi depois de muito pesquisar que vim aqui abrir esse tópico. 
      Enfim, eu até consegui colocar uma teoria em prática que era a de criar uma coluna na tabela `usuarios` com 1 para ativo, e 2 para  inativo. e depois coloquei no topo a condição IF para se 1 já preenchido não permite o login. até ai de boa. o problema vem se o usuário não desloga só fecha a janela. a coluna ainda permanece como ativa 1. mesmo expirando o login, não ocorre o update na base de dados. Se alguém puder me ajudar nessa, preciso concluir esse trabalho ainda essa semana. desde já agradeço 
    • By paulojk
      Como faço essa funçao alguem sabe? Depos que o usuario clica no botao so libera depois de um determinado tempo.
       


    • By Anderson Maciel
      Boa tarde pessoal,

      Estou quebrando a cabeça para resolver um problema, tenho uma div dinâmica que carrega uma <table> em uma das colunas deveria apresentar o componente Switchery, esta <table> é montada a partir de uma função PHP que faz o select em uma tabela do banco de dados conforme abaixo:
       
      echo '<table class="table table-hover"> <thead> <tr> <th>Nome</th> <th>Agrupamento</th> <th>Ativo</th> </tr> </thead> <tbody>'; foreach($data as $row) { If ($row['ativo'] == 1) {$vativochk = "checked";} else {$vativochk = "";} echo '<tr> <td>'.$row['nome'].'</td> <td>'.$row['agrupamento'].'</td> <td><input type="checkbox" name="ativo_grid" class="js-switch" '.$vativochk.' disabled="disabled"></td> </tr>'; } echo ' </tbody> </table>'; Aqui está o Ajax que chama e retorna atualizando a DIV:
      //funcoes do grid dos graficos function atualiza_grid_graficos() { $.ajax({ type: "POST", url: "hubfuncind.php", data: { id_tabindicadores_paineis: $('#id_tabindicadores_paineis').val(), acao: "gridgraficos" }, success: function(data) { $('#conteudo').html(data); } }); } O retorno vem certinho, mas apenas o componente Switchery está vindo desconfigurado, ou seja vem um checkbox normal (html).

      O que é mais incrível é que neste mesmo formulário mais acima tenho este mesmo componente funcionando normalmente, somente dentro da DIV dinâmica é que fica desconfigurado conforme imagem anexa.

      Será que alguém já passou por isso?

    • By violin101
      Caros amigos membros do grupo, saudações...
       
      Gostaria de tirar uma dúvida com os amigos.
       
      Tenho uma rotina onde consigo efetuar o Download de arquivos para uma pasta dentro do sistema, o que preciso seria mudar o nome do arquivo, por exemplo:
       
      após selecionar  o arquivo criado com o nome de: ESTOQUE.PDF
       
      gostaria de gravar na pasta de upload's com um novo nome, como por exemplo: cliente[1]-estoque.pdf.
       
      Onde poderia fazer essa alteração na rotina abaixo, para gravar o arquivo com um novo nome ?
       
      abaixo posto o fonte da rotina.
      <?php public function anexar() { $this->load->library('upload'); $this->load->library('image_lib'); $upload_conf = array( 'upload_path' => realpath('./assets/anexos'), 'allowed_types' => 'pdf|PDF|doc|DOC|docx|DOCX', // formatos permitidos para anexos de os 'max_size' => 1024, ); //Recebe a variável via POST $validade = $this->input->post('validade'); $this->upload->initialize($upload_conf); foreach ($_FILES['userfile'] as $key => $val) { $i = 1; foreach ($val as $v) { $field_name = "file_".$i; $_FILES[$field_name][$key] = $v; $i++; } } unset($_FILES['userfile']); $error = array(); $success = array(); foreach ($_FILES as $field_name => $file) { if (! $this->upload->do_upload($field_name)) { $error['upload'][] = $this->upload->display_errors(); } else { $upload_data = $this->upload->data(); if ($upload_data['is_image'] == 1) { // set the resize config $resize_conf = array( 'source_image' => $upload_data['full_path'], 'new_image' => $upload_data['file_path'].'thumbs/thumb_'.$upload_data['file_name'], 'width' => 200, 'height' => 125 ); $this->image_lib->initialize($resize_conf); if (! $this->image_lib->resize()) { $error['resize'][] = $this->image_lib->display_errors(); } else { $success[] = $upload_data; $this->load->model('Dados/Dadosclie_model'); $this->Dadosclie_model->anexar($this->input->post('idCli'), $this->input->post('descricao'), $validade, $upload_data['file_name'], base_url().'assets/anexos/', 'thumb_'.$upload_data['file_name'], realpath('./assets/anexos/')); } } else { $success[] = $upload_data; $this->load->model('Dados/Dadosclie_model'); $this->Dadosclie_model->anexar($this->input->post('idCli'), $this->input->post('descricao'), $validade, $upload_data['file_name'], base_url().'assets/anexos/', '', realpath('./assets/anexos/')); } } } if (count($error) > 0) { echo json_encode(array('result'=> false, 'mensagem' => 'Nenhum arquivo foi anexado.')); } else { echo json_encode(array('result'=> true, 'mensagem' => 'Arquivo(s) anexado(s) com sucesso .')); } } ?>  
      Grato,
       
      Cesar
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.