Back to Top

Create a payment extension in Opencart version4

Updated 19 December 2023

In this blog, we will provide a comprehensive guide on creating a payment extension in Opencart version 4. Online payment systems have become indispensable in e-commerce, acting as the backbone of transactions.

To begin, it is essential to familiarize ourselves with the folder structure of an extension.

Folder structure

payment-extensio-folder-structure

Payment extension backend code

Finally, we have our folder structure in place, let’s start creating an extension, we will show ”Webkul Payment” on the checkout page.

admin/controller/payment/example_payment.php

Searching for an experienced
Opencart Company ?
Find out More
<?php
 /**
 * Extension name: Webkul Payment
 * Descrption: Using this extension we will show payment methods on the checkout page.
 * Author: Webkul Software Pvt. Ltd. 
 * 
 */
namespace Opencart\Admin\Controller\Extension\ExamplePayment\Payment;

class ExamplePayment extends \Opencart\System\Engine\Controller {
    
    /**
     * index
     *
     * @return void
     */
    public function index(): void {
        
        $this->load->language('extension/example_payment/payment/example_payment');

        $this->document->setTitle($this->language->get('heading_title'));

        $data['breadcrumbs'] = [];

        $data['breadcrumbs'][] = [
            'text' => $this->language->get('text_home'),
            'href' => $this->url->link('common/dashboard', 'user_token=' . $this->session->data['user_token'])
        ];

        $data['breadcrumbs'][] = [
            'text' => $this->language->get('text_extension'),
            'href' => $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=payment')
        ];

        if (!isset($this->request->get['module_id'])) {
            $data['breadcrumbs'][] = [
                'text' => $this->language->get('heading_title'),
                'href' => $this->url->link('extension/example_payment/payment/example_payment', 'user_token=' . $this->session->data['user_token'])
            ];
        } else {
            $data['breadcrumbs'][] = [
                'text' => $this->language->get('heading_title'),
                'href' => $this->url->link('extension/example_payment/payment/example_payment', 'user_token=' . $this->session->data['user_token'] . '&module_id=' . $this->request->get['module_id'])
            ];
        }

        $data['save'] = $this->url->link('extension/example_payment/payment/example_payment.save', 'user_token=' . $this->session->data['user_token']);
        $data['back'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=payment');

        // getting payment extension config
        $data['payment_example_payment_order_status_id'] = $this->config->get('payment_example_payment_order_status_id');

        // loading order status model
		$this->load->model('localisation/order_status');

        // getting order status as array
		$data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses();

        // zeo zone id
		$data['payment_example_payment_geo_zone_id'] = $this->config->get('payment_example_payment_geo_zone_id');

        // loading geo_zone model
		$this->load->model('localisation/geo_zone');

        // getting all zeo zones
		$data['geo_zones'] = $this->model_localisation_geo_zone->getGeoZones();
        
		$data['payment_example_payment_status'] = $this->config->get('payment_example_payment_status');
		$data['payment_example_payment_sort_order'] = $this->config->get('payment_example_payment_sort_order');

        $data['header'] = $this->load->controller('common/header');
        $data['column_left'] = $this->load->controller('common/column_left');
        $data['footer'] = $this->load->controller('common/footer');

        $this->response->setOutput($this->load->view('extension/example_payment/payment/example_payment', $data));
    }
    
    /**
     * save method
     *
     * @return void
     */
    public function save(): void {
        // loading example payment language
        $this->load->language('extension/example_payment/payment/example_payment');

        $json = [];

        // checking file modification permission
        if (!$this->user->hasPermission('modify', 'extension/example_payment/payment/example_payment')) {
            $json['error']['warning'] = $this->language->get('error_permission');
        }

        if (!$json) {
            $this->load->model('setting/setting');

            $this->model_setting_setting->editSetting('payment_example_payment', $this->request->post);

            $json['success'] = $this->language->get('text_success');
        }

        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }

}

admin/language/en-gb/payment/example_payment.php

<?php
/**
 * Webkul Software
 * 
 * @category Webkul
 * @package Opencart Payment Tutorial
 * @author [Webkul] <[<http://webkul.com/>]>
 * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
 * @license https://store.webkul.com/license.html
 */
// Heading
$_['heading_title']      = 'Webkul Payment';

// Text
$_['text_extension']     = 'Extensions';
$_['text_success']       = 'Success: You have modified Webkul Payment payment module!';
$_['text_edit']          = 'Edit Webkul Payment';

// Entry
$_['entry_order_status'] = 'Order Status';
$_['entry_geo_zone']     = 'Geo Zone';
$_['entry_status']       = 'Status';
$_['entry_sort_order']   = 'Sort Order';

// Error
$_['error_permission']   = 'Warning: You do not have permission to modify payment Webkul Payment!';

admin/view/template/payment/example_payment.twig

{{ header }}{{ column_left }}
<div id="content">
  <div class="page-header">
    <div class="container-fluid">
      <div class="float-end">
        <button type="submit" form="form-payment" data-bs-toggle="tooltip" title="{{ button_save }}" class="btn btn-primary"><i class="fa-solid fa-save"></i></button>
        <a href="{{ back }}" data-bs-toggle="tooltip" title="{{ button_back }}" class="btn btn-light"><i class="fa-solid fa-reply"></i></a></div>
      <h1>{{ heading_title }}</h1>
      <ol class="breadcrumb">
        {% for breadcrumb in breadcrumbs %}
          <li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
        {% endfor %}
      </ol>
    </div>
  </div>
  <div class="container-fluid">
    <div class="card">
      <div class="card-header"><i class="fa-solid fa-pencil"></i> {{ text_edit }}</div>
      <div class="card-body">
        <form id="form-payment" action="{{ save }}" method="post" data-oc-toggle="ajax">
          <div class="row mb-3">
            <label for="input-order-status" class="col-sm-2 col-form-label">{{ entry_order_status }}</label>
            <div class="col-sm-10">
              <select name="payment_example_payment_order_status_id" id="input-order-status" class="form-select">
                {% for order_status in order_statuses %}
                  <option value="{{ order_status.order_status_id }}"{% if order_status.order_status_id == payment_example_payment_order_status_id %} selected{% endif %}>{{ order_status.name }}</option>
                {% endfor %}
              </select>
            </div>
          </div>
          <div class="row mb-3">
            <label for="input-geo-zone" class="col-sm-2 col-form-label">{{ entry_geo_zone }}</label>
            <div class="col-sm-10">
              <select name="payment_example_payment_geo_zone_id" id="input-geo-zone" class="form-select">
                <option value="0">{{ text_all_zones }}</option>
                {% for geo_zone in geo_zones %}
                  <option value="{{ geo_zone.geo_zone_id }}"{% if geo_zone.geo_zone_id == payment_example_payment_geo_zone_id %} selected{% endif %}>{{ geo_zone.name }}</option>
                {% endfor %}
              </select>
            </div>
          </div>
          <div class="row mb-3">
            <label for="input-status" class="col-sm-2 col-form-label">{{ entry_status }}</label>
            <div class="col-sm-10">
              <div class="form-check form-switch form-switch-lg">
                <input type="hidden" name="payment_example_payment_status" value="0"/>
                <input type="checkbox" name="payment_example_payment_status" value="1" id="input-status" class="form-check-input"{% if payment_example_payment_status %} checked{% endif %}/>
              </div>
            </div>
          </div>
          <div class="row mb-3">
            <label for="input-sort-order" class="col-sm-2 col-form-label">{{ entry_sort_order }}</label>
            <div class="col-sm-10">
              <input type="text" name="payment_example_payment_sort_order" value="{{ payment_example_payment_sort_order }}" placeholder="{{ entry_sort_order }}" id="input-sort-order" class="form-control"/>
            </div>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>
{{ footer }}

Now, let’s initiate the development of the frontend code to display the payment methods on the checkout page.

Frontend code

catalog/controller/payment/example_payment.php

<?php
/**
 * Extension name: Webkul Payment
 * Descrption: Using this extension we will show payment methods on the checkout page.
 * Author: Webkul Software Pvt. Ltd. 
 * 
 */
namespace Opencart\Catalog\Controller\Extension\ExamplePayment\Payment;

class ExamplePayment extends \Opencart\System\Engine\Controller
{    
    /**
     * index
     *
     * @return mix
     */
    public function index(): string
    {   
        // loading example payment language
        $this->load->language('extension/example_payment/payment/example_payment');

        $data['language'] = $this->config->get('config_language');

        return $this->load->view('extension/example_payment/payment/example_payment', $data);
    }
    
    /**
     * confirm
     *
     * @return json|string
     */
    public function confirm(): void
    {
        // loading example payment language
        $this->load->language('extension/example_payment/payment/example_payment');

        $json = [];

        if (!isset($this->session->data['order_id'])) {
            $json['error'] = $this->language->get('error_order');
        }
        
        if (!isset($this->session->data['payment_method']) || $this->session->data['payment_method']['code'] != 'example_payment.example_payment') {
            $json['error'] = $this->language->get('error_payment_method');
        }

        if (!$json) {
            $this->load->model('checkout/order');

            $this->model_checkout_order->addHistory($this->session->data['order_id'], $this->config->get('payment_example_payment_order_status_id'));

            $json['redirect'] = $this->url->link('checkout/success', 'language=' . $this->config->get('config_language'), true);
        }

        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }
}

catalog/model/payment/example_payment.php

<?php
/**
 * Extension name: Webkul Payment
 * Descrption: Using this extension we will show payment methods on the checkout page.
 * Author: Webkul Software Pvt. Ltd. 
 * 
 */
namespace Opencart\Catalog\Model\Extension\ExamplePayment\Payment;

class ExamplePayment extends \Opencart\System\Engine\Model {
    	
	/**
	 * getMethods
	 *
	 * @param  mixed $address
	 * @return array
	 */
	public function getMethods(array $address = []): array {

        // loading example payment language
		$this->load->language('extension/example_payment/payment/example_payment');

		if ($this->cart->hasSubscription()) {
			$status = false;
		} elseif (!$this->cart->hasShipping()) {
			$status = false;
		} elseif (!$this->config->get('config_checkout_payment_address')) {
			$status = true;
		} elseif (!$this->config->get('payment_example_payment_geo_zone_id')) {
			$status = true;
		} else {
            // getting payment data using zeo zone
			$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone_to_geo_zone` WHERE `geo_zone_id` = '" . (int)$this->config->get('payment_example_payment_geo_zone_id') . "' AND `country_id` = '" . (int)$address['country_id'] . "' AND (`zone_id` = '" . (int)$address['zone_id'] . "' OR `zone_id` = '0')");

            // if the rows found the status set to True
			if ($query->num_rows) {
				$status = true;
			} else {
				$status = false;
			}
		}

		$method_data = [];
        
		if ($status) {
			$option_data['example_payment'] = [
				'code' => 'example_payment.example_payment',
				'name' => $this->language->get('heading_title')
			];

			$method_data = [
				'code'       => 'example_payment',
				'name'       => $this->language->get('heading_title'),
				'option'     => $option_data,
				'sort_order' => $this->config->get('payment_example_payment_sort_order')
			];
		}

		return $method_data;
	}
}

catalog/language/en-gb/payment/example_payment.php

<?php
/**
 * Webkul Software
 * 
 * @category Webkul
 * @package Opencart Payment Tutorial
 * @author [Webkul] <[<http://webkul.com/>]>
 * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
 * @license https://store.webkul.com/license.html
 */
// Heading
$_['heading_title']        = 'Webkul Payment';

// Error
$_['error_order_id']       = 'No order ID in the session!';
$_['error_payment_method'] = 'Payment method is incorrect!';

catalog/view/template/payment/example_payment.twig

<div class="text-end">
  <button type="button" id="button-confirm" class="btn btn-primary">{{ button_confirm }}</button>
</div>
<script type="text/javascript"><!--
$('#button-confirm').on('click', function () {
    var element = this;

    $.ajax({
        url: 'index.php?route=extension/example_payment/payment/example_payment.confirm&language={{ language }}',
        dataType: 'json',
        beforeSend: function () {
            $(element).button('loading');
        },
        complete: function () {
            $(element).button('reset');
        },
        success: function (json) {
            if (json['error']) {
                $('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
            }

            if (json['redirect']) {
                location = json['redirect'];
            }
        },
        error: function (xhr, ajaxOptions, thrownError) {
            console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
        }
    });
});
//--></script>

Once you have created the extension, you will need to include some information within the module’s “install.json” file. This file supports the following keys: name, version, author, and link.

{
  "name": "Webkul Payment Extension",
  "version": "1.0",
  "author": "Webkul Software Pvt. Ltd.",
  "link": "https://www.webkul.com",
  "instruction": ""
}

Once install.json is inside the directory, you can zip it and name it that ends with .ocmod.zip, then upload it from the Opencart extension installer.

payment extension installer

Upon successful installation of the extension, you can locate it by navigating to “Extensions > Extensions > Payment” where it will be listed for further configuration and customization.

Extensions-1-1
extension-configure

Once the configuration is complete, the “Webkul Payment” payment method will become visible on the checkout page for you to select and proceed with your order.

payment-checkout-1

These instructions will guide you through the process of creating a payment module for Opencart

If you need custom Opencart Development services then feel free to reach us and also explore our exclusive range of Opencart Addons.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


2 comments

  • Keith
    • Yash Gupta (Moderator)
  • Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home