Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
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.>
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.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);>
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!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.
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).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.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?
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.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.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!
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.
De que forma você está consumindo o webservice? Pois, a forma de recuperar o valor depende da forma de acesso.