My first web service Client

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
marty pain
Forum Contributor
Posts: 105
Joined: Thu Jun 11, 2009 5:32 am
Location: Essex

My first web service Client

Post by marty pain »

This week my bosses have decided we have to change our entire product so that it just queries a web service ( :banghead: ) and as I don't know anyone who even knows what a web service is ( :crazy: ) and it has to be completed by tomorrow I'm back on here asking questions.

Basically the main question I have is, what tools should I use? I know this has been asked a number of time on here (I think I've read a million posts this morning) but the answers always seem a little vague.

To help things along here's the situation. I will have to query a .NET WSDL web service which has not been built yet, but some test ideas were/will be available for test connections

I have tried the following, all with varied results.

cURL -> Was nice and easy when connecting to a third party service but the service I am connecting to requires the header M-POST and it all got complicated.
PHP SOAP Library -> Connected to the service and got a huge nested object in return, which is basically unusable.
PEAR-SOAP -> Have not yet tried this, but hear it's pretty much been depreciated due to the SOAP library.
Nu-SOAP -> Read about this in an old book, is it even worth looking at or has it died a death?

Which one of these is the standard? Should I just look at using a framework to make my life easy?

One last question, the web service name dosen't end with .wsdl. Does this make a difference to PHP?

Thanks for reading. Any nudge in the right direction would be helpful

EDIT: Just found WSF/PHP. Is this in common usage, or should I stick to something like cakePHP/Zend/Symphony and such?
dejvos
Forum Contributor
Posts: 122
Joined: Tue Mar 10, 2009 8:40 am

Re: My first web service Client

Post by dejvos »

Hi,

I use PEAR_SOAP library. It's very easy to use. The next, I have read a lot of good about Nu-SOAP but I don't have an experience with it.

With the question what is standard?
Web Services
Standard is SOAP for messages and WSDL to description of services. So appendix .wsdl should contain information about a service. The tool doesn't metter in question of standard.
ell0bo
Forum Commoner
Posts: 79
Joined: Wed Aug 13, 2008 4:15 pm

Re: My first web service Client

Post by ell0bo »

Personally, I use the built in soap client that comes with PHP. I find it relatively simple to use. The hardest part is writing the actual SOAP WSDL file. You have to do this all in one day, man I'm sorry to hear that. I'll be around if you need help.
marty pain
Forum Contributor
Posts: 105
Joined: Thu Jun 11, 2009 5:32 am
Location: Essex

Re: My first web service Client

Post by marty pain »

Thanks all. After a mad google session I think I'll either use the build in support or the Zend Framework. Probably will go for soapClient as I guess it will be lighter, and this thing is going to run real slow now.
You have to do this all in one day, man I'm sorry to hear that. I'll be around if you need help.
Thanks mate! It's only the client so shouldn't be too hard, already have a working example using the built in soapClient, just need to link the output to a custom class I guess. The Web Service hasn't even been written yet, but thankfully I'm not doing that. The server is being done in .NET by other people so the wsdl file is their worry.
ell0bo
Forum Commoner
Posts: 79
Joined: Wed Aug 13, 2008 4:15 pm

Re: My first web service Client

Post by ell0bo »

Actually... let me try to be a little more useful to start. I really should start a blog with stuff like this... Let me give you an example of a SOAP client and a SOAP server.

SOAP client:

Code: Select all

$client = new SoapClient("https://localhost/OrderService.php?WSDL");

$send = array(
			'batchID' => '',
			'customerRequestID' => $FILE_NAME,
			'orderStatus' => '',
			'orders' => $t,
			'password' => $password,
			'username' => $username,
		);

$res = $client->__soapCall("OrderEntry", array(array('Request' => $send)) );
// your could also do $res = $client->OrderEntry(array('Request' => $send)); but I still do it the old way

return ( $res->OrderEntryReturn->orderStatus == 10 );
Dummy SOAP server:

function OrderEntry($data){
$data = $data->Request;

$pwd = $data->password;
$uname = $data->username;
$batchId = $data->batchID;
$custID = $data->customerRequestID;
$ostat = $data->orderStatus;

$return->batchID = 'batch this';
$return->customerRequestID = 'some string 2';
$return->orderStatus = 10;

$response->OrderEntryReturn = $return;

return $response;
}

function Noop($data){
$data = $data->Noop;

$response->NoopResponse->NoopReturn = 'I Can Haz Cheezburger?';

return $response;
}
// this is a hack, there is some kung fu going on here which I don't want you to understand, but trust me
$server = new SoapServer('OrderEntrService.wsdl');
$server->addFunction('OrderEntry');
$server->addFunction('Noop');
$server->handle();

And now an example WSDL file for that...

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

<wsdl:definitions targetNamespace="http://soap.service.com" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://soap.service.pitney.com" xmlns:intf="http://soap.service.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<wsdl:types>
<schema elementFormDefault="qualified" targetNamespace="http://soap.service.com" xmlns="http://www.w3.org/2001/XMLSchema">
<element name="OrderEntry">
<complexType>
<sequence>
<element name="Request" type="impl:Request"/>
</sequence>
</complexType>
</element>
<complexType name="Request">
<sequence>
<element name="batchID" nillable="true" type="xsd:string"/>
<element name="customerRequestID" nillable="true" type="xsd:string"/>
<element name="orderStatus" nillable="true" type="xsd:string"/>
<element name="password" nillable="true" type="xsd:string"/>
<element name="username" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<element name="OrderEntryResponse">
<complexType>
<sequence>
<element name="OrderEntryReturn" type="impl:OrderEntryReturn"/>
</sequence>
</complexType>
</element>
<complexType name="OrderEntryReturn">
<sequence>
<element name="batchID" nillable="true" type="xsd:string"/>
<element name="customerRequestID" nillable="true" type="xsd:string"/>
<element name="orderStatus" nillable="true" type="xsd:string"/>
<element name="orders" nillable="true" type="impl:ArrayOfOrder"/>
</sequence>
</complexType>
<element name="Noop">
<complexType>
<sequence>
<element name="Noop" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="NoopResponse">
<complexType>
<sequence>
<element name="NoopReturn" type="xsd:string"/>
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>

<wsdl:message name="NoopResponse">
<wsdl:part element="impl:NoopResponse" name="parameters"/>
</wsdl:message>

<wsdl:message name="NoopRequest">
<wsdl:part element="impl:Noop" name="parameters"/>
</wsdl:message>

<wsdl:message name="OrderEntryResponse">
<wsdl:part element="impl:OrderEntryResponse" name="parameters"/>
</wsdl:message>

<wsdl:message name="OrderEntryRequest">
<wsdl:part element="impl:OrderEntry" name="parameters"/>
</wsdl:message>

<wsdl:portType name="OrderEntrServicePortType">
<wsdl:operation name="OrderEntry">
<wsdl:input message="impl:OrderEntryRequest" name="OrderEntryRequest"/>
<wsdl:output message="impl:OrderEntryResponse" name="OrderEntryResponse"/>
</wsdl:operation>
<wsdl:operation name="Noop">
<wsdl:input message="impl:NoopRequest" name="NoopRequest"/>
<wsdl:output message="impl:NoopResponse" name="NoopResponse"/>
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name="OrderEntrServiceBinding" type="impl:OrderEntrServicePortType">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="OrderEntry">
<wsdlsoap:operation soapAction="OrderEntry"/>
<wsdl:input name="OrderEntryRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="OrderEntryResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Noop">
<wsdlsoap:operation soapAction="Noop"/>
<wsdl:input name="NoopRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="NoopResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name="OrderEntrServiceService">
<wsdl:port binding="impl:OrderEntrServiceBinding" name="OrderEntrServicePort">
<wsdlsoap:address location="https://localhost/OrderService.php"/>
</wsdl:port>
</wsdl:service>

</wsdl:definitions>


Admittedly... I had to cut this down, but it should help you out.
marty pain
Forum Contributor
Posts: 105
Joined: Thu Jun 11, 2009 5:32 am
Location: Essex

Re: My first web service Client

Post by marty pain »

Nice one mate! I'll have a crack at building a simple reflection service when I get home, suppose it would be good to learn both side whilst I'm at it.

Excellent example, thanks again!
marty pain
Forum Contributor
Posts: 105
Joined: Thu Jun 11, 2009 5:32 am
Location: Essex

Re: My first web service Client

Post by marty pain »

Hi all,

OK, they have finally put up a test web service for us to query, and the basic client works, but I have a question regarding the returned information.

All the information is in a collection of nested (standard) objects, not dis-similar to a simple XML object I guess. Is there anyway to automatically parse/cast this to a non-generic glass of my choosing? Again, if so what tools are you using to do it?

Thanks!
ell0bo
Forum Commoner
Posts: 79
Joined: Wed Aug 13, 2008 4:15 pm

Re: My first web service Client

Post by ell0bo »

I don't have the time to look into this to make sure I'm 100% here, but I don't think there is. You can configure the client to pass back an object or an array, but I don't think you can configure it to pass back a object of a specific class. The best thing to do would build a class capable of consuming the object the client tosses back and using that to populate the private data of your class. Just then write methods to do this.

I wouldn't be shocked if there is a way to automate that process, however I don't know it off the top of my head.
marty pain
Forum Contributor
Posts: 105
Joined: Thu Jun 11, 2009 5:32 am
Location: Essex

Re: My first web service Client

Post by marty pain »

Hi all.

OK, the next hurdle. The web service I have to work with has now been created. I have written a script to use the thing but I'm getting some very odd results.

I have spoken to the people who wrote it and they have tested it in .NET and Java and say it works fine. When I try to use it in PHP I can create a SoapClient using the WSDL and can use the __getFunctions() method to show the three available functions. When I try to call one of the functions a SOAPFault exception is returned saying "Looks like we don't have an XML document" (or words to that effect).

After a bit of a read I learnt how to set trace and turned the exceptions off, and got a suprise. The service is returning an HTML web page.

The only thing I can think of is that PHP is not interpreting the WSDL correctly. the WSDL is here:
http://svr04.xreservations.com/TravelSy ... Proxy.wsdl

and here is my code (minus the actual arguments)

Code: Select all

<?php
        $client = new SoapClient("http://svr04.xreservations.com/TravelSystemOne/RedBackProxy.wsdl",array('trace'=>1,'exceptions'=>0));

        echo "<pre>";
        print_r($client->__getFunctions());
        echo "</pre>";

        $params = array();
        $params['RBOServer'] = "";
        $params['RBOModule'] = "";
        $params['RBOClass'] = "";
        $client->getRBOSchema($params);

        //var_dump($client->__getLastRequest());
        //var_dump($client->__getLastResponseHeaders());
        var_dump($client->__getLastResponse());


?>
Again, any help appreciated here!
ell0bo
Forum Commoner
Posts: 79
Joined: Wed Aug 13, 2008 4:15 pm

Re: My first web service Client

Post by ell0bo »

Well... the web service is returning a web page, then the odds are your problem is at the server's side. What language is the web service server written in? .NET doesn't always like to play nice.

Also, I'm unable to access the WSDL file so I can't really help you out too much.

What sort of web page is being returned?

I would work with the team on the other side, and have them monitor the access logs. When you fire off your service, have them watch what pages or end points you're hitting.

I'm currently moving to Philadelphia, so I won't be around too much this week to help, but I'll try to check back and give you a hand if possible.
marty pain
Forum Contributor
Posts: 105
Joined: Thu Jun 11, 2009 5:32 am
Location: Essex

Re: My first web service Client

Post by marty pain »

I'm currently moving to Philadelphia, so I won't be around too much this week to help, but I'll try to check back and give you a hand if possible.
Thanks again mate, and good luck with the move! I have been told that the service was written in Java, and judging by some of the errors I have been getting back I believe them. Sorry about the wsdl link. I found that it’s fire-walled so only we can access it.

I have had some progress. To be honest I'd be lying if I said I understood what the problem was, but I'll (try to) explain it none the less.

The wsdl URL used ?wdsl on the end. When you viewed that location in Firefox it redirected the page to a slightly different URL, where it displayed the XML as if it had no format information, like Firefox does. To get this to work in PHP I was using the wsdl as above, with .wsdl as the ?wsdl didn't work.

When you viewed the .wsdl location in Firefox the text was not being formatted as XML, as if Firefox didn't recognise it as XML (it didn't say there is no format information for this file).

So, to get this to work I used the location that the ?wsdl URL redirected me to. I have tried this in the past, but it didn't work before so I can only assume that was due to either the wsdl cache (Which I have turned off for the time being), or something their end has changed.

If anyone understands what was going on, please let me know!
Post Reply