Recently, i had to do some integration work on RetailPro – a Point of Sale (POS) software and Magento – a E-Commerce software and platform.
While the only thing i found online was this link, i found it to be less technical than i would expect because it gave what i would describe as an overview rather than the “how-to” details. I decided to write more on the subject to help whoever would want to carry out the same integration.
A Brief Introduction
Retail Pro is a complete retail management solution providing not only Point of Sale but also Store Operations Management, Customer Management, Back Office, Analytics, Reporting and more. There are several editions of Retail Pro to specifically meet the needs of the retailer and the industry, for example, Small Business Edition, Global Enterprise or Global Enterprise Edition. With Retail Pro software, one is able to completely tailor their retail software to meet all the unique demands of their business. Source:About Retail Pro Point of Sale Software
Magento on the other hand is an open-source content management system for e-commerce web sites. It is quite popular as Large E-Commerce websites have adopted Magento as their defacto E-Commerce platform.
So, the basic gist from the above is RetailPro is used in retail stores to manage inventory and all the POS (sales, receipt generation, book balancing) paparazzi. It is used locally in the retail stores while Magento caters for the online presence of the store i.e the ecommerce website (where the store would sell to its online/remote users).
Why do we need to integrate Magento and RetailPro?
- We don’t want to keep two sets of Inventory, we would want the same set of items and quantity on the RetailPro database be the same as the items in magento datastore
- Processing Sales Order should pass through the same channel, due to need of updating the inventory when a sales order is processed
- Customer Data on the E-Commerce website should be maintained on RetailPro. This facilitates the preparation of Sales Order easily. Although data is duplicated, but the Pros beats the Cons
A point to Note
You don’t need to be a Magento Administration expert or have tons of experience working with magento before you can carry out this integration. Although, i should point out that you need a solid experience in using APIs (SOAP/REST).
The Magento API
The Magento API provides you with the ability to manage your eCommerce stores by providing calls for working with resources such as customers, categories, products, and sales orders. It also allows you to manage shopping carts and inventory.
In this tutorial, i made references to the SOAP API v1 (no particular reason, but it gets the job done).
Introduce your self to the API by visiting this link here.
In using different resources connected to the Magento API, samples are provided in PHP (thank you, Magento) to help facilitate the usage.
What do we want to achieve
Basically, we want to carry out three tasks,
- Push Inventory Items from RetailPro software to Magento
- Push Sales Order from Magento to the RetailPro Software for processing
- Push New customers from Magento to the RetailPro Software
So, its a two way communication.
Does RetailPro have an API? Well, not exactly. What they have is an Add-On module called – Enterprise Communication Manager (ECM). And what this module (which is a desktop app) does is it sends data via open transport using XML, which allows open data exchange between Retail Pro and other systems (in our case, Magento). Using the ECM, we can generate Inventory XML files that contains the items in the inventory in a specified XML format. We can also import Sales Order and Customer XML files from other systems into RetailPro by dropping the files in a specified directory that is accessible to the ECM. ECM can be set to run a polling service to fetch the new files for import. The XML files we would be working with need to conform with the format specifications as specified by RetailPro. Kindly go through the “XML Files” document provided by RetailPro which would help understand not only the format of the file, but what each attribute of each node of the XML file stands for, the data type, the data length and if required or not.
Inventory XML
This file would be gotten from the ECM. It contains the list of items that have been defined in RetailPro. We need to push this to Magento.
We would be making use of the Catalog Product Create API. It is used for creating the items in the inventory file that doesn’t exist in Magento store.
We should define a folder on the Magento server that would host the inventory XML files that would be uploaded, and have a cron job that runs periodically (preferably every 2 days) to scan the folder for new XML files, upon sighting a new file, the script should process it.
The processing steps include:
For each file present in the folder, it should check if it is an .xml file (we don’t want to try to process files which aren’t XML), it should interpret the XML file into an object using the simplexml_load_file function in PHP.
For each, INVENTORY node in the INVENTORYS node in the DOCUMENT root node, the Item attributes should be fetched and passed as an Array to the catalog_product.create method of the create API referenced above. Its always a good idea to log a message (in a file) after a product has been successfully added, this helps you monitor the process. Also, do not forget to use try..catch to catch any exception that might occur when making the API calls. It is also a good idea to log whatever exception message is caught. Below is a code segment that illustrate how to push the items in the Inventory XML (already passed into the $xmlDoc object) to Magento store
foreach ($xmlDoc->INVENTORYS->INVENTORY as $inventory){ $item_sid = $inventory->INVN['item_sid']; $sku=removeMinus($inventory->INVN['item_sid']); $name = $inventory->INVN_SBS['description1']; $description=$inventory->INVN_SBS['long_description']; $short_description = $inventory->INVN_SBS['description2']; $weight = $inventory->INVN_SBS['siz']; $url_key=replaceEmptySpace($inventory->INVN_SBS['description1']).'-'.$inventory->INVN['item_sid']; $url_path=replaceEmptySpace($inventory->INVN_SBS['description1']); $price=$inventory->INVN_SBS->INVN_SBS_PRICES->INVN_SBS_PRICE[0]['price']; $meta_title=$inventory->INVN_SBS['description1']; $meta_description=$inventory->INVN_SBS['long_description']; $qty = $inventory->INVN_SBS->INVN_SBS_QTYS->INVN_SBS_QTY['qty']; try{ $result = $result = $client->call($session, 'catalog_product.create', array('simple', $attributeSet['set_id'], $sku,array( 'categories' => array(2), 'websites' => array(1), 'name' => "$name", 'description' =>"$description", 'short_description' => "$short_description", 'weight' => "$weight", 'status' => '1', 'url_key' => "$url_key", 'url_path' => "$url_path", 'visibility' => '4', 'price' => "$price", 'tax_class_id' => 1, 'meta_title' => "$meta_title", 'meta_keyword' => '', 'meta_description' => "$meta_description", 'stock_data'=>array('qty' => "$qty") ))); /*$savedItem = */ $allSavedItems[] = array("sid"=>"$item_sid","mangentoId"=>"$result"); ++$count; } catch(Exception $e) { logMessage('Error: ' .$e->getMessage()); } logMessage($count." Items are saved"); }
Kindly take note that the item_sid in RetailPro is used as the sku in Magento. It is quite important that we keep the item_sid coming from RetailPro. This would help RetailPro identify the Item in the Sales order XML that we would be generating subsequently.
While using the script above to push items (about 12,000 items) to Magento, i noticed it was very slow. It was pushing the items at an average rate of about 20 Items per Minute. So it took about 10hours to complete. Find below the tweet that explains why it is that slow:
This script has been running for over 12hrs now. Less than 10000 products pushed. Why is #magento API this slow? #php #ecommerce
— Ahmed (@western_peey) March 10, 2015
@western_peey Because it goes through the ORM. It's a pain point we're fixing in Magento 2.
— Ben (@benmarks) March 11, 2015
While we wait for Magento 2. There is actually a faster way to push items to Magento. There is a free tool called “MAGMI” that helps carry out mass import. Here is a post that shows how to use it.
Customer XML
We need to generate the Customer XML file from Magento. This file would contain the details of our newly registered customers on our website that can be pushed to RetailPro using the ECM.
We need to setup another cron job for this. This Cron Job would periodically generate the files and put them in a defined location on our web server. The administrator can pick up the file and transfer it to the location where the ECM is set to pull from.
Kindly note that we need to generate a unique cust_sid from our script and keep track of it – either by storing it in the database or in a separate XML file, i prefer the latter.
Below is the call to get the list of new customers using the Customer List API
$result = $client->call($session, 'customer.list',array(array('created_at' => array('from' => "$fromDate")))); foreach ($result as $customerData) { //..Pass the attributes to the appropriate attribute node in the XML file../// }
The root node is the “DOCUMENT” node. It contains the “CUSTOMERS” node which in turn contains n number of “CUSTOMER” node. The attributes of each customer gotten from the $result is passed into the “CUSTOMER” node in the format specified by the ECM
Do not forget to log a message after each customer is added to the XML file. Also remember to catch and log any exception.
Sales Order XML
To retrieve Sales order from the Magento E-commerce website through the API, we make use of the Sales Order List API and the Sales Order Info API. The former helps us retrieve the list of orders, while the latter helps us retrieve the details of a specified order.
Note that the sku of the product would be used as the item_sid and we would need to fetch the cust_sid that was generated and saved when we were generating the customer XML file.
Like the Customer XMl file, we need to setup another cron job for this. This Cron Job would periodically generate the sales order XML files and put them in a defined location on our web server. The administrator can pick up the file and transfer it to the location where the ECM is set to pull from.
Below is a snippet that explains the process populating the Sales order XML file for the ECM to process.
$result = $client->call($session,'order.list',array(array('status'=>'pending'),array('created_at' => array('from' => "$yestDate")))); if (isset($result)) { //create the DOCUMENT node //create the SOS node inside the DOCUMENT node foreach ($result as $salesOrder) { //Get the SalesInfo for the current order $saleOrderInfo = $client->call($session, 'sales_order.info', $salesOrder['increment_id']); //create the SO node inside the SOS node //pass the $saleOrderInfo attributes to the SO node attributes as specified in the format. } }
Do not forget to log a message after each order is added to the XML file. Also remember to catch and log any exception.
Conclusion
The processes involved in the integration task has been fairly covered in the above post. Full code samples were not provided for the Customer and Sales Order XML integration due to its length. They can be provided on request – always happy to help. While this is not a herculean task, it would take an Intermediate to Advanced Skill in programming and development to pull off. To simplify my task, i had to generate some of the PHP codes to create the element/nodes and attribute from the sample XML file i had – it seemed mundane to manually write.
Kindly drop a comment if there is any clarification or explanation needed. Cheers!