Magento extension for logging SOAP V1 and V2 API requests

Magento SoapLogger ExtensionMagento application programming interface allows third party applications to programatically interact with Magento instance. Magento supports two API standards, SOAP/XML-RPC and REST. Distinctive characteristics of SOAP (Simple Object Access Protocol) is that it uses XML as it's message format, and when used over HTTP it delivers data trough POST request method. My personal preference lies with REST APIs, but in my experience with version 2 of Magento SOAP API, I can freely say that it's one of the most enjoyable SOAP APIs I had privilege of working with. Only thing that bothers me is that Magento currently doesn't provide feature for allowing developers to peek inside SOAP envelope when something isn't working as it should. Essentially it isn't possible to easily debug SOAP API calls Magento receives. In this article I'm bringing Magento extension allowing you to capture SOAP API requests and log them into file.

General idea of my solution is to intercept API requests and log raw POST data to log file. Best place to do this is inside Mage_Api_Model_Server_Handler for SOAP V1 API and Mage_Api_Model_Server_V2_Handler for SOAP V2 API. Because of that it is necessary to rewrite these classes to add our own logging code. Here's some XML to get us started:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
 
<!-- app/code/community/Inchoo/SoapLogger/etc/config.xml -->
 
<config>
    <modules>
        <Inchoo_SoapLogger>
            <version>1.0.0</version>
        </Inchoo_SoapLogger>
    </modules>
    <global>
        <models>
            <api>
                <rewrite>
                    <!-- Handle SOAP V1 API-->
                    <server_handler>Inchoo_SoapLogger_Model_Api_Server_Handler</server_handler>
                    <!-- Handle SOAP V2 API-->
                    <server_v2_handler>Inchoo_SoapLogger_Model_Api_Server_V2_Handler</server_v2_handler>
                </rewrite>
            </api>
            <inchoo_soaplogger>
                <class>Inchoo_SoapLogger_Model</class>
            </inchoo_soaplogger>
        </models>
        <helpers>
            <inchoo_soaplogger>
                <class>Inchoo_SoapLogger_Helper</class>
            </inchoo_soaplogger>
        </helpers>
    </global>
</config>

Next thing we need is helper class allowing us to capture raw POST data sent by SOAP clients. For this purpose we will need to access PHP's input stream directly trough php:// wrapper. Here's code for our base helper:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
// app/code/community/Inchoo/SoapLogger/Helper/Data.php
 
class Inchoo_SoapLogger_Helper_Data extends Mage_Core_Helper_Abstract
{
    protected $logFileName = 'soap.log';
 
    public function logPostXml()
    {
        if(($postData = file_get_contents('php://input'))) {
            // DOMDocument
            $apiDomDocument = new DOMDocument('1.0');
 
            // Remove white space
            $apiDomDocument->preserveWhiteSpace = false;
 
            // Format output for logging into file
            $apiDomDocument->formatOutput = true;
 
            // Load XML
            $apiDomDocument->loadXML($postData);
 
            if($apiDomDocument->loadXML($postData)) {
                $this->logMessage($apiDomDocument->saveXML());
            }
        }
    }
 
    public function logMessage($message)
    {
        Mage::log(
            $message,
            null,
            $this->logFileName
        );
    }
}

I've added two more helpers allowing us to log SOAP V1 and V2 API calls into separate files (v1_soap.log and v2_soap.log).

Finally, here's code for extending SOAP V1 Mage_Api_Model_Server_Handler class with our logging functionality:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
// app/code/community/Inchoo/SoapLogger/Model/Api/Server/Handler.php
 
class Inchoo_SoapLogger_Model_Api_Server_Handler
extends Mage_Api_Model_Server_Handler
{
    /**
     * Logs V1 API call
     *
     * @param type $sessionId
     * @param type $apiPath
     * @param type $args
     * @return mixed Null or whatever API call method returns
     */
    public function call($sessionId, $apiPath, $args = array())
    {
        Mage::helper('inchoo_soaplogger/v1')
            ->logPostXml();
 
        return parent::call($sessionId, $apiPath, $args);
    }
 
    /**
     * Logs V1 API fault
     *
     * @param type $faultName
     * @param type $resourceName
     * @param type $customMessage
     */
    protected function _fault($faultName, $resourceName = null, $customMessage = null) {
        Mage::helper('inchoo_soaplogger/v1')
            ->logMessage('Fault while processing API call: '.$faultName);
 
        parent::_fault($faultName, $resourceName, $customMessage);
    }
 
}

Code for extending SOAP V2 Mage_Api_Model_Server_V2_Handler is identical, except it uses it's own helper for logging into separate file.

Now here's an example of PHP SOAP client code for fetching list of Magento users trough SOAP V1 API together with the contents of v1_soap.log file after this API request has been processed:

1
2
3
4
5
6
7
8
9
$client = new SoapClient('http://community.loc/index.php/api/soap/?wsdl');
 
$session = $client->login('user', 'pass');
 
$result = $client->call($session, 'customer.list');
 
var_dump ($result);
 
$client->endSession($session);
1
2
3
4
5
6
7
8
9
10
11
2013-11-10T09:08:22+00:00 DEBUG (7):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:call>
      <sessionId xsi:type="xsd:string">1fb76fb43bfa656a32e829c980b91191</sessionId>
      <resourcePath xsi:type="xsd:string">customer.list</resourcePath>
      <args xsi:nil="true"/>
    </ns1:call>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

And here's an example of the same PHP SOAP client code but this time using SOAP V2 API, followed by the SOAP envelope logged into v2_soap.log file.

1
2
3
4
5
6
7
8
9
10
11
$client = new SoapClient(
    'http://community.loc/index.php/api/v2_soap/?wsdl'
);
 
$session = $client->login('user', 'pass');
 
$result = $client->customerCustomerList($session);
 
var_dump($result);
 
$client->endSession($session);
1
2
3
4
5
6
7
8
9
10
2013-11-10T09:11:28+00:00 DEBUG (7):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:customerCustomerList>
      <sessionId xsi:type="xsd:string">31e4864837e32e50ccd4cd3d7b8ddd6c</sessionId>
      <filters xsi:nil="true" xsi:type="ns1:filters"/>
    </ns1:customerCustomerList>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

To spare you from additional hassle, I've prepared complete extension containing this functionality. This Magento extension named SoapLogger can be downloaded from it's GitHub repository archive:

DOWNLOAD SoapLogger from GitHub

You can also access SoapLogger's official page here at TechyTalk.info:

SoapLogger - Official Page
DevGenii

E-commerce is a breeze with Magento Certified Developer Plus & Zend Certified PHP Engineer nearby. Get in touch!

5 thoughts on “Magento extension for logging SOAP V1 and V2 API requests

  1. Jiri

    Hello,

    Thanks for your post. But there is one small issue. For XML-RPC it throws

    PHP Fatal error:  Uncaught exception 'Zend_XmlRpc_Client_FaultException' with message 'Calling parameters do not match signature' in /home/jich/Sources/magento/beck/lib/Zend/XmlRpc/Client.php:381

    Reason is the signature of the method call, instead of this

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
       /**
         * Logs V1 API call
         *
         * @param type $sessionId
         * @param type $apiPath
         * @param type $args
         * @return mixed Null or whatever API call method returns
         */
        public function call($sessionId, $apiPath, $args = array())
        ...

    there should be rather

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
       /**
         * Logs V1 API call
         *
         * @param string $sessionId
         * @param string $apiPath
         * @param array $args
         * @return mixed Null or whatever API call method returns
         */
        public function call($sessionId, $apiPath, $args = array())
        ...

    If types in PHPDoc were missing then Zend_XmlRpc_Server would not be able to parse the types of the method’s arugments.

    Reply
  2. ambient

    i got session expires error continue when a android developer call a api soap v1 to add product in a cart.
    hows i solve this.
    please help me to solve this problem.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *