Basket lock (zamrażanie koszyka)¶
Proces składania zamówienia w niektórych sklepach może wymagać zablokowania (zamrożenia) koszyka, aby zapewnić dostępność produktów i niezmienność cen pomiędzy złożeniem zamówienia przez klienta a dokonaniem przez niego płatności. OA umożliwia konfigurację żądania zablokowania koszyka (basket lock), przed rozpoczęciem autoryzacji płatności:
sequenceDiagram
  autonumber
  actor User
  participant OpenApp
  participant Merchant
  Merchant->>User: pokaż widget OpenApp
  User->>User: skan widgeta
  User->>+OpenApp: załaduj koszyk
  OpenApp->>+Merchant: pobierz koszyk
  Merchant->>-OpenApp: wyślij koszyk
  OpenApp->>-User: wyślij koszyk
  User->>+OpenApp: dodaj kupon rabatowy
  OpenApp->>+Merchant: przelicz koszyk
  Merchant->>-OpenApp: wyślij koszyk
  OpenApp->>-User: wyślij koszyk
  User->>+OpenApp: potwierdź
  OpenApp->>+Merchant: zablokuj koszyk
  Merchant->>-OpenApp: wyślij zablokowany koszyk
  OpenApp->>OpenApp: autoryzuj płatność
  OpenApp->>+Merchant: złoż zamówienie
  Merchant->>-OpenApp: potwierdź
  OpenApp->>-User: potwierdźRequest¶
W tym przypadku OpenApp wykona HTTP POST do endpointu skonfigurowanego w panelu merchanta dla requestu recalculate, ze zaktualizowanym koszykiem w body requestu:
Jeśli skonfigurowałeś wartość https://shop.example.com/api/openapp/basket, request wykonany przez OpenApp będzie następujący:
Treść requestu zawiera koszyk użytkownika. Na przykład:
{
    "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#"
}
Odpowiedź¶
W odpowiedzi, sklep przesyła zawartość koszyka oraz dostępne opcje dostawy, w takim samym formacie jak w przypadku odpowiedzi na pobieranie koszyka. Parametr expiresAt wskazuje czas do którego koszyk jest aktualny i zablokowany.
Tak jak w poniższym przykładzie:
{
    "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#"
}
Jest oczywiście możliwe, że sklep nie będzie w stanie zrealizować żądanego koszyka, na przykład z powodu braku towaru lub zmiany ceny. Wówczas sklep odpowiada przesyłając część koszyka, która jest dostępna oraz kod błędu wskazujący błędy w koszyku. OpenApp wyświetli te informacje użytkownikowi, aby mógł on zdecydować o dalszym zakupie.
To jest przykład prostego koszyka. Pełen opis znajduje się tu recalculate basket JSON schema.