Reading list Switch to dark mode

    Create simple shipping module in Opencart

    Updated 26 April 2023

    In our previous blogs, we learned to create a module in Opencart. Now, we learn to build a simple shipping module in Opencart. Shipping is one of the major part of an e-commerce website. So, we must learn this part for the Opencart.

    For building a shipping module, we will first create a file named simple_shipping.php in admin->language->en-gb->shipping. Here’s our language file:

    <?php
    /**
     * Webkul Software
     * 
     * @category Webkul
     * @package Opencart Module 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']    = 'Simple Shipping';
    
    // Text
    $_['text_shipping']    = 'Shipping';
    $_['text_success']     = 'Success: You have modified Simple Shipping shipping!';
    $_['text_edit']        = 'Edit Simple Shipping Shipping';
    
    // Entry
    $_['entry_tax_class']  = 'Tax Class';
    $_['entry_geo_zone']   = 'Geo Zone';
    $_['entry_status']     = 'Status';
    $_['entry_sort_order'] = 'Sort Order';
    
    // Error
    $_['error_permission'] = 'Warning: You do not have permission to modify Simple Shipping shipping!';

    Now, we will create a file named ‘simple_shipping.php’ in admin->controller->shipping (Opencart version 2.2.0.0). Here’s the code of the controller file.

    <?php
    /**
     * Webkul Software
     * 
     * @category Webkul
     * @package Opencart Module Tutorial
     * @author [Webkul] <[<http://webkul.com/>]>
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license https://store.webkul.com/license.html
     */
    class ControllerShippingSimpleshipping extends Controller {
    	private $error = array();
    
    	public function index() {
    		$this->load->language('shipping/simple_shipping');
    
    		$this->document->setTitle($this->language->get('heading_title'));
    
    		$this->load->model('setting/setting');
    
    		if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
    			$this->model_setting_setting->editSetting('simple_shipping', $this->request->post);
    
    			$this->session->data['success'] = $this->language->get('text_success');
    
    			$this->response->redirect($this->url->link('extension/shipping', 'token=' . $this->session->data['token'], true));
    		}
    
    		$data['heading_title'] = $this->language->get('heading_title');
    		
    		$data['text_edit'] = $this->language->get('text_edit');
    		$data['text_enabled'] = $this->language->get('text_enabled');
    		$data['text_disabled'] = $this->language->get('text_disabled');
    		$data['text_all_zones'] = $this->language->get('text_all_zones');
    		$data['text_none'] = $this->language->get('text_none');
    
    		$data['entry_tax_class'] = $this->language->get('entry_tax_class');
    		$data['entry_geo_zone'] = $this->language->get('entry_geo_zone');
    		$data['entry_status'] = $this->language->get('entry_status');
    		$data['entry_sort_order'] = $this->language->get('entry_sort_order');
    
    		$data['button_save'] = $this->language->get('button_save');
    		$data['button_cancel'] = $this->language->get('button_cancel');
    
    		if (isset($this->error['warning'])) {
    			$data['error_warning'] = $this->error['warning'];
    		} else {
    			$data['error_warning'] = '';
    		}
    
    		$data['breadcrumbs'] = array();
    
    		$data['breadcrumbs'][] = array(
    			'text' => $this->language->get('text_home'),
    			'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], true)
    		);
    
    		$data['breadcrumbs'][] = array(
    			'text' => $this->language->get('text_shipping'),
    			'href' => $this->url->link('extension/shipping', 'token=' . $this->session->data['token'], true)
    		);
    
    		$data['breadcrumbs'][] = array(
    			'text' => $this->language->get('heading_title'),
    			'href' => $this->url->link('shipping/simple_shipping', 'token=' . $this->session->data['token'], true)
    		);
    
    		$data['action'] = $this->url->link('shipping/simple_shipping', 'token=' . $this->session->data['token'], true);
    
    		$data['cancel'] = $this->url->link('extension/shipping', 'token=' . $this->session->data['token'], true);
    
    		if (isset($this->request->post['simple_shipping_tax_class_id'])) {
    			$data['simple_shipping_tax_class_id'] = $this->request->post['simple_shipping_tax_class_id'];
    		} else {
    			$data['simple_shipping_tax_class_id'] = $this->config->get('simple_shipping_tax_class_id');
    		}
    
    		$this->load->model('localisation/tax_class');
    		/**
    		 * Tax classes are used in the case if you want to put any kind of tax on your shipping
    		 */
    		$data['tax_classes'] = $this->model_localisation_tax_class->getTaxClasses();
    
    		if (isset($this->request->post['simple_shipping_geo_zone_id'])) {
    			$data['simple_shipping_geo_zone_id'] = $this->request->post['simple_shipping_geo_zone_id'];
    		} else {
    			$data['simple_shipping_geo_zone_id'] = $this->config->get('simple_shipping_geo_zone_id');
    		}
    
    		$this->load->model('localisation/geo_zone');
    		/**
    		 * Geo zones are used in order to set in which zone(s) you want this shipping service to work
    		 */
    		$data['geo_zones'] = $this->model_localisation_geo_zone->getGeoZones();
    
    		if (isset($this->request->post['simple_shipping_status'])) {
    			$data['simple_shipping_status'] = $this->request->post['simple_shipping_status'];
    		} else {
    			$data['simple_shipping_status'] = $this->config->get('simple_shipping_status');
    		}
    
    		if (isset($this->request->post['simple_shipping_sort_order'])) {
    			$data['simple_shipping_sort_order'] = $this->request->post['simple_shipping_sort_order'];
    		} else {
    			$data['simple_shipping_sort_order'] = $this->config->get('simple_shipping_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('shipping/simple_shipping', $data));
    	}
    
    	protected function validate() {
    		if (!$this->user->hasPermission('modify', 'shipping/simple_shipping')) {
    			$this->error['warning'] = $this->language->get('error_permission');
    		}
    
    		return !$this->error;
    	}
    }

    Now, we will create a file named simple_shipping.tpl in admin->view->template->shipping. Here’s the code for this file:

    <!-- 
    /**
     * Webkul Software
     * 
     * @category Webkul
     * @package Opencart Module Tutorial
     * @author [Webkul] <[<http://webkul.com/>]>
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license https://store.webkul.com/license.html
     */ -->
    <?php echo $header; ?><?php echo $column_left; ?>
    <div id="content">
      <div class="page-header">
        <div class="container-fluid">
          <div class="pull-right">
            <button type="submit" form="form-simple-shipping" data-toggle="tooltip" title="<?php echo $button_save; ?>" class="btn btn-primary"><i class="fa fa-save"></i></button>
            <a href="<?php echo $cancel; ?>" data-toggle="tooltip" title="<?php echo $button_cancel; ?>" class="btn btn-default"><i class="fa fa-reply"></i></a></div>
          <h1><?php echo $heading_title; ?></h1>
          <ul class="breadcrumb">
            <?php foreach ($breadcrumbs as $breadcrumb) { ?>
            <li><a href="<?php echo $breadcrumb['href']; ?>"><?php echo $breadcrumb['text']; ?></a></li>
            <?php } ?>
          </ul>
        </div>
      </div>
      <div class="container-fluid">
        <?php if ($error_warning) { ?>
        <div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> <?php echo $error_warning; ?>
          <button type="button" class="close" data-dismiss="alert">&times;</button>
        </div>
        <?php } ?>
        <div class="panel panel-default">
          <div class="panel-heading">
            <h3 class="panel-title"><i class="fa fa-pencil"></i> <?php echo $text_edit; ?></h3>
          </div>
          <div class="panel-body">
            <form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-simple-shipping" class="form-horizontal">
              <div class="form-group">
                <label class="col-sm-2 control-label" for="input-tax-class"><?php echo $entry_tax_class; ?></label>
                <div class="col-sm-10">
                  <select name="simple_shipping_tax_class_id" id="input-tax-class" class="form-control">
                    <option value="0"><?php echo $text_none; ?></option>
                    <?php foreach ($tax_classes as $tax_class) { ?>
                    <?php if ($tax_class['tax_class_id'] == $simple_shipping_tax_class_id) { ?>
                    <option value="<?php echo $tax_class['tax_class_id']; ?>" selected="selected"><?php echo $tax_class['title']; ?></option>
                    <?php } else { ?>
                    <option value="<?php echo $tax_class['tax_class_id']; ?>"><?php echo $tax_class['title']; ?></option>
                    <?php } ?>
                    <?php } ?>
                  </select>
                </div>
              </div>
              <div class="form-group">
                <label class="col-sm-2 control-label" for="input-geo-zone"><?php echo $entry_geo_zone; ?></label>
                <div class="col-sm-10">
                  <select name="simple_shipping_geo_zone_id" id="input-geo-zone" class="form-control">
                    <option value="0"><?php echo $text_all_zones; ?></option>
                    <?php foreach ($geo_zones as $geo_zone) { ?>
                    <?php if ($geo_zone['geo_zone_id'] == $simple_shipping_geo_zone_id) { ?>
                    <option value="<?php echo $geo_zone['geo_zone_id']; ?>" selected="selected"><?php echo $geo_zone['name']; ?></option>
                    <?php } else { ?>
                    <option value="<?php echo $geo_zone['geo_zone_id']; ?>"><?php echo $geo_zone['name']; ?></option>
                    <?php } ?>
                    <?php } ?>
                  </select>
                </div>
              </div>
              <div class="form-group">
                <label class="col-sm-2 control-label" for="input-status"><?php echo $entry_status; ?></label>
                <div class="col-sm-10">
                  <select name="simple_shipping_status" id="input-status" class="form-control">
                    <?php if ($simple_shipping_status) { ?>
                    <option value="1" selected="selected"><?php echo $text_enabled; ?></option>
                    <option value="0"><?php echo $text_disabled; ?></option>
                    <?php } else { ?>
                    <option value="1"><?php echo $text_enabled; ?></option>
                    <option value="0" selected="selected"><?php echo $text_disabled; ?></option>
                    <?php } ?>
                  </select>
                </div>
              </div>
              <div class="form-group">
                <label class="col-sm-2 control-label" for="input-sort-order"><?php echo $entry_sort_order; ?></label>
                <div class="col-sm-10">
                  <input type="text" name="simple_shipping_sort_order" value="<?php echo $simple_shipping_sort_order; ?>" placeholder="<?php echo $entry_sort_order; ?>" id="input-sort-order" class="form-control" />
                </div>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
    <?php echo $footer; ?>

    As we have to show the shipping cost in the front end. So, we need to create some files in the front end as well and this is the main part of shipping module as well. In the front end, we just need to create two files viz. language file and model file. The shipping calculation is done in the language file.

    Searching for an experienced
    Opencart Company ?
    Find out More

    So, in the front end, we will first create a language file named simple_shipping.php in the catalog->language->en-gb->shipping(Opencart version 2.2.0.0). The language part is here:

    <?php
    /**
     * Webkul Software
     * 
     * @category Webkul
     * @package Opencart Module Tutorial
     * @author [Webkul] <[<http://webkul.com/>]>
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license https://store.webkul.com/license.html
     */
    // Text
    $_['text_title']       = 'Simple Shipping';
    $_['text_description'] = 'Simple Shipping Rate';

    Now, we will head towards the model file of the shipping. This is the most important file as all the calculations are conducted in this file itself.

    So, we will create a file named simple_shipping.php in catalog->model->shipping(Opencart version 2.2.0.0). The model file name must be same as the controller name in the backend, otherwise, the shipping will not be detected by the Opencart. You can make a lot of calculations in this file, I haven’t made any. Here’s the code of model file:

    <?php
    /**
     * Webkul Software
     * 
     * @category Webkul
     * @package Opencart Module Tutorial
     * @author [Webkul] <[<http://webkul.com/>]>
     * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
     * @license https://store.webkul.com/license.html
     */
    class ModelShippingSimpleshipping extends Model {
    	function getQuote($address) {
    		$this->load->language('shipping/simple_shipping');
    		/**
    		 * Query for finding if the customer is from the same zone as selected by the admin in the backend
    		 * @var [type]
    		 */
    		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this->config->get('simple_shipping_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
    
    		if (!$this->config->get('simple_shipping_geo_zone_id')) {
    			$status = true;
    		} elseif ($query->num_rows) {
    			$status = true;
    		} else {
    			$status = false;
    		}
    
    		/**
    		 * This is the cost you want to set for using your shipping service
    		 * Instead of this, you can use the APIs to calculate your shipping rate
    		 * You can also make use of $address array as it contains the address of the customer
    		 * @var integer
    		 */
    		$cost = 10;
    
    		$method_data = array();
    
    		if ($status) {
    			$quote_data = array();
    
    			$quote_data['simple_shipping'] = array(
    				'code'         => 'simple_shipping.simple_shipping',
    				'title'        => $this->language->get('text_description'),
    				'cost'         => $cost,
    				'tax_class_id' => $this->config->get('simple_shipping_tax_class_id'),
    				'text'         => $this->currency->format($this->tax->calculate($cost, $this->config->get('simple_shipping_tax_class_id'), $this->config->get('config_tax')), $this->session->data['currency'])
    			);
    
    			$method_data = array(
    				'code'       => 'simple_shipping',
    				'title'      => $this->language->get('text_title'),
    				'quote'      => $quote_data,
    				'sort_order' => $this->config->get('simple_shipping_sort_order'),
    				'error'      => false
    			);
    		}
    
    		return $method_data;
    	}
    }

    So, we have completed building our simple shipping module. Now, we will install the shipping by heading to Extensions->Shipping->Simple Shipping from the admin panel and after installing you can configure the shipping by enabling it.

    When you will go to the checkout page, we will have a look like this. See image:

    checkout shipping method

    Hope, you will get an idea of building a shipping module in Opencart. In the case of any query, just comment.

    . . .

    Leave a Comment

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


    3 comments

  • Dare
  • DeadSEC Ninja
    • Vikhyat Sharma
  • Back to Top

    Message Sent!

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

    Back to Home