===== Create your own API ===== ... api for customer module, that operates with basic customer info (firstname, lastname, email ...). ==== 1. Describe API Resource in api.xml ==== Create api.xml in customer module /etc folder with this contents: We have to implement create, list, info, update and remove methods for customer resource. Lets add it to resources. .... Customer Resource Retrive customers Create customer Retrieve customer data Update customer data Delete customer .... Our resource will return some faults, let's list them in the config: .... .... 100 Invalid customer data. Details in error message. 101 Invalid filters specified. Details in error message. 102 Customer doesn't exist. 103 Customer was not deleted. Details in error message. .... ==== 2. Describe ACL For API Resource ==== In order to prevent unathorized access to our custom API we have to define the ACL resources that can be restricted. .... Customers View All Create Get Info Update Delete We also have to map ACL resources to API resource methods: Customer Resource customer Retrive customers customer/list Create customer customer/create Retrieve customer data customer/info Update customer data customer/update Delete customer customer/delete .... .... ==== 3. Creating API Resource Model ==== Let's create Mage_Customer_Model_Api that extends Mage_Api_Model_Resource_Abstract class Mage_Customer_Model_Api extends Mage_Api_Model_Resource_Abstract { public function create($customerData) { } public function info($customerId) { } public function items($filters) { } public function update($customerId, $customerData) { } public function delete($customerId) { } } We cannot create method "list" because it's a PHP keyword, so we will add the following to api.xml: customer/api Customer Resource customer Retrive customers items customer/list .... .... .... And now will add some simple functionality to our resource model. Create Customer: public function create($customerData) { try { $customer = Mage::getModel('customer/customer') ->setData($customerData) ->save(); } catch (Mage_Core_Exception $e) { $this->_fault('data_invalid', $e->getMessage()); // We cannot know all the possible exceptions, // so let's try to catch the ones that extend Mage_Core_Exception } catch (Exception $e) { $this->_fault('data_invalid', $e->getMessage()); } return $customer->getId(); } Customer Info: public function info($customerId) { $customer = Mage::getModel('customer/customer')->load($customerId); if (!$customer->getId()) { $this->_fault('not_exists'); // If customer not found. } return $customer->toArray(); // We can use only simple PHP data types in webservices. } Customers List with filtering. public function items($filters) { $collection = Mage::getModel('customer/customer')->getCollection() ->addAttributeToSelect('*'); if (is_array($filters)) { try { foreach ($filters as $field => $value) { $collection->addFieldToFilter($field, $value); } } catch (Mage_Core_Exception $e) { $this->_fault('filters_invalid', $e->getMessage()); // If we are adding filter on non-existent attribute } } $result = array(); foreach ($collection as $customer) { $result[] = $customer->toArray(); } return $result; } Customer Update: public function update($customerId, $customerData) { $customer = Mage::getModel('customer/customer')->load($customerId); if (!$customer->getId()) { $this->_fault('not_exists'); // No customer found } $customer->addData($customerData)->save(); return true; } Customer Delete: public function delete($customerId) { $customer = Mage::getModel('customer/customer')->load($customerId); if (!$customer->getId()) { $this->_fault('not_exists'); // No customer found } try { $customer->delete(); } catch (Mage_Core_Exception $e) { $this->_fault('not_deleted', $e->getMessage()); // Some errors while deleting. } return true; } ===== Creating custom adapter for api ===== In order to create custom webservice adapter we should implement Mage_Api_Model_Server_Adapter_Interface interface Mage_Api_Model_Server_Adapter_Interface { /** * Set handler class name for webservice * * @param string $handler * @return Mage_Api_Model_Server_Adapter_Interface */ function setHandler($handler); /** * Retrive handler class name for webservice * * @return string */ function getHandler(); /** * Set webservice api controller * * @param Mage_Api_Controller_Action $controller * @return Mage_Api_Model_Server_Adapter_Interface */ function setController(Mage_Api_Controller_Action $controller); /** * Retrive webservice api controller * * @return Mage_Api_Controller_Action */ function getController(); /** * Run webservice * * @return Mage_Api_Model_Server_Adapter_Interface */ function run(); /** * Dispatch webservice fault * * @param int $code * @param string $message */ function fault($code, $message); } // Class Mage_Api_Model_Server_Adapter_Interface End XmlRpc Adapter example: class Mage_Api_Model_Server_Adapter_Customxmlrpc extends Varien_Object implements Mage_Api_Model_Server_Adapter_Interface { /** * XmlRpc Server * * @var Zend_XmlRpc_Server */ protected $_xmlRpc = null; /** * Set handler class name for webservice * * @param string $handler * @return Mage_Api_Model_Server_Adapter_Xmlrpc */ public function setHandler($handler) { $this->setData('handler', $handler); return $this; } /** * Retrive handler class name for webservice * * @return string */ public function getHandler() { return $this->getData('handler'); } /** * Set webservice api controller * * @param Mage_Api_Controller_Action $controller * @return Mage_Api_Model_Server_Adapter_Xmlrpc */ public function setController(Mage_Api_Controller_Action $controller) { $this->setData('controller', $controller); return $this; } /** * Retrive webservice api controller * * @return Mage_Api_Controller_Action */ public function getController() { return $this->getData('controller'); } /** * Run webservice * * @param Mage_Api_Controller_Action $controller * @return Mage_Api_Model_Server_Adapter_Xmlrpc */ public function run() { $this->_xmlRpc = new Zend_XmlRpc_Server(); $this->_xmlRpc->setClass($this->getHandler()); $this->getController()->getResponse() ->setHeader('Content-Type', 'text/xml') ->setBody($this->_xmlRpc->handle()); return $this; } /** * Dispatch webservice fault * * @param int $code * @param string $message */ public function fault($code, $message) { throw new Zend_XmlRpc_Server_Exception($message, $code); } } // Class Mage_Api_Model_Server_Adapter_Customxmlrpc End "setHandler", "getHandler", "setController" and "getController" methods have simple implementation that uses Varien_Object getData/setData methods. "run" an "fault" have native implementation for XmlRpc webservice. Method "run" defines webservice logic in this adapter for creating XmlRpc server to handle XmlRpc requests. public function run() { $this->_xmlRpc = new Zend_XmlRpc_Server(); $this->_xmlRpc->setClass($this->getHandler()); $this->getController()->getResponse() ->setHeader('Content-Type', 'text/xml') ->setBody($this->_xmlRpc->handle()); return $this; } Method "fault" allows us to send fault exceptions for XmlRpc service while handling request. public function fault($code, $message) { throw new Zend_XmlRpc_Server_Exception($message, $code); }