PHP Soap Client for Uk Mail Webservice API

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!

Processing / Servicing a SOAP request in PHP

have a look at this answer - php soap client for uk mail webservice api?

as well as the following links:

  • http://devzone.zend.com/article/689
  • http://www.codewalkers.com/c/a/Miscellaneous/Using-SOAP-with-PHP/
  • http://www.packtpub.com/article/soap-and-php-5

you can find more in at this question: PHP SOAP tutorial?

PHP SOAP - Could not connect to host error message (Royal Mail Shipping API integration)

SOAP connection with Royal Mail, Could not connect to host
I'm using the code in my answer and it works, if you keep having problem with that code call royal mail and ask to test in the live server, some timer they have problems with the onboarding.

SOAP request in PHP with CURL

Tested and working!

  • with https, user & password

     <?php 
    //Data, connection, auth
    $dataFromTheForm = $_POST['fieldName']; // request data from the form
    $soapUrl = "https://connecting.website.com/soap.asmx?op=DoSomething"; // asmx URL of WSDL
    $soapUser = "username"; // username
    $soapPassword = "password"; // password

    // xml post structure

    $xml_post_string = '<?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
    <GetItemPrice xmlns="http://connecting.website.com/WSDL_Service"> // xmlns value to be set to your WSDL URL
    <PRICE>'.$dataFromTheForm.'</PRICE>
    </GetItemPrice >
    </soap:Body>
    </soap:Envelope>'; // data from the form, e.g. some ID number

    $headers = array(
    "Content-type: text/xml;charset=\"utf-8\"",
    "Accept: text/xml",
    "Cache-Control: no-cache",
    "Pragma: no-cache",
    "SOAPAction: http://connecting.website.com/WSDL_Service/GetPrice",
    "Content-length: ".strlen($xml_post_string),
    ); //SOAPAction: your op URL

    $url = $soapUrl;

    // PHP cURL for https connection with auth
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string); // the SOAP request
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    // converting
    $response = curl_exec($ch);
    curl_close($ch);

    // converting
    $response1 = str_replace("<soap:Body>","",$response);
    $response2 = str_replace("</soap:Body>","",$response1);

    // convertingc to XML
    $parser = simplexml_load_string($response2);
    // user $parser to get your data out of XML response and to display it.
    ?>

PHP SOAP client not sending parameters when calling function

From the comments, now that you've got the WSDL I see this in it:

<xsd:element name="Authenticate">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="loginName" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="password" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

So you could try this for your auth:

$resp = $client->Authenticate(array("loginName"=> $username, "password" => $password));

Of course you'll need to supply a valid $username and $password to that service, though.

How do I send XML data to an API via SOAP in PHP?

Try this with your valid credentials :

<?php
define('REEF_USERNAME','YOUR_VALID_USERNAME');
define('REEF_PASSWORD','YOUR_VALID_PASSWORD');

$URL = 'http://www.reefservices.co.uk/leadws/lead.asmx';

function createRequestXML($params = array()) {
$DealerCode = (array_key_exists('DealerCode',$params)) ? $params['DealerCode'] : 2603; // required
$LeadType = (array_key_exists('LeadType',$params)) ? $params['LeadType'] : 'Used Car Enquiry'; // required
$LeadSource = (array_key_exists('LeadSource',$params)) ? $params['LeadSource'] : 'Website'; // required
$LeadId = (array_key_exists('LeadId',$params)) ? $params['LeadId'] : 'Null'; // not required
$CustomerType = (array_key_exists('CustomerType',$params)) ? $params['CustomerType'] : 1; // required. can be : 0 for Company, 1 for Individual
$Title = (array_key_exists('Title',$params)) ? $params['Title'] : 'Null'; // not required
$Forename = (array_key_exists('Forename',$params)) ? $params['Forename'] : 'Ben'; // required
$Lastname = (array_key_exists('Lastname',$params)) ? $params['Lastname'] : 'Thomas'; // required
$Companyname = (array_key_exists('Companyname',$params)) ? $params['Companyname'] : 'Null'; // not required

/* One of the following fields is required to have a value */
$Homephone = (array_key_exists('Homephone',$params)) ? $params['Homephone'] : 'Null';
$Workphone = (array_key_exists('Workphone',$params)) ? $params['Workphone'] : 'Null';
$Mobilephone = (array_key_exists('Mobilephone',$params)) ? $params['Mobilephone'] : 'Null';
$Email = (array_key_exists('Email',$params)) ? $params['Email'] : 'aa@test.com';
/* One of the above fields is required to have a value */

$Address1 = (array_key_exists('Address1',$params)) ? $params['Address1'] : 'Null'; // not required
$Address2 = (array_key_exists('Address2',$params)) ? $params['Address2'] : 'Null'; // not required
$City = (array_key_exists('City',$params)) ? $params['City'] : 'Null'; // not required
$County = (array_key_exists('County',$params)) ? $params['County'] : 'Null'; // not required
$Postcode = (array_key_exists('Postcode',$params)) ? $params['Postcode'] : 'Null'; // not required

$dpapostal = (array_key_exists('dpapostal',$params)) ? $params['dpapostal'] : 'Y'; // required. can be Y/N
$dpasms = (array_key_exists('dpasms',$params)) ? $params['dpasms'] : 'Y'; // required. can be Y/N
$dpstel = (array_key_exists('dpstel',$params)) ? $params['dpstel'] : 'Y'; // required. can be Y/N
$dpaemail = (array_key_exists('dpaemail',$params)) ? $params['dpaemail'] : 'Y'; // required. can be Y/N

$Methodofcontact = (array_key_exists('Methodofcontact',$params)) ? $params['Methodofcontact'] : 'Null'; // not required
$Sourceofenquiry = (array_key_exists('Sourceofenquiry',$params)) ? $params['Sourceofenquiry'] : 'Null'; // not required

$Message = (array_key_exists('Message',$params)) ? $params['Message'] : 'Null'; // not required

$Regno = (array_key_exists('Regno',$params)) ? $params['Regno'] : 'Null'; // not required
$Newused = (array_key_exists('Newused',$params)) ? $params['Newused'] : 'Null'; // not required. can be "NEW"/"USED"
$Make = (array_key_exists('Make',$params)) ? $params['Make'] : 'Null'; // not required
$Model = (array_key_exists('Model',$params)) ? $params['Model'] : 'Null'; // not required
$Derivative = (array_key_exists('Derivative',$params)) ? $params['Derivative'] : 'Null'; // not required
$Fuel = (array_key_exists('Fuel',$params)) ? $params['Fuel'] : 'Null'; // not required
$Colour = (array_key_exists('Colour',$params)) ? $params['Colour'] : 'Null'; // not required

$PartEx_Regno = (array_key_exists('PartEx_Regno',$params)) ? $params['PartEx_Regno'] : 'Null'; // not required
$PartEx_Mileage = (array_key_exists('PartEx_Mileage',$params)) ? $params['PartEx_Mileage'] : 'Null'; // not required

$xml = ' <?xml version="1.0" encoding="UTF-8" ?>
<SecurityInfo>
<Username>'.REEF_USERNAME.'</Username>
<Password>'.REEF_PASSWORD.'</Password>
</SecurityInfo>
<Lead>
<DealerCode>'.$DealerCode.'</DealerCode>
<LeadType>'.$LeadType.'</LeadType>
<LeadSource>'.$LeadSource.'</LeadSource>
<LeadId>'.$LeadId.'</LeadId>
<Customer>
<CustomerType>'.$CustomerType.'</CustomerType>
<Title>'.$Title.'</Title>
<Forename>'.$Forename.'</Forename>
<Lastname>'.$Lastname.'</Lastname>
<Companyname>'.$Companyname.'</Companyname>
<Homephone>'.$Homephone.'</Homephone>
<Workphone>'.$Workphone.'</Workphone>
<Mobilephone>'.$Mobilephone.'</Mobilephone>
<Email>'.$Email.'</Email>
<Address>
<Address1>'.$Address1.'</Address1>
<Address2>'.$Address2.'</Address2>
<City>'.$City.'</City>
<County>'.$County.'</County>
<Postcode>'.$Postcode.'</Postcode>
</Address>
<Dpa>
<dpapostal>'.$dpapostal.'</dpapostal>
<dpasms>'.$dpasms.'</dpasms>
<dpstel>'.$dpstel.'</dpstel>
<dpaemail>'.$dpaemail.'</dpaemail>
</Dpa>
<Marketing>
<Methodofcontact>'.$Methodofcontact.'</Methodofcontact>
<Sourceofenquiry>'.$Sourceofenquiry.'</Sourceofenquiry>
</Marketing>
<Message>'.$Message.'</Message>
</Customer>
<Vehicle>
<Regno>'.$Regno.'</Regno>
<Newused>'.$Newused.'</Newused>
<Make>'.$Make.'</Make>
<Model>'.$Model.'</Model>
<Derivative>'.$Derivative.'</Derivative>
<Fuel>'.$Fuel.'</Fuel>
<Colour>'.$Colour.'</Colour>
</Vehicle>
<PartEx>
<Regno>'.$PartEx_Regno.'</Regno>
<Mileage>'.$PartEx_Mileage.'</Mileage>
</PartEx>
</Lead>';

return str_replace("\n","",$xml);
}

$send = createRequestXML(array(
'Title' => 'Mr',
'Companyname' => 'Reef',
'Email' => 'test@test.com',
'Methodofcontact' => 'Internet',
'Sourceofenquiry' => 'Stackoverflow',
'Message' => 'I would like to buy a car',
'Newused' => 'USED',
'Make' => 'BMW',
'Model' => '3 Series',
'Derivative' => '330D Coupe',
'Fuel' => 'Diesel',
'Colour' => 'Silver',
'PartEx_Mileage' => '45600'
));

try {
$client = new SoapClient("http://www.reefservices.co.uk/leadws/lead.asmx?WSDL",array(
'location' => $URL,
'uri' => "http://www.reefservices.co.uk/leadws/",
'trace' => 1,
'exceptions' => true
));

$return = $client->Submit(array('Data' => $send));

echo '<pre>';
print_r($return);
echo '</pre>';
} catch(SoapFault $e) {
echo '<h3>Exception</h3>';
echo '<pre>';
print_r($e);
echo '</pre>';
}

?>

Also left some comments regarding the parameters as they were in the docs.



Related Topics



Leave a reply



Submit