Custom Delivery Adapter
If you want total control of the provided delivery methods, you can build and host an own adapter that will empower Walley Checkout with delivery methods. This allows you to separate the items in the cart in different shipments, set specific pickup/delivery dates, add options to each delivery etc.
How to get started πβ
- Contact Walley Merchant Services for help with setup in our test environment and for questions regarding integration with the Delivery Module.
- Build a delivery adapter (api) with an endpoint that Walley Checkout will do a GET request towards to get the delivery methods that should respond according to the response below. Use basic auth as authentication.
- Provide Walley Merchant Services with the adapter endpoint url, basic auth credentials as well as what fallback strategy to use.
How delivery methods are fetchedβ
Walley Checkout fetches the list of available delivery methods every time the customer changes any information that might lead to a change in available delivery methods, e.g. the customer changes delivery address or updates the cart.
Default Request Query Parameters
When the Checkout sends the GET request to the delivery adapter, it will include some default query parameters.
Parameter | Explanation |
---|---|
storeId | The storeId for the checkout session |
privateId | The checkout's private id which can be used to fetch information about the checkout |
storeType | CustomerType for the checkout session, b2b or b2c |
currency | Currency used for the checkout session |
language | The display language used for the checkout session. Supported language are: sv, no, fi, da, en |
cartPrice | The total price for cart |
cartWeight | The total weight for the cart, sum of all the article's weights sent in set cart request |
The customer's email address | |
address | The address for the customer's current delivery address |
postalCode | The postal code for the customer's current delivery address |
countryCode | The country code for the customer's current delivery address |
When requesting for available shipping methods, apart from all the parameters above, you can set custom parameters that is related to articles in the cart.
This is done by adding shippingProperties
to the cart object in either Initialize Checkout
or Update Cart
as a JSON object that will be be added in the request query parameters automatically the following way:
{
"items": [
{
"id": "2",
"description": "A bulky product",
"unitPrice": 100,
"unitWeight": 2,
"quantity": 1,
"vat": 20,
"requiresElectronicId": true,
"sku": "a unique alphanumeric code for article identification"
}
],
"shippingProperties": {
"height": 10,
"width": 20,
"isBulky": true
}
}
The following scenario would result in the following query parameters when the GET-request is sent to your adapter:
https://{UriToAdapter}?storeId={storeId}&....&address={address}&height=10&width=20&isBulky=true
Please note
Since the privateId is sent in the query, it is possible to Acquire Checkout Information to get more information. Consider that this will add some time for your customer in the checkout.
Adapter responseβ
The response can contain a lot of data and options that will be presented for the customer, but not many of them are required. Here is an example of a successful response as well as an error response:
Response headerβ
Header | Required | Explanation |
---|---|---|
Expires | No | A DateTime set if the choices should be valid only for a certain time. We will force the customer to reload delivery methods if a selection is made with delivery methods that has expired |
Response bodyβ
Property | Required | Explanation |
---|---|---|
shipments | Yes | Array of shipments, at least one must be present but it is possible to split the cart items into multiple shipments |
Shipment Property
Property | Required | Explanation |
---|---|---|
id | Yes | Id of the shipment |
name | Yes | Name of shipment, will be displayed as a header for the entire shipment selection |
shippingChoices | Yes | Array of choices that the customer can choose from for the shipment, at least one must be present |
metadata | No | Any metadata for the delivery, will not be used in checkout but returned every time you aquire checkout information |
ShippingChoice Property
Property | Required | Explanation |
---|---|---|
id | Yes | Id of the choice |
name | Yes | Name of the choice, will be the title for the selection |
description | No | Description of the choice, will be the subtitle for the selection |
icon | No | Icon for the choice. Available icon propery values can be found below. If none is provided, a default icon will be used. |
fee | No | Fee for the option, if combined with destinations and/or options, this fee will be added to all of them. Set to 0 if not present |
destinations | No | Array of destinations that will be a subselection for the shipping choice |
options | No | Array of options that the customer can add optionally to add to the shipping choice |
metadata | No | Any metadata for the shipping choice, will not be used in checkout but returned every time you aquire checkout information |
Destinations Property
Property | Required | Explanation |
---|---|---|
id | Yes | Id of the destination |
name | Yes | Name of the destination, will be the title of the selectable destination |
description | No | Description of the destination, will be the subtitle of the selectable destination |
deliveryDates | No | Array of available delivery dates for the ShippingChoice |
metadata | No | Any metadata for the destination, will not be used in checkout but returned every time you aquire checkout information |
DeliveryDate Property
Property | Required | Explanation |
---|---|---|
date | Yes | DateTime of the selectable delivery date |
timeFrom | Yes | Time of the day from where the selectable delivery date option starts |
timeTo | Yes | Time of the day from where the selectable delivery date option ends |
fee | no | Fee for the specified delivery date. Set to 0 if not present |
metadata | No | Any metadata for the delivery date, will not be used in checkout but returned every time you aquire checkout information |
Option Property
Property | Required | Explanation |
---|---|---|
id | Yes | Id of the option |
description | Yes | Description of the option |
type | Yes | Type of the option, available types: "bool" - checkbox, "string" - text field, "number" - digits only |
metadata | No | Any metadata for the option, will not be used in checkout but returned every time you aquire checkout information |
Iconsβ
The icons for a shippingChoice
can either have a company logo or a generic icon. Below are the available icons:
Icon property value | Icon | Icon property value | Icon |
---|---|---|---|
postnord | walley-home | ||
dbschenker | walley-mail | ||
dhl | walley-plane | ||
airmee | walley-ship | ||
best | walley-store | ||
bring | walley-truck | ||
budbee | default * | ||
citymail | |||
dsv | |||
earlybird | |||
helthjem | |||
instabox | |||
posti |
*Default icon is used if no value is provided, or if the value mismatches with any of the available icon property values.
Fallback strategyβ
If, for any reasons, Walley Checkout does not receive any delivery methods from your adapter, there is a setting that you will set up in advance that will decide if the purchase should be stopped or not
- true: We will show an error and stop the purchase if we cannot fetch at least one valid delivery method
- false: We will allow the customer to complete the purchase, saying that a delivery method will be selected automatically without cost
Error message responseβ
If the GET-request is received successfully but no delivery methods can be returned, you can choose to return a non-2xx response with the following properties to inform the customer what is wrong and what action to take. This requires the fallback strategy to be set to true.
Property | Required | Explanation |
---|---|---|
title | No | The title of the failure displayed in the Checkout. Truncated to max 512 chars. |
message | No | The message with a more descriptive text why no delivery methods was found, and how the customer should proceed. Truncated to max 512 chars. |
A default message will be shown if not overridden with title and message from the response. Both title and message must be specified in the response to be used.
Response examplesβ
- Delivery methods response - 200
- Custom error message response - non 2xx
/*
Expires: "1/1/0001 12:00:00 AM +00:00"
*/
{
"shipments": [
{
"id": "shipmentId-1",
"name": "Delivery 1",
"metadata": {
"key-for-shipment": "metadata-for-shipment",
"from-store-id": "1234"
},
"shippingChoices": [
{
"id": "choiceId-1",
"name": "Pickup in store",
"icon": "walley-store",
"description": "Pick up your order within five days from your chosen day for pick up",
"destinations": [
{
"id": "destinationId-gothenburg",
"name": "Gothenburg",
"description": "Kortedala",
"deliveryDates": [
{
"date": "2021-02-25T00:00:00+00:00",
"timeFrom": "07:00",
"timeTo": "17:00",
"fee": 0.0,
"metadata": {
"duringOpenHours": "true"
}
},
{
"date": "2021-02-25T00:00:00+00:00",
"timeFrom": "17:00",
"timeTo": "21:00",
"fee": 250.0,
"metadata": {
"duringOpenHours": "true"
}
},
{
"date": "2021-02-25T00:00:00+00:00",
"timeFrom": "21:00",
"timeTo": "22:00",
"fee": 500.0,
"metadata": {
"duringOpenHours": "false"
}
},
{
"date": "2021-02-26T00:00:00+00:00",
"timeFrom": "07:00",
"timeTo": "17:00",
"fee": 100.0
},
{
"date": "2021-03-01T00:00:00+00:00",
"timeFrom": "07:00",
"timeTo": "17:00",
"fee": 0.0
}
]
},
{
"id": "destinationId-varberg",
"name": "Varberg",
"description": "Hunnestad",
"deliveryDates": [
{
"date": "2021-02-28T00:00:00+00:00",
"timeFrom": "09:00",
"timeTo": "16:00",
"fee": 0.0
},
{
"date": "2021-02-28T00:00:00+00:00",
"timeFrom": "16:00",
"timeTo": "18:00",
"fee": 250.0
}
]
}
],
"fee": 0,
"options": [
{
"id": "option-1",
"description": "Rent trailer",
"type": "bool",
"fee": 500
},
{
"id": "option-2",
"description": "Help to pack",
"type": "bool",
"fee": 250
},
{
"id": "option-3",
"description": "Additional information",
"type": "string",
"fee": 0
}
]
},
{
"id": "choiseId-2",
"name": "Home delivery",
"icon": "walley-home",
"description": "Goods will be delivered as close to your home as possible",
"destinations": [
{
"id": "destinationId-home",
"name": "The most comfortable delivery",
"description": "Select day for delivery",
"deliveryDates": [
{
"date": "2021-03-11T00:00:00+00:00",
"timeFrom": "07:00",
"timeTo": "17:00",
"fee": 200.0
},
{
"date": "2021-03-12T00:00:00+00:00",
"timeFrom": "07:00",
"timeTo": "17:00",
"fee": 50.0
}
]
},
{
"id": "destinationId-home-express",
"name": "Express - a lot faster",
"description": "When you are in a hurry",
"fee": 500,
"deliveryDates": [
{
"date": "2020-10-01T00:00:00+00:00",
"timeFrom": "08:00",
"timeTo": "18:00"
}
]
}
],
"fee": 500,
"options": [
{
"id": "option1",
"description": "Notify when delivered",
"type": "bool",
"fee": 500
}
]
},
{
"id": "choiceId-3",
"name": "Pick up at service point with Postnord",
"icon": "postnord",
"description": "Select service point",
"destinations": [
{
"id": "service-point-1",
"description": null,
"name": "Postnord store, Avenyn"
},
{
"id": "service-point-2",
"description": null,
"name": "Postnord store, Backa"
}
],
"fee": 29
},
{
"id": "choiceId-4",
"name": "Pick up at service point with Schenker",
"icon": "dbschenker",
"description": "Select service point",
"destinations": [
{
"id": "service-point-1",
"description": null,
"name": "Schenker store, Avenyn"
},
{
"id": "service-point-2",
"description": null,
"name": "Schenker store, Backa"
}
],
"fee": 29
},
{
"id": "choice-without-destination",
"name": "Pick up at central warehouse, Kalmar",
"icon": "walley-store",
"description": "Kalmar street 8",
"destinations": null,
"fee": 100
}
]
},
{
"id": "shipmentId-2",
"name": "Delivery 2",
"shippingChoices": [
{
"id": "choice-home-delivery",
"name": "Home delivery",
"icon": "walley-home",
"destinations": [
{
"id": "standard-home-delivery",
"description": "Delivery within 5-7 days",
"name": "Standard, the most comfortable delivery"
},
{
"id": "express-home-delivery",
"description": "Delivery within 2 days",
"name": "Express - a lot faster",
"fee": 500
}
],
"fee": 1500,
"options": [
{
"id": "option1",
"description": "Bring my old stuff out",
"type": "bool",
"fee": 500
}
]
},
{
"id": "choice-without-destination-2",
"name": "Pick up at warehouse",
"icon": "walley-store",
"destinations": null,
"fee": 100
}
]
}
]
}
{
"title": "Title to be displayed",
"message": "Message to be displayed"
}
The 200-response from the example above will render the following delivery methods to the customer.

Fetch the customer's selected delivery methodβ
When Acquiring Checkout Information, a data.shipping
object will be available that will reflect the customer's current delivery selection.
If this value is null, there are no selection at that current state of the checkout.
After purchase the selections are included in the order.
- Scenario 1. Successfully fetched delivery methods
- Scenario 2. Failed to fetch delivery methods, with fallback strategy to allow purchase anyway
// Simplified Get Checkout Information response with focus on shipping and order object
{
"id": "9eec015f-4b97-44be-a711-d22f3af75069",
"data": {
"customer": {...},
...,
...,
"status": "PurchaseCompleted",
"order": {
"totalAmount": 2757,
"items": [
{
"id": "11111",
"description": "Item one",
"unitPrice": 5,
"quantity": 1,
"vat": 25,
"sku": "Item one sku"
},
{
"id": "222222",
"description": "Item two",
"unitPrice": 2,
"quantity": 1,
"vat": 25,
"sku": "Item two sku"
},
{
"id": "Frakt-1",
"description": "Pickup in store",
"unitPrice": 750,
"quantity": 1,
"vat": 25
},
{
"id": "Frakt-2",
"description": "Home delivery",
"unitPrice": 2000,
"quantity": 1,
"vat": 25
}
]
},
"shipping": {
"provider": "DeliveryAdapterName",
"shippingFee": 2750,
"shipments": [
{
"id": "shipmentId-1",
"feeItemId": "Frakt-1",
"metadata": {
"key-for-shipment": "metadata-for-shipment",
"from-store-id": "1234"
},
"shippingChoice": {
"id": "choiceId-1",
"fee": 0,
"metadata": {
"key-for-choice-1": "metadata-for-choice-1"
},
"destination": {
"id": "destinationId-gothenburg",
"fee": 0,
"metadata": {
"key-for-destination": "metadata-for-destination"
},
"deliveryDate": {
"fee": 0,
"metadata": {
"duringOpenHours": "true"
},
"date": "2021-02-25",
"timeFrom": "07:00",
"timeTo": "17:00"
}
},
"options": [
{
"id": "option-1",
"description": "Rent trailer",
"type": "bool",
"fee": 500,
"value": true
},
{
"id": "option-2",
"description": "Help to pack",
"type": "bool",
"fee": 250,
"value": true
},
{
"id": "option-3",
"description": "Additional information",
"type": "string",
"fee": 0,
"value": "Some info"
}
]
}
},
{
"id": "shipmentId-2",
"feeItemId": "Frakt-2",
"metadata": null,
"shippingChoice": {
"id": "choice-home-delivery",
"fee": 1500,
"metadata": null,
"destination": {
"id": "standard-home-delivery",
"fee": 0,
"metadata": null,
"deliveryDate": null
},
"options": [
{
"id": "option1",
"description": "Bring my old stuff out",
"type": "bool",
"fee": 500,
"value": true
}
]
}
}
]
},
...
},
"error": null
}
// Simplified Get Checkout Information response with focus on shipping and order object
{
"id": "9eec015f-4b97-44be-a711-d22f3af75069",
"data": {
"customer": {...},
...,
"status": "PurchaseCompleted",
"order": {
"totalAmount": 7,
"items": [
{
"id": "11111",
"description": "Item one",
"unitPrice": 5,
"quantity": 1,
"vat": 25,
"sku": "Item one sku"
},
{
"id": "222222",
"description": "Item two",
"unitPrice": 2,
"quantity": 1,
"vat": 25,
"sku": "Item two sku"
}
]
},
...
},
"error": null
}