Custom Shipping Carrier Integration | EasyStore - Documentation | JoomShaper
Black Friday sale is live with flat 50% OFF. Sale ends soon! Grab your deal now!

EasyStore

Updated Last: 12 November 2025

Custom Shipping Carrier Integration

This guide will help you build a custom shipping carrier integration plugin for EasyStore. By following these steps, you can connect any external shipping provider’s API to EasyStore’s checkout system and calculate live shipping rates directly in your store. Please download the sample plugin file below:

Download Sample Shipping Plugin

Prerequisites

Before proceeding, ensure that you have the following:

  • Basic knowledge of PHP and Joomla CMS.
  • EasyStore is installed and configured on your Joomla site.

Getting Started

  • Download the provided sample plugin from the documentation.
  • Extract the downloaded file and open it in your preferred code editor.
  • Familiarize yourself with the structure of the plugin files.

1. Understand the Plugin Structure

Every EasyStore shipping plugin follows a specific folder structure. So your custom plugin structure should look like this:

Here:

  • src/Extension contains the plugin main class that ties into EasyStore events. This isolates framework integration logic.
  • src/Helper contains HTTP/API logic so network code is separated from business logic.
  • services/provider.php registers the plugin with Joomla dependency injection. This ensures Joomla constructs your plugin correctly.
  • language/ holds translatable strings. This makes the plugin usable in different locales and consistent with Joomla best practices.
  • assets/images/logo.svg gives a visible brand for admin UI.
  • yourcarrier.xml is the installation and configuration manifest. Joomla needs it to install, provide settings, and show fields in the admin UI.

This structure ensures that EasyStore can recognize, install, and load your plugin correctly.

2. Create the Plugin Manifest

Create a file named yourcarrier.xml (replace “yourcarrier” with the shipping carrier name you are integrating, for example: j&t_express.xml) in the plugin root directory. This file defines your plugin’s metadata, configuration fields, and structure.

Example path: 

project_directory > plugins > easystoreshipping > j&t_express.xml

You can follow a similar structure:

<?xml version="1.0" encoding="utf-8"?>
<extension type="plugin" group="easystoreshipping" method="upgrade">
    <name>PLG_EASYSTORESHIPPING_YOURCARRIER</name>
    <version>1.0.0</version>
    <releaseDate>2025-01-01</releaseDate>
    <author>Your Name</author>
    <authorEmail>[email protected]</authorEmail>
    <authorUrl>https://www.example.com</authorUrl>
    <copyright>Copyright (C) 2025 Your Company. All rights reserved.</copyright>
    <license>GNU General Public License version 3</license>
    <description>PLG_EASYSTORESHIPPING_YOURCARRIER_DESC</description>
    <namespace path="src">YourNamespace\Plugin\EasyStoreShipping\YourCarrier</namespace>

    <files>
        <folder plugin="yourcarrier">services</folder>
        <folder>assets</folder>
        <folder>src</folder>
        <folder>language</folder>
    </files>

    <languages>
        <language tag="en-GB">language/en-GB/en-GB.plg_easystoreshipping_yourcarrier.ini</language>
        <language tag="en-GB">language/en-GB/en-GB.plg_easystoreshipping_yourcarrier.sys.ini</language>
    </languages>

    <config>
        <fields name="params">
            <fieldset name="basic">
                <!-- Basic plugin configuration -->
                <field name="title" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_TITLE"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_TITLE_DESC"
                    default="Your Carrier" />

                <!-- Environment selection -->
                <field name="environment" type="radio"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_ENVIRONMENT_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_ENVIRONMENT_DESC"
                    default="mock" class="btn-group btn-group-yesno">
                    <option value="mock">PLG_EASYSTORESHIPPING_YOURCARRIER_MOCK</option>
                    <option value="test">PLG_EASYSTORESHIPPING_YOURCARRIER_TEST</option>
                    <option value="live">PLG_EASYSTORESHIPPING_YOURCARRIER_LIVE</option>
                </field>

                <!-- API credentials -->
                <field name="api_key" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_API_KEY_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_API_KEY_DESC"
                    showon="environment:live" />
                <field name="api_secret" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_API_SECRET_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_API_SECRET_DESC"
                    showon="environment:live" />

                <!-- Test credentials -->
                <field name="test_api_key" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_TEST_API_KEY_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_TEST_API_KEY_DESC"
                    showon="environment:test" />
                <field name="test_api_secret" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_TEST_API_SECRET_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_TEST_API_SECRET_DESC"
                    showon="environment:test" />

                <!-- Default package dimensions -->
                <field name="default_weight" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_WEIGHT_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_WEIGHT_DESC"
                    default="1.0" />
                <field name="default_length" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_LENGTH_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_LENGTH_DESC"
                    default="10" />
                <field name="default_width" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_WIDTH_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_WIDTH_DESC"
                    default="10" />
                <field name="default_height" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_HEIGHT_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_DEFAULT_HEIGHT_DESC"
                    default="10" />

                <!-- Handling fee -->
                <field name="handling_fee" type="text"
                    label="PLG_EASYSTORESHIPPING_YOURCARRIER_HANDLING_FEE_LABEL"
                    description="PLG_EASYSTORESHIPPING_YOURCARRIER_HANDLING_FEE_DESC"
                    default="0" />
            </fieldset>
        </fields>
    </config>
</extension>

The manifest should include:

  • Basic information like name, version, author, and license
  • File paths to all your plugin folders
  • Configurable parameters such as API credentials, environment mode, and default package dimensions

This XML file tells EasyStore how to install, configure, and run your plugin.

3. Build the Main Plugin Class

Inside src/Extension/, create YourCarrierShipping.php.

This class acts as the main entry point for your shipping carrier. It listens to the onEasyStoreGetShippingMethods event and provides available shipping methods to the checkout page.

Your class should:

  • Fetch store and destination addresses
  • Prepare a shipping rate request for your carrier’s API
  • Retrieve rates using your custom API client
  • Format and return the shipping methods to EasyStore

Key responsibilities:

  • Handle both live and sandbox API environments
  • Apply additional handling fees (if any)
  • Use mock data for development/testing

4. Create the API Client Helper

Inside src/Helper/, create YourCarrierApiClient.php.

This helper handles communication with your carrier’s API. It should:

  • Accept API credentials and base URLs (production or sandbox)
  • Send GET/POST requests to fetch shipping rates
  • Validate required parameters
  • Handle and log API errors gracefully
  • Return parsed JSON responses (or mock data if needed)

Use cURL or any preferred PHP HTTP client to manage API requests securely.

5. Add Language Files

In language/en-GB/, create two files:

  • en-GB.plg_easystoreshipping_yourcarrier.ini

  • en-GB.plg_easystoreshipping_yourcarrier.sys.ini

These files define the text displayed in the EasyStore admin interface, including labels, field names, and descriptions.
You can customize translations for multiple languages by adding folders like language/fr-FR/, language/de-DE/, etc.

6. Register the Plugin Service

In services/, create provider.php.

This file registers your plugin in Joomla’s dependency injection container. It links your plugin’s logic with EasyStore’s plugin system and ensures it loads properly when the store needs shipping rates.

Notes

  • Ensure the plugin group and name match the manifest and the getPlugin call.

  • If your environment does not require DI registration, confirm compatibility with the EasyStore plugin loading mechanism.

Place your carrier’s logo (in SVG format) inside:
assets/images/logo.svg

This logo will appear in the EasyStore admin panel and possibly during checkout to identify your shipping method.

8. Install and Test Your Plugin

  1. Zip your plugin folder (yourcarrier/)
  2. Go to your Joomla admin panel > Extensions > Manage > Install
  3. Upload and install the plugin
  4. Go to Extensions > Plugins and enable it
  5. Open your plugin’s configuration and enter API credentials
  6. Save settings and test your store’s checkout page to confirm rates appear correctly

If you use the test mode, ensure your test data is well structured for realistic rate simulations.

Testing Tips

  • Use browser developer tools and network logs to capture responses.
  • Integrate unit tests for helper methods such as validateShippingParams() and formatShippingMethod() using mocks for HTTP requests.

9. Follow Best Practices

To ensure smooth integration and reliability:

  • Error Handling: Gracefully handle API failures and provide fallback options
  • Logging: Log both requests and responses for debugging purposes
  • Caching: Cache API results temporarily to reduce response time
  • Validation: Validate all request data before sending it to the carrier
  • Security: Never expose API keys or sensitive information in client-side scripts

10. Integration Tips

EasyStore triggers specific events for extensions to interact with the checkout process.
For shipping integrations, the main event is:

onEasyStoreGetShippingMethods

Your plugin should hook into this event to:

  • Fetch destination data
  • Call the carrier’s API
  • Return available shipping methods and their prices

Conclusion

Once you’ve followed all these steps, you’ll have a fully functional shipping carrier plugin that integrates seamlessly with EasyStore. It can fetch live rates, handle sandbox testing, and display accurate shipping options during checkout.

Use this foundation to build custom integrations for any local courier APIs.