Magento Create Custom Payment Method

credit-card
In this blog post, we are going to see the basics of how to create a new payment method.

We will first see a very basic version of the payment method i.e it won’t have any payment gateway integration (e.g Cash on Delivery). Next, we will see how to create a little advanced version where we will see how to show a form for the payment method and save the values to database.

Basic Payment Method

Here is a screenshot of how the payment method will look like

Custom Payment Method

Custom Payment Method


As you can see its the most basic version, where only title of payment method show up. Now lets see what are all the steps to do this. Create a payment method is almost same as shipping method. We need to edit the files system.xml, config.xml and create a model class for the payment method. Before starting with a payment method, first we need to decide on a unique code for the payment method, in my i have chosen the code to be ‘pay’ and name of my module is Excellence_Pay.
system.xml
Create a system.xml file inside your module’s etc folder. The content of the system.xml file are

<?xml version="1.0" encoding="UTF-8"?>
<config>
   <sections>
        <payment>
            <groups>
                <pay translate="label" module="pay">
                    <label>Excellence Payment Module</label>
                    <sort_order>670</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>0</show_in_store>
                    <fields>
                        <active translate="label">
                            <label>Enabled</label>
                            <frontend_type>select</frontend_type>
                            <source_model>adminhtml/system_config_source_yesno</source_model>
                            <sort_order>1</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </active>
                        <order_status translate="label">
                            <label>New order status</label>
                            <frontend_type>select</frontend_type>
                            <source_model>adminhtml/system_config_source_order_status_processing</source_model>
                            <sort_order>2</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </order_status>
                        <title translate="label">
                            <label>Title</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>3</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </title>
                    </fields>
                </pay>
            </groups>
        </payment>
    </sections>
</config>

the important thing to notice here is

<config>
   <sections>
        <payment>
            <groups>
                <pay translate="label" module="pay">

The xml path is required for all payment method i.e it needs to be inside the <payment> tag and <pay> here is our payment method’s code. The above xml will create fields in the System->Configuration->Payment Methods as shown

config.xml
Next in our module config.xml file we need to put in default values for the fields created in system.xml. Here is the code to put in config.xml directly inside the <config> tag.

<default>
        <payment>
            <pay>
                <active>1</active>
                <model>pay/pay</model>
                <order_status>processing</order_status>
                <title>Excellence Payment Method</title>
            </pay>
         </payment>
    </default>

Here is the important thing to note is the <model> tab which has the classpath of the payment method model class.
Model Class
Next we will create the model class for our payment method at location Excellence_Pay_Model_Pay, as mentioned in the config.xml <model> tag.

<?php
class Excellence_Pay_Model_Pay extends Mage_Payment_Model_Method_Abstract
{
	protected $_code = 'pay';
}
?>

This is all that is required to create a simple payment method. Attached is source code of this module
Error... Unable to load download template. Search single-download-template.tpl in your plugin folder!

Payment Method with Form Fields

We will now see how to create a payment method with form fields, this is a bit more complex than what we created above. Here is a screenshot of the payment method

Magento Custom Payment Method

Magento Custom Payment Method


As you can see in the screenshot, the title of the payment method is “Pay by Check” and it has two fields Check No and Check Date. These fields are entered by the user and saved to the database for order processing. I will use the same module as above, so only the new files created will be explained in this section. Attached is the source code for this section
Error... Unable to load download template. Search single-download-template.tpl in your plugin folder!
Step1
First we will see how to add the form html to the payment method. That is, when we click on ‘Pay by Check’ it show the two form fields. To do this in our payment model class Excellence_Pay_Model_Pay we will add a variable

protected $_formBlockType = 'pay/form_pay';

This variable has the path of the block class which contains form. The code written in the block class is

<?php
class Excellence_Pay_Block_Form_Pay extends Mage_Payment_Block_Form
{
	protected function _construct()
	{
		parent::_construct();
		$this->setTemplate('pay/form/pay.phtml');
	}
}

This is simple, it just basically sets the template of the form to be ‘pay/form/pay.phtml’. In the pay.phtml file the code written is

<?php $_code=$this->getMethodCode() ?>
<ul class="form-list" id="payment_form_<?php echo $_code ?>" style="display:none;">
    <li>
        <label for="<?php echo $_code ?>_check_no" class="required"><em>*</em><?php echo $this->__('Check No#') ?></label>
        <span class="input-box">
            <input type="text" title="<?php echo $this->__('Check No#') ?>" class="input-text required-entry" id="<?php echo $_code ?>_check_no" name="payment[check_no]" value="<?php echo $this->htmlEscape($this->getInfoData('check_no')) ?>" />
        </span>
    </li>
    <li>
        <label for="<?php echo $_code ?>_check_date" class="required"><em>*</em><?php echo $this->__('Check Date:') ?></label>
        <span class="input-box">
            <input type="text" title="<?php echo $this->__('Check Date:') ?>" class="input-text required-entry" id="<?php echo $_code ?>_check_date" name="payment[check_date]" value="<?php echo $this->htmlEscape($this->getInfoData('check_date')) ?>" />
        </span>
    </li>
</ul>
<div>
	<?php echo $this->getMethod()->getConfigData('message');?>
</div>

The <ul> tag width id ‘payment_form_<?php echo $_code ?>’ is important. Since we have made it display:none by default, it won’t show when the payment step is loaded. But when we click on the ‘Pay by Check’ option the <ul> tag will automatically have display:block. This is all that is required to make the form block show up. The important thing to remember is that protected $_formBlockType = ‘pay/form_pay'; is used for showing the form
Step2
After we have created the form, we need to make sure the values go into the database and are visible in Admin -> Sales -> Orders. So here we will see how to save the form fields to database and also how to validate the fields. In our payment method model class Excellence_Pay_Model_Pay we will add two function

public function assignData($data)
	{
		if (!($data instanceof Varien_Object)) {
			$data = new Varien_Object($data);
		}
		$info = $this->getInfoInstance();
		$info->setCheckNo($data->getCheckNo())
		->setCheckDate($data->getCheckDate());
		return $this;
	}


	public function validate()
	{
		parent::validate();

		$info = $this->getInfoInstance();

		$no = $info->getCheckNo();
		$date = $info->getCheckDate();
		if(empty($no) || empty($date)){
			$errorCode = 'invalid_data';
			$errorMsg = $this->_getHelper()->__('Check No and Date are required fields');
		}

		if($errorMsg){
			Mage::throwException($errorMsg);
		}
		return $this;
	}

The function assignData($data) is called, when we click the ‘Continue’ button in the checkout Payment Step. The $data variable has our fields data in it, so in the assignData function, we get the information from $data variable in assign to a object called $this->getInfoInstance(). The $this->getInfoInstance() returns an object of class Mage_Payment_Model_Info, this object is used in many places and is considered to have the information of a payment method.
Next we have validate() function, it is clear from the name it is used to validate the form fields data and check if they meet the business requirement or not.
Now, to store these two fields in the database, we need to create columns for these. By default in magento payment method fields are stored in two tables
‘sales_flat_quote_payment’ and ‘sales_flat_order_payment’. If you see the existing structure of the tables, these have many column for store credit cart info, purchase order no, etc which are default magento payment methods. Now, we need to add 2 more columns to both these table for our fields i.e check_no and check_date.
So in your mysql install file put in this sql code

<?php
$installer = $this;
$installer->startSetup();
$installer->run("

ALTER TABLE `{$installer->getTable('sales/quote_payment')}` ADD `check_no` VARCHAR( 255 ) NOT NULL ;
ALTER TABLE `{$installer->getTable('sales/quote_payment')}` ADD `check_date` VARCHAR( 255 ) NOT NULL ;

ALTER TABLE `{$installer->getTable('sales/order_payment')}` ADD `check_no` VARCHAR( 255 ) NOT NULL ;
ALTER TABLE `{$installer->getTable('sales/order_payment')}` ADD `check_date` VARCHAR( 255 ) NOT NULL ;

");
$installer->endSetup();

Next we need to make another change to our config.xml file, inside the <global> tag put in this xml

<fieldsets>
    		 <sales_convert_quote_payment>
    		 	<check_no>
    		 		<to_order_payment>*</to_order_payment>
    		 	</check_no>
    		 	<check_date>
    		 		<to_order_payment>*</to_order_payment>
    		 	</check_date>
    		 </sales_convert_quote_payment>
    	</fieldsets>

Once the above steps are done the two form fields, we be stored to quote and order database perfectly and should be visible in Admin -> Sales -> Order as well.
Step3
This is last thing remaining for the payment method, that is the information block. This info block is used in many places, it is basically the information of the payment method that shows up in progress area, order email, my account -> order area, admin order area etc. Attached are screenshot of where the info block shows up

Payment Method Info Block Admin

Payment Method Info Block Admin

Payment Method Info Block MyAccount

Payment Method Info Block MyAccount

Payment Method Info Block Progress

Payment Method Info Block Progress

To create the info block we need to put this variable inside our payment method model.

protected $_infoBlockType = 'pay/info_pay';

This variable has the block class path of the info block. The code inside the info block is

<?php
class Excellence_Pay_Block_Info_Pay extends Mage_Payment_Block_Info
{
	protected function _prepareSpecificInformation($transport = null)
	{
		if (null !== $this->_paymentSpecificInformation) {
			return $this->_paymentSpecificInformation;
		}
		$info = $this->getInfo();
		$transport = new Varien_Object();
		$transport = parent::_prepareSpecificInformation($transport);
		$transport->addData(array(
			Mage::helper('payment')->__('Check No#') => $info->getCheckNo(),
			Mage::helper('payment')->__('Check Date') => $info->getCheckDate()
		));
		return $transport;
	}
}

The _prepareSpecificInformation() is basically called by magento, to get an object which has the information we need to display.
The default phtml file used to display this information is ‘app\design\frontend\base\default\template\payment\info\default.phtml’ but if you want to have a custom design you can specify a different phtml file in the block constructor like this

protected function _construct() // sample code, not used in current module.
    {
        parent::_construct();
        $this->setTemplate('payment/info/purchaseorder.phtml'); 
    }

These are all the steps required to create a payment method with form fields.

We have seen in this blog post, how to create basic payment methods, in the next upcoming blog post we will see how to create payment method with payment gateway api integration.