Monday, February 4, 2013

Developing OpenCart Modules


 The OpenCart (http://www.opencart.com/) is an open-source shopping cart with a MySQL database back-end. Because I couldn't find any appropriate documentation when I was doing this, I decide I should share this, in case someone else gets stuck with a similar task/problem/challenge .

 More details about the OpenCart can be found here :


 It's an MVC concept, and the next image shows that (directory structure of the OpenCart):


In this post we will be talking about how to create a new module and the popular version of OpenCart in the time when I was working on this subject, was 1.5.1.3.

The OpenCart has two parts : the shopping cart front-end and the admin back-end . Both sections have almost identical directory and file structure.

Shopping Cart front-end:  The files for the shopping cart are (models, views, controller, language files) are located in the catalog directory.  The important files for this section are the  config.php file and the files located in the catalog directory.  The config.php file contains all of the settings (file paths, image paths, database username and password) and a user/developer can add additional settings.

Admin , back-end: The files for the admin section are located in the admin directory. The structure is same as  the front - end, the important file here is the config.php also (same as the front-end).

This means that, the module we are building, will have 2 parts, one used to interface with the front-end and another one used to interface with the back-end(admin).  Let's build a new payment module and call it ExpressPayment (the same method can be applied on your module).

The structure of the module will have:


  • front -end :
    • controller : located in catalog/controller/payment/express_payment.php
    • model : located in catalog/model/payment/express_payment.php
    • view: located in catalog/view/theme/[name_of_the_theme(default)]/template/payment/express_payment.tpl (more than one template can exist, depending on our goal and how are different messages handled)
    • language files: located in catalog/language/[language(english)]/payment/express_payment.php
  • admin section :
    • controller: located in admin/controller/payment/express_payment.php
    • view : located in  admin/view/template/payment/express_payment.tpl
    • language files :  located in  admin/language/[language(english)]/payment/express_payment.tpl


Front-end:

As I said, the OpenCart's structure is completely MVC oriented(personally, to me, it looks like someone took CodeIgniter and decided he could make a shopping cart). Let's go over the front-end components, one by one.

Controller : 
Every controller extends the main controller, named "Controller" (not very creative, but, pretty much, straight forward, isn't it?). It has a default/main method, called index() (If you ever had a chance to work with a popular framework, like Zend or CodeIgniter, this will look very familiar). You can add your own methods, depending on the functionality.

Model:

The typical model structure will contain methods for interacting with the database and/or the current session data. Every model extends the main model class, named "Model".

View:
I was never good at design, so I'm just going to describe the structure and functionality of a view. It's just a *.tpl file, containing the HTML and a couple of lines of PHP code.

Language files:
These files are PHP files, containing arrays with localized messages for your views.





Admin section:

As you can see, the structure is almost the same as the Front-end, only the model is missing here. This controller is accessed by the admin section, and it will be located under payment methods in the Extension menu.
You can add a check if the module was installed already (this will help if you want to define some custom fields in the database, you can run your queries here). The default method is index() . This method is called when the administrator clicks on the payment method, listed in the payment section. You will have to load any relevant data here, specific merchant token, long-term key...

I think it would be a waste of time for me to explain the structure of the template, because it's very simple and self-explaining (and I will paste in some example code at the end of my post).


You can use the files attached to try out the following .


Aaaaand, now....

Let's talk business. Let's assume that our payment method needs some sort of merchant ID, so the merchant using the cart can be identified, a token to confirm the merchant's identity . We (meaning I ) don't want to waste any time, so, we are going to make some changes by hand, in the database. Just a simple and fast insert() in the database will do the job for now. We need to add the 2 new fields, so we should do :

 insert into `setting` (`setting_id`, `store_id`, `group`, `key`, `value`, `serialized`)

values(24829, 0, 'express_payment', 'express_payment_token', 'token', 0),
values(24829, 0, 'express_payment', 'express_payment_merchant_id', 'merchant01', 0);

These are the default values of the fields. The insert() speaks for itself, so there's no point of explaining what's going on here.

Admin :
Here, the administrator/owner of the cart is setting up everything. Let's have a look at the payment method. If you go to Extensions => Payments, you should be see the payment method. If you click on it, the controller in admin/controller/payment/express_payment is called. First the language file is loaded, than the settings model is loaded and finally, the settings for this particular module (the two inserts).
That's it, nothing complicated.

Front-end:

Party time!!! Controller, loads data from database/session including , currency, amount, merchant ID, merchant token, loads a view. OpenCart has a modular template approach, this means that in most of the controllers, when a view i loaded, it doesn't load a whole page, but, the view itself is part of a bigger page. Why? Because OpenCart is AJAX based, javascript/jQuery makes a call to a specific controller, the controller returns HTML, but in a JSON format. If you look at the express payment controller, you'll see that  in the index() method, everything is read/loaded from somewhere, and then, the view is rendered. The view is actually returned as JSON, and represents an HTML form with a HTTP POST action. The callback is used to get response from your payment processor (transaction successful , failed, bad data , etc.).

Every order has history behind it, that's why we're using a call-back method, we have to keep a record.



All in all, I think I covered all of the things you need to create your own payment module. The same approach/concept can be used to make different type of module. Change the name and location, and you can create, well, what ever you like.

Example code, attached here: express_payment.zip.


1 comment: