Skip to main content

Overview

Shipping methods calculate shipping costs during checkout based on order weight, dimensions, destination, and other factors.

Shipping Method Structure

extension/myvendor/
├── admin/controller/shipping/myshipping.php
├── admin/language/en-gb/shipping/myshipping.php
├── admin/view/template/shipping/myshipping.twig
└── catalog/model/shipping/myshipping.php

Admin Controller

From admin/controller/extension/opencart/shipping/flat.php:8:
<?php
namespace Opencart\Admin\Controller\Extension\Opencart\Shipping;

class Flat extends \Opencart\System\Engine\Controller {
    public function index(): void {
        $this->load->language('extension/opencart/shipping/flat');
        
        $this->document->setTitle($this->language->get('heading_title'));
        
        $data['save'] = $this->url->link('extension/opencart/shipping/flat.save', 'user_token=' . $this->session->data['user_token']);
        $data['back'] = $this->url->link('marketplace/extension', 'user_token=' . $this->session->data['user_token'] . '&type=shipping');
        
        $data['shipping_flat_cost'] = $this->config->get('shipping_flat_cost');
        
        // Tax Class
        $this->load->model('localisation/tax_class');
        $data['shipping_flat_tax_class_id'] = (int)$this->config->get('shipping_flat_tax_class_id');
        $data['tax_classes'] = $this->model_localisation_tax_class->getTaxClasses();
        
        // Geo Zone
        $this->load->model('localisation/geo_zone');
        $data['shipping_flat_geo_zone_id'] = $this->config->get('shipping_flat_geo_zone_id');
        $data['geo_zones'] = $this->model_localisation_geo_zone->getGeoZones();
        
        $data['shipping_flat_status'] = $this->config->get('shipping_flat_status');
        $data['shipping_flat_sort_order'] = $this->config->get('shipping_flat_sort_order');
        
        $this->response->setOutput($this->load->view('extension/opencart/shipping/flat', $data));
    }
    
    public function save(): void {
        $this->load->language('extension/opencart/shipping/flat');
        
        $json = [];
        
        if (!$this->user->hasPermission('modify', 'extension/opencart/shipping/flat')) {
            $json['error'] = $this->language->get('error_permission');
        }
        
        if (!$json) {
            $this->load->model('setting/setting');
            $this->model_setting_setting->editSetting('shipping_flat', $this->request->post);
            
            $json['success'] = $this->language->get('text_success');
        }
        
        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }
}

Shipping Model

Catalog model calculates shipping rates:
<?php
namespace Opencart\Catalog\Model\Extension\Myvendor\Shipping;

class Myshipping extends \Opencart\System\Engine\Model {
    /**
     * Get Quote
     *
     * @param array $address Shipping address
     *
     * @return array Quote with rates
     */
    public function getQuote(array $address): array {
        $this->load->language('extension/myvendor/shipping/myshipping');
        
        // Check if enabled for this geo zone
        if ($this->config->get('shipping_myshipping_geo_zone_id')) {
            $this->load->model('localisation/zone');
            
            $zone_to_geo_zones = $this->model_localisation_zone->getZoneToGeoZones();
            
            $match = false;
            
            foreach ($zone_to_geo_zones as $zone_to_geo_zone) {
                if ($zone_to_geo_zone['zone_id'] == $address['zone_id'] &&
                    $zone_to_geo_zone['geo_zone_id'] == $this->config->get('shipping_myshipping_geo_zone_id')) {
                    $match = true;
                    break;
                }
            }
            
            if (!$match) {
                return [];
            }
        }
        
        // Calculate shipping cost
        $cost = $this->calculateCost($address);
        
        $quote_data = [];
        
        $quote_data['myshipping'] = [
            'code'         => 'myshipping.myshipping',
            'name'         => $this->language->get('text_description'),
            'cost'         => $cost,
            'tax_class_id' => $this->config->get('shipping_myshipping_tax_class_id'),
            'text'         => $this->currency->format(
                $this->tax->calculate($cost, $this->config->get('shipping_myshipping_tax_class_id'), $this->config->get('config_tax')),
                $this->session->data['currency']
            )
        ];
        
        return [
            'code'         => 'myshipping',
            'name'         => $this->language->get('heading_title'),
            'quote'        => $quote_data,
            'sort_order'   => $this->config->get('shipping_myshipping_sort_order'),
            'error'        => false
        ];
    }
    
    /**
     * Calculate shipping cost based on cart and address
     *
     * @param array $address
     *
     * @return float
     */
    private function calculateCost(array $address): float {
        // Get cart weight
        $weight = $this->cart->getWeight();
        
        // Base cost
        $cost = (float)$this->config->get('shipping_myshipping_base_cost');
        
        // Add weight-based cost
        $cost_per_kg = (float)$this->config->get('shipping_myshipping_cost_per_kg');
        $cost += $weight * $cost_per_kg;
        
        // Add distance-based cost (if applicable)
        if ($address['country_id'] != $this->config->get('config_country_id')) {
            $cost += (float)$this->config->get('shipping_myshipping_international_surcharge');
        }
        
        return $cost;
    }
}

Real-Time Rate Calculation

For API-based shipping (UPS, FedEx, etc.):
private function getRealTimeRates(array $address): array {
    // Prepare package dimensions
    $package = [
        'weight' => $this->cart->getWeight(),
        'length' => 10,
        'width'  => 10,
        'height' => 10
    ];
    
    // API request
    $curl = curl_init();
    
    curl_setopt($curl, CURLOPT_URL, 'https://api.shippingprovider.com/rates');
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode([
        'origin' => [
            'postal_code' => $this->config->get('config_postcode'),
            'country_code' => $this->config->get('config_country_code')
        ],
        'destination' => [
            'postal_code' => $address['postcode'],
            'country_code' => $address['iso_code_2']
        ],
        'package' => $package
    ]));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $this->config->get('shipping_myshipping_api_key')
    ]);
    
    $response = curl_exec($curl);
    curl_close($curl);
    
    $rates = json_decode($response, true);
    
    $quote_data = [];
    
    if (isset($rates['services'])) {
        foreach ($rates['services'] as $service) {
            $code = 'myshipping.' . $service['service_code'];
            
            $quote_data[$code] = [
                'code'         => $code,
                'name'         => $service['service_name'],
                'cost'         => $service['total_cost'],
                'tax_class_id' => $this->config->get('shipping_myshipping_tax_class_id'),
                'text'         => $this->currency->format($service['total_cost'], $this->session->data['currency'])
            ];
        }
    }
    
    return $quote_data;
}

Multiple Service Levels

Offer different shipping speeds:
public function getQuote(array $address): array {
    $quote_data = [];
    
    // Standard shipping
    $quote_data['standard'] = [
        'code'         => 'myshipping.standard',
        'name'         => 'Standard Shipping (5-7 days)',
        'cost'         => 10.00,
        'tax_class_id' => $this->config->get('shipping_myshipping_tax_class_id'),
        'text'         => '$10.00'
    ];
    
    // Express shipping
    $quote_data['express'] = [
        'code'         => 'myshipping.express',
        'name'         => 'Express Shipping (2-3 days)',
        'cost'         => 25.00,
        'tax_class_id' => $this->config->get('shipping_myshipping_tax_class_id'),
        'text'         => '$25.00'
    ];
    
    // Overnight shipping
    $quote_data['overnight'] = [
        'code'         => 'myshipping.overnight',
        'name'         => 'Overnight Shipping',
        'cost'         => 50.00,
        'tax_class_id' => $this->config->get('shipping_myshipping_tax_class_id'),
        'text'         => '$50.00'
    ];
    
    return [
        'code'       => 'myshipping',
        'name'       => 'My Shipping',
        'quote'      => $quote_data,
        'sort_order' => $this->config->get('shipping_myshipping_sort_order'),
        'error'      => false
    ];
}

Next Steps

Creating Themes

Build custom themes

Cart Library

Work with cart data