Blog‎ > ‎

Magento API and Python

posted Jun 9, 2012, 12:22 AM by Pasi Orovuo   [ updated Oct 3, 2012, 12:34 AM ]

Some time back I was assigned the task of finishing a Magento web store project started by someone else. The site was in a pretty good shape, but still had quite a few loose ends here and there. In addition of the actual Magento site, the project contained an integration module, which enabled Magento to pass data from and to an ERP system. The integration module was written in PHP as is Magento. While in the process of figuring out what had to be done and where, something (perhaps more about that later) lit my long forgotten love for Python, and made me wonder how could the Magento integration API be exploited with Python.

My initial take was to go for the same route we used in PHP - the SOAP (v1) api. It's pretty simple to use so I was guessing it would be pretty trivial to use in Python. Python does not contain a SOAP library, so we need use an external one. I decided to go for SUDS, which is very Pythonic, light and simple to use. I won't describe the installation process as it's no different from any other high quality Python library.

Before we start, we need to set up the Magento API. Log in to the administrative backend i.e. http://127.0.0.1/magento/admin and go to System / Web Services Roles and click Add New Role. Enter a name on the role info and add All permissions on it (see screenshot below). Please note that All-permissions should be used for testing and on test site only. Be extremely careful with permissions when working on public or production sites.

Once the role has been created, go to System / Web Services Users and click Add New User. Type in the whatever information you like and make note of username and password. They are needed afterwards.

Finally, on the menu on the left, choose User Role and assign your freshly created role on the user. Magento configuration is now finished and we're ready proceed to the programming part.

Okay, here's my first take with Magento API and SUDS:

from suds.client import Client

c = Client( "http://127.0.0.1/magento/index.php/api/soap/?wsdl" )
session = c.service.login( "apiUser", "apiKey" )
print c.service.call( session, "customer_group.list" )

The result was not exactly a success:

por:~/Temp$ python magentotest.py 
Traceback (most recent call last):
  File "magentotest.py", line 4, in <module>
    c = Client( "http://127.0.0.1/magento/index.php/api/soap/?wsdl" )

# snip...

  File "/home/por/Temp/suds/xsd/sxbasic.py", line 259, in dependencies
    raise TypeNotFound(self.ref)
suds.TypeNotFound: Type not found: '(Array, http://schemas.xmlsoap.org/soap/encoding/, )'

The problem is well documented on the SUDS site, and occurs because the WSDL is slightly broken and does not import the SOAP encoding schema properly. Apparently PHP works fine without it. SUDS developers found a neat fix for such cases - the ImportDoctor. See more here.

ImportDoctored code looks like this:

from suds.client import Client
from suds.xsd.doctor import ImportDoctor, Import

d = ImportDoctor( Import( "http://schemas.xmlsoap.org/soap/encoding/" ) )
c = Client( "http://127.0.0.1/magento/index.php/api/soap/?wsdl", doctor = d )
session = c.service.login( "apiUser", "apiKey" )
print c.service.call( session, "customer_group.list" )

And now the there are at least no exceptions raised:

por:~/Temp$ python magentotest.py 
[(item){
   item[] = 
      (item){
         key[] = 
            "customer_group_id",
         value[] = 
            "0",
      },
      (item){
         key[] = 
            "customer_group_code",
         value[] = 
            "NOT LOGGED IN",
      },
 },

# snip...

But it still doesn't seem right... Even though it would be possible to clean up the result to something easier to use, it seems like pointless extra work compared to PHP. Fortunately Magento developers have provided us with an alternative API - XMLRPC. And support for XMLRPC is included in the Python core, so no 3rd party libraries are required. Here we go:

from xmlrpclib import ServerProxy

proxy = ServerProxy( "http://127.0.0.1/magento/index.php/api/xmlrpc" )
session = proxy.login( "apiUser", "apiKey" )
print proxy.call( session, "customer_group.list" )

And the result (formatted for readability):

por:~/Temp$ python magentotest.py
[
  {
    'customer_group_code': 'NOT LOGGED IN',
    'customer_group_id': '0'
  },
  {
    'customer_group_code': 'General',
    'customer_group_id': '1'
  },
  {
    'customer_group_code': 'Wholesale',
    'customer_group_id': '2'
  },
  {
    'customer_group_code': 'Retailer',
    'customer_group_id': '3'
  }
]

A list of dictionaries! That's more like it.

Apparenly Magento API access with SOAP (at least with SUDS) is not the way to go with Python. Thankfully there are alternative ways available and XMLRPC seems to work just as nicely. I'm not aware of any drawbacks at least at this point. Our project continues to use PHP so my experiments with Magento and Python are over for the moment. Perhaps I'll return to the subject later.

Next, I'll be posting some information about custom integration modules for Magento. Stay tuned.


Comments