views:

316

answers:

3

Figured it out, see Update below.

I'm trying to work with a particular web service via PHP (tried both the native and Zend SOAP clients) and it only returns a failure status.

I suspect that it has something to do with the multiple beans in the retrieveMemberInfo method call (authBean, memberInfoBean).

Could someone take a look at the WSDL and point me in the right direction for this particular method call via the PHP client?

Here is what I have so far:

$service = new SoapClient('https://qa.everbridge.net/ws3/services/WebServices3?wsdl');
$result = $service->retrieveMemberInfo(array('loginId', 'orgName', 'password'), array('firstname', 'lastname'));
var_dump($result);

Update

The problem was not with the WSDL call as originally thought. It was the format for the parameters used in the retrieveMemberInfo method call. Here is the full solution that correctly returns the SOAP response:

$params->authBean->loginId = 'username';
$params->authBean->orgName = 'orgName';
$params->authBean->password = 'password';
$params->memberInfoBean->firstName = 'firstName';
$params->memberInfoBean->lastName = 'lastName';

$service = new SoapClient('https://qa.everbridge.net/ws3/services/WebServices3?wsdl');
$result = $service->retrieveMemberInfo($params);

var_dump($result);

Now I just have to figure out how to parse the returned stdObject.

Thanks for the assistance.

A: 

The problem seems to come before that method call:

Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://qa.everbridge.net/ws3/services/WebServices3?wsdl' : Extra content at the end of the document in /.../wsdl.php:2 Stack trace: #0 /.../wsdl.php(2): SoapClient->SoapClient('https://qa.ever...') #1 {main} thrown in /.../wsdl.php on line 2

<?php
$service = new SoapClient('https://qa.everbridge.net/ws3/services/WebServices3?wsdl');
//$result = $service->retrieveMemberInfo(array('loginId', 'orgName', 'password'), array('firstname', 'lastname'));

echo '<pre>';
var_dump($result);
echo '</pre>';
?>

I fetched from that URL with wget and I didn't notice anything extra at the end of the returned document. Not that I know much about WSDL, but I would track the cause of this error.

Update:

After confirming Artefacto's findings, I was motivated to try a workaround:

$curl = curl_init('https://qa.everbridge.net/ws3/services/WebServices3?wsdl');    
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);

$wsdl_string = curl_exec($curl);

file_put_contents('/var/tmp/wsdl.xml',$wsdl_string);

try
{
    $service = new SoapClient('/var/tmp/wsdl.xml');
    $result = $service->retrieveMemberInfo(array('loginId', 'orgName', 'password'), array('firstname', 'lastname'));

    print '<pre>';
    var_dump($result);
    print '</pre>';
}
catch (Exception $e)
{
    print '<pre>';
    var_dump(libxml_get_last_error());
    print '</pre>';
}

Of course, remove the debugging code. You may also want to delete the temporary file after using it.

George Marian
you better use tempnam(), or download the wsdl only once if you're it won't change. Otherwise, you'll get into problems when several instances of the script run at once.
Artefacto
@Artefacto Good point, I didn't think about that. This was merely a proof-of-concept for using cURL to work around the download issue.
George Marian
+1  A: 

This is apparently a bug in PHP. The file is not completely read. There's nothing wrong with the WSDL itself.

The XML parsing error is this:

object(LibXMLError)#1 (6) {
  ["level"]=>
  int(3)
  ["code"]=>
  int(5)
  ["column"]=>
  int(5)
  ["message"]=>
  string(41) "Extra content at the end of the document
"
  ["file"]=>
  string(56) "https://qa.everbridge.net/ws3/services/WebServices3?wsdl"
  ["line"]=>
  int(537)
}

Line 537 is quite before the end of the file.

I suggest you report this to http://bugs.php.net/

Artefacto
Apparently there's already a bug report that describes this exact problem (chunked encoding, etc.). See http://bugs.php.net/bug.php?id=48216 Comment or simply vote there to signal you're experiencing the same problem. (I couldn't edit my answer, I was getting the "workin on ur problemz" cat all the time)
Artefacto
I'll add my vote and report to the list. Thanks for the help.
d_ethier
A: 

I've tried copying it locally and using the example provided in the PHP bug submission.

$tmpWsdlPath = tempnam(sys_get_temp_dir(), 'wsdl');
copy("https://qa.everbridge.net/ws3/services/WebServices3?wsdl", $tmpWsdlPath);
$service = new SoapClient($tmpWsdlPath);
$result = $service->retrieveMemberInfo(array('loginId', 'orgName', 'password'), array('firstName', 'lastName'));

It correctly grabs the WSDL file and writes it to the temp folder. It is the entire file.

It still returns the failure status.

d_ethier
Why don't you try my approach? Admittedly, I didn't flesh it out completely. As Artefacto points out, you need to generate a unique temp name for it to be useful in a real scenario. Otherwise, the proof-of-concept is indeed valid. That's all I was attempting.
George Marian
Also, why don't you just sign up for a regular account and join the community? This answer should be added to original question as an update, not as an answer. Stack Overflow doesn't function like a forum.
George Marian
I agree. I should have signed-up prior to submitting the original question. As I'm not a member (and session cleared) I could not update the original post.I did try your example. I could not get CURL to grab the file and create the local xml file. Copy worked so I went with that. Essentially, I think it does the same thing as I have a local copy of the WSDL to load with the client.Thanks for your help.
d_ethier
OIC. The issue with copy() used like that is that it requires a potentially insecure php configuration. See P1 here: http://www.owasp.org/index.php/PHP_Top_5 Did you try using `$tmpWsdlPath = tempnam(sys_get_temp_dir(), 'wsdl');` to create the temp file name for use with `file_put_contents` in my example?
George Marian
Turns out that I did not need to copy the file locally. I was passing the params to the retrieveMemberInfo method incorrectly.Unfortunately, I cannot update the original post. But, I used the following format: $params->authBean->loginId = 'username'; etc. Then, $service->retrieveMemberInfo($params). It is working now.
d_ethier
But you can update this answer. I don't understand why you `did not need to copy the file locally` as it was throwing an exception before the call to `retrieveMemberInfo`.
George Marian
I've updated the original post. I did not have to copy it locally because it was not the issue. It was the format for the passed parameters into the method that created the original issue. Once I addressed that, using the SOAP client call pointing to the remote WSDL worked fine.
d_ethier