Troubleshooting SOAP web service - php

I am trying to invoke the Web Service PersonalDetails_Update by passing an array of values to it. These values are being successfully written to the database that the web service is designed to do. However, it is also supposed to return an ID for the record written to the database. But I don't get anything back. Just a blank screen with no XML or underlying source.
When using getLastRequest, I get this error:
Fatal error: Uncaught SoapFault exception: [Client] Function ("getLastRequest") is not a valid method for this service in
Code used to pass data to web service and request/response headers:
$client->PersonalDetails_Update(array('personaldetails' => $params));
printf("<br/> Request = %s </br>", htmlspecialchars($client->getLastRequest()));
$result = $client->__getLastResponse();
$header = $client->__getLastResponseHeaders();
When using getLastResponse and getLastResponseHeaders, I don't get anything back.

you forgot the "__":
printf("<br/> Request = %s </br>", htmlspecialchars($client->__getLastRequest()));
your soap client thinks "getLastRequest" is a method of a soap service this way, not a soap client method.
also you should tell us what soap client you are using. i assume you use php built-in soap client...
use __soapCall method to be sure, you are making a request to the service:
try {
$result = $client->__soapCall('PersonalDetails_Update', array('personaldetails' => $params));
} catch (SoapFault $exception) {
echo 'soap fault occured: '.$exception->getMessage().'<br/>';
}
you should check if the returned value is a soap fault.. see the manual

Related

Uncaught SoapFault exception: [HTTP]

I'm trying to handle an Api in PhP made with .Net and I user SoapClient to do it.
I can return the functions that it has like this:
$client = new SoapClient($url);
print_r($client->__getFunctions());
But when I'm trying to call a function with parameters it returns me the error:
Uncaught SoapFault exception: [HTTP] Cannot process the message
because the content type 'text/xml; charset=utf-8' was not the
expected type 'application/soap+msbin1'
I use this:
$client = new SoapClient($url, array('soap_version' => 'SOAP_1_2','location'=>$urlWithoutWsdl, $params));
$response = $client->RegisterLoyaltyUser() ;
print_r($response);
So my question really is, do I have to call it with another way or with another library?
EDIT
The api is protected with username and password, maybe this is something I'm missing?
Thanks in advance.
Remove the quotes surrounding SOAP 1_2. It's a constant not a string value

Why is Soapclient not recognizing my accountInfo object

I am trying to create a Soap request to query an automotive vehicle api. Whenever I run the call I get a client error of the following.
Fatal error: Uncaught SoapFault exception: [Client] SOAP-ERROR: Encoding: object hasn't 'accountInfo' property in ...
However I have defined it as a property. Relevant lines below:
DEFINE ('API_ENDPOINT',"http://services.chromedata.com/Description/7a?wsdl");
DEFINE ('API_SECRET',"xxx");
DEFINE ('API_ACCTNO',"123456");
DEFINE ('DEBUG',"1");
$useridentification = array('accountInfo' =>array('_'=>"",'number'=>API_ACCTNO, 'secret'=>API_SECRET, 'country'=>'US', 'language'=>'EN', 'behalfof'=>'?'));
enter code here
$vinobject = array('vin'=>$vin);
$buildrequest=array($useridentification, $vinobject);
$client = new SoapClient(API_ENDPOINT);
$response = $client->describeVehicle($buildrequest);
Hopefully this is something obvious to those that work with soap APIs regularly.
Screw SoapClient, using curl. Hope it workks for you.

How to do error handling of SOAP request failures?

I'm writing a PHP application which does a SOAP request. Sometimes their server isn't up or has some sort of problem and my application blows with an error like this:
Undefined property: stdClass::$getSomethingJSONResult
There could be a number of reasons why the SOAP request fails and I want to be able to check for those error conditions so the program can handle it.
I have two SOAP functions I use in PHP. One for logging in to the SOAP server and the other for making a query to get the soapFunction. They look something like this:
// --------------------- FUNCTIONS -----------------------
function login_soap($username,$password) {
global $soapClient;
$soapURL = "http://SOAPServerSomeplace.asmx?WSDL";
$ns = 'http://microsoft.com/webservices/'; //Namespace of the WS.
$soapParameters = array('userName' => $username, 'password' => $password);
$soapClient = new SoapClient($soapURL);
$header = new SoapHeader($ns,'UserCredentials',$soapParameters,false);
$soapClient->__setSoapHeaders($header);
}
// -------------------------------------------------------
function getSomething($option) {
global $soapClient;
$soapFunctionParameters = array('this' => $option) ;
$soapFunction = "getSomethingJSON" ;
$this_json = $soapClient->$soapFunction($soapFunctionParameters);
$stdClassObject = json_decode($this_json->getSomethingJSONResult);
$this_obj = $stdClassObject->this;
return $this_obj;
}
// -------------------------------------------------------
I was wondering if I could just do this:
if (login_soap($username,$password)) {
echo "This worked." . "\n";
} else {
echo "This failed." . "\n";
}
or with getSomething($option)?
I don't know how to simulate a SOAP request failure to test this, but I think the SOAP request failing would cause PHP to abort. I'd need to capture this so it doesn't abort PHP so I can direct it to do something else.
My first concern is to make sure the SOAP request worked. Then check the JSON file it returns to make sure it has all the data needed before the program proceeds. Checking the JSON file I have figured out, but not with the SOAP request. Thanks!
SOAP will throw a SoapFault Exception if there is an error. You just have to catch the Exception and you can handle the error.
http://www.php.net/manual/de/class.soapfault.php
The SoapClient can throw exceptions if there are errors.
If throwing of exceptions is disabled, those exception objects are only returned. You'd have to check whether the return value is an instance of SoapFault, but the better approach would be to throw them, and use try/catch.
This is even more true because the SoapClient cannot detect HTTP errors otherwise. You MUST throw errors as exceptions if you want to catch those errors as well (it does not work if XDebug is enabled, though, but this should only be the case in development).

How do I view the last request from Zend_Soap_Client->getLastRequest() after a soap fault exception?

I am using a Zend_Soap_Client to call a web service. I am getting an exception from the error which I suspect is down to me not sending something along with the request:
Fatal error: Uncaught SoapFault exception: [Sender] SOAP-ERROR:
Encoding: object hasn't 'V24Flag' propert
Because it throws an exception I want to try view what is the actual request being sent, however because of the exception, I can not use Zend_Soap_Client->getLastRequest() to get the request (it returns null). Looking at the Zend_Soap_Client->getLastRequest() its a thin wrapper for soapClient->__soapCall() which I'm not sure how to dig deeper from.
Your problem is actually slightly different to what you think it is. The reason Zend_Soap_Client::getLastRequest() returns NULL for you is that no request was ever made: the error is being thrown at the stage where the request internally is being compared against the WSDL you are using. So the method is perfectly correct to return NULL.
As to how to form the parameter for your SOAP call so this error isn't thrown, I can't be of much greater help right now (I expect it depends partly on the services you are integrating with), but there's a userland answer on the php.net page for SoapClient::__soapCall() which may point you in a fruitful direction. Essentially, some people seem to have got somewhere by doing a deep conversion of an array structure into stdClass objects. That doesn't seem to be the whole story (it isn't for the issue I'm currently investigating), and indeed this may be down to a bug in PHP, but I hope it helps you towards an answer.
How about
try {
$client = new Zend_Soap_CLient();
$client->doSomething($params);
} catch(SoapFault $f) {
echo $f->getTraceAsString();
}
Btw. Zend_Soap_Client->getLastRequest() wraps SoapClient::__getLastRequest();

Checking a URL is valid (from php soap client)

I am writing a web app which will allow the user to specify a URL for a SoapClient. I wanted to validate that php can connect to the client when the user submits a form. I thouhgt I could do this via try catch or set_error_handler (or some combination of the two). However it looks like this is not possible for fatal errors. Is there a way to get SoapClent to test a URL which won't throw an unrecoverable error?
Fatal error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://example.com/wibble'
I want it to flag an error as the URL doesn’t exist, but I would like to be able to catch it.
Otherwise I suppose I could try to download and validate the URL myself, but I would have thought that it would be possible to do it from the SoapClient.
Should this be a fatal error?
Edit
After reading rogeriopvl's answer I reaslise that I should have said that I had tried the 'exceptions' option to the soapclient constructor and (in desperation) the use-soap-error-handler function.
Are you using xdebug? According to this PHP bug report and discussion, the issue has been fixed at least since PHP 5.1, but this xdebug bug messes with 'fatal error to exception conversions' in a way that the exception is not generated and the fatal error 'leaks through'.
I can reproduce this locally, with xdebug enabled:
try {
$soapClient = new SoapClient('http://www.example.com');
}
catch(Exception $e) {
$exceptionMessage = t($e->getMessage());
print_r($exceptionMessage);
}
This gives me the fatal error you described, without even entering the catch clause:
Fatal error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://www.example.com'
It works if I disable xdebug right before the call:
xdebug_disable();
try {
$soapClient = new SoapClient('http://www.example.com');
}
catch(Exception $e) {
$exceptionMessage = t($e->getMessage());
print_r($exceptionMessage);
}
This triggers the exception as expected, and I get a proper SoapFault Object in the catch clause with a message of:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://www.example.com'
So basically exceptions work as advertised. If they don't work in your case, you might encounter the xdebug bug, or maybe a similar issue with another 3rd party component.
Quoting SoapClient documentation:
The exceptions option is a boolean value defining whether soap errors throw exceptions of type SoapFault.
So you should try something like:
$client = new SoapClient("some.wsdl", array('exceptions' => TRUE));
This way will throw SoapFault exceptions allowing you to catch them.
See: http://bugs.xdebug.org/view.php?id=249
Possible solution:
Index: trunk/www/sites/all/libraries/classes/defaqtoSoapClient.class.php
===================================================================
--- classes/defaqtoSoapClient.class.php
+++ classes/defaqtoSoapClient.class.php
## -31,10 +31,23 ##
try {
+ // xdebug and soap exception handling interfere with each other here
+ // so disable xdebug if it is on - just for this call
+ if (function_exists('xdebug_disable')) {
+ xdebug_disable();
+ }
//Create the SoapClient instance
parent::__construct($wsdl, $options);
}
catch(Exception $parent_class_construct_exception) {
+ if (function_exists('xdebug_enable')) {
+ xdebug_enable();
+ }
// Throw an exception an say that the SOAP client initialisation is failed
throw $parent_class_construct_exception;
+ }
+ if (function_exists('xdebug_enable')) {
+ xdebug_enable();
}
}
you could try and do a curl or fsockopen request to check the URL is valid.
For your information, i'm using SoapClient with PHPUnit to test remote WebServices and got the same problem!
when using an old PHPUnit version (3.3.x) as third party, phpunit crash
when using current version of PHPUnit (3.4.6) as third party, phpunit display "RuntimeException".
Here is my first test method :
public function testUnavailableURL() {
$client = new SoapClient("http://wrong.URI");
}
Here is PHPUnit first result :
There was 1 error:
1) MyTestCase::testUnavailableURL
RuntimeException:
FAILURES!
Here is my second test method :
public function testUnavailableURL() {
try {
$client = #new SoapClient("http://wrong.URI");
} catch (SoapFault $fault) {
print "SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})";
}
}
Here is PHPUnit second test result :
PHPUnit 3.4.6 by Sebastian Bergmann.
.SOAP Fault: (faultcode: WSDL, faultstring: SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://wrong.URI' : failed to load external entity "http://wrong.URI"
)...
Time: 3 seconds, Memory: 4.25Mb
OK
NB: i found a phpunit ticket on this subject : ticket 417

Categories