Add Custom API

Posted Almost 3 years ago. Visible to the public.

Define the API in the custom module app\code\local\{vendor}\{module}\etc\api.xml:

<config>
    <api>
        <resources>
            <member translate="title" module="benefit">
                <model>benefit/api_member</model>
                <title>Member API</title>
                <acl>benefit/member</acl>
                <methods>
                    <!-- Element name must be in lower case, see note 1. -->
                    <check_in translate="title" module="benefit">
                        <title>Check-In</title>
                        <method>checkIn</method>
                        <acl>benefit/member/checkIn</acl>
                    </check_in>
                </methods>   
                <!-- Defined faults are only applicable to module benefit and cannot be shared with Other modules. -->
                <!-- Other module must redefine the faults even if they are the same faults. -->
                <faults module="benefit">
                    <not_found>
                        <!-- For JSON-RPC, the code must be in the range -32000 to -32099. -->
                        <code>-32001</code>
                        <message>Not found.</message>
                    </not_found>
                    <missing_param>
                        <code>-32002</code>
                        <message>Missing required parameter(s).</message>
                    </missing_param>
                    <invalid_param>
                        <code>-32602</code><!-- Reuse system code for Invalid method parameter(s). -->
                        <message>A parameter has an invalid value.</message>
                    </invalid_param>       
                </faults>
            </member>
        </resources>
        <acl>
            <resources>
                <benefit translate="title" module="benefit">
                    <title>Benefit</title>
                    <sort_order>100</sort_order>
                    <member translate="title" module="benefit">
                        <title>Member</title>
                        <sort_order>10</sort_order>
                        <!-- Attribute module is required for it to be listed, see note 2. -->
                        <check_in translate="title" module="benefit">
                            <title>Check-in</title>
                        </check_in>
                    </member>
                </benefit>
            </resources>
        </acl>
    </api>
</config>

Note 1.

// app\code\core\Mage\Adminhtml\Block\Api\Tab\Rolesedit.php line 40
        foreach ($rules_set->getItems() as $item) {
            if (array_key_exists(strtolower($item->getResource_id()), $resources)
                && $item->getApiPermission() == 'allow')
            {
                $resources[$item->getResource_id()]['checked'] = true;
                array_push($selrids, $item->getResource_id());
            }
        }

array_key_exists is false if the XML element name has capital letter, the result is that the element will not be checked in the rendered page.

The lowercase restriction may have something to do with API v2.

Note 2.

// app\code\core\Mage\Adminhtml\Block\Api\Tab\Rolesedit.php line 104
            foreach ($children as $child) {
                if ($child->getName()!='title' && $child->getName()!='sort_order' && $child->attributes()->module) {
                    if ($level != 0) {
                        $item['children'][] = $this->_getNodeJson($child, $level+1);
                    } else {
                        $item = $this->_getNodeJson($child, $level+1);
                    }
                }
            }

See the check on $child->attributes()->module, if module attribute is missing, it will not be added to the tree.

Resource path is not callable.

Error is thrown in

// app\code\core\Mage\Api\Model\Server\Handler\Abstract.php
            try {
                $model = Mage::getModel($modelName);
                if ($model instanceof Mage_Api_Model_Resource_Abstract) {
                    $model->setResourceConfig($resources->$resourceName);
                }
            } catch (Exception $e) {
                throw new Mage_Api_Exception('resource_path_not_callable');
            }

            if (method_exists($model, $method)) {
                $result = array();
                if (isset($methodInfo->arguments) && ((string)$methodInfo->arguments) == 'array') {
                    $result = $model->$method((is_array($args) ? $args : array($args)));
                } elseif (!is_array($args)) {
                    $result = $model->$method($args);
                } else {
                    $result = call_user_func_array(array(&$model, $method), $args);
                }
                return $this->processingMethodResult($result);
            } else {
                throw new Mage_Api_Exception('resource_path_not_callable');
            }

So just make sure the model defined in api.xml can be instantiated and the method defined is callable.

kiatng
Last edit
Almost 3 years ago
kiatng
Posted by kiatng to OpenMage (2021-05-24 07:28)