Creating a Magento Payment Module – Part 3 – Model, Controllers and Events

There are many tutorials out there which show parts of implementing a payment module. None completely build the module. They all stop short of showing how they implemented their nameless payment method.

This is part 3 of the tutorial. Here's part 1 and part 2 in case you missed them.

This post will walk through the model, action controllers and how they interact with the mockpay api.


This model extends Mage_Payment_Model_Method_Abstract and if you look at the code of the base model, you'll see it has a lot of protected boolean attributes. These attributes are probed by the various consumers of these payment methods to figure out which features of the payment API our module supports.

Most of the modules I looked at for examples do this by overriding the properties instead of just setting them in the constructor. Our model defines four properties:

  • $_canUseForMultiShipping which enables/disables this method to be used for orders split up and shipped to many addresses,
  • $_canUseInternal which enables/disables using this method from the admin order screen,
  • $_code which is the unique payment method code for this module. It should match the code defined in the config.xml file. Its just text.
  • $_isInitializeNeeded, which enables a call to the initialize method when payment is captured.

The model::initialize() method is called when the order is placed. (Last step of the checkout process when the "place order" button is clicked.)
Looking at other modules is a great way to figure out how this code should work and if you look at the paypal or modules you'll find a bunch more options are configured. These modules do the full authorize/capture process. Authorize occurs when the payment method is selected and the capture method is called when you click the "place order" button is clicked.

My module is very simple, needed only one method to be called at the very end of the payment process.
I opted to use initialize() instead of capture/authorizenbsp;because it always occurs at the same point in the process and I observed that initialize is only called in one place. I didn't find that to be true of the other methods.

In my initialize method, I'm setting the order state to "pending payment". This provides a clue to the folks working with the order in the backend that no payment has been collected for this order yet. I'm also connecting to the mockpay api and sending the order details. Mockpay will respond by providing a session token which will be unique to this order. The token is used to associate the customer on our site to the order details on the mockpay site with the order info and amount we're requesting. This is also where we'll inform mockpay about the cancel, error and success urls for this order.

Once payment is completed or canceled. The customer will be redirected back to our site. At that point we have a little more work to do with the order to either make an invoice and change the order state if successful or cancel it if the order fails or is canceled.

We'll use action controllers to handle these requests.

These are in the controllers/StandardController.php file. This is also extending an existing magento resource called "Mage_Core_Controller_Front_Action".

The successAction() will handle the success condition of the api where payment was completed successfully.
We'll get a token back from the mockpay api and we'll be able to use the token to query the api to get more details about the payment.

If everything checks out, we can change the state of the order from STATE_PENDING_PAYMENT to STATE_NEW, so its ready for someone on the store to ship and complete. This is also where we'll convert the quote into an invoice and mark it as paid. I skipped this step in the first version and it means someone on the backend has to do the extra step of creating an invoice and marking it as paid in magento.

Once all these steps are completed, I can then redirect the customer to the order complete page.

The other possible conditions are cancel, the person doesn't want to pay or failure where payment can't be completed because of lack of funds. I have these two conditions routed to the same action, the cancelAction().

Cancel will make the quote inactive and call the order objects cancel method.

With these actions in place, we have a functional payment module integrated with the mock pay api.

I've tried to comment as much as possible in the code so hopefully it will be instructive as you attempt to create your own payment method.

The full code for this payment module can be found on github.

Creating a Magento Payment Module – Part 2 – Module structure

There are many tutorials out there which show parts of implementing a payment module. None completely build the module. They all stop short of showing how they implemented their nameless payment method. These holes made something which should have taken a day or so to work out take two weeks to complete. Most of that time was spent figuring out the "Magento way" to do things. Once that was established, the module itself is very small. 6 files and 300 lines of code.

The previous post created a fake payment gateway. Part 2 will cover the structure of your magento module and part 3 will discribe how magento and the api interact.

The completed module can be downloaded from github.

Magento module file structure

Magento's file structure is based on the PEAR/Zend Framework autoloader where class xx_yyy_zz relates directly to a physical file of ./xx/yyy/zz.php.
Our module will use the namespace/folder structure of My_Mockpay_*

Example folder structure:


Controllers are related to Zend_Action_Controllers.
In this example, we'll have one controller action for each possible response of the api: Success, Cancel and Failure.

Model is for your model code and business logic.
We'll extend Mage_Payment_Model_Method_Abstract, create a custom observer to hook into events which are fired during checkout, and create a custom class which will talk to our mockpay soap API.

Helper is for custom Mage_Payment_Helper_* classes. Only one helper is required and it need not be customized.
We'll extend Mage_Payment_Helper_Data.

Block is for custom code which alters the display of our payment method.
In this example, we're going to use the default block so this folder will be empty.

Etc contains the config files which glue the module together.

System.xml is for configuring the back-end of your module.
The args defined here will have a UI for editing them in the System->config->Payment Methods screen automatically.

Config.xml lets Magento know what the module is supposed to do and which files to load.

Lets take a look at Config.xml

the root element is


You set the module version here. It's important later when the next version of your module is released.
(Which is outside the scope of this tutorial. We don't need a custom database table so upgrading is irrelevant.)

Then start the




This registers a route to your model files in Magento.


Ditto for the helpers.


This lets mageto know this is a payment module.


Events are triggered at specific points in the code and allow you to attach custom code to an event without overriding it. In the example, the "checkout_type_onepage_save_order_after" event is a part of one-page checkout and is fired right after the order is created, but before the redirect to the payment form.
That's the end of the global section of the config.xml

The default section establishes the default values for the fields defined in system.xml file.

                <title>Credit Card (MockPay - Fake Payment Gateway) </title>

The last section of my file is the front-end


Here we're registering a route to the controller for magento to use.
When the module is installed its actions will be accessible from:

http://domain.tld/magento/index.php/mockpay/standard/action/param/value/param2/value2 ...

This defines where the files will go an what we need to do.
Lets take a look at the system.xml

Each child node of


is a field of data which will be save into the "core_config" table in the magento database.
The configuration option for your module should go here. You'll be able to edit these values from the magento configuration panel in thte back-end
and retrieve these values in your module. The sample file includes the options you'd see most often when configuring a new module.

Take note of the "merchantkey" element:

                        <merchantkey translate="label">
                            <label>Merchant Key</label>
                            <comment><![CDATA[Data entered into this field is stored encrypted in the db.]]></comment>

The name of the element is arbitrary. You get to pick.
Each field has a label, optional comment, type, model, order and visibility options.
This data is stored in the core_config table in the database.

If your saving passwords or sensitive information here, use the "system_config_backend_encrypted" back-end. (aka Mage_Adminhtml_Model_System_Config_Backend_Encrypted)
This stores your data in the core_config table encrypted and prevents prying eyes from discovering sensitive information like api username or keys.

You can see the other back-ends by browsing the "/Mage/Adminhtml/Model/System/Config/Backend" folder.

The final config file is the module config file, called "My_Mockpay.xml". This file is normally stored in the "magento/app/ete/module" folder and enables the module withinMmagento. If you need to remove the module, delete this file and clear the Magento cache.

We'll dive into the controller and event modules in part 3.

Creating a Magento Payment Module – Part 1 – Creating a Payment Gateway

There are many tutorials out there which show parts of implementing a payment module. None completely build the module. They all stop short of showing how they implemented their nameless payment method. These holes made something which should have taken a day or take two weeks. Most of that time was spent figuring out the “magento way” to do things. Once that was established, the module itself is very small. 6 files and 300 lines of code.

For the purpose of this discussion on creating a payment module, I’ve made a fake payment gateway to integrate with.

Mockpay is a simple payment gateway consisting of a soap API with two methods and a payment form page.
The methods let you inform the api about the payment and the externally hosted form accepts the payment and sends the customer back to your store after payment is complete. Its similar to PayPal standard, minus the instant pay notification.

How to accept a payment with mockpay

Mockpay Sequence Diagram

Collect the payment details, and pass them to the api via the beginPayment() method.

$wsdl = '';
$client = new SoapClient($wsdl);
$response = $client->beginPayment(string $email, float $amount, string $orderId, string $desc, string $uriSuccess, string $uriFailure, string $uriCancel);

The response with be an array with a ‘hasErrors’ element and a ‘errorMessage’ element.
If ‘hasErrors’ is > 1, there was an error. If the submission was successful, the response will include a ‘token’ element. You’ll need this value to get your customer to the payment page.

Once you have the token, you can direct the customer to the payment page, located here:
When your customer arrives at the payment page, the payment details associated with this token will be pulled up automatically, including the amount, email, etc.

The customer puts in the payment details and clicks the pay now button or the cancel button.
Once the payment is complete, you will be redirected to the $uriSuccess,$uriFailre, or $uriCancel uri you filled in when you called beginPayment(). In all cases, the token will be appended to your uri.

At this point, you can use the second method in the api, queryPayment($token), to determine if the payment was successful and take some useful action like completing the order, sending an email, etc.

Simple right?

The code for this fake payment method is on github and has been deployed to my phpcloud container here:
wsdl = “
form = “”

The next post will go into creating a magento payment module which utilizes the mockpay payment gateway.