php soap client for uk mail webservice api?

Introduction

Obviously, documentation is missing here. Unfortunately, $soapClient->__getTypes() doesn't tell much. It only shows available complex types supported by a web service, but it doesn't show us the relationship among them. Even if You have a list of all available operations with their input and output types returned by $soapClient->__getFunctions(), there is no guarantee You can proceed without knowing the exact nature of the complex types or without having any kind of documentation. But fortunately, this is a SOAP-based web service that provides a WSDL document. The WSDL document describes all the supported operations and complex types, as well as their relationships. So, we can figure out how to use the service by only examining the WSDL document.

There are two ways of examining the WSDL document:

  1. generate artifacts (client classes) from the WSDL document and examine the artifacts
  2. look through the WSDL document and the XML Schema documents.

1. Artifacts

The artifacts can be generated by tools provided by the strong typed languages like Java or C#. The https://qa-api.ukmail.com/Services/UKMAuthenticationServices/ page suggests to use the svcutil.exe tool to generate the artifacts for the C# programming language, or You can also use the wsimport tool to generate the artifacts for the Java programming language. I doubt that there can be any good tool for generating the artifacts for the PHP programming language.

2. WSDL document and XML Schemas

If You're not familiar with C# or Java, You can always examine the WSDL document by looking through it and the XML Schemas. The XML Schemas can be included in the WSDL document or imported from an external file. While the WSDL document describes the operations that can be performed on the web service, the XML Schemas describe the complex types and their relationships.

Action

I wrote the Introduction part so that You know how to do it on Your own. Below I want to show an example of it. For the purpose of examining the WSDL document I used both ways. First I generated the artifacts using the wsimport tool, then I read a lot of XML.

The WSDL document for this service is divided into several files using import statements. So, in order to find all the operations and complex types You have to follow the import statements.

Authentication

If We look at the Authentication Service's WSDL document (location), We can see that it imports another WSDL document:

<wsdl:import namespace="http://tempuri.org/" location="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl=wsdl1"/>

The latter (location), in its turn, imports another one:

<wsdl:import namespace="http://www.UKMail.com/Services/Contracts/ServiceContracts" location="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl=wsdl0"/>

The final one (location), imports all the related XML Schemas:

<wsdl:types>
  <xsd:schema targetNamespace="http://www.UKMail.com/Services/Contracts/ServiceContracts/Imports">
    <xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd0" namespace="http://www.UKMail.com/Services/Contracts/ServiceContracts"/>
    <xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
    <xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd2" namespace="http://www.UKMail.com/Services/Contracts/DataContracts"/>
    <xsd:import schemaLocation="https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?xsd=xsd3" namespace="http://schemas.datacontract.org/2004/07/UKMWebAPICommon.WebResponses"/>
  </xsd:schema>
</wsdl:types>

It also describes the operations which can also be viewed by calling $soapClient->__getFunctions():

Array
(
    [0] => LoginResponse Login(Login $parameters)
    [1] => LogoutResponse Logout(Logout $parameters)
)

Here, We see that the Login() operation accepts $parameters of type Login as its argument and returns a response of type LoginResponse. This is how it looks in the WSDL document:

<wsdl:operation name="Login">
  <wsdl:input wsaw:Action="http://www.UKMail.com/Services/IUKMAuthenticationService/Login" message="tns:IUKMAuthenticationService_Login_InputMessage"/>
  <wsdl:output wsaw:Action="http://www.UKMail.com/Services/Contracts/ServiceContracts/IUKMAuthenticationService/LoginResponse" message="tns:IUKMAuthenticationService_Login_OutputMessage"/>
</wsdl:operation>

Login is a complex type, this can be seen in one of the imported XML Schema documents (schemaLocation):

<xs:element name="Login">
  <xs:complexType>
    <xs:sequence>
      <xs:element xmlns:q1="http://www.UKMail.com/Services/Contracts/DataContracts" minOccurs="0" name="loginWebRequest" nillable="true" type="q1:LoginWebRequest"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

It has an element named loginWebRequest which is also a complex type called LoginWebRequest which is described in another imported XML Schema:

<xs:complexType name="LoginWebRequest">
  <xs:sequence>
    <xs:element name="Password" nillable="true" type="xs:string"/>
    <xs:element name="Username" nillable="true" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

LoginWebRequest is simpler. It has two simple types Username and Password of type String.

In PHP complex types are represented by objects of stdClass. So, in order to call the Login() operation, We have to create two objects Login and LoginWebRequest:

$LoginWebRequest = new stdClass();
$LoginWebRequest->Username = 'Username';
$LoginWebRequest->Password = 'p@$$w0rd';

$Login = new stdClass();
$Login->loginWebRequest = $LoginWebRequest;

$soapClient = new SoapClient('https://qa-api.ukmail.com/Services/UKMAuthenticationServices/UKMAuthenticationService.svc?wsdl');
$LoginResponse = $soapClient->Login($Login);

This gives us a result of type LoginResponse:

<xs:element name="LoginResponse">
  <xs:complexType>
    <xs:sequence>
      <xs:element xmlns:q2="http://www.UKMail.com/Services/Contracts/DataContracts" minOccurs="0" name="LoginResult" nillable="true" type="q2:UKMLoginResponse"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

, which contains an element named LoginResult which has a type of UKMLoginResponse:

<xs:complexType name="UKMLoginResponse">
  <xs:complexContent mixed="false">
    <xs:extension base="tns:UKMWebResponse">
      <xs:sequence>
        <xs:element minOccurs="0" name="Accounts" nillable="true" type="tns:ArrayOfAccountWebModel"/>
        <xs:element name="AuthenticationToken" nillable="true" type="xs:string"/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

UKMLoginResponse has two elements of its own Accounts of type ArrayOfAccountWebModel and AuthenticationToken of type String and three more elements inhereted from UKMWebResponse (note the extension statement) Errors of type ArrayOfUKMWebError, Warnings of type ArrayOfUKMWebWarning and Result of type UKMResultState:

<xs:complexType name="UKMWebResponse">
  <xs:sequence>
    <xs:element minOccurs="0" name="Errors" nillable="true" type="tns:ArrayOfUKMWebError"/>
    <xs:element xmlns:q1="http://schemas.datacontract.org/2004/07/UKMWebAPICommon.WebResponses" name="Result" type="q1:UKMResultState"/>
    <xs:element minOccurs="0" name="Warnings" nillable="true" type="tns:ArrayOfUKMWebWarning"/>
  </xs:sequence>
</xs:complexType>

In the artifacts generated by the wsimport tool it looks like this:

public class UKMLoginResponse extends UKMWebResponse { ... }

So, in order to get the authentication token from the LoginResponse, we do the following:

$LoginResponse = $soapClient->Login($Login);
$AuthenticationToken = $LoginResponse->LoginResult->AuthenticationToken;

Calling a method

I won't be very specific here, because it's very similar to what we did above.

As an example, let's call a AddDomesticConsignment() method. According to the WSDL document of the Consignment Service and the result returned by $soapClient->__getFunctions() the AddDomesticConsignment() method takes one $parameters argument of type AddDomesticConsignment and returns a result of type AddDomesticConsignmentResponse. By analyzing the AddDomesticConsignment complex type, we see that it has an element named request of type AddDomesticConsignmentWebRequest which extends AddConsignmentWebRequest which itself extends WebRequest. Following is the list of all of the elements of the AddDomesticConsignmentWebRequest type:

// AddDomesticConsignmentWebRequest's own elements
boolean BookIn
decimal CODAmount
string ConfirmationEmail
string ConfirmationTelephone
boolean ExchangeOnDelivery
int ExtendedCover
boolean LongLength
PreDeliveryNotificationType PreDeliveryNotification
string SecureLocation1
string SecureLocation2
boolean SignatureOptional

// elements inhereted from AddConsignmentWebRequest
string AccountNumber
AddressWebModel Address
string AlternativeRef
string BusinessName
string CollectionJobNumber
boolean ConfirmationOfDelivery
string ContactName
string CustomersRef
string Email
int Items
int ServiceKey
string SpecialInstructions1
string SpecialInstructions2
string Telephone
decimal Weight

// elements inhereted from WebRequest
string Username
string AuthenticationToken

Note that not all of the elements are required. Those which are optional have the minOccurs attribute set to 0 in the XML Schema.

<xs:element minOccurs="0" name="PreDeliveryNotification" type="tns:PreDeliveryNotificationType"/>

So, eventually this is how We call the method:

$AddDomesticConsignmentWebRequest = new stdClass();
$AddDomesticConsignmentWebRequest->Username = 'Username';
// setting the Authentication Token from the previous step
$AddDomesticConsignmentWebRequest->AuthenticationToken = $AuthenticationToken;
// other properties are set here...

$AddDomesticConsignment = new stdClass();
$AddDomesticConsignment->request = $AddDomesticConsignmentWebRequest;

$soapClient = new SoapClient('https://qa-api.ukmail.com/Services/UKMConsignmentServices/UKMConsignmentService.svc?wsdl');
$AddDomesticConsignmentResponse = $soapClient->AddDomesticConsignment($AddDomesticConsignment);

The AddDomesticConsignmentResponse is parsed as We parsed the LoginResponse according to its definition in the XML Schema document.

Well, I guess this is all to it. I didn't try it myself, but in theory it should work. Hope this helps.

UPDATE

According to the documentation tracking the consignment should be as easy as doing the following:

// create the SOAP client
$soapClient = new SoapClient('http://web-service/?wsdl');
// call the `ConsignmentTrackingSearchV1` method and pass the search parameters
$ConsignmentTrackingSearchV1Response = $soapClient->ConsignmentTrackingSearchV1(
    'mail.com', // Username
    '123',      // Password
    '',         // Token
    '01161',    // ConsignmentNumber
    'false',    // IsPartialConsignmentNumber
    '',         // CustomerReference
    'false'     // IsPartialCustomerReference
    '',         // DeliveryPostCode
    '',         // MailingID
    100         // MaxResults
);
// parse the response
$ConsignmentTrackingSearchV1Result = $ConsignmentTrackingSearchV1Response->ConsignmentTrackingSearchV1Result;
$ResultState = $ConsignmentTrackingSearchV1Result->ResultState; // Successful
$ConsignmentResults = $ConsignmentTrackingSearchV1Result->ConsignmentResults;
// loop through the `ConsignmentResults`
foreach ($ConsignmentResults as $ConsignmentSearchResult) {
    $ConsignmentNumber = $ConsignmentSearchResult->ConsignmentNumber;
    $ConsignmentStatus = $ConsignmentSearchResult->ConsignmentStatus;
    // other properties
}

That's it!


Well Mr zafarkhaja helped me a lot but for others like me i will like to explain what worked for me so that might be helpfull to others too in future ..

For dealing with complex types For Example Like in my Uk Mail Api For login i did this

$LoginWebRequest = new stdClass();
$LoginWebRequest->Username = 'username';
$LoginWebRequest->Password = 'password';



$Login = new stdClass();
$Login->loginWebRequest = $LoginWebRequest;



$soapClient = new SoapClient('somewsdl?wsdl', array('cache_wsdl' => WSDL_CACHE_NONE) );


$LoginResponse = $soapClient->Login($Login);

and hurray i could login . it gave me a response which i needed to retreive

 $AuthenticationToken = $LoginResponse->LoginResult->AuthenticationToken; 

and i got the auth token well sure you can change parameters according to your webservice

Well using a soap Client When You are not dealing with complex type

   $soapClient = new SoapClient('http://somewsdl?wsdl');

    //create an array whose valuse will be passed has parameters
          $input_array = array (   
               UserName => 'username',
               Password => 'password'

     ) ;

    // passes our array
    $ConsignmentResponse = $soapClient1->TrackingSearch($input_array);

  //retrieve the response like this 

    $ResultState =  $ConsignmentResponse->ResultState; // Successful

Well i searched everwhere but no one had posted any working example well all the code works for me in php soap 1.1 with both complex type and without .