Monthly Archives: July 2009

Magento API / web service work

Magento has strong web service features. I can say Magento’s web service is one step ahead than others e-commerce. Magneto has soap, v2_soap(soap 2) and xmlrpc adapter facilities. Using magento web services you can synchronize customer, categories, products, orders etc data with existing stores. Here I am going to describe magento’s web service deals step by step.

Setup API: At first create api user and api key from Magento’s admin. Follow below steps.
1. Create api user from admin->system->web services-> Users->Add New User->User Info. See picture.

Api user create with api key

Api user create with api key

2. Create role to set permission on api method under admin->system->web services-> Roles->Add New Role.
3. Define “Role Resources” for created role. See picture.

Set api permission on role

Set api permission on role

4. Set “User Role” from admin->system->web services-> Users->choose user->User Role.

Call API:
API user and key is created. Now we can call api methods in two ways.
1. Soap call
2. V2_Soap call

Here I am going to discuss both ways.

Soap call:
Magento wiki and help center have described this method. So who are beginner in web service work they can call magento api using this soap method. You get all api documentations in Magento site. Here is an example.


//create soap object
$proxy = new SoapClient('http://127.0.0.1/magento/api/soap/?wsdl');

// create authorized session id using api user name and api key
// $sessionId = $proxy->login('apiUser', 'apiKey');
$sessionId = $proxy->login('m4u_admin', '12345678');

 // Get customer info for customer id = 1
$customerinfo = $proxy->call($sessionId, 'customer.info', 1);

print_r($customerinfo);


V2_Soap call:

V2_soap call is for advance user. Who are expert in web service work they can easily use this method to call any magento api method from remote place. Whose magento knowledge is zero they also can use this soap method to work with magento web service. But about this method you will not get any api documentation in Magento wiki. But I think it will easy for you.

Here I am going to describe a-z about v2_soap method as any beginner also can use this soap calling method.


//create soap object
$proxy = new SoapClient('http://127.0.0.1/magento/api/v2_soap/?wsdl');

// create authorized session id using api user name and api key
// $sessionId = $proxy->login('apiUser', 'apiKey');
$sessionId = $proxy->login('m4u_admin', '12345678');

 // Get customer info for customer id = 1
$customerinfo = $proxy->customerCustomerInfo($sessionId,1);

print_r($customerinfo);

Which method you need to call?

At first decide which method you need to call of api. Suppose you want to retrieve customer info from Magento store. So you should call customer related api method to get customer info. But you donot know which method exactly you need. To view all available methods in your magento api please run http://127.0.0.1/magento/api/v2_soap/?wsdl. Now pick appropriate api method from wsdl operation list. Suppose I pick “customerCustomerInfo” method to get customer info.

<operation name="customerCustomerInfo">
   <documentation>Retrieve customer data</documentation> 
   <input message="typens:customerCustomerInfoRequest"/>
   <output message="typens:customerCustomerInfoResponse"/>
</operation>

What is request parameter?

From wsdl you get a clear concept about api request/input parameter. For “customerCustomerInfo” operation input message is “customerCustomerInfoRequest”. So you will get all input/request parameter info (name and type) to call customerCustomerInfo method in message “customerCustomerInfoRequest”. customerCustomerInfo has three request parameter such sessionid(string), customerid(int) and atribuates(Array).

<message name="customerCustomerInfoRequest"> 
    <part name="sessionId" type="xsd:string"/>
    <part name="customerId" type="xsd:int"/>
    <part name="attributes" type="typens:ArrayOfString"/>
</message>   

So we can request customerCustomerInfo method as below.

// Get customer info for customer id = 1 and attribute is optional
$attribute = array(‘firstname’, ‘lastname’, ‘email’, ‘store_id’);
$customerinfo = $proxy->call($sessionId, ‘customer.info’, 1, $attribute);

see picture for details-

API v2_soap wsdl request and response message.

API v2_soap wsdl request and response message.

What is return/response data?

From wsdl you also get idea about api response/return/output. For “customerCustomerInfo” operation output message is “customerCustomerInfoResponse”. So you will get output/result info (name and type) of customerCustomerInfo method in message “customerCustomerInfoResponse”. customerCustomerInfo will return customerCustomerEntity object as data. Please see what the format of customerCustomerEntity object in wsdl.

<message name="customerCustomerInfoResponse">
    <part name="customerInfo" type="typens:customerCustomerEntity"/>
</message>

That’s it!!

Update Magento product / inventory from external source.

Magento is newly coming great e-commerce. So if you wish you can move your existing store in Magento or if you interested then you can create another new store in Magento. In this case you may want to synchronize your existing inventory with new magento store. Here I am going to explain how we can update magento product/inventory from outside of Magento admin. We can use corn job to process inventory synchronization in automatic way. Magento also have corn job feature.

In two ways we can update magento’s inventory.
1. By creating new module or
2. Using product API/web service.

Here I will discuss update through module system.

Update inventory creating new module:

At first create new module in local pool to handle inventory update work. And create all of your necessary files. Then follow below steps to update your inventory.

Load product: load product using product id. If you have product sku then retrieve product id for corresponding sku.

// retrieve product id using sku
 $product_id = Mage::getModel('catalog/product')
                    ->getIdBySku($sku);

// call product model and create product object
$product    = Mage::getModel('catalog/product');
// Load product using product id
 $product ->load($product_id);

Set updated inventory data: set all of your updated data in product object.

// get product's general info such price, status, description
$productInfoData = $product->getData();

// update general info using new data
$productInfoData['price'] = 11;
$productInfoData['description'] = 'Testing product update';
$productInfoData['status'] = 1;

// then set product's general info to update
$product->setData($productInfoData);

// get product's stock data such quantity, in_stock etc
$stockData = $product->getStockData();

// update stock data using new data
$stockData['qty'] = 356;
$stockData['is_in_stock'] = 1;

// then set product's stock data to update
$product->setStockData($stockData);

// call save() method to save your product with updated data
$product->save();

Basically our product update process is completed but in this situation updated product will not be save. Magento want origData to save product object. Without admin session magento cannot create origData for product. This is a magento security issue. So if you want to update magento product outside of admin or without creating admin session then you need to override Mage_Catalog_Model_Product class.

Configure new module and create app/local/M4U/catalog/etc/c onfig.xml file and write below code.

<?xml version="1.0"?>
<config> 
    <global>
	<modules>
           <m4u_catalog>
               <version>0.1.0</version>
           </m4u_catalog>
        </modules>
	<models>
	  <catalog>
            <rewrite>
              <product>M4U_Catalog_Model_Product</product>
            </rewrite>
          </catalog>
       </models> 
   </global>	
</config>

Override Mage_Catalog_Model_Product class and write setOrigData method as below.

class M4U_Catalog_Model_Product extends Mage_Catalog_Model_Product
{
    /**
     * Set original loaded data if needed
     * @param string $key
     * @param mixed $data
     * @return Varien_Object
     */
    public function setOrigData($key=null, $data=null)
    {
       return Mage_Catalog_Model_Abstract::setOrigData($key, $data);
    }
}

If you expert in Magento module system or in override system only then you can follow this process to update magento inventory otherwise you should proceed with api. For alternative solution, you can see “update product through api / web service” post.

Have any query or question? Feel free to post.

Magento CMS controller override / cms page controller override in magento

Whoops !! what Magento’s bad ? Ofcourse documentation. Bullshit documentation !!. Magento have features but without documentation !!!!

Magento cms module has some nice functionality. Using Magento’s 404 event handlers of cms module you can integrate 3rd Party CMS Content such Expression Engine, Drupal, wordpress, joomla etc within Magento.
Magento is robust and have some great nice features but still their documentation is very poor. In Magento forum and wiki they just demonstrate “how to override a controller?” as a general theory. But how to override exceptional cms and api controller is not clear. Even Magento did not mention anything about exceptionality of cms and api module. Cms module calls internally. So we cannot override cms module’s controller using as usual magento controller override process. Here I described how to overrite cms index and page controller.

Target : Override Cms module’s Index (Mage_Cms_IndexController) controller and Page (Mage_Cms_IndexController) controller.

Hint: IndexController is responsible for displaying errors (404) & home page and PageController is responsible for displaying pages like ‘about-us’, keep this in mind as you may want to rewrite which controller.

Ok, let’s start—

Firsty, it’s wise to name your module differently to avoid name collisions. Lets call my module M4U_Mycms for that case.

<?xml version="1.0"?>
<config>
    <modules>
        <M4U_Mycms>
            <active>true</active>
            <codePool>local</codePool>
        </M4U_Mycms>
    </modules>
</config>

Now create config xml for new module in app/code/local/M4U/Mycms/etc/config.xml. Here as example I mention xml to override norouteAction method of IndexController.

<?xml version="1.0"?>
<config>

    <modules>
        <M4U_Mycms>
            <version>0.1.0</version>
        </ M4U_Mycms>
    </modules>
   
    <frontend>
        <routers>
            <mycms>
                <use>standard</use>
                <args>
                    <module> M4U_Mycms</module>
                    <frontName>mycms</frontName>
                </args>
            </mycms>
        </routers>
</frontend>	
	
<global>
     <routers>
            <cms>
                <rewrite>
                    <index>
                        <to>M4U_Mycms/index</to>
                        <override_actions>true</override_actions>
                        <actions>
                           <noroute><to> M4U_Mycms/index/noroute</to></noroute>
                        </actions>
                    </index>
                </rewrite>
            </cms>
        </routers>

       </global>
</config>

N.B: Please take care about tag. It will let you create additional NEW actions that will be rewritten to new controller.

Now create new index controller in app/code/local/M4U/Mycms/controllers/IndexController.php and update noRouteAction method.


require_once "Mage/Cms/controllers/IndexController.php";
class M4U_Mycms_IndexController extends Mage_Cms_IndexController
{
    public function noRouteAction($coreRoute = null)
    {
        //modify this method as you need
        
        exit('Yes, I can successfully override cms/index noRoute method ');
		
        //$this->getResponse()->setHeader('HTTP/1.1','404 Not Found');
        //$this->getResponse()->setHeader('Status','404 File not found');
       // $pageId = Mage::getStoreConfig('web/default/cms_no_route');
       // if (!Mage::helper('cms/page')->renderPage($this, $pageId)) {
       //     $this->_forward('defaultNoRoute');
       // }
    }
}

Done !!

When any requested class/method is not found in system then Magento throw “404 Not Found” error using noRouteAction method. So we can test this method calling any undefined page url like http://127.0.0.1/magento/index.php/undefinedpagename. Here, undefinedpagename is not a defined page in magento.

ok, now run http://127.0.0.1/magento/index.php/undefinedpagename and if you get result
“Yes, I can successfully override cms/index noRoute method” in browser then noRouteAction method override is success.

Here i just describe noRouteAction method modification system. Like this way you can modify all of the indexController and pageController method.

You will get source code in right side box widget. Download code and enjoy your work.

if need any help let me know.