Shipping

Integration Overview

In this guide, you'll learn how to integrate a 3rd party shipping provider into your checkout to calculate shipping costs.

This guide uses the Shippo API as an integration example.

Let’s get started

To start, create a copy of the open source ChopChop demo store using the Chec CLI:

$> chec login
$> chec demo-store commercejs-chopchop-demo chopchop-shippo
✔ Downloaded commercejs-chopchop-demo to /Users/guymarriott/projects/tmp/chopchop-shippo

chopchopmarketing

We now have a store, and products that make sense for physical fulfillments. Now, in the Chec dashboard, add the shipping zones we want to ship to. This is an important step as we still want to use Commerce.js to provide valid destination countries. Next, create a single zone with the Chec Dashboard called “Valid Shippo destinations”, and add a single rate called “unused” (priced at $0.00). You’ll see why we’ve named this “unused” later.

Edit shipping zones

Finally, ensure that this rate is enabled on each product that requires a delivery.

Set shipping options

Configuring shipping costs with Shippo

Next, let’s look at the requirements for calculating shipping costs with Shippo. Looking at their API reference, they have a create a new shipment API that provides the information we need. The response provides us shipping rates, with carrier names and estimated shipping dates. We can then eventually use this shipment to manage the label and interaction with the carrier.

We need a few things to power this API; the origin address, the destination address, and details on the packages we wish to send. Our destination address is easy, the customer must provide that anyway. The origin address is information that is entered into the Chec dashboard, and can be fetched with Commerce.js. The details required for the parcels is a little more involved. Each product will have its own attributes. Luckily, the Chec API allows us to add arbitrary attributes to our products using the meta attribute on any resource. We can specify our package dimensions and weights with this API:

$> curl -X PUT "https://api.chec.io/v1/products/prod_8XO3wpgq4lYAzQ" \
    -H "Content-Type: application/json" \
    -H "X-Authorization: sk_abc123" \
    -d "{
          \"product\": {
            \"meta\": {
              \"shipping\": {
                \"height\": 3,
                \"width\": 5,
                \"length\": 36,
                \"weight\": 550,
                \"distance_unit\": \"cm\",
                \"mass_unit\": \"g\"
              }
            }
          }
        }"

In this case, we are setting the dimensions and weight for the “Walnut Cook's Tools” product. We can do the same thing for each product being sold.

Connecting to the update checkout API

Now that we have configured the Shippo API, we now need to tie it into the existing ChopChop store using Commerce.js and the update checkout API. The update checkout API we’ve developed is a secret key API. It allows you to take control of specific requirements of your checkout, which need to be fulfilled by the customer using the checkout. If this were a public API, a tech savvy user could update their own checkout in order to pay less — a security hole for sure. The approach that we’ve taken here is to develop a serverless function that will be a drop-in replacement for Commerce.js’s get shipping methods API.

You can see the finished serverless function here: https://github.com/chec/shippo-integration-example/blob/master/pages/api/shipping.js

I’ve created a function, using the Next.js API routes feature, that takes the checkout token and delivery address for the checkout. We’ll use Commerce.js to fetch details about the products in the checkout, and at the same time, fetch details about the merchant so that I will have the origin address (where the package originates from). Once I have details on the line items in the checkout, we can fetch the specific details for each product in the checkout, including the dimension and weight data we attached to each product earlier. We can then use this information to create the shipment in Shippo.

The final step here is where the real power of the new API we’ve developed is shown. We can use this secret key API to completely replace the shipping options provided by Commerce.js. Normally when we use Commerce.js to fetch shipping methods, the zero dollar “unused” shipping rate will be returned as it’s the rate configured in the dashboard. What we can do instead is use the shipping rates provided by Shippo and update the checkout so that they are the only valid rates for shipping. In the serverless function that is being used, the update checkout API sets the shipping methods, and the response will give me the new state of the checkout after that change is applied. We can then return the valid shipping methods from the new API route.

What does this look like in practice? Well, now we can cURL the new API:

$> curl -X GET "http://localhost:3000/api/shipping?token=chkt_2JwrB4pbWgXjwP&address={\"name\":\"Guy\",\"street1\":\"301/318 Homer St\",\"city\":\"Vancouver\",\"zip\":\"V6B2V2\",\"state\":\"BC\",\"country\":\"CA\"}" \
    -H "Accept: application/json"

We’ve provided the checkout token and address, and the API route will use this information to:

  • Fetch the origin address from the merchant details
  • Pull the items chosen by the customer for the checkout
  • Generate a list of packages that will be sent to the customer should they complete the order
  • Use Shippo to get real quotes from carriers to deliver the packages
  • Update the Commerce.js checkout so the shipping options provided by Shippo are the only valid options
  • Return the shipping options

The response will look something like this:

[
  {
    "id": "40dae94b17664fafbf8e5eb544771439",
    "description": "USPS: Priority Mail International",
    "provider": "",
    "price": {
      "raw": 41.09,
      "formatted": "41.09",
      "formatted_with_symbol": "$41.09",
      "formatted_with_code": "41.09 USD"
    },
    "countries": [],
    "regions": []
  },
  {
    "id": "c0dae6ca4f7b4d8888ef5b0a8210fa85",
    "description": "USPS: Priority Mail Express International",
    "provider": "",
    "price": {
      "raw": 51.81,
      "formatted": "51.81",
      "formatted_with_symbol": "$51.81",
      "formatted_with_code": "51.81 USD"
    },
    "countries": [],
    "regions": []
  }
]

This output is exactly the same as the get shipping methods API provided by Commerce.js. The IDs listed here will also work with the rest of the shipping APIs provided by Commerce.js — so we don’t need to do anything further to make this work, all the existing functionality built into the ChopChop demo store will still work ✨!

Shipping integrated

What’s next

Commerce.js allows you to attach attributes to orders as you capture the checkout, again using the meta attribute. The shipping method ID that was used will be available with the shipping information on the order. Then you can build another serverless function that is invoked by a webhook (when the order is created) to finalize the shipment with Shippo, and generate shipping labels if required.

Explore using webhooks to automate your operations and business flows after the checkout.

What about other shipping providers?

You can choose to integrate any shipping provider and implement custom business rules with your own serverless functions.

Edit this page on GitHub