[Mini Tutorial] – Extend the Magento API

Extend the Magento API to Better Suit Your Business

This article serves as a follow-up to an excellent blog post a colleague of mine wrote last year concerning the ability to “break-out” and display collected taxes in Magento. Recently, I had a request from a client to extend Magento’s Core API with additional resources to return so-called “break-out” taxes. With that in mind, I thought this would be a good opportunity to demonstrate how to extend the Magento API while simultaneously leveraging the functionality (or at least the shared idea) discussed here in a previous article. This guide will act as a quick, introductory overview of how to extend the Magento API in order to better meet your business requirements. In this example, we will be reusing and extending an existing method but new methods can be implemented in a similar fashion.

To reiterate, the requirement (much like that of my colleague’s client at the time) was to display an accurate breakdown of collected tax rates – only this time returned through the Magento Core API.

In this instance, I have extended the salesOrderInfo method. On the actual project, I also included a tax rate breakdown per product item in the order. I will provide some short tips and guidance to accomplish this, but largely will focus on the broader task of returning the tax breakdown on the order as a whole.
Let’s start by creating a new module that will extend from the Mage_Sales module…

Our Module

Step 1: Create config.xml to define our module.

<?xml version="1.0"?>
<config>
<modules>
<Demac_BreakoutTaxes>
<version>0.1.0</version>
</Demac_BreakoutTaxes>
</modules>
<global>
<models>
<demac_breakouttaxes>
<class>Demac_BreakoutTaxes_Model</class>
</demac_breakouttaxes>
<sales>
<rewrite>
<order_api_v2>Demac_BreakoutTaxes_Model_Sales_Order_Api_V2</order_api_v2>
</rewrite>
</sales>
</models>
<helpers>
<demac_breakouttaxes>
<class>Demac_BreakoutTaxes_Helper</class>
</demac_breakouttaxes>
</helpers>
</global>
</config>

Note that as we are extending an existing API method, we only need to include a rewrite for Mage_Sales_Model_Order_Api_V2 in addition to defining a model and standard helper Data class for our module.

Step 2: Create wsdl.xml extending the WSDL definition of the Core API.

<?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="salesOrderPaymentEntity">
<all>
<element name="tax_rates" type="typens:salesOrderTaxEntityArray" minOccurs="0"/>
</all>
</complexType>
<complexType name="salesOrderTaxEntityArray">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="typens:salesOrderTaxEntity[]"/>
</restriction>
</complexContent>
</complexType>
<complexType name="salesOrderTaxEntity">
<all>
<element name="code" type="xsd:string"/>
<element name="amount" type="xsd:string"/>
<element name="base_amount" type="xsd:string"/>
<element name="base_real_amount" type="xsd:string"/>
<element name="percent" type="xsd:string"/>
</all>
</complexType>
</schema>
</types>
</definitions>

Here, we are defining a new entity named tax_rates within Magento’s existing payment entity from the salesOrderInfo method. This new tax_rates complex type will contain further elements representing the ID, amount, base amount, base real amount, and percent of the tax rate.

Step 3: Extend the info() method through our rewritten Order API V2 class.

<?php
/**
* Order API V2
*/
class Demac_BreakoutTaxes_Model_Sales_Order_Api_V2 extends Mage_Sales_Model_Order_Api_V2
{
/**
* Retrieve full order information
*
* @param string $orderIncrementId
*
* @return array
*/
public function info($orderIncrementId)
{
$result = parent::info($orderIncrementId);
$order = parent::_initOrder($orderIncrementId);
$taxRates = $order->getFullTaxInfo();
foreach ($taxRates as $taxRate) {
$result['payment']['tax_rates'][] = array(
'code' => $taxRate['id'],
'amount' => $taxRate['amount'],
'base_amount' => $taxRate['base_amount'],
'base_real_amount' => $taxRate['base_real_amount'],
'percent' => $taxRate['rates'][0]['percent'],
);
}
return $result;
}
}
It is important to note here that we are preserving as much of the original method as possible. We are retaining the $result and $order from the parent class, which enables us to reuse this data without rewriting the entire method, better enabling our module to remain compatible following an update to the original module gracefully.

In the custom code for this method, we are taking the existing tax information from the original order. This enables us to get the complete set of tax rates used on the order; for instance Canadian GST and PST. We then loop through this collection of applicable tax rates on the order and add each one to the original result returned from the parent class method. In the results array, each individual tax rate element is added to the [‘tax_rates’] element within [‘payment’] – this is inline with our WSDL definition from earlier.

DELVING FURTHER

For the purposes of my task, I also had to provide a tax breakdown per individual order item. This can be accomplished in a similar manner to what we have already applied to the API. You would first extend the WSDL and include a new complex type entity for item tax. Then, in our overwritten info() method you would again alter the returned parent result, taking the order items from there, looping through them, and applying tax rates in a similar fashion as above. I added the tax rates to each item element in the array, taking into consideration the quantity of each item ordered. I then used this data alongside the order’s tax rates to calculate specific taxes on each individual item.

Serve your business needs

I hope this tutorial was able to provide some valuable insight into exploring and extending Magento’s Core API to better serve your business needs and also serve as a compliment to our existing article on displaying breakout taxes.