Converting xml response to Array with php - php

Please i'm developping a php application, i want to know how to convert the xml reponse of a soap webservice into strings or array or json, i want to insert the values returned by the webservice into my database.
here is my xml respnse:
<env:Envelope xmlns:env="">
<env:Header/>
<env:Body>
<soap:getUserInfoResponse xmlns:soap="">
<getUserInfoResult>
<userInformation>
<detailuserInformationList>
<detailuserInformation>
<Name>Alex</Name>
<alias>Lex</alias>
<age>24</age>
<function>agent</function>
<birthdate>1</birthdate>
<birthmounth>02</birthmounth>
<birthyear>1990</birthyear>
<address>wall street</address>
<civility>mr</civility>
<gender>m</gender>
</detailuserInformation>
</detailuserInformationList>
<lastLogin>14:22</lastLogin>
<userId>A52241</userId>
<cnxTimes>125</cnxTimes>
</userInformation>
<requestTag/>
</getUserInfoResult>
</soap:getUserInfoResponse>
</env:Body>
</env:Envelope>
and here is my php code, calling the ws:
$client = new SoapClient('$url', array("trace" => 1, "exception" => 0));
$client->__setLocation('$url');
$response = $client->__soapCall("getUserInfo", array( parameters...);
print htmlspecialchars($client->__getLastResponse());

Try to use php SoapClient class
SoapClient class
If you generate WSDL use
NuSOAP

Firstly, check what do you have in $response in your code:
print htmlspecialchars($response);
Sceondly, this is proper way or working with SoapClient:
$client = new SoapClient($wsdl_url, array('trace' => 1, 'exception' => 0));
$response = $client->getUserInfo( /* parameters */ );
You'll get array in $response. You can laso view request and response XML with $client->__getLastRequest() and $client->__getLastResponse().

Related

Create Soap Auth request in PHP

I'm new with SOAP and trying to connect it with PHP but without positive results. Maybe you can give me a hand
SOAP 1.2 Request
POST /XXXservice.asmx HTTP/1.1
Host: XXX.prueba.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?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>
<GetAcData xmlns="https://prueba.com/">
<Userid>string</Userid>
<Password>string</Password>
</GetAcData>
</soap12:Body>
</soap12:Envelope>
SOAP 1.2 Response
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?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>
<GetAcDataResponse xmlns="https://prueba.com/">
<XX>xml</GetAcDataResult>
</GetAcDataResponse>
</soap12:Body>
</soap12:Envelope>
I used the following code but I'm getting this message:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://XXX.YYYY.com/XXXservice.asmx' : Premature end of data in tag html line 3
<?php
$options = array(
'Userid' => 'xx',
'Password' => 'xx',
);
$client = new SoapClient("https://XXX.YYYY.com/XXXservice.asmx", $options);
$result = $client('GetAcData');
?>
First of all you need an endpoint url of your webservice, that provides you the wsdl content. As #camelsWrittenInCamelCase has written in his comment, you should try https://XXX.YYYY.com/XXXservice.asmx?wsdl instead of https://XXX.YYYY.com/XXXservice.asmx.
Next you should wrap all your soap client stuff in a try/catch block, to get all possible exceptions and the most informations in case of an error.
try {
$client = new \SoapClient(
'https://XXX.YYYY.com/XXXservice.asmx?wsdl',
[
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'soap_version' => SOAP_1_2,
'trace' => true,
]
);
} catch (\SoapFault $fault) {
echo "<pre>";
var_dump($fault);
echo "</pre>";
echo "<pre>";
var_dump($client->__getLastRequest());
echo "</pre>";
echo "<pre>";
var_dump($client->__getLastResponse());
echo "</pre>";
}
As shown in the example above the soap client is initialized with an options array. We use the trace option, to enable tracing for getting the last send request and response. Additionally wie use the exception option, to force the client to throw exceptions in case of any error. Further more we disable caching the wsdl settings as long as you are developing. If you are going into production, this option should be set to WSDL_CACHE_DISK or WSDL_CACHE_MEMORY.
Now you need to know, which functions and types (complex types) your webservice provides. For this purpose you can do the following.
// getting the functions of your webservice
echo "<pre>";
var_dump( $client->__getFunctions() );
echo "</pre>";
// getting the types of your webservice
echo "<pre>";
var_dump( $client->__getTypes() );
echo "</pre>";
Since I do not know the exact scope of your web service, I'll just assume that the webservice delivers a method called DetAcData with two parameters Userid and Password. With this informations I can only guess, how the right call could look like. For detailed informations I 'd need the output of __getFunctions() and __getTypes().
An examplary call could look like this.
try {
$client = new \SoapClient(
'https://XXX.YYYY.com/XXXservice.asmx?wsdl',
[
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'soap_version' => SOAP_1_2,
'trace' => true,
]
);
$data = new \stdClass();
$data->Userid = 'YourUserId';
$data->Username = 'YourUsername';
$result = $client->GetAcData($data);
// $result will be an object
echo "<pre>";
var_dump($result);
echo "</pre>";
} catch (\SoapFault $fault) {
// error handling
}
Further more you can write data objects for every complex type mentioned in the functions and types output from your webservice. You can add a classmap to the options array when instantiating your soap client, so that every response and request will automatically be parsed in the corresponding data object. How soap client classmaps work is explained in the php documentation.
Just have a try. I 'm sure you will get it on your own. ;)

soap request and response in php LARAVEL

i am new to soap request and response in PHP ,i am working with recharge API.
API providers given me below XML(I Am using Arzoo API Providers).
<MobileRechargeRequest>
<Clientid>Given By Arzoo</Clientid>
<Clientpassword>Given By Arzoo</Clientpassword>
<ClientType>ArzooFWS1.1</ClientType>
<ServiceProvider>AIRTEL-TopUp</ServiceProvider>
<ServiceProviderId>1</ServiceProviderId>
<Rechrgeamount>100.0</Rechrgeamount>
<SubscriberID>9876543210</SubscriberID>
<PartnerReferenceId>123456</PartnerReferenceId>
</MobileRechargeRequest>
They said this is SOAP API, how can i send this request to their URL:-
http://demo.arzoo.com/ArzooWS/services/MobileRecharge?wsdl
using SOAP in PHP.
I tried like below code
$soapclient = new \SoapClient('http://demo.arzoo.com/ArzooWS/services/MobileRecharge?wsdl');
//Use the functions of the client, the params of the function are in
//the associative array
$params = array('CountryName' => 'Spain', 'CityName' => 'Alicante');
$response = $soapclient->getMobileDetails('<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Body>
<getMobileDetails xmlns="http://demo.arzoo.com/ArzooWS/services/MobileRecharge">
<MobileRechargeRequest>
<Clientid>77743781</Clientid>
<Clientpassword>******</Clientpassword>
<Clienttype>ArzooFWS1.1</Clienttype>
<ServiceProvider>AIRTEL-TopUp</ServiceProvider>
<ServiceProviderId>1</ServiceProviderId>
<Rechrgeamount>100.0</Rechrgeamount>
<SubscriberID>9164995714</SubscriberID>
<PartnerReferenceId>123456</PartnerReferenceId>
</MobileRechargeRequest> </getMobileDetails> </soap:Body></soap:Envelope>');
var_dump($response);
I am not getting any response please help me , if i have error in SOAP XML request

How to make PHP SOAP Header like this xml snippet?

I'm trying to make a soap header that would look like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<a-user xmlns="a">testName</a-user>
<a-pass xmlns="a">testPassword</a-pass>
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>
I'm pretty new to soap so I'm pretty sure I just don't understand what I'm supposed to put in for the parameters of the SoapHeader constructor, this is what I'm currently trying and it keeps failing to authenticate:
$authHeader = new SoapHeader("http://schemas.xmlsoap.org/soap/envelope/", "Envelope", array("Header" => array("a-user" => "testName", "a-pass" => "testPassword")));
Can someone explain how I'm supposed to translate that header from the xml into a php soapheader please?
Edit: Yes, agunn, I'm using a real user name and pass, I get a SoapFault exceptions saying "Vendor not authorized!" when I make my soapCall.
Here's the soap call part included:
$this->client->__setSoapHeaders($authHeader);
$response = $this->client->__soapCall("Foo", $params);
$authHeader = new SoapHeader("http://schemas.xmlsoap.org/soap/envelope/", "Envelope", array("Header" => array("a-user" => "testName", "a-pass" => "testPassword")));
By the SoapClient spec you should try like this
$this->client->__setSoapHeaders(array($authHeader));
$response = $this->client->__soapCall("Foo", $params);

PHP SoapClient: Action mismatch

I am trying to use the PHP SoapClient extension to communicate with an external SOAP server.
This is my code:
$this->_client = new SoapClient(SOAP_TAGGING_URL, array(
'trace' => 1,
'soap_version' => SOAP_1_2,
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'uri' => SOAP_URI,
));
try {
$actionHdr = array();
$actionHdr[] = new SoapHeader(SOAP_TAGGING_URL, 'Action', 'GetMessagesByTagsByGroup');
$this->_client->__setSoapHeaders($actionHdr);
$info = $this->_client->GetMessagesByTagsByGroup(
new SoapParam($this->params['mPID'], 'ParentMessageID'),
new SoapParam($gid, 'GroupId'),
new SoapParam(REQUEST_TOKEN, 'RequestToken'),
new SoapParam(ACCESS_TOKEN, 'AccessToken'),
new SoapParam(ACCESS_TOKEN_SECRET, 'AccessTokenSecret')
);
} catch (SoapFault $fault) {
print("\n<br/>SOAP server returned the following ERROR: ".$fault->faultcode."-".$fault->faultstring);
}
echo "\n<br/>SOAP request: ". htmlentities($this->_client->__getLastRequest());
echo "\n<br/>SOAP response: ". htmlentities($this->_client->__getLastResponse());
This is the response I get (formatting added):
SOAP server returned the following ERROR: s:Sender-The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/ITagging/GetMessagesByTagsByGroup'.
SOAP request:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://tempuri.org/" xmlns:ns2="https://mywebserver.com/myWSDL.svc/ws?wsdl">
<env:Header>
<ns2:Action>GetMessagesByTagsByGroup</ns2:Action>
</env:Header>
<env:Body>
<ns1:GetMessagesByTagsByGroup/>
<GroupId>2178</GroupId>
<RequestToken>odwedwo09i0jACqbbjsw6KnlCA=</RequestToken>
<AccessToken>OlVbHurPJrNrEFR54Y0hV9kI/TZs=</AccessToken>
<AccessTokenSecret>js1kerfe453FLuaXpL 892DY o=</AccessTokenSecret>
</env:Body>
</env:Envelope>
SOAP response:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/fault</a:Action>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Sender</s:Value>
<s:Subcode>
<s:Value>a:ActionMismatch</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/ITagging/GetMessagesByTagsByGroup'. </s:Text>
</s:Reason>
<s:Detail>
<a:ProblemHeaderQName>a:Action</a:ProblemHeaderQName>
</s:Detail>
</s:Fault>
</s:Body>
</s:Envelope>
I thought I added the 'Action' parameter in the header, but clearly that is not the place to put it. Or am I doing something else wrong?
Unfortunately I cannot try NuSoap because I have no control over the server.
Thank you,
gm
It means meant that not only you must specify the HTTP header SOAPAction: "http://www.bla.com:MyAction"
but you need to specify also in the SOAP Envelope the header:
Check these links for some ref:
SOAP ACTION
You're passing it as SoapHeader, but actually it is HTTP header.
The way I found to do it is: http://lt.php.net/manual/en/soapclient.dorequest.php by setting $action parameter.
You'll probably need to extend SoapClient class to do it using less lines of code.

SOAP fault: object not set to an instance of an object

I found this question on here:
PHP Soap Issue: Server was unable to process request. ---> Object reference not set to an instance of an object
I have a similar issue, only the WSDL is private, so I figured I'd try and get a basic timezone SOAP Client working.
The solution in the other question isn't possible for me to use with the private WSDL.
$response = $client->getTimeZoneTime(array('timezone'=>'ZULU'));
Really what I need is a way of taking a multidimensional PHP array and putting it into the SOAP formed XML document, without it going crazy and producing stuff like, for this example, this:-
<key>GetTimeZoneTime</key>
<item>ZULU</item>
Here's my PHP:
try {
$WSDL = 'http://www.nanonull.com/TimeService/TimeService.asmx?WSDL';
$client = new SoapClient($WSDL,
array(
"trace" => 1,
"exceptions" => 1,
"soap_version" => SOAP_1_1
));
$xml = '<GetTimeZoneTime><timezone>ZULU</timezone></GetTimeZoneTime>';
$xmlvar = new SoapVar(
$xml,
XSD_ANYXML
);
$response = $client->getTimeZoneTime($xmlvar);
echo "<pre>\n";
echo "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
echo "Response:\n".htmlspecialchars($client->__getLastResponse())."\n";
echo "</pre>";
} catch (SoapFault $exception) {
echo "<pre>\n";
echo "Request :\n".htmlspecialchars($client->__getLastRequest()) ."\n";
echo "Response:\n".htmlspecialchars($client->__getLastResponse())."\n";
echo $exception;
echo "</pre>";
}
This is the request it produces:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.Nanonull.com/TimeService/">
<SOAP-ENV:Body>
<GetTimeZoneTime>
<timezone>ZULU</timezone>
</GetTimeZoneTime>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And the SOAP Fault is:
Server was unable to process request. ---> Object reference not set to an instance of an object.
What's the correct way of turning a multidimensional PHP array into the appropriate format for a SOAP request?
What does the SOAP fault returned actually mean?
Edit: After some searching around elsewhere I thought I'd try the approach of creating a PHP class to mirror the variables on the server. This doesn't work either.
class TimeZone {
public function __construct ()
{
$this->timezone = 'ZULU';
}
}
$WSDL = 'http://www.nanonull.com/TimeService/TimeService.asmx?WSDL';
$client = new SoapClient($WSDL,
array(
"trace" => 1,
"exceptions" => 1,
"soap_version" => SOAP_1_1
));
$xmlvar = new SoapVar(new TimeZone(), SOAP_ENC_OBJECT, "TimeZone");
$response = $client->getTimeZoneTime($xmlvar);
For the Timezone one, adding the classmap parameter made it work:
$client = new SoapClient($WSDL,
array(
"trace" => 1,
"exceptions" => 1,
"soap_version" => SOAP_1_1,
"classmap" => array('timezone' => 'TimeZone')
));
$obj = new TimeZone();
$response = $client->getTimeZoneTime($obj);
echo "<h1>".$response->getTimeZoneTimeResult."</h1>";
For the main problem I'm having, it warrants a new question.
I may be wrong, but I gather the meaning of the error message to be twofold:
The object passed into the soap call may not be an object at all.
The object passed into the soap call may be an object, but if all of its attributes do not match what the server expects it will return that error.

Categories