Post by Qphoria » Tue Apr 19, 2011 4:02 am

Payment extensions can be created by cloning an existing one that does something similar to what you want.

There are generally 2 types of payment extension methods:
  1. Gateway Hosted (aka: Redirect, offsite, SIM, Simple). This means the customer is redirected to the secure payment gateway site to enter their payment details, then returned back to your store's success page.
    Examples of payments that use this method: Paypal, PayPoint, FirstData Connect, Moneybookers
  2. Merchant Hosted (aka: API, XML, onsite, AIM, Advanced). This means you collect credit card details directly on your site and the customer never leaves your site. This requires you to have your own SSL certificate.
    Examples of payments that use this method: AIM, Paypal Pro, SagePay Direct
The method you choose must be supported by the gateway you are integrating with.

After deciding what method you want, choose one of the example payment extensions listed above as your basis. For this example I will use the Paypal Pro files as my basis for a new extension called "My Pay". Regardless of the fact that Paypal Pro uses the "Merchant Hosted" method, the process of getting the files ready is the same. Only the internal code of the catalog controller file really changes for the method.

1. Clone the Files
Payment extensions in their MVC layout have a minimum of 7 files:

Code: Select all

Copy all the pp_pro files and name the new ones "my_pay".
Be sure to use the correct extension (php or tpl) where appropriate.
Also, be sure you have follow the same folder structure.

2. Global Replaces:
In most cases, you can usually use a good editor like notepad++ to do a "Replace in Files" and simply run that twice for lower and uppercase wording separately:
- replace the word "pp_pro" with "my_pay"
- replace the word "PPPro" with "MyPay"
The upper case only applies to the main class extends (e.g. ControllerPaymentPPPro). In some cases where there are underscores in the main name, like "pp_pro", note that the uppercase version will NOT likely have the underscore. e.g. replace "pp_pro" with "my_pay" but replace "PPPro" with "MyPay"

3. Setup the Admin side
I always start on the admin side first...
- Setup the username/password/secret keys etc fields that the extension will need to access the API
- Setup any special settings for things like transaction type, test/production mode, etc
The admin/controller/payment/my_pay.php file handles all the form and variable control.
The admin/language/english/payment/my_pay.php file shows the text values for the different fields. You can clone and translate this file for any language.
The admin/view/template/payment/my_pay.tpl file is the html file that shows the actual form for configuring the extension settings. These all work together to form the page. You should be able to follow the existing pp_pro code and modify only parts of it to make it work for my_pay

4. Setup the Catalog side
After the admin is setup and working, it is easier to test as you code on the catalog side.
The catalog/language/english/payment/my_pay.php file will have the special error scenarios and the title of the
shipping extension as you want to show it in which ever languages you support.
The catalog/model/payment/my_pay.php file will have checks for geozone and any other special cases you want to add like subtotal must be a certain amount or the store must have a certain currency installed. Usually this is almost never changed and using the existing clone with just the replacing of the name is all that is needed in this file.
The catalog/controller/payment/my_pay.php file is for all the code logic. Use your payment gateway's API document to set up what you need for the extension here. It will of course require you know some advanced php at this point.

That's it. Step 4 is where most of the work gets done, but with the first 3 steps done, it makes it easier to test as you go.

If you have other advice to make this tutorial clearer and easier to understand, or if you think I missed a step, please PM me with tips.


User avatar


Tue Jul 22, 2008 3:02 am

Post by alexmath » Sat Oct 28, 2017 6:20 am

Thanks for the tutorial. I have been trying to follow this for a while but not successful so far hence a few questions:
1. I am not sure for what version this was intended but currently OC 3x, there are some significant changes in the file structure. Anyway, will putting the files in their corresponding places suffice or do i need to create extra files?
2. Assuming I want to create an extension to handle just credit/debit cards and only deal with the banks involved; is that possible? What's the minimum amount of data/requirements I need for that. To which of the two gateway types you have mentioned above does this belong? Thank you.

New member


Sat Sep 23, 2017 7:35 am

Post by IP_CAM » Sun Oct 29, 2017 1:09 am

It would probably be much simpler, to just download some
free extensions on this, and check on how they are made to work: ... load_id=55
Just an idea! ;)

My Github OC Site:
5'300 + FREE OC Extensions, on the World's largest private Github OC Repository Archive Site.

User avatar
Legendary Member


Tue Mar 04, 2014 1:37 am
Location - Switzerland

Post by » Tue Aug 25, 2020 7:19 am

For Opencart 3, here is the tutorial:
How to create a payment module or extension in the Opencart 3? Developer guide Part I of III
How to create a payment module or extension in the Opencart 3? Developer guide Part II of III

Here are some of the normal steps that happen in the payment section:
  • When the customer is ready to pay for goods or services on your website, they select the payment method on your website.
  • There are two ways of payment gateway processing:
  • One is Off-site payment processing
    In the off-site payment, the website is redirected to the payment service website and payment is made on the payment service website.
    There will be no place to enter the credit card information or login to payment gateways.
    The payment gateway provides a Payment form in which we matched similar fields.
    Data are passed from Form.
    Need return URL or cancel URL so that when payment is a success it returns to that return URL and if the payment fails then it returns to the cancel URL.
    Skrill, Paypal Standard, Liqpay, etc. are the default payment modules for Off-site payment processing.
  • Another is on-site payment processing.
    In the on-site payment, the payment is made on the same site, the payment processing is done through APIs.
    The payment gateway provides a JSON request.
    There will be a form where they can enter the credit card details or bank information etc.
    Data are passed as JSON format.
    It will return success or failure messages through API in JSON format. Once you get the success or failure data then further processing can be done in the website server and the message can be shown or redirected to the success page.’s AIM, Paypal Pro, Square, etc. are the default payment modules for on-site payment processing.
  • Mostly the payment gateway provides us with the form method type, action URL, and fields that we can pass to them for processing. Once you click the “Confirm Order” button, these hidden fields data are passed to the payment gateway and processing happens in their website.
  • When a payment gateway process the payment and is successful then the customer is directed to the success URL.
  • When the payment method is On-side payment processing then data are passed from website Server to payment gateway through API, as we are using Opencart which is builtin PHP so we use CURL to call the API.
  • The website server passes the data to the payment gateway through API, mostly CURL is used to communicate with the APIs, we pass JSON-formatted HTTP requests to the API endpoint in either the sandbox or production environment of the payment gateway.
  • Payment gateway requests authorization for the payment from the customer’s bank, third party provider, or card issuer.
  • The bank/provider/card issuer approves or rejects the transaction.
  • Payment gateway sends the success or failure response, containing the transaction result, and calls the Callback where the website server can process the data.
  • The website server processes data returned by the payment gateway and it redirects to the success page.
All codes are defined at ... ii-of-iii/

Opencart 4 book
Blog free tips and tricks
Free extensions
OpenCart Tutorials
OpenCart Tutorials Youtube Video for developers

User avatar
New member


Fri Feb 02, 2018 11:51 pm

Post by br0therjay1 » Tue Nov 03, 2020 5:11 pm

Hi guys,

Looking for some help in adding functionality to my cloned extension. I have successfully cloned the 'Bank Transfer' payment extension, and now am looking to add some extra functionalities to it:

I'm looking into adding the 'allowed categories' and 'allowed customer groups' settings for my extension. For the purpose of my question, allow me to just focus on 'allowed categories'. These options are taken from the lay-buy payment extension

i have tried copying these codes
and added them into my admin/controller/.php file

added this line into the admin/language/.php file

added this line into the admin/view/.twig file

and unfortunately, it's not working. I'm pretty sure I'm missing a few things more, but hope that I could be pointed the right way.

More notes:
Yes, there are the respective files created for

I didn't see any required changes that I need to add into any of the above files in the catalog folders. Please correct me if I'm wrong.

Why is there no admin/model file?
- This was a copy of the 'bank transfer' extension, and it too did not have a admin/model/ file.

Did you change the files correctly? if its "payment_laybuy_category" of course it wont work, it needs to be "payment_EXTENSIONNAME_category"
- yep I made all the necessary changes, photos above are just for context purposes.

So yeah, anybody can provide advice, btw I'm no super awesome web developer, I'm self taught, and trying to learn this, thanks..



Wed Sep 23, 2020 2:00 pm

Post by SohBH » Thu Jul 13, 2023 4:52 pm

In the view file, we have an input field of type "hidden" with the name attribute set to "payment_bank_category". This input field allows you to store a value in the form data without displaying it to the user. When the form is submitted, the value of this input field will be included in the POST data and can be accessed in the controller using $this->request->post['payment_bank_category'].

controller (simplified example)

Code: Select all

if (isset($this->request->post['payment_bank_category'])) {
    $data['payment_bank_category'] = $this->request->post['payment_bank_category'];
} else {
    $data['payment_bank_category'] = array();

Code: Select all

<input type="hidden" name="payment_bank_category" value="{{ payment_bank_category }}" />

Web Development for service businesses serious about online growth

User avatar
Active Member


Mon Nov 02, 2020 12:01 am
Location - Malaysia
Who is online

Users browsing this forum: No registered users and 0 guests