Solved

Trouble receiving WebService SOAP XML response in PHP

Posted on 2010-08-19
28
4,216 Views
Last Modified: 2013-12-13
From my PHP program, I am successfully able to send a SOAP/HTP request to a remote server. Using wireshark/etheral, I confirmed that the expected response is being obtained from the remote server. Using SoapUI and wireshark/ethereal , I further confirmed that request/response in SoapUI and wireshark are exactly the same.
  However, in my PHP program I am not receiving the SOAP response.

Please review the code snippet and comments and advise.
Thankyou
// Open the Socket
$fp = fsockopen('stage.xxxxxx.com',80,$errno,$errstr,30);
// TEST FOR VERIFICATION
if (!$fp) // HTTP ERROR
{
        die("fsockopen() FAILED \n\n ERRNO=$errno \n\n 
              ERRSTR=$errstr \n\n");
}

// WITH HTTP OPEN - WRITE HEADER AND REQUEST
// Header and Request have been properly created and 
// confirmed via echo command, SoapUI and wireshark
fputs ($fp, $header . $xml);

// HTTP OPEN - READ WEBSERVICE RESPONSE, INCLUDING HEADERS 
// AND BODY
$reply  = '';
while (!feof($fp))
{
        $reply  .= fgets ($fp, 128);
        
}
fclose($fp);
echo $reply;

// Upon executing the above, I get the following error msg:
// Fatal error: Maximum execution time of 60 seconds exceeded 
// and it mentions the fgets line

// Instead of fputs, I also tried fwrite and I get the 
// following output when I attempt to echo the response
HTTP/1.1 200 OK Date: Fri, 20 Aug 2010 02:10:56 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 Cache-Control: private, max-age=0 Content-Type: application/soap+xml; charset=utf-8 Content-Length: 3543 Fatal error: Maximum execution time of 60 seconds exceeded 

// From the above it seems the the content is there since it is showing a content length of 3543. However I am not being able to see and access the content

Open in new window

0
Comment
Question by:caliea
  • 16
  • 12
28 Comments
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
What is the URL of the WSDL?

I'll use a tool called WSDL2PHP (available from http://sourceforge.net/projects/wsdl2php/ and look at RazorsEdgeUK's patches) to create a set of client classes which do all the hard lifting for you.

You can alter the time limit ...

set_time_limit(n);

where n = 0 === forever or some other value to represent seconds ...

set_time_limit(600); // 10 minutes.

But, getting a WSDL file should be VERY VERY quickly.

What version of PHP are you using? Hopefully V5.2+ (makes things a LOT easier if you are, compared to a V4). Ideally a V5.3+
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
0
 

Author Comment

by:caliea
Comment Utility

The URL of the WSDL is:
http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL

PHP Version is 5.3.1
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Here is the file produced using wsdl2php.

Now you can ...

try
      {
      $sm = new ServiceManager
            (
            $wsdl = "http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL",
            $options = array
                  (
                  'encoding'  => 'ISO-8859-1',
                  'exception' => True,
                  'trace'     => True,
                  )
            );
      
      $sm->xxx(yyy,zzz);
      }
catch(Exception $e)
      {
      die($e->getMessage());
      }


where xxx are methods for the service.

No XML, SOAP, or anything complicated.
ServiceManager.php
0
 

Author Comment

by:caliea
Comment Utility
When I run the following test, I get the message:

Fatal error: Maximum execution time of 60 seconds exceeded in C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\soap\ServiceManager.php on line 0

Prior to running this code, in php.ini, I uncommented the following line:
extension=php_soap.dll
and restarted apache
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

    <head>

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

        <title></title>

    </head>

    <body>

        <?php

         include_once "ServiceManager.php";



         $sm = new ServiceManager

            (

            $wsdl = "http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL",

            $options = array

                  (

                  'encoding'  => 'ISO-8859-1',

                  'exception' => True,

                  'trace'     => True,

                  )

            );

                  

         echo "Init Done";



        ?>

    </body>

</html>

Open in new window

0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Hmmmm...

Can you take out the $sm call?

So, just include the ServiceManager.php script.

0
 

Author Comment

by:caliea
Comment Utility
I ran the following code and it runs successfully.
End of Test message is displayed in the browser window
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title></title>
    </head>
    <body>
        <?php
         include_once "ServiceManager.php";
                  
         echo "End of Test";

        ?>
    </body>
</html>

Open in new window

0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
In my testing locally, it was all OK.

Can you check the SOAP ini settings : http://docs.php.net/manual/en/soap.configuration.php

0
 

Author Comment

by:caliea
Comment Utility
I disconnected the VPN client and am able to instantiate the ServiceManager Class.

Per Authentication requirement of the Service Provider from their documentation:
The userid and pw are passed to a web service through the web service header. In most cases the proxy generator should generate the "AuthenticationHeader" class from the wsdl specification and the developer should be able to set that header in the code. The XML payload of the authentication header is as follows:
<AuthenticationHeader xmlns="http://www.pininteract.com">
<userId>user123</userId>
<password>pass123</password>
</AuthenticationHeader>

So the SOAP header for each call needs to include the above payload.

In the manual approach that I was taking earlier, I was creating the XML (Envelope+Header+Body) as follows:
$xml = '
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:pin="http://www.pininteract.com">
<soap:Header>
<pin:AuthenticationHeader>
<pin:userId>user123</pin:userId>
<pin:password>pass123</pin:password>
</pin:AuthenticationHeader>
</soap:Header>
<soap:Body>
<pin:GetCarrierList>
<pin:version>1.0</pin:version>
</pin:GetCarrierList>
</soap:Body>
</soap:Envelope>
';

Using SoapUI and Wireshark, I verified that the Request was composed correctly and the expected response was coming back (the problem was that PHP was not processing the response).

Per one of your appends above, with the suggested method, we need to do the following:
$sm->xxx(yyy,zzz);
     
where xxx are methods for the service.

So how can I meet the Service Provider requirement of having the authentication header in the soap Header section for each Service Method Call ?
Thanks

0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
The class ServiceManager is a subclass of SoapClient.

SoapClient has a method called SoapClient::__setSoapHeaders (See : http://docs.php.net/manual/en/soapclient.setsoapheaders.php)

http://docs.php.net/manual/en/soapclient.setsoapheaders.php#93460 has some notes regarding a more complex usage.

I've not used SoapHeaders in my work. If you can give me a few minutes, I'll construct something for you to test.

0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
So, setting the header SHOULD be (see snippet).Once you've set the header, you should be able to make the xxxx calls.Hopefully something along the lines of (see snippet).UNTESTED!!!! May have typos - it is late for me (10 past midnight).Hopefully this will at least help you get some of the way.One thing that is different here is that the request/response are objects in their own right. I've always felt that that method was a bit cumbersome.So, you had to do ...$request = new request;$request->param1 = value1;$request->param2 = value2;$service->method($request);rather than ...$service->method(value1, value2);sort of thing.
<?php
include_once 'ServiceManager.php';

try
	{
	$sm = new ServiceManager
		(
		$wsdl = "http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL",
		$options = array
			(
			'encoding'  => 'ISO-8859-1',
			'exception' => True,
			'trace'     => True,
			)
		);
	
	$sm->__setSoapHeaders
		(
		new SOAPHeader
			(
			'http://pininteract.com',
			'AuthenticationHeader',
			array
				(
				'userId'   => 'user123',
				'password' => 'pass123',
				)
			)
		);

	$GCLRequest = new GetCarrierList;
	$GCLRequest->version = '1.0';

	$GCLResponse = $sm->GetCarrierList($GCLRequest);
	
	print_r($GCLResponse->carrierListResponse->carriers);
	}
catch(Exception $e)
	{
	die($e->getMessage());
	}
?>

Open in new window

0
 

Author Comment

by:caliea
Comment Utility
I tried the logic as per your append above and get an XML exception. Wireshark trace file review of the request and response shows an issue/problem with the XML header. Kindly take a look at the attached files:
test.php:  PHP program as per logic provided in you append above
test-original.php:  PHP program with the original logic that I was trying
wireshark-ReqResp.txt: Wireshark trace file showing the Request and Response packets obtained by running the above 2 test programs

In the test-original.php, I am creating the xml manually and the the correct response is coming back, however PHP is not being able to process it.
So using your technique, we need to make the XML request to be exactly the same as what is in the test-orignal.php and the wireshark trace file for the original test scenario.

The 2 PHP files have the valid userid and password, so you can run them in your environment to submit the requests.
Thankyou
test.php
test-original.php
wireshark-ReqResp.txt
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
http://docs.php.net/manual/en/soapheader.soapheader.php#88527 seems to comment on this specific issue. It seems .NET doesn't like to build from key/value pairings.

I'm not able to look any further on this until Tuesday (evening travelling, wedding tomorrow, recovery and travelling Monday - not my wedding, so you don't need to send a card or anything).


A simple class like ...

class AuthenticationHeader {
 public $userId = '123user';
 public $password = '123pass';
}

and then use ...

$sm->__setSoapHeaders
            (
            new SOAPHeader
                  (
                  'http://pininteract.com',
                  'AuthenticationHeader',
                  new AuthenticationHeader(),
                  false
                  )
            );

Maybe.

Please have a play with this. I may have some more time in a couple of hours ... sorry for dropping it for a few days.


If you don't get anywhere and need some more help, then certainly try the "Request Attention" option.
0
 

Author Comment

by:caliea
Comment Utility
Hi, Per your append above, I placed the following lines in ServiceManager.php:
class AuthenticationHeader {
  public $userid="ites";
  public $password="Vikram123";
}
 
In the php file, I did the following:
$sm->__setSoapHeaders
            (
            new SOAPHeader
                  (
                  'http://pininteract.com',
                  'AuthenticationHeader',
                  new AuthenticationHeader(),
                        false
                        )
            );

I still get and Exception message. In the Header, I see only the password field being passed. Given below is the information from the Wireshark trace:
POST /posaservice/servicemanager.asmx HTTP/1.1

Host: stage.valuetopup.com

Connection: Keep-Alive

User-Agent: PHP-SOAP/5.3.1

Content-Type: text/xml; charset=utf-8

SOAPAction: "http://www.pininteract.com/GetCarrierList"

Content-Length: 530



<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.pininteract.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://pininteract.com"><SOAP-ENV:Header><ns2:AuthenticationHeader xsi:type="ns1:AuthenticationHeader"><ns1:password>Vikram123</ns1:password></ns2:AuthenticationHeader></SOAP-ENV:Header><SOAP-ENV:Body><ns1:GetCarrierList><ns1:version>1.0</ns1:version></ns1:GetCarrierList></SOAP-ENV:Body></SOAP-ENV:Envelope>
HTTP/1.1 500 Internal Server Error

Date: Mon, 23 Aug 2010 04:28:47 GMT

Server: Microsoft-IIS/6.0

X-Powered-By: ASP.NET

X-AspNet-Version: 4.0.30319

Cache-Control: private

Content-Type: text/xml; charset=utf-8

Content-Length: 617



<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object.

   at ServiceManager.GetCarrierList(String version)

   --- End of inner exception stack trace ---</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>

0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Change $userid to $userId

Case sensitive I think.

0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Can you supply the working request (via wireshark) so I can see what is different.

The namespaces are not important (as far as I know), but they do need to point to the right place.
0
 

Author Comment

by:caliea
Comment Utility
I changed $userid to $userId, sorry for the mistake. Now I see both the userid and password being passed in the Request. However, the exception is still there.
Given below is the wireshark trace:
POST /posaservice/servicemanager.asmx HTTP/1.1

Host: stage.valuetopup.com

Connection: Keep-Alive

User-Agent: PHP-SOAP/5.3.1

Content-Type: text/xml; charset=utf-8

SOAPAction: "http://www.pininteract.com/GetCarrierList"

Content-Length: 559



<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.pininteract.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://pininteract.com"><SOAP-ENV:Header><ns2:AuthenticationHeader xsi:type="ns1:AuthenticationHeader"><ns1:userId>ites</ns1:userId><ns1:password>Vikram123</ns1:password></ns2:AuthenticationHeader></SOAP-ENV:Header><SOAP-ENV:Body><ns1:GetCarrierList><ns1:version>1.0</ns1:version></ns1:GetCarrierList></SOAP-ENV:Body></SOAP-ENV:Envelope>
HTTP/1.1 500 Internal Server Error

Date: Tue, 24 Aug 2010 15:15:42 GMT

Server: Microsoft-IIS/6.0

X-Powered-By: ASP.NET

X-AspNet-Version: 4.0.30319

Cache-Control: private

Content-Type: text/xml; charset=utf-8

Content-Length: 617



<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object.

   at ServiceManager.GetCarrierList(String version)

   --- End of inner exception stack trace ---</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>
0
 

Author Comment

by:caliea
Comment Utility
Given below is the wireshark trace of the scenario where I am manually composing the xml header in the PHP code - The expected response is coming back, however PHP is not processing it . One of the differences is that the Content-Type is specified as below:
Content-Type: application/soap+xml;charset=UTF-8;  (In the working case)
whereas it is text/xml in the above append.
Also, perhaps the namespace values could be an issue.


POST /posaservice/servicemanager.asmx HTTP/1.1

Accept-Encoding: gzip,deflate

Content-Type: application/soap+xml;charset=UTF-8;action="http://www.pininteract.com/GetCarrierList"

User-Agent: Jakarta Commons-HttpClient/3.1

Host: stage.valuetopup.com

Content-Length: 378




<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:pin="http://www.pininteract.com">
<soap:Header>
<pin:AuthenticationHeader>
<pin:userId>ites</pin:userId>
<pin:password>Vikram123</pin:password>
</pin:AuthenticationHeader>
</soap:Header>
<soap:Body>
<pin:GetCarrierList>
<pin:version>1.0</pin:version>
</pin:GetCarrierList>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK

Date: Tue, 24 Aug 2010 15:26:29 GMT

Server: Microsoft-IIS/6.0

X-Powered-By: ASP.NET

X-AspNet-Version: 4.0.30319

Cache-Control: private, max-age=0

Content-Type: application/soap+xml; charset=utf-8

Content-Length: 3543



<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetCarrierListResponse xmlns="http://www.pininteract.com"><carrierListResponse version="1.0" responseCode="000" xmlns="urn:pininteract.com"><carriers><carrier carrierId="8" carrierName="ATT" category="Pin" /><carrier carrierId="9" carrierName="Boost" category="Pin" /><carrier carrierId="11" carrierName="TMobile" category="Pin" /><carrier carrierId="12" carrierName="Verizon" category="Pin" /><carrier carrierId="13" carrierName="Airvoice" category="Pin" /><carrier carrierId="14" carrierName="Call Plus" category="Pin" /><carrier carrierId="15" carrierName="Omni" category="Pin" /><carrier carrierId="16" carrierName="Tracfone" category="Pin" /><carrier carrierId="17" carrierName="STI" category="Pin" /><carrier carrierId="19" carrierName="Page Plus" category="Pin" /><carrier carrierId="20" carrierName="Virgin Mobile" category="Pin" /><carrier carrierId="22" carrierName="Locus Platinum" category="Pin" /><carrier carrierId="23" carrierName="Oxygen" category="Pin" /><carrier carrierId="24" carrierName="Omobile" category="Pin" /><carrier carrierId="25" carrierName="Platinum Tel" category="Pin" /><carrier carrierId="26" carrierName="Net 10" category="Pin" /><carrier carrierId="27" carrierName="Tuyo" category="Pin" /><carrier carrierId="30" carrierName="Xtreme" category="Pin" /><carrier carrierId="31" carrierName="Bravo" category="Pin" /><carrier carrierId="35" carrierName="Movida" category="Pin" /><carrier carrierId="37" carrierName="Airtel India" category="Rtr" /><carrier carrierId="38" carrierName="Ufone Pakistan" category="Rtr" /><carrier carrierId="41" carrierName="Page Plus UNW" category="Pin" /><carrier carrierId="42" carrierName="Total Call" category="Pin" /><carrier carrierId="43" carrierName="Ready Mobile" category="Pin" /><carrier carrierId="44" carrierName="TelCel" category="Rtr" /><carrier carrierId="45" carrierName="Verizon Topup" category="Rtr" /><carrier carrierId="46" carrierName="Tigo Honduras" category="Pin" /><carrier carrierId="47" carrierName="Tigo Guatemala" category="Pin" /><carrier carrierId="48" carrierName="Cricket Paygo" category="Pin" /><carrier carrierId="49" carrierName="Express Airvoice" category="Pin" /><carrier carrierId="50" carrierName="Alltel" category="Pin" /><carrier carrierId="51" carrierName="Globe " category="Rtr" /><carrier carrierId="52" carrierName="TC Unlimited" category="Pin" /><carrier carrierId="53" carrierName="Airvoice Unlimited" category="Pin" /><carrier carrierId="54" carrierName="Powerlink Unlimited" category="Pin" /><carrier carrierId="55" carrierName="H20 Unlimited" category="Pin" /><carrier carrierId="56" carrierName="Digicel HAITI" category="Rtr" /><carrier carrierId="57" carrierName="Digicel JAMAICA" category="Rtr" /><carrier carrierId="58" carrierName="Digicel HONDURAS" category="Rtr" /><carrier carrierId="59" carrierName="Digicel GUYANA" category="Rtr" /><carrier carrierId="60" carrierName="Haiti - Voila" category="Rtr" /><carrier carrierId="61" carrierName="Simple Mobile" category="Pin" /><carrier carrierId="62" carrierName="Viva" category="Rtr" /><carrier carrierId="63" carrierName="Claro" category="Rtr" /><carrier carrierId="64" carrierName="Boost RTR" category="Rtr" /><carrier carrierId="65" carrierName="TM RTR" category="Rtr" /></carriers></carrierListResponse></GetCarrierListResponse></soap:Body></soap:Envelope>
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
http://docs.php.net/manual/en/book.soap.php#93888 gives a note regarding an error around the content type.

So, let's add the content type to the headers ... not sure how to do that with the normal kit as the content-type is text/xml ... hmmm


Probably not an issue. Can you change the SOAPHeader from http://pininteract.com to http://www.pininteract.com. They are the same in the working example.


.....


Ha! Just realised that the class AuthenticationHeader already exists in the wsdl2php output...

No need to redeclare it.

There is an error in the original code I used ...

new SOAPHeader
      (
      'http://www.pininteract.com',

and NOT

new SOAPHeader
      (
      'http://pininteract.com',



I've attached my latest test code to the snippet below.

The output is ...


Request Headers
---------------
POST /posaservice/servicemanager.asmx HTTP/1.1
Host: stage.valuetopup.com
Connection: Keep-Alive
User-Agent: PHP
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://www.pininteract.com/GetCarrierList"
Content-Length: 341


Request
-------
<?xml version="1.0" encoding="UTF-8"?>
1.0

Response Headers
----------------
HTTP/1.1 500 Internal Server Error
Date: Tue, 24 Aug 2010 23:03:10 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 4.0.30319
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Content-Length: 924

Response
--------
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault>soap:ServerSystem.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.ArgumentNullException: Value cannot be null.
Parameter name: username
   at System.Web.Util.SecUtility.CheckParameter(String&amp; param, Boolean checkForNull, Boolean checkIfEmpty, Boolean checkForCommas, Int32 maxSize, String paramName)
   at System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline)
   at Utility.Authenticate(String userId, String password)
   at ServiceManager.GetCarrierList(String version)
   --- End of inner exception stack trace ---</soap:Fault></soap:Body></soap:Envelope>

Exception
---------
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.ArgumentNullException: Value cannot be null.
Parameter name: username
   at System.Web.Util.SecUtility.CheckParameter(String& param, Boolean checkForNull, Boolean checkIfEmpty, Boolean checkForCommas, Int32 maxSize, String paramName)
   at System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline)
   at Utility.Authenticate(String userId, String password)
   at ServiceManager.GetCarrierList(String version)
   --- End of inner exception stack trace ---








The error is the validation of the username which is called from System.Web.Security.Membership.GetUser which is called from Utility.Authenticate and that is from ServiceManager.GetCarrierList.

Are you sure that the userId you've given me is accurate.



<?php

require_once 'ServiceManager.php';

$AuthenticationHeader = new AuthenticationHeader;
$AuthenticationHeader->userId="ites";
$AuthenticationHeader->password="Vikram123";

try
	{
	$sm = new ServiceManager
		(
		$wsdl = "http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL",
		$options = array
			(
			'encoding'  => 'ISO-8859-1',
			'exception' => True,
			'trace'     => True,
			)
		);
	
	$sm->__setSoapHeaders
		(
		new SOAPHeader
			(
			'http://www.pininteract.com',
			'AuthenticationHeader',
			new AuthenticationHeader
			)
		);

	$GCLRequest = new GetCarrierList;
	$GCLRequest->version = '1.0';

	$GCLResponse = $sm->GetCarrierList($GCLRequest);
	
	print_r($GCLResponse->carrierListResponse->carriers);
	}
catch(Exception $e)
	{
	echo 'Request Headers', PHP_EOL, '---------------', PHP_EOL, $sm->__getLastRequestHeaders(), PHP_EOL;
	echo 'Request', PHP_EOL, '-------', PHP_EOL, $sm->__getLastRequest(), PHP_EOL;
	echo 'Response Headers', PHP_EOL, '----------------', PHP_EOL, $sm->__getLastResponseHeaders(), PHP_EOL;
	echo 'Response', PHP_EOL, '--------', PHP_EOL, $sm->__getLastResponse(), PHP_EOL, PHP_EOL;
	echo 'Exception', PHP_EOL, '---------', PHP_EOL, $e->getMessage(), PHP_EOL;
	}

Open in new window

0
 

Author Comment

by:caliea
Comment Utility
1.
In the new SOAPHeader, I changed new(AuthenticationHeader) to $AuthenticationHeader and the userid & pw is getting passed.The correct Request is being generated and the expected response is coming back.
  In the wireshark trace, BEFORE the POST, I also see a GET message being sent. Why is the GET being sent ? Should this be a concern ? When the XML header is created manually (details in earlier appends), this GET is not there.

2.
Please provide pointers on how to process the Response. Given below is partial info from a response:
stdClass Object ( [carrier] => Array ( [0] => Carrier Object ( [carrierId] => 8 [carrierName] => ATT [category] => Pin ) [1] => Carrier Object ( [carrierId] => 9 [carrierName] => Boost [category] => Pin ) [2] => Carrier Object ( [carrierId] => 11 [carrierName] => TMobile [category] => Pin )

The information of interest in the above is: carrierid-8;  carrierName-ATT;   category-Pin

3.
For future WSDL's, I need to be in a position to be able to generate the ServiceManager.php on my own
 I came across the following link:
http://labs.wso2.org/wsf/php/wsdl2phptool.php

When I use the ServiceManager.php generated by the above link, I get a
Class 'WSClient' not found  error message.

Please advise on the best way to be able to generate the ServiceManager.php file.
Thankyou
0
 
LVL 40

Accepted Solution

by:
RQuadling earned 500 total points
Comment Utility
I downloaded the wsdl2php script from sourceforge. Fixed it a bit (all the patches are via RazorsEdgeUK).

Or use the attached code.

You then ...

wsdl2php.php http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL

And that produces the php script with the classes you need.


The WSO2 stuff is certainly an option. One that I've not gone down.


And once I made the change ... TA DA!!! It all worked!!!!

So, now to process the results...

print_r($GCLResponse);

shows an object which is an instance of ...

class GetCarrierListResponse {
  public $carrierListResponse; // CarrierListResponse
}

class CarrierListResponse {
  public $carriers; // ArrayOfCarrier
  public $version; // string
  public $responseCode; // string
}

class Carrier {
  public $carrierId; // int
  public $carrierName; // string
  public $category; // string
}

See the fully working code below.

It now outputs ...

ID :  8    Name : ATT                     Category : Pin
ID :  9    Name : Boost                   Category : Pin
ID : 11    Name : TMobile                 Category : Pin
ID : 12    Name : Verizon                 Category : Pin
ID : 13    Name : Airvoice                Category : Pin
ID : 14    Name : Call Plus               Category : Pin
ID : 15    Name : Omni                    Category : Pin
ID : 16    Name : Tracfone                Category : Pin
ID : 17    Name : STI                     Category : Pin
ID : 19    Name : Page Plus               Category : Pin
ID : 20    Name : Virgin Mobile           Category : Pin
ID : 22    Name : Locus Platinum          Category : Pin
ID : 23    Name : Oxygen                  Category : Pin
ID : 24    Name : Omobile                 Category : Pin
ID : 25    Name : Platinum Tel            Category : Pin
ID : 26    Name : Net 10                  Category : Pin
ID : 27    Name : Tuyo                    Category : Pin
ID : 30    Name : Xtreme                  Category : Pin
ID : 31    Name : Bravo                   Category : Pin
ID : 35    Name : Movida                  Category : Pin
ID : 37    Name : Airtel India            Category : Rtr
ID : 38    Name : Ufone Pakistan          Category : Rtr
ID : 41    Name : Page Plus UNW           Category : Pin
ID : 42    Name : Total Call              Category : Pin
ID : 43    Name : Ready Mobile            Category : Pin
ID : 44    Name : TelCel                  Category : Rtr
ID : 45    Name : Verizon Topup           Category : Rtr
ID : 46    Name : Tigo Honduras           Category : Pin
ID : 47    Name : Tigo Guatemala          Category : Pin
ID : 48    Name : Cricket Paygo           Category : Pin
ID : 49    Name : Express Airvoice        Category : Pin
ID : 50    Name : Alltel                  Category : Pin
ID : 51    Name : Globe                   Category : Rtr
ID : 52    Name : TC Unlimited            Category : Pin
ID : 53    Name : Airvoice Unlimited      Category : Pin
ID : 54    Name : Powerlink Unlimited     Category : Pin
ID : 55    Name : H20 Unlimited           Category : Pin
ID : 56    Name : Digicel HAITI           Category : Rtr
ID : 57    Name : Digicel JAMAICA         Category : Rtr
ID : 58    Name : Digicel HONDURAS        Category : Rtr
ID : 59    Name : Digicel GUYANA          Category : Rtr
ID : 60    Name : Haiti - Voila           Category : Rtr
ID : 61    Name : Simple Mobile           Category : Pin
ID : 62    Name : Viva                    Category : Rtr
ID : 63    Name : Claro                   Category : Rtr
ID : 64    Name : Boost RTR               Category : Rtr
ID : 65    Name : TM RTR                  Category : Rtr

(Better spacing).

BTW. I ran all this from the command line. You'd need to turn the output into a table.

You have to remember that arrays in SOAP are a class until themselves.

One could have expected ...

$GCLResponse->carrierListResponse->carriers

to be the array containing instances of Carrier, but it isn't.

$GCLResponse->carrierListResponse->carriers is of type ArrayOfCarriers.

So, $GCLResponse->carrierListResponse->carriers->carrier is the actual array of Carriers.

Slightly cumbersome, but once you see it, you can get it fairly easily.

This is commented in the classes I showed you above.



WOW.

What a question.

I'm really glad to have got this working for you.

Now I can incorporate this sort of work into my own code. Very useful!!!!

Thanks for the question.

Enjoy the answer.
<?php

require_once 'ServiceManager.php';

$AuthenticationHeader = new AuthenticationHeader;
$AuthenticationHeader->userId="ites";
$AuthenticationHeader->password="Vikram123";

try
        {
        $sm = new ServiceManager
                (
                $wsdl = "http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL",
                $options = array
                        (
                        'encoding'  => 'ISO-8859-1',
                        'exception' => True,
                        'trace'     => True,
                        )
                );
        
        $sm->__setSoapHeaders
                (
                new SOAPHeader
                        (
                        'http://www.pininteract.com',
                        'AuthenticationHeader',
                        $AuthenticationHeader
                        )
                );

        $GCLRequest = new GetCarrierList;
        $GCLRequest->version = '1.0';

        $GCLResponse = $sm->GetCarrierList($GCLRequest);
        
        foreach($GCLResponse->carrierListResponse->carriers->carrier as $Carrier)
        	{
        	echo
        		'ID : ', str_pad($Carrier->carrierId, 2, ' ', STR_PAD_LEFT),
        		"    Name : ", str_pad($Carrier->carrierName, 20),
        		"    Category : ", $Carrier->category,
        		PHP_EOL;
        	}
        }
catch(Exception $e)
        {
        echo 'Request Headers', PHP_EOL, '---------------', PHP_EOL, $sm->__getLastRequestHeaders(), PHP_EOL;
        echo 'Request', PHP_EOL, '-------', PHP_EOL, $sm->__getLastRequest(), PHP_EOL;
        echo 'Response Headers', PHP_EOL, '----------------', PHP_EOL, $sm->__getLastResponseHeaders(), PHP_EOL;
        echo 'Response', PHP_EOL, '--------', PHP_EOL, $sm->__getLastResponse(), PHP_EOL, PHP_EOL;
        echo 'Exception', PHP_EOL, '---------', PHP_EOL, $e->getMessage(), PHP_EOL;
        }

Open in new window

wsdl2php.php
0
 

Author Comment

by:caliea
Comment Utility
Thankyou for the solution, and I am glad that it will be useful for your work.

1.
 Please clarify the root cause of the issue. My understanding is that wsdl2php creates a local proxy / class, which are used by the client and facilitates the interaction with the Service Provider.
  The earlier approach that I was taking involved creating the XML manually, opening a socket connection to the service provider, do a post and process the response with fgets(). Per the wireshark trace, the request was being properly created and the expected response was coming back. So why does fgets() not process the response ? And why does wsdl2php based solution not have the issue that fgets() has ?

2.
At the command prompt on my WinXP system, I typed the following:
wsdl2php.php http://stage.valuetopup.com/posaservice/servicemanager.asmx?WSDL
and Microsoft Expression Web, which is installed on the system, starts up and loads the php file.

I then loaded the wsdl2php.php file into Netbeans and could not find the way to specify the WSDL as a parameter.

Please advise.
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
1 - You were not detecting the end of transmission appropriately. But also, in general, you were doing things the hard way. The very very VERY hard way.

The wsdl2php solution just produces a set of classes which utilises the SoapClient class built into PHP. The wsdl2php script doesn't actually communicate with the service. It just uses a URL parameter to read the WSDL file. From there it is just plain text and xml manipulation.


2 - You will need to have PHP installed and accessible via the command line.

Read the following manual pages

http://docs.php.net/manual/en/install.windows.manual.php
http://docs.php.net/manual/en/install.windows.commandline.php <<<< VERY IMPORTANT ONE!!!

The wsdl2php script is a command line script. You supply the WSDL url to the command line.

wsdl2php URL

0
 

Author Comment

by:caliea
Comment Utility
Yes, the technique taught by you is what I will be using in my current and future work related to Web Services development in the PHP environment.

 For future reference, could you briefly explain why fgets() was not detecting the end of transmission appropriately. For file i/o it seems to work fine.However, per your above append there seems to be issue with fgets() when used with socket i/o.

Thankyou very much for your time and effort and I am ready to close this issue. For future questions on this topic is it possible to specifically specify your userid in order to request your assistance while opening a query/question ?

0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
Not 100% on this.

I wonder if an EOF is being sent or if the socket is being closed by the remote server.

If neither of these happen, then the fgets() will sit there waiting until it can read all the bytes it has been asked to read.

If there is nothing coming down the pipe, then it just sits there.

You could prove this by fgets() 1 character at a time and echoing it.

See what is the last character you receive.

Compare that with what is happening in WireShark with regard to the communication (being closed).
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
I'm watching the SOAP topic area and I watch the PHP ones too. So if you have a question, I should see it. Others may answer it though. It's all good!

Ray Paseur is a top expert, so what he says would be good too. And we have different opinions on web services - he prefers RESTful interfaces. I prefer SOAP. Both have +ve/-ves. It'll be upto you to decide which you want/need.
0
 

Author Closing Comment

by:caliea
Comment Utility
Thankyou for providing a solution to this issue. Your explanations, support and response time were exceptionally good.
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
fgets() is a blocking call. If there is no data to read it waits.

fread() is the one to use.

But you won't be doing that now though, will you ... ;-)

Good question. Glad to have helped AND learn at the same time.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Shoutout to Emily Plummer (http://www.experts-exchange.com/members/eplummer26.html) for giving me this article! She did most of it, I just finished it up and posted it for her :)    Introduction In a previous article (http://www.experts-exchang…
These days socially coordinated efforts have turned into a critical requirement for enterprises.
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now