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.