Creating a Shipping Method in Magento 2
Creating a Shipping Method in Magento 2

Creating a Shipping Method in Magento 2

Published November 30, 2017 in Classy Llama, Development
A look at CSS and Less in Magento 2
A Look at CSS and Less in Magento 2
October 17, 2017
Top 3 Tips for Making Holiday Shipping Easier
Top 3 Tips for Making Holiday Shipping Easier
December 6, 2017

There are existing extensions available for many of the shipping carriers that you may choose to utilize on your Magento 2 site, but what about a shipping method of your own? Adding a custom shipping method like this is a straightforward approach that requires only a handful of files in order to implement – five, to be exact.

Let’s create a ‘Customer Pickup’ shipping method that is used to provide customers who are local to our warehouse the option of picking up their order as opposed to paying for shipping.

Our new shipping method will get its own extension, and as with other custom extensions, it will reside within a vendor folder in our site’s app\code\ folder. We will be using the following path for our new extension:app\code\ClassyLlama\CustomerPickup For the remainder of this article, all file and path references will be in relation to the CustomerPickup folder.

We start by creating the two files that are required for all custom extensions: registration.php and module.xml. I will assume you are familiar enough with Magento 2 development to know what these two files are and why they are required, so I won’t go into depth about that here. If you are new to creating extensions in Magento 2, the DevDocs’ PHP Developer Guide is a must-read.

Configuration files

First, we have to tell Magento about our new shipping method’s existence; this is accomplished with the system.xml and config.xml files. The system.xml file will define the configuration settings available for our shipping method in the Magento 2 admin (in STORES > Configuration > SALES > Shipping Methods) and the config.xml file will set default values for those settings.

There are certain configuration settings for shipping carriers that are expected by Magento and thus should be included in all shipping methods:

  • active – This boolean value indicates whether this shipping method is active or not.
  • model – The path to the shipping method’s model.
  • title – The name of the shipping “carrier” that will be displayed in the frontend.
  • sallowspecific – This boolean value indicates whether this shipping method should be available for all countries or only those specified.
  • sort_order – This parameter tells Magento wherein the list of available shipping methods this method will display.

There are some additional settings we are including as well:

  • price – This shipping method will have a price of $0.00.
  • name – The name of this shipping method to be displayed to the customer.
  • showmethod – Whether or not to show this shipping method even when not applicable.

Our extension’s system.xml file has a default structure that should be followed:

  • Configuration elements must be created using the following node structure:
    <system>
    <section>
    <group>
  • The <section> node must have an id value of "carriers".
  • The <group> node must have an id value equal to our new shipping code, in this case customerpickup.

By building the XML file in this manner, Magento knows where to place the configuration settings in the backend (in this case with the other shipping methods) and how to retrieve them when called.

etc\adminhtml\system.xml

Our extension’s config.xml (the file that defines the default values for the settings defined in system.xml) also has layout rules that must be followed:

  • Configuration elements must be created under the main node of <default> with a child node of <carriers> in a child node named with the shipping method code we’ve created, in this case <customerpickup>.

etc\config.xml

The Shipping Method Class

At this point, we’ve created the extension, but it doesn’t yet do anything for us. To get the extension working for us, we need to create the model at app\code\ClassyLlama\CustomerPickup\Model\Carrier\CustomerPickup.php.

There are some specific items worth noting when creating our custom shipping method’s class:

  • Every shipping method’s class in Magento 2 must extend \Magento\Shipping\Model\Carrier\AbstractCarrier and implement \Magento\Shipping\Model\Carrier\CarrierInterface.
  • Every shipping method’s class must include a minimum of two methods: getAllowedMethods and collectRates.
    • The method getAllowedMethods:
      • Must return an array of the available shipping options for our shipping method (e.g. ‘Standard Delivery”, ‘Expedited Delivery’).
      • Can include as few or as many shipping options as are applicable to the method. In our example case, there is only the one – ‘Customer Pickup’.
    • The method collectRates returns either:
      • A boolean false, which effectively disables the shipping method, excluding it from a list of shipping options.
      • An instance of \Magento\Shipping\Model\Rate\Result instantiated via a Magento factory.
        • If returning an instance of Result, it can have as many, or as few, methods appended to it as is applicable; each appended method is a factory-generated instance of \Magento\Quote\Model\Quote\Address\RateResult\Method. This model represents a shipping method and has its details set within it (e.g. Carrier code and title, method code and title, Price). In our example below, we are only attaching a single method, but the process can be repeated as many times as necessary.
  • The $_code variable in the class must be set to the unique shipping code chosen for our custom shipping method, in this case customerpickup.
  • The method $this->getConfigData is used to retrieve the configuration settings that are defined in the extension’s system.xml file (e.g. $this->getConfigData(‘name’) will return the value set for the method’s name).

app/code/ClassyLlama/CustomerPickup/Model/Carrier/CustomerPickup.php

Our new shipping method can be customized however we need it to be. For example, we could check whether any items in the customer’s order are being drop shipped, and if so, not offer ‘Customer Pickup’ as an available shipping method; we could also disable our shipping method for orders placed from outside of specific regions.

Configure and test the shipping method

After enabling our new extension and clearing the cache, we can visit our site’s admin section (e.g. https://mystore.xyz/backend/admin) and head to the Shipping Methods section at STORES > Configuration > SALES > Shipping Methods. We should now see a page similar to the one below, with our new shipping method’s default configuration settings we defined earlier in the system.xml file.

To test our new shipping method, we just have to head to our store’s website like a customer would, create a qualifying order (don’t forget what rules you had previously put in place in the model), and head to the shopping cart. As you can see in the screenshot below, our new shipping method is available for us to choose.

If we proceed to checkout, we see in the screenshot below that we again have the option of Customer Pickup as our shipping method.

Conclusion

We have now completed the creation, configuration, and testing of a custom shipping method that allows our local customers to save on the cost of shipping and pick their qualifying orders up at our warehouse at their convenience.

This tutorial can be used to tailor your online store’s shipping logic to match what is right for you and your business, rather than being tied to native rate models that may not fit every scenario. Custom shipping methods can be a powerful tool; and since the creation process is straightforward, it makes for a handy tool in your Magento tool belt!

2 Comments

  1. Guilherme says:

    Great post, it’s been very useful!

    However, if a customer chooses to pickup his order, he shouldn’t need to fill up his Shipping Address during the checkout.

    And the order confirmation information should inform the pickup address (which could be set on Admin) as the delivery address.

    Is there a way to do that?

    • Guilherme,

      You bring up a good point. A savvy user may actually be able to circumvent sales tax by using a shipping address in a nontaxable region, but then selecting the option of picking up the order in person, which means the order should be taxed.

      I would imagine the solution would still require the customer to choose a shipping address, since this is necessary to display shipping methods, but if they were to select the “Customer Pickup” shipping method, continuing to the payment step would replace their shipping address with a taxable one (e.g. the merchant’s address). However, addressing that in detail is beyond the scope of this particular blog post.

Leave a Reply

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

Related postsView all
October 17, 2017

A Look at CSS and Less in Magento 2

Magento 2 leverages the enormous power of CSS pre-processing (via Less) to make theme customization intuitive and easily maintainable through features like variables, mixins, and imports. […]
October 9, 2017

Canonical Tags: Did You Get It Right on Your Magento Site?

A few weeks ago, a llama posed a seemingly simple question: “Does anyone know the details of canonical URLs and pagination?”. But here’s the thing about […]
April 28, 2017

Creating a Custom Widget in Magento 2

Sometimes you need to change the functionality of a widget or increase the selection of customization options, and in order to do this you need to create your own. In this article we will be looking at how to create a widget that extends the functionality of a core widget.
Most Recent PostsView all
February 12, 2018

Display Configurable Product Price Ranges in Magento 2

Today we’re going to look at the advantages of using configurable products and how we can update how their prices display on Magento 2 product listing […]
January 11, 2018

Selling Bundles the Right Way on Magento 2

Magento has a variety of product types to help you find the right way to sell your products. There are downloadable products for digital items (such […]
December 20, 2017

What does ROAS Really Mean?

ROAS (Return on Ad Spend) is a popular metric that can help businesses evaluate if their campaigns are successful. It’s a simple calculation of ad spend […]