PHP Soap call xml isnt formated correctly - php

I am trying to talk to a SOAP api a partner provided us with.
I create the client using a WSDL:
$client = new SoapClient('Path/to/WSDL',array('soap_version' => SOAP_1_2,'trace' => 1));
and then call a function like this:
var_dump($client->__call('gsLogin',[new SoapParam("0", '0'),
new SoapParam("User", 'sUser'),
new SoapParam("Password", 'sPassword'),
new SoapParam("Database", 'sDatabase'),
new SoapParam(1, 'lDivision'),
new SoapParam("", 'sError')]));
out comes this xml:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://www.namespace.de/">
<env:Body>
<ns1:gsLogin/>
<sUser>User</sUser>
<sPassword>Password</sPassword>
<sDatabase>Database</sDatabase>
<lDivision>1</lDivision>
<sError></sError>
</env:Body>
</env:Envelope>
As you can see gsLogin is closed immediately with the /.
The parameters go nowhere and I get back the error that no user was given.
Any idea what causes this problem or how to fix it?

Related

PHP SOAP xml namespace missing from WSDL

I am trying to connect to a SOAP server with PHP in WSDL mode.
In the WSDL file there are defined serveral xmlns in the header.
I am creating a request with the client like this:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="NS1" xmlns:ns2="NS2" xmlns:ns3="NS3">
<env:Body>
<ns3:calculate>
<ns1:something>01</ns1:something>
<ns3:calcnode>
<ns1:beginning>2020-07-01</ns1:beginning>
<ns3:data>
<ns1:Hauptfaelligkeit>01.07</ns1:Hauptfaelligkeit>
<ns3:someothernode>
<ns3:code>AH</ns3:code>
<EL-Sum SumCd="ABC" Sum="20000000"/>
<ns3:something>VB</ns3:something>
<EL-Test TestCd="A" TestVal="9"/>
</ns3:someothernode>
</ns3:data>
</ns3:calcnode>
</ns3:calculate>
</env:Body>
</env:Envelope>
I've modified it a bit because the WSDL is confidental so I cannot provide it.
The problem is with there should be a NS4 but it isn't imported so the SOAP server doesn't get the value.
I found a solution that I can modify the XSD of NS4 and add elementFormDefault=qualified but I cannot do this because I cannot load the locally need to leave them remote.
Can I add the NS manually in the header?
Thanks

Stuck at converting xml request to corresponding Savon request

I am trying to communicate with a 3-rd party API. I tried both savon and Soap UI but both failed, then I asked them and they gave me equivalent that works. Confused, I toggled the logger and got following XML request which is quite different from what Savon is sending.
Here is the PHP code (I guess that's not needed, but still)
$apiauth =array('UserName'=>'XXXXXX','Password'=>'XXXXXXX','ClientCode'=>'1234')
$wsdl = 'http://stagewebapi.mylescars.com/service.asmx?wsdl';
$soap = new SoapClient($wsdl);
$header = new SoapHeader('http://tempuri.org/', 'AuthHeader', $apiauth);
$soap->__setSoapHeaders($header);
$data = $soap->fetchCities($header);
print_r($data);
Here is the XML request that PHP is sending and which is working just fine
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/"><SOAP-ENV:Header><ns1:AuthHeader><ns1:UserName>XXXXXXX</ns1:UserName><ns1:Password>XXXXXXX</ns1:Password><ns1:ClientCode>1234</ns1:ClientCode></ns1:AuthHeader></SOAP-ENV:Header><SOAP-ENV:Body><ns1:fetchCities/></SOAP-ENV:Body></SOAP-ENV:Envelope>
Here is my ruby code so far
require 'savon'
auth_header = { 'UserName'=>'XXXXXXX','Password'=>'XXXXXXXX','ClientCode'=>'1234'}
client = Savon.client(:wsdl => "http://stagewebapi.mylescars.com/service.asmx?wsdl",
:namespace_identifier => :ns1 ,:namespace => "http://tempuri.org/" , :log => true, :soap_header => auth_header,
:pretty_print_xml => true, :env_namespace => 'SOAP-ENV')
puts client.call(:fetch_cities)
Here is what Savon is producing
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://tempuri.org/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<UserName>XXXXXXXXXXXXXXX</UserName>
<Password>XXXXXXXXXXXXX</Password>
<ClientCode>2873</ClientCode>
</soap-env:Header>
<soap-env:Body>
<ns1:fetchCities/>
</soap-env:Body>
</soap-env:Envelope>
I don't know how to make it equivalent to the PHP one. Am I missing something obvious ?
I tried to look at Savon documentation to find if there are some methods to manipulate tags with fine grain control but couldn't find much about it.
Questions similar to this are either unanswered or are specific to the requests.
Some SO questions that helped a little
Convert this xml request to a proper savon request
Replicating xml requests with savon ruby
Little curious, how PHP gets it right most of the time. Is it the parser they use for wsdl?

PHP SOAP Why are parameters not being sent?

I need to send a SOAP request to a .NET Web Services (*.asmx). I am creating a WSDL SoapClient object and I need to make a __soapCall sending 2 parameters: LoginName and Password. The XML should be something like the exemple to work, but the XML created has the parameters all confused.
This is the code:
$client = new SoapClient("https://server/service.asmx?WSDL",array("trace"=>1,'soap_version' => SOAP_1_2));
$client->__setCookie('ticket',$ticket);
$param= array('LoginName'=>'name','Password'=> base64_encode('123456'));
$client->__soapCall('AddPlayer', $param);
echo "REQUEST:\n" . htmlentities($sweepStakesClient->__getLastRequest()) . "\n";
Also tried:
$param = array(new SoapParam('name','LoginName'),new SoapParam(base64_encode('123456'),'Password'));
Echo returns:
REQUEST: <?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://server.com/Service">
<env:Body>
<ns1:AddPlayer/>
<Password>MTIyMzQ1NTY=</Password>
</env:Body>
</env:Envelope>
I need it to be something like:
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<AddPlayer xmlns="http://server.com/Service">
<request>
<LoginName>name</LoginName>
<Password>MTIyMzQ1NTY=</Password>
</request>
</AddPlayer>
</soap12:Body>
</soap12:Envelope>
Please pay attention to the documentation provided on php.net regarding the method you use here, SoapClient::__soapCall():
This is a low level API function that is used to make a SOAP call. Usually, in WSDL mode, SOAP functions can be called as methods of the SoapClient object. This method is useful in non-WSDL mode when soapaction is unknown, uri differs from the default or when sending and/or receiving SOAP Headers.
You're in WSDL mode, so you don't need to use it at all. Instead call the method directly:
$client->AddPlayer('name', 'MTIyMzQ1NTY');
When you debug you should see that it matches up with the method name and the two parameters. In case not, fall-back to SoapClient::__call() and use the array with the named parameters again as second parameter. But it's much more comfortable to do it the WSDL style with named methods.

Problems in using PHP Soap Client

I have this web service to access with this kind of configuration:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Executar xmlns="http://localhost/I9ProWebService">
<Servico>string</Servico>
<conteudoXML>string</conteudoXML>
</Executar>
</soap:Body>
</soap:Envelope>
So I tried this:
$client = new soapclient('https://domain/webservice/I9ProWebService.asmx?WSDL');
printf($client->Executar("ListarTomador","<i9proerp><listar_tomador id_pessoa_corretor =\"205\" /></i9proerp>"));
it shows this error:
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object. at I9ProWebService.Executar(String Servico, String conteudoXML) --- End of inner exception stack trace ---
Have you tried using htmlentities or similar to encode the XML you are sending as your second parameter? That might be causing problems with the XML sent by the SOAP client.
EDIT: In order to see what XML the PHP SOAP client is sending and what it's getting back, you can use $client->__getLastRequest() and $client->__getLastResponse() and compare the results with your soapUI call.
I found the solution of my problem.
$client = new SoapClient("http://domain/webservice/I9ProWebService.asmx?WSDL", array("features" => SOAP_SINGLE_ELEMENT_ARRAYS, "encoding" => "utf-8","trace"=> TRUE));
$strVariavel = "<ns1:conteudoXML><i9proerp><listar_tomador id_pessoa =\"999\"/></i9proerp></ns1:conteudoXML>";
$soapvar = new SoapVar($strVariavel, 147);
$xml = $client->ExecutarXML(array('Servico'=>'ListarTomador','conteudoXML'=>$soapvar));
print_r($xml);
and voilá
The problem is that it returns and object and not a XML as I expected...
It returns:
stdClass Object
(
[ExecutarXMLResult] => stdClass Object
(
[any] => <i9proerp xmlns=""><listatomador id_pessoa="5251" nm_pessoa="nome1" nr_cnpj_cpf="132132121332"/><listatomador id_pessoa="939" nm_pessoa="nome2" nr_cnpj_cpf="3213213123213"/></i4proerp>
)
)
So, I have to discover how to deal with it. Is it a case to open another question?

Barnes and Noble seller SOAP API using PHP

I am new to SOAP and have been trying to connect to Barnes and Noble SOAP API using the php5 built in soap functions.
http://www.php.net/manual/en/class.soapclient.php
My question is, does anyone have any documentation or experience using Barnes and Noble system? I have been going back and forth with the support person and I feel like they assume we should just be able to figure it out.
The faultcode i am getting is "HTTP" and fault string is "Method Not Allowed".
Here is what the support guy says my header should look like.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<SessionInfo xmlns="http://tempuri.org/SessionInfoHeader">
<User xmlns="">your username goes here</User>
<Password xmlns="">your password goes here.</Password>
</SessionInfo>
</soap:Header>
This is as close as i can get it.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://tempuri.org">
<SOAP-ENV:Header><ns1:SessionInfo>
<item>
<key>SessionInfo</key>
<value>
<item><key>User</key><value>[username]</value></item>
<item><key>Password</key><value>[password]</value></item>
</value>
</item>
</ns1:SessionInfo>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<searchCriteria/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I am not even sure this is the problem. Any help would be awesome.
In order to get the child nodes instead of the item key/value pairs you have to pass the parameter as an object.
$client = new SoapClient( 'test.wsdl' );
class SessionInfo {
public $User = 'test#example.com';
public $Password = '12345';
}
$sessionInfo = new SessionInfo();
$soap_headers = new SoapHeader( 'http://tempuri.org/SessionInfoHeader',
'SessionInfo', $sessionInfo );
$client->__setSoapHeaders( $soap_headers );
This will output what the support guy said should work. i think you could also create an array and type cast it to an object but i haven't tried that yet.

Categories