Pobieranie koszyka¶
Zapytanie o szczegóły koszyka wywoływane jest w wyniku skanu kodu QR (lub tapnięcie w widget OA w przeglądarce mobilnej)przez użytkownika. Na poniższym diagramie oznaczone jest to jako krok 3.
sequenceDiagram
autonumber
actor User
participant OpenApp
participant Merchant
Merchant->>User: Wyświetlenie widgetu OA
User->>+OpenApp: Pobranie koszyka
OpenApp->>+Merchant: Pobranie koszyka i opcji dostawy
Merchant->>-OpenApp: Zwrócenie koszyka i opcji dostawy
OpenApp->>-User: Zwrócenie koszyka
User->>User: Opcje checkoutu (dostawa itp)
opt Inventory change
Merchant->>+OpenApp: Przesłanie zmienionego koszyka
OpenApp->>-User: Zwrócenie koszyka
end
User->>+OpenApp: Płatność i złożenie zamówienia
OpenApp->>OpenApp: Autoryzacja płatności
OpenApp->>+Merchant: Potwierdzenie płatności i złożenie zamówienia
Merchant->>-OpenApp: Potwierdzenie złożenia zamówienia
OpenApp->>-User: Potwierdzenie zamówienia
Request¶
Gdy klient zeskanuje kod QR lub kliknie widget, OpenApp pobiera koszyk. Jest to żądanie HTTP GET z serwera OpenApp do endpointu skonfigurowanego w panelu sprzedawcy, z request parametrem „basketId” równym temu, co zostało ustawione w data-basket w integracji biblioteki JavaScript sklepu internetowego:
Więc jeśli skonfigurowałeś jako URL pobierania koszyka wartość https://shop.example.com/api/openapp/basket
i ID koszyka to 6548654ef654d654aa
, żądanie do serwera będzie wyglądało tak:
Response¶
W odpowiedzi sklep powinien przesłać zawartość koszyka i skonfigurowane opcje dostawy. Pokazuje to poniższy przykład. W tym przypadku użytkownik ma w swoim koszyku dwie sztuki „Superb product”, każdy w cenie 70,00 zł. Ale ponieważ zastosował również kod rabatowy, aby uzyskać 10 zł zniżki, łączna cena wynosi 130 zł. Zamówienie może zostać dostarczone do Paczkomatu InPost bezpłatnie lub dostarczone do domu za dopłatą 10 zł.
expiresAt¶
Ważność koszyka określana jest w polu "expiresAt". OpenApp pozwala użytkownikowi złożyć zamówienie do tej godziny (krok 9 w powyższym diagramie). Po otrzymaniu zamówienia od użytkownika, OpenApp autoryzuje płatność, co maksymalnie może trwać 3 minuty. Tak więc OpenApp wyśle zamówienie do sklepu najpóżniej 3 minuty po czasie określonym w expiresAt. Jeśli przez 5 minut nie uda się nawiązać komunikacji z backendem sklepu (tak więc łącznie to maksymalnie 8 minut od expiresAt), OpenApp anuluje transakcję i dokonuje zwrotu płatności użytkownikowi.
{
"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#"
}
Powyższy przykład reprezentuje bardzo prosty koszyk. Po pełny opis modelu koszyka sprawdź JSON schema koszyka