Monday, April 25, 2016

How to use PHP SoapClient TLS Request - Advanced Tutorial

Basics
To start with PHPSoap you need a WSDL (Web Service Definition Language) file. Its an XML file looks like following.

WSDL XML File Sample Structure
Unlike REST api, SOAP uses XML file structure.

This article will focus on

  1. How to start with PHP SoapClient
  2. Using SoapUI
  3. Sending First SOAP request
  4. Sending TLS Request with PHP SoapClient

1. Using SoapUI

(Consider You are Developer and you have a Hosting A and you are trying to integrate a ThirdParty Service)

WSDL file (created by ThirdParty) should always be hosted in a publicly accessible URL. Some time WSDL file will be splitted into two, one is hosted locally (Hosting A) and another one will be kept with ThirdParty Service.

For this example I used the WSDL file from here. (Thanks TutorialsPoint)

I hosted it here for your convenience http://code.educationgovt.com/wsdl/sample.wsdl

Step 1: Install SoapUI and Open it.
Step 2: Click File -> New Soap Project   or Ctrl+N. When you click ok, it will load the file.
New SoapUI Project
Step 3: See the Projects Pane. The Requests in the WSDL file are listed here. Right click, Double click and see the available options. It will clear most of your basic Doubts.

Step 4: Double click on Request 1 it will open the Request Pane. It has two sections as shown below. Request and Response (Right Column).

SoapUI Sending Request and Process the Response
Step 5: Click the Green Play button in the top of Request window. It says "Submit request to specific endpoint URL".
You should see the response in the Right column. In this Example, you should see a 404 page .

In the Production WSDL definitions file, this Request pane will create a Request for you.

Soap Request with paramets

<firstName xsi:type="xsd:string">?</firstName>

SoapUI will put ?  for the parameters you need to pass.
Here firstName is expecting a String.

It can be any complex WSDL definition, you just open the SoapUI and Do above, you will see the Request and Variables you need to pass.

I hope i covered a basic understanding you need to start with Soap.

Example 2: use http://www.webservicex.net/globalweather.asmx?WSDL


Simple Soap Response Successful 


2. How to start with PHP SoapClient

PHP Provides a SoapClient class to do the above through php code.

<?php 

//Create the client object
$soapclient = new SoapClient('http://www.webservicex.net/globalweather.asmx?WSDL');

//Use the functions of the client, the params of the function are in 
$params = array('CountryName' => 'India');
$response = $soapclient->GetCitiesByCountry($params);
print_r($response);

If you cannot see complete response, View Source in browser or var_dump

You can do the above in many ways.

<?php 

//Create the client object
$soapclient = new SoapClient('http://www.webservicex.net/globalweather.asmx?WSDL');

//Use the functions of the client, the params of the function are in 
$params = array('CountryName' => 'India');
$response = $soapclient->__soapCall('GetCitiesByCountry', array($params));
print_r($response);

Produces the same above output. Here we have called __soapCall a low level method from SoapClient Class.

Code explanation:
We created the SoapClient object from SoapClient() class. Using that we send the request parameters to the particulat Soap Request Method.

The Basic SoapClient usage is explained here.

3. Advanced Soap Request in PHP

Project like bank B2B and other Transaction related services will usually have a complex SOAP request. 

Start Looking at the functions provided by SoapClient class http://php.net/manual/en/class.soapclient.php

Consider you have a WSDL file, how to know what is the Request End point?
If the Service Provider doesn't provide you document, you can follow below methods to find the Service End point (Request URL's).

Method 1: (Recommended)
In SOAPUI you can see the Service End points. If you double click on request you will see the required parameters for every request.

Soap Service End Points 
Method 2:
Use the following code to list all the available functions inside the WSDL. It list all the functions.

$soapclient->__getFunctions()

Simple Request with Certificate

<?php 
$wsdl = "someURL-with.wsdl";
$local_cert = "YourDirectory\ClientKeyAndCer.pem";

$soapclient = new SoapClient($wsdl, array('local_cert' => $local_cert));

$theResponse = $soapclient->test();

Request with Certificate and Other Parameters

<?php 
$wsdl = "someURL-with.wsdl";
$local_cert = "YourDirectory\ClientKeyAndCer.pem";

$soapclient = new SoapClient($wsdl,array(
        "trace"         => 1, 
        "exceptions"    => true, 
        "local_cert"    => $local_cert, 
        "uri"           => "urn:xmethods-delayed-quotes",
        "style"         => SOAP_RPC,
        "use"           => SOAP_ENCODED,
        "soap_version"  => SOAP_1_2 ,
        "location"      => $this->location
    ));

Using PHP Soap for Request with Certificate and Private Key

PHP SoapClient is limited with functionalities. You can attach a Certificate with SoapClient Request if needed. But Private key cannot be send.

To handle these situation you need to create your own class extending SoapClient functionality.

Creating your Own Soap Class to handle Custom Request
<?php 
class Myclass extends SoapClient{
    
    function __construct($wsdl, $options = null) {
        parent::__construct($wsdl, $options);
    }
    
    function __doRequest($request, $location, $action, $version) {
        return parent::__doRequest($request, $location, $action, $version);        
    }
    
}
Print the parameters and see the individual data like URL, and $request.

If you see the PHP SoapClient Functionality, it actually sends the formatted XML string (same like the ones created through SoapUI) with parameters filled.

Following line is the one which handles the Network Data Transport from You to Other Server.

parent::__doRequest()

Replace this code with cURL or any other code which handles your own Data transport mechanism.

Example 2:

<?php

define('WSDL_URL', 'http://www.webservicex.com/CurrencyConvertor.asmx?wsdl');

class MyOwnSOAPClient extends SoapClient {

    //Required variables
    public $url = "";

    function __construct($wsdl, $options = null) {
        parent::__construct($wsdl, $options);
    }

    function __doRequest($request, $location, $action, $version) {
        $requestDOM = new DOMDocument('1.0');
        $soapHeaderDOM = new DOMDocument('1.0');

        try {
            $requestDOM->loadXML($request);
            $request = $requestDOM->saveXML();
        } catch (DOMException $e) {
            die('Error adding UsernameToken: ' . $e->code);
        }
        return parent::__doRequest($request, $location, $action, $version);
    }

}

    $soapClient = new MyOwnSOAPClient(WSDL_URL, array());
    $ConversionRateObj = new stdClass();
    $ConversionRateObj->FromCurrency = "USD";
    $ConversionRateObj->ToCurrency = "INR";
//    print_r($soapClient->__getFunctions());
    $reply = $soapClient->ConversionRate($ConversionRateObj);
    print_r($reply);


Read more…