Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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

Compartilhar este post


Link para o post
Compartilhar em outros 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.

Compartilhar este post


Link para o post
Compartilhar em outros 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);

 

Compartilhar este post


Link para o post
Compartilhar em outros 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!

Compartilhar este post


Link para o post
Compartilhar em outros 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.

Compartilhar este post


Link para o post
Compartilhar em outros 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).

Compartilhar este post


Link para o post
Compartilhar em outros 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.

 

Compartilhar este post


Link para o post
Compartilhar em outros 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?

Compartilhar este post


Link para o post
Compartilhar em outros 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.

Compartilhar este post


Link para o post
Compartilhar em outros 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.

 

Compartilhar este post


Link para o post
Compartilhar em outros 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!

Compartilhar este post


Link para o post
Compartilhar em outros 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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

  • Conteúdo Similar

    • Por Rafael_Ferreira
      Não consigo carregar a imagem do captcha do meu formulário. Foi testado com o xampp e easyphp. Também não carregou a imagem de outros captcha. 
       
       
    • Por luiz monteiro
      Olá, tudo bem?
       
      Estou melhorando meu conhecimento em php e mysql e, me deparei com o seguinte. A tabela da base de dados tem um campo do tipo varchar(8) o qual armazena números. Eu não posso alterar o tipo desse campo. O que preciso é fazer um select para retornar o números que contenham zeros a direita ou a esquerda.
      O que tentei até agora
       
      Ex1
      $busca = $conexao->prepare("select campo form tabela where (campo = :campo) ");
      $busca->bindParam('campo', $_REQUEST['campo_form']);
       
      Se a direita da string $_REQUEST['campo_form'] termina ou inicia com zero ou zeros, a busca retorna vazio.
      Inseri dados numéricos, da seguinte maneira para testar: 01234567;  12345670: 12345678: 12340000... entre outros nessa coluna. Todos os valores que não terminam ou não iniciam com zero ou zeros, o select funciona.
       
       
      Ex2
      $busca = $conexao->prepare("select campo form tabela where (campo = 0340000) ");
      Esse número está cadastrado, mas não retorna.
       
      Ex3
      $busca = $conexao->prepare("select campo form tabela where (campo = '02340001' ) ");
      Esse número está cadastrado, mas não retorna.
       
       
      Ex4
      $busca = $conexao->prepare("select campo form tabela where (campo like 2340000) ");
      Esse número está cadastrado, mas não retorna.
       
      Ex5
      $busca = $conexao->prepare("select campo form tabela where (campo like '12340000') ");
      Esse número está cadastrado, mas não retorna.
       
      Ex6
      $busca = $conexao->prepare("select campo form tabela where (campo like '"12340000"' ) ");
      Esse número está cadastrado, mas não retorna.
       
       
      Ex7
      $busca = $conexao->prepare("select campo form tabela where (campo like :campo) ");
      $busca->bindParam('campo', $_REQUEST['campo_form'])
      Não retorna dados.
       
      O  $_REQUEST['campo_form'] é envio via AJAX de um formulário. 
      Usei o gettype para verificar o post, e ele retorna string.
      Fiz uma busca com número 12345678 para verificar o que o select retorna, e também retrona como string.
       
      Esse tipo de varchar foi usado porque os números que serão gravados nesse campo,  terão zeros a direita ou na esquerda. Os tipos number do mysql não gravam zeros, então estou usando esse. O problema é a busca.
      Agradeço desde já.
       
       
    • Por daemon
      Boa tarde,
       
      Eu tenho uma rotina que faz uma leitura do arquivo .xml de vários sites.

      Eu consigo pegar o tópico e a descrição, e mostrar a imagem que esta na pagina do link.
      Para isso utilizo esta função:
      function getPreviewImage($url) { // Obter o conteúdo da página $html = file_get_contents($url); // Criar um novo objeto DOMDocument $doc = new DOMDocument(); @$doc->loadHTML($html); // Procurar pela tag meta og:image $tags = $doc->getElementsByTagName('meta'); foreach ($tags as $tag) { if ($tag->getAttribute('property') == 'og:image') { return $tag->getAttribute('content'); } } // Se não encontrar og:image, procurar pela primeira imagem na página $tags = $doc->getElementsByTagName('img'); if ($tags->length > 0) { return $tags->item(0)->getAttribute('src'); } // Se não encontrar nenhuma imagem, retornar null return null; } // Uso: $url = "https://example.com/article"; $imageUrl = getPreviewImage($url); if ($imageUrl) { echo "<img src='$imageUrl' alt='Preview'>"; } else { echo "Nenhuma imagem encontrada"; }  
      Mas estou com um problema, esta funcão funciona quando coloco em uma pagina de teste.php. Preciso mostrar em uma página inicial diversas fotos de todos os links. (No caso acima só funciona 1).
    • Por violin101
      Caros amigos, saudações.
       
      Por favor, me permita tirar uma dúvida com os amigos.

      Tenho um Formulário onde o Usuário digita todos os Dados necessários.

      Minha dúvida:
      --> como faço após o usuário digitar os dados e salvar, o Sistema chamar uma Modal ou mensagem perguntando se deseja imprimir agora ?

      Grato,
       
      Cesar
    • Por Carcleo
      Tenho uma abela de usuarios e uma tabela de administradores e clientes.
      Gostaria de uma ajuda para implementar um cadastro
       
      users -> name, login, passord (pronta) admins -> user_id, registratiom, etc.. client -> user_id, registratiom, etc...
      Queria ajuda para extender de user as classes Admin e Client
      Olhem como estáAdmin
      <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Admin extends User {     use HasFactory;            protected $fillable = [         'name',         'email',         'password',         'registration'     ];      private string $registration;     public function create(         string $name,          string $email,          string $password,         string $registration     )     {         //parent::create(['name'=>$name, 'email'=>$email, 'password'=>$password]);         parent::$name = $name;         parent::$email = $email;         parent::$password = $password;         $this->registration = $registration;     } } User
      <?php namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class User extends Authenticatable {     /** @use HasFactory<\Database\Factories\UserFactory> */     use HasFactory, Notifiable;     static string $name;     static string $email;     static string $password;     /**      * The attributes that are mass assignable.      *      * @var list<string>      */     protected $fillable = [         'name',         'email',         'password',     ];          /**      * The attributes that should be hidden for serialization.      *      * @var list<string>      */     protected $hidden = [         'remember_token',     ];     /**      * Get the attributes that should be cast.      *      * @return array<string, string>      */     protected function casts(): array     {         return [             'email_verified_at' => 'datetime',             'password' => 'hashed',         ];     }          public function roles() : BelongsToMany {         return $this->belongsToMany(Role::class);     }       public function hasHole(Array $roleName): bool     {                 foreach ($this->roles as $role) {             if ($role->name === $roleName) {                 return true;             }         }         return false;     }         public function hasHoles(Array $rolesName): bool     {                 foreach ($this->roles as $role) {             foreach ($rolesName as $rolee) {             if ($role->name === $rolee) {                 return true;             }          }         }         return false;     }         public function hasAbility(string $ability): bool     {         foreach ($this->roles as $role) {             if ($role->abilities->contains('name', $ability)) {                 return true;             }         }         return false;     }     } Como gravar um Admin na tabela admins sendo que ele é um User por extensão?
      Tentei assim mas é claro que está errado...
      public function store(Request $request, Admin $adminModel) {         $dados = $request->validate([             "name" => "required",             "email" => "required|email",             "password" => "required",             "registration" => "required"         ]);         $dados["password"] =  Hash::make($dados["password"]);                  $admin = Admin::where("registration",  $dados["registration"])->first();                  if ($admin)              return                    redirect()->route("admin.new")                             ->withErrors([                                 'fail' => 'Administrador já cadastrados<br>, favor verificar!'                   ]);                            $newAdmin = $adminModel->create(                                    $dados['name'],                                    $dados['email'],                                    $dados['password'],                                    $dados['registration']                                 );         dd($newAdmin);         $adminModel->save();         //$adminModel::create($admin);                  return redirect()->route("admin.new")->with("success",'Cadastrado com sucesso');     }  
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.