Magento Soap API V1 and V2 Creation

Tutorial for creating Magento Soap API V1 and V2

Posted on May 11, 2016 in Magento

One of my clients is asking me to develop a Magento Soap API V1 and V2 to update the customer attribute, ‘Sale Representative’, which is created by myself. Due to the variations of customer service forces, this field has to be updated monthly so that the campaign emails will be sent out with correct sale representative information for each customer.

The following code snippets are generated to achieve this goal.

Register new Module


#app/etc/modules/Jeff_Customapi.xml
<?xml version="1.0"?>
<config>
    <modules>
        <Jeff_Customapi>
            <active>true</active>
            <codePool>local</codePool>
        </Jeff_Customapi>
    </modules>
</config>

Create new Module


#app/code/local/Jeff/Customapi/etc/config.xml
<?xml version="1.0"?>
<config>
    <modules>
        <Jeff_Customapi>
            <version>0.1.0</version>
        </Jeff_Customapi>
    </modules>
    <global>
        <models>
            <customapi>
                <class>Jeff_Customapi_Model</class>
            </customapi>
        </models>
        <helpers>
            <customapi>
                <class>Jeff_Customapi_Helper</class>
            </customapi>
        </helpers>
    </global>
</config>

Register new Soap API for V1 and V2


#app/code/local/Jeff/Customapi/etc/api.xml
<?xml version="1.0"?>
<config>
    <api>
        <resources>
            <customapi_customer translate="title" module="customapi">
                <model>customapi/customer_api</model>
                <title>Custom Api Demo</title>
                <acl>customapi/customer</acl>
                <methods>
                    <list translate="title" module="customapi">
                        <title>List of customers</title>
                        <method>items</method>
                    </list>
                    <update translate="title" module="customapi">
                        <title>Update Customer</title>
                        <acl>customapi/customer/update</acl>
                    </update>
                </methods>
            </customapi_customer>
        </resources>
        <resources_alias>
            <mycustomer>customapi_customer</mycustomer>
        </resources_alias>
        <v2>
            <resources_function_prefix>
                <customapi_customer>customapiCustomer</customapi_customer>
            </resources_function_prefix>
        </v2>
        <acl>
            <resources>
                <customapi translate="title" module="customapi">
                    <title>Customers</title>
                    <sort_order>5</sort_order>
                    <customer translate="title" module="customapi">
                        <title>Customer Data</title>
                        <update translate="title" module="customapi">
                            <title>Update</title>
                        </update>
                    </customer>
                </customapi>
            </resources>
        </acl>
    </api>
</config>

soap web service file wsdl.xml


#app/code/local/Jeff/Customapi/etc/wsdl.xml
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"
  name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}">
  <types>
    <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento">
      <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" />
      <complexType name="fieldInfo">
        <sequence>
          <element name="entity_id" type="xsd:string"/>
          <element name="email" type="xsd:string"/>
        </sequence>
      </complexType>
      <complexType name="fieldInfoArray">
        <complexContent>
          <restriction base="soapenc:Array">
            <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:fieldInfo[]" />
          </restriction>
        </complexContent>
      </complexType>
      <complexType name="customapiCustomerEntityToCreate">
        <all>
            <element name="customer_id" type="xsd:int" minOccurs="0" />
            <element name="firstname" type="xsd:string" minOccurs="0" />
            <element name="lastname" type="xsd:string" minOccurs="0" />
            <element name="middlename" type="xsd:string" minOccurs="0" />
            <element name="group_id" type="xsd:int" minOccurs="0" />
            <element name="salesrep" type="xsd:string" minOccurs="0" />
        </all>
      </complexType>
    </schema>
  </types>
  <message name="customapiCustomerListRequest">
    <part name="sessionId" type="xsd:string" />
  </message>
  <message name="customapiCustomerListResponse">
    <part name="customers" type="typens:fieldInfoArray" />
  </message>
  <message name="customapiCustomerUpdateRequest">
    <part name="sessionId" type="xsd:string" />
    <part name="customerId" type="xsd:int" />
    <part name="customerData" type="typens:customapiCustomerEntityToCreate" />
  </message>
  <message name="customapiCustomerUpdateResponse">
    <part name="result" type="xsd:boolean" />
  </message>

  <portType name="{{var wsdl.handler}}PortType">
    <operation name="customapiCustomerList">
      <documentation>List of Customers</documentation>
      <input message="typens:customapiCustomerListRequest" />
      <output message="typens:customapiCustomerListResponse" />
    </operation>
    <operation name="customapiCustomerUpdate">
        <documentation>Update customer data</documentation>
        <input message="typens:customapiCustomerUpdateRequest" />
        <output message="typens:customapiCustomerUpdateResponse" />
    </operation>
  </portType>
  <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
    <operation name="customapiCustomerList">
      <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
      <input>
        <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </input>
      <output>
        <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
      </output>
    </operation>
    <operation name="customapiCustomerUpdate">
        <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
        <input>
            <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
        </input>
        <output>
            <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
        </output>
    </operation>
  </binding>
  <service name="{{var wsdl.name}}Service">
    <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding">
      <soap:address location="{{var wsdl.url}}" />
    </port>
  </service>
</definitions>

Module Helper Class for Translation


#app/code/local/Jeff/Customapi/Helper/Data.php
<?php
class Jeff_Customapi_Helper_Data extends Mage_Core_Helper_Abstract {

}

API Business Logic & Core - Model class


#app/code/local/Jeff/Customapi/Model/Customer/Api.php
<?php
class Jeff_Customapi_Model_Customer_Api extends Mage_Customer_Model_Api_Resource { //Mage_Api_Model_Resource_Abstract {
    public function items() {
        $arr_customers = array();

        $customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToSelect('*')->setOrder('entity_id', 'DESC')->setPageSize(5);

        foreach ($customers as $customer) {
            $arr_customers[] = $customer->toArray(array('entity_id', 'email'));
        }

        return $arr_customers;
    }

    public function update($customerId, $customerData) {
        $customerData = $this->_prepareData($customerData);
        $customer = Mage::getModel('customer/customer')->load($customerId);

        if (!$customer->getId()) {
            $this->_fault('not_exists');
        }

        foreach ($this->getAllowedAttributes($customer) as $attributeCode=>$attribute) {
            if (isset($customerData[$attributeCode])) {
                $customer->setData($attributeCode, $customerData[$attributeCode]);
            }
        }
        $customer->save();
        return true;
    }
    protected function _prepareData($data)
    {
        foreach ($this->_mapAttributes as $attributeAlias=>$attributeCode) {
            if(isset($data[$attributeAlias]))
            {
                $data[$attributeCode] = $data[$attributeAlias];
                unset($data[$attributeAlias]);
            }
        }
        return $data;
     }

}

Soap API V2 Model


#app/code/local/Jeff/Customapi/Model/Customer/Api/V2.php
<?php
class Jeff_Customapi_Model_Customer_Api_V2 extends Jeff_Customapi_Model_Customer_Api {
    protected function _prepareData($data)
    {
        if (null !== ($_data = get_object_vars($data))) {
                return parent::_prepareData($_data);
        }
        return array();
    }
}

If you add all these files to your magento and refresh cache, the new Api with both V1 and V2 has been installed.

The way to call this new Soap API V2


<?php
//ini_set("soap.wsdl_cache_enabled", 0);

function microtime_float() {

    list($usec, $sec) = explode(" ", microtime());

    return ((float)$usec  + (float) $sec);
}

$time_start = microtime_float();

//call Magento outside Magento
require_once('app/Mage.php');
umask(0);
Mage::app();
$customers = Mage::getModel('customer/customer')
    ->getCollection()
    ->addAttributeToSelect('*')
    ->addAttributeToFilter('group_id', array(array('eq'=>8), array('eq'=>9), array('eq'=>10))) 
    ->setOrder('entity_id','desc');

$customArray = array();

foreach($customers as $customer) {
    $no = $customer->getData('company_no');
    if((strlen($no) > 0) && $no != 'TBD') {
        $temp = new stdClass();
        $temp->customerId = $customer->getId();
        $temp->companyNo = $no;
    }

    $customArray[] = $temp;
}

$last = null;

$client = new SoapClient('http://www.yourdomain.com/api/v2_soap?wsdl=1');
$sessionId = $client->login('user', 'password');

foreach($customArray as $item) {
    $last = $item;
    echo 'Customer Id: ' . $item->customerId ."\n\n";
    if((strlen($item->companyNo) > 0) && $itme->companyNo != 'TBD') {
        $url = 'http://api.yourdomain.com/ecom/api_sales_agent.php?c='; //I called another api to provide the sale representative's name
        $url .= $item->companyNo;
        $json = file_get_contents($url);

        $obj = json_decode($json);
        if($obj->status == 'Found') {
            $result = $obj->result;
            $repname = $result[0]->FIRSTNAME. ' '. $result[0]->LASTNAME;

            $data = new stdClass();
            $data->salesrep = $repname;
            $customerId = $item->customerId;
        
            try{
                $result = $client->customapiCustomerUpdate($sessionId, $customerId, $data);
                echo "updated successfully!\n\n";
            }
            catch(Exception $e) {
                var_dump($e);
                echo "failed!\n\n";
            }
        }
    }
}

$client->endSession($sessionId);

$time_end = microtime_float();

$time = $time_end - $time_start;
echo "\nScript lasts for about $time Seconds\n";

echo "Done\n";

I hope these code snippets can help you in your future projects.


comments powered by Disqus