How To Create A Shipping Module

A Basic Example

/includes/modules/shipping/sm_my_shipping_module.inc.php:


<?php

  class sm_my_shipping_module {
    public $id = __CLASS__;
    public $name = 'My Shipping Module';
    public $description = '';
    public $author = 'ACME Corp.';
    public $version = '1.0';
    public $website = 'https://www.acme.com';

    public function options($items, $subtotal, $tax, $currency_code, $customer) {

      if (empty($this->settings['status'])) return;

      return [
        'title' => $this->name,
        'options' => [
          [
            'id' => 'option_1',
            'icon' => $this->settings['icon'],
            'name' => 'Option 1',
            'description' => 'This is the description for option 1',
            'fields' => '',
            'cost' => $this->settings['fee_1'],
            'tax_class_id' => $this->settings['tax_class_id'],
            'incoterm' => $this->settings['incoterm'],
            'exclude_cheapest' => false,
            'error' => '',
          ],
          [
            'id' => 'option_2',
            'icon' => $this->settings['icon'],
            'name' => 'Option 2',
            'description' => 'This is the description for option 2',
            'fields' => '',
            'cost' => $this->settings['fee_2'],
            'tax_class_id' => $this->settings['tax_class_id'],
            'incoterm' => $this->settings['incoterm'],
            'exclude_cheapest' => false,
            'error' => '',
          ],
        ],
      ];
    }

    public function settings() {
      return [
        [
          'key' => 'status',
          'default_value' => '1',
          'title' => language::translate(__CLASS__.':title_status', 'Status'),
          'description' => language::translate(__CLASS__.':description_status', ''),
          'function' => 'toggle("e/d")',
        ],
        [
          'key' => 'icon',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_icon', 'Icon'),
          'description' => language::translate(__CLASS__.':description_icon', 'Web path of the icon to be displayed.'),
          'function' => 'text()',
        ],
        [
          'key' => 'fee_1',
          'default_value' => '10',
          'title' => 'Fee 1',
          'description' => 'This is the fee for option 1',
          'function' => 'decimal()',
        ],
        [
          'key' => 'fee_2',
          'default_value' => '10',
          'title' => 'Fee 2',
          'description' => 'This is the fee for option 2',
          'function' => 'decimal()',
        ],
        [
          'key' => 'tax_class_id',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_tax_class', 'Tax Class'),
          'description' => language::translate(__CLASS__.':description_tax_class', 'The tax class for the shipping cost.'),
          'function' => 'tax_class()',
        ],
        [
          'key' => 'incoterm',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_incoterm', 'Incoterm'),
          'description' => language::translate(__CLASS__.':description_incoterm', 'The incoterm set by this module.'),
          'function' => 'incoterm()',
        ],
        [
          'key' => 'priority',
          'default_value' => '0',
          'title' => language::translate(__CLASS__.':title_priority', 'Priority'),
          'description' => language::translate(__CLASS__.':description_priority', 'Process this module by the given priority value.'),
          'function' => 'number()',
        ],
      ];
    }
  }

Class Methods

options($items, $subtotal, $tax, $currency_code, $customer)

This method is called by the checkout page requesting available shipping options.

If you need to collect some additional data, add your custom input fields to the 'fields' element. They can then be used in a later event in the shipping module.

    public function options($items, $subtotal, $tax, $currency_code, $customer) {
      return [
        'title' => $this->name,
        'options' => [
          [
            'id' => 'option_1',
            'icon' => $this->settings['icon'],
            'name' => 'Option 1',
            'description' => 'This is the description for option 1',
            'fields' => '<input type="text" name="foo" value="'. @$this->userdata['foo'] .'" />' . PHP_EOL
                      . '<input type="text" name="bar" value="'. @$this->userdata['bar'] .'" />',
            'cost' => $this->settings['fee_1'],
            'tax_class_id' => $this->settings['tax_class_id'],
            'incoterm' => $this->settings['incoterm'],
            'exclude_cheapest' => false,
          ],
        ],
      ];
    }

select($module_id, $option_id)

The method is triggered upon an option of the module being selected, making it possible to verify any input data.

    public function select($module_id, $option_id) {
    // Do something
      // ...
    }

after_process($order)

This method is triggered after the order has been created, making it possible to automate e.g. booking of shipping.

    public function after_process($order) {
    // Do something
      // ...

    // Save order
      $order->save();
    }

install()

The method is triggered upon installing the module. Good for creating necessary database tables or such.

    public function install() {
    // Do something
      // ...
    }

uninstall()

The method is triggered upon uninstalling the module. Good for cleaning up database tables and such.

    public function uninstall() {
    // Do something
      // ...
    }

update()

The method is triggered upon changing the module configuration. Good for updating database tables and such.

    public function update() {
    // Do something
      // ...
    }

settings()

This method returns a settings structure with editable parameters. Mandatory parameters are status, icon and priority.

    public function settings() {
      return [
        [
          'key' => 'status',
          'default_value' => '1',
          'title' => language::translate(__CLASS__.':title_status', 'Status'),
          'description' => language::translate(__CLASS__.':description_status', ''),
          'function' => 'toggle("e/d")',
        ],
        [
          'key' => 'icon',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_icon', 'Icon'),
          'description' => language::translate(__CLASS__.':description_icon', 'Web path of the icon to be displayed.'),
          'function' => 'text()',
        ],
        [
          'key' => 'weight_class',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_weight_class', 'Weight Class'),
          'description' => language::translate(__CLASS__.':description_weight_class', 'The weight class for the rate table.'),
          'function' => 'weight_class()',
        ],
        [
          'key' => 'geo_zone_id',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_zone', 'Zone') . language::translate(__CLASS__.':title_geo_zone', 'Geo Zone'),
          'description' => language::translate(__CLASS__.':description_geo_zone', 'Geo zone to which the cost applies.'),
          'function' => 'geo_zone()',
        ],
        [
          'key' => 'rate_table',
          'default_value' => '5:8.95;10:15.95',
          'title' => language::translate(__CLASS__.':title_rate_table', 'Rate Table'). language::translate(__CLASS__.':title_rate_table', 'Rate Table'),
          'description' => language::translate(__CLASS__.':description_rate_table', 'Ascending rate table of the shipping cost. The format must be weight:cost;weight:cost;.. (I.e. 5:8.95;10:15.95;..)'),
          'function' => 'text()',
        ],
        [
          'key' => 'tax_class_id',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_tax_class', 'Tax Class'),
          'description' => language::translate(__CLASS__.':description_tax_class', 'The tax class for the shipping cost.'),
          'function' => 'tax_class()',
        ],
        [
          'key' => 'incoterm',
          'default_value' => '',
          'title' => language::translate(__CLASS__.':title_incoterm', 'Incoterm'),
          'description' => language::translate(__CLASS__.':description_incoterm', 'The incoterm set by this module.'),
          'function' => 'incoterm()',
        ],
        [
          'key' => 'priority',
          'default_value' => '0',
          'title' => language::translate(__CLASS__.':title_priority', 'Priority'),
          'description' => language::translate(__CLASS__.':description_priority', 'Process this module by the given priority value.'),
          'function' => 'number()',
        ],
      ];
    }

Revisions

Top Editors
Recently Edited Articles