Skip to content

Basket recalculate

It is possible that a user modifies the basket from OpenApp, for instance to change the quantity of a product or to add a discount coupon. OpenApp will validate that change at the website to make sure that it is applied corectly. This is visible as step 8 in the sequence diagram:

sequenceDiagram
  autonumber
  actor User
  participant OpenApp
  participant Merchant
  Merchant->>User: show OpenApp widget
  User->>User: scan widget
  User->>+OpenApp: load basket
  OpenApp->>+Merchant: retrieve basket
  Merchant->>-OpenApp: send basket
  OpenApp->>-User: send basket
  User->>+OpenApp: add discount coupon
  OpenApp->>+Merchant: recalculate basket
  Merchant->>-OpenApp: send basket
  OpenApp->>-User: send basket
  User->>+OpenApp: confirm
  OpenApp->>OpenApp: validate payment
  OpenApp->>+Merchant: place order
  Merchant->>-OpenApp: confirm
  OpenApp->>-User: confirm

Request

In this case OpenApp will execute a HTTP POST to the to the endpoint configured in the control panel, with an updated basket in the request body:

POST <recalculate-url>

So if you configured the value https://shop.example.com/api/openapp/basket, the request executed by OpenApp will be:

POST https://shop.example.com/api/openapp/basket

The request body contains the basket from the user. For example:

Basket recalculate request
1
2
3
4
5
6
7
{
  "requestId": "request-id",
  "id": "basket-id",
  "price": { "currency": "PLN", "discounts": [{ "code": "new-discount-code-text" }] },
  "products": [{ "ean": "12312", "id": "id123", "quantity": 3 }],
  "loggedUser": "user-id-from-webshop"
}
Basket recalculate schema
{
    "description": "Basket recalculate request",
    "additionalProperties": false,
    "type": "object",
    "properties": {
        "requestId": {
            "description": "The ID of the request as generated by OpenApp.",
            "maxLength": 36,
            "type": "string",
            "title": "requestId"
        },
        "id": {
            "description": "A null value for the basket id indicates that this is a request to create a new basket for a repurchase.",
            "maxLength": 36,
            "type": "string",
            "title": "id"
        },
        "price": {
            "$ref": "#/definitions/RecalculatePrice",
            "title": "price"
        },
        "products": {
            "type": "array",
            "items": {
                "$ref": "#/definitions/RecalculateProduct"
            },
            "title": "products"
        },
        "loggedUser": {
            "type": "string",
            "title": "loggedUser"
        }
    },
    "required": [
        "price",
        "products",
        "requestId"
    ],
    "definitions": {
        "RecalculatePrice": {
            "title": "RecalculatePrice",
            "type": "object",
            "properties": {
                "currency": {
                    "description": "The currency",
                    "type": "string",
                    "title": "currency"
                },
                "discounts": {
                    "description": "Discounts to apply in price calculation.",
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/RecalculateDiscount"
                    },
                    "title": "discounts"
                }
            },
            "required": [
                "currency",
                "discounts"
            ]
        },
        "RecalculateDiscount": {
            "title": "RecalculateDiscount",
            "type": "object",
            "properties": {
                "code": {
                    "description": "The discount code.",
                    "maxLength": 36,
                    "type": "string",
                    "title": "code"
                }
            },
            "required": [
                "code"
            ]
        },
        "RecalculateProduct": {
            "title": "RecalculateProduct",
            "type": "object",
            "properties": {
                "ean": {
                    "description": "The ean (or other barcode on the product). Specifying this allows the user to search in his order history by scanning the barcode to do a re-purchase.",
                    "maxLength": 36,
                    "type": "string",
                    "title": "ean"
                },
                "id": {
                    "description": "The unique ID of the product.",
                    "maxLength": 36,
                    "type": "string",
                    "title": "id"
                },
                "quantity": {
                    "description": "The requested quantity",
                    "type": "number",
                    "title": "quantity"
                }
            },
            "required": [
                "id",
                "quantity"
            ]
        }
    },
    "$schema": "http://json-schema.org/draft-07/schema#"
}

Response

In reponse, the website should send the basket content and configured delivery options in the same format as for the retrieve basket response. Of course it is possible that the website can not accomodate the requested basket change, for instance because not enough stock is available. In that scenario the website should repond with the part of the basket that is available, plus an error code to indicate any errors in the basket. This is shown in the example below:

Retrieve basket response
{
  "id": "basket-id",
  "expiresAt": "2022-03-23T21:00:00Z",
  "price": {
    "currency": "PLN",
    "discounts": [
      {
        "code": "discount-code-text",
        "value": 1000
      }
    ],
    "basketValue": 18000
  },
  "deliveryOptions": [
    {
      "key": "INPOST_APM",
      "cost": 0
    },
    {
      "key": "DPD_COURIER",
      "cost": 1000
    }
  ],
  "products": [
    {
      "ean": "12312",
      "id": "id123",
      "name": "Superb product",
      "images": ["http://cdn.merchant.com/static/products/id123/1", "http://cdn.merchant.com/static/products/id123/2"],
      "quantity": 2,
      "unitPrice": 6000,
      "linePrice": 12000,
      "originalUnitPrice": 7000,
      "originalLinePrice": 14000,
      "error": "QUANTITY_TOO_BIG"
    }
  ],
  "loggedUser": "user-id-from-webshop"
}
Recalculate basket response v1
{
    "description": "Basket returned on retrieval or recalculation",
    "additionalProperties": false,
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique ID of the basket.",
            "maxLength": 36,
            "type": "string",
            "title": "id"
        },
        "requestId": {
            "description": "The ID of the basket request as generated by OpenApp. Mandatory in case of an asynchronous connection through a queue in order to correlate the placed order with the response.",
            "maxLength": 36,
            "type": "string",
            "title": "requestId"
        },
        "expiresAt": {
            "description": "The moment until which the basket is valid. This can be used to indicate a basket needs to be ordered before a specific time in order to guarantee availability.",
            "format": "date-time",
            "type": "string",
            "title": "expiresAt"
        },
        "oaOrderId": {
            "description": "The OpenApp order ID (if known).",
            "type": "string",
            "title": "oaOrderId"
        },
        "price": {
            "$ref": "#/definitions/BasketPrice",
            "title": "price"
        },
        "deliveryOptions": {
            "type": "array",
            "items": {
                "$ref": "#/definitions/BasketDeliveryOption"
            },
            "title": "deliveryOptions"
        },
        "products": {
            "type": "array",
            "items": {
                "$ref": "#/definitions/BasketProduct"
            },
            "title": "products"
        },
        "invoiceAddressMandatory": {
            "description": "Whether an invoice address is mandatory",
            "type": "boolean",
            "title": "invoiceAddressMandatory"
        },
        "loggedUser": {
            "description": "The unique ID of the user.",
            "maxLength": 255,
            "type": "string",
            "title": "loggedUser"
        }
    },
    "required": [
        "deliveryOptions",
        "expiresAt",
        "id",
        "price",
        "products"
    ],
    "definitions": {
        "BasketPrice": {
            "title": "BasketPrice",
            "type": "object",
            "properties": {
                "currency": {
                    "type": "string",
                    "title": "currency"
                },
                "basketValue": {
                    "description": "The price of the basket. Price is expressed as the number (integer) of 1/100s of the price.",
                    "minimum": 0,
                    "type": "integer",
                    "title": "basketValue"
                },
                "discounts": {
                    "description": "Applied discounts",
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/BasketPriceDiscount"
                    },
                    "title": "discounts"
                }
            },
            "required": [
                "basketValue",
                "currency",
                "discounts"
            ]
        },
        "BasketPriceDiscount": {
            "title": "BasketPriceDiscount",
            "type": "object",
            "properties": {
                "code": {
                    "description": "The discount code.",
                    "maxLength": 36,
                    "type": "string",
                    "title": "code"
                },
                "value": {
                    "description": "The value of the discount. Value is expressed as the number (integer) of 1/100s of the currency.",
                    "minimum": 0,
                    "type": "integer",
                    "title": "value"
                },
                "error": {
                    "description": "The error code of the discount",
                    "enum": [
                        "EXPIRED",
                        "INVALID",
                        "NOT_APPLICABLE",
                        "USED"
                    ],
                    "type": "string",
                    "title": "error"
                }
            },
            "required": [
                "code",
                "value"
            ]
        },
        "BasketDeliveryOption": {
            "title": "BasketDeliveryOption",
            "type": "object",
            "properties": {
                "key": {
                    "$ref": "#/definitions/MerchantDeliveryOptions",
                    "title": "key"
                },
                "cost": {
                    "description": "The price of the delivery. Price is expressed as the number (integer) of 1/100s of the price.",
                    "type": "integer",
                    "title": "cost"
                },
                "timing": {
                    "description": "The estimation of the delivery time, i.e. 'next business day' or 'July 18th'.",
                    "maxLength": 40,
                    "type": "string",
                    "title": "timing"
                }
            },
            "required": [
                "cost",
                "key"
            ]
        },
        "MerchantDeliveryOptions": {
            "title": "MerchantDeliveryOptions",
            "enum": [
                "DHL_COURIER",
                "DHL_PICKUP",
                "DPD_COURIER",
                "DPD_PICKUP",
                "ELECTRONIC",
                "FEDEX_COURIER",
                "GEIS_COURIER",
                "GLS_COURIER",
                "INPOST_APM",
                "INPOST_COURIER",
                "INSTORE_PICKUP",
                "ORLEN_APM",
                "POCZTA_POLSKA_APM",
                "POCZTEX_COURIER",
                "UPS_COURIER"
            ],
            "type": "string"
        },
        "BasketProduct": {
            "title": "BasketProduct",
            "type": "object",
            "properties": {
                "name": {
                    "description": "The product name.",
                    "type": "string",
                    "title": "name"
                },
                "images": {
                    "description": "The URLs of the product image",
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "title": "images"
                },
                "originalUnitPrice": {
                    "description": "The original (before discount) price of a single product. Price is expressed as the number (integer) of 1/100s of the price.",
                    "type": "integer",
                    "title": "originalUnitPrice"
                },
                "originalLinePrice": {
                    "description": "The original (before discount) price of the products. Price is expressed as the number (integer) of 1/100s of the price.",
                    "type": "integer",
                    "title": "originalLinePrice"
                },
                "error": {
                    "description": "Error code when the product request can not be accomodated in a recalculate request.",
                    "enum": [
                        "OUT_OF_STOCK",
                        "QUANTITY_TOO_BIG"
                    ],
                    "type": "string",
                    "title": "error"
                },
                "ean": {
                    "description": "The ean (or other barcode on the product). Specifying this allows the user to search in his order history by scanning the barcode to do a re-purchase.",
                    "maxLength": 36,
                    "type": "string",
                    "title": "ean"
                },
                "id": {
                    "description": "The unique ID of the product.",
                    "maxLength": 36,
                    "type": "string",
                    "title": "id"
                },
                "quantity": {
                    "description": "The number of items in the purchase.",
                    "minimum": 0,
                    "type": "integer",
                    "title": "quantity"
                },
                "unitPrice": {
                    "description": "The price of a single product. Price is expressed as the number (integer) of 1/100s of the price.",
                    "type": "integer",
                    "title": "unitPrice"
                },
                "linePrice": {
                    "description": "The price of the products. Price is expressed as the number (integer) of 1/100s of the price.",
                    "type": "integer",
                    "title": "linePrice"
                }
            },
            "required": [
                "id",
                "images",
                "linePrice",
                "name",
                "originalLinePrice",
                "originalUnitPrice",
                "quantity",
                "unitPrice"
            ]
        }
    },
    "$schema": "http://json-schema.org/draft-07/schema#"
}

This example is an example of a simple basket. For a complete description of the basket response see the recalculate basket JSON schema.