Skip to content

How to work with checkout components

Checkout components provide functionality for ordering various products for discover.swiss frontend partners. These applications are compiled into native web-components and can be embedded into any website / web application. There are currently three web components:

Info

Before using these components, you need to go through a marketplace onboarding with our support.

Checkout Product Selector

This component monitors the click on the button for adding an item to the cart and activates the flow of choosing the collection of additional information that is needed to add the item to the cart (selection of size / color, etc. parameters when adding an item to the cart).

Usage notes and requirements

Before using the webComponent you need to load its script checkout-product-selector.js.

<script src="/path/or/url/to/checkout-product-selector.js"></script>

To be able to add product to the shopping cart each "add to basket" button should be wrapped like showed below. product-id should be replaced with the real product identifier.

Info

This component does not change the DOM.

<checkout-select-variant product-id="product-id">
        <button id="product-id" class="add-to-basket-btn" slot="productBtn">ADD TO BASKET</button>
</checkout-select-variant>

Checkout Product Variant Selector

This component is responsible for displaying product variants. It does not open in full screen and can be embedded anywhere on a web page.

Usage notes and requirements

Before using the webComponent you need to load its script checkout-product-variant-selector.js.

<script src="/path/or/url/to/checkout-product-variant-selector.js"></script>
To be able to show variants for the product product-id should be replaced with the real product identifier.
<checkout-product-variant-selector
    product-id="product-id"
    language="language"
    show-title="true|false"
    show-description="true|false"
    config="`
    {
      'assetsPrefix': 'path/to/static/files' or 'https://some.url.cdn.storage'
    }
  `">
</checkout-product-variant-selector>

Checkout Shopping Cart

The component displays the number of product Items in the shopping cart and activates checkout flow if you click on it.

Usage notes and requirements

Before using the webComponent you need to load its script checkout-shopping-cart.js.

<script src="/path/or/url/to/checkout-shopping-cart.js"></script>

checkout-shopping-cart tag should be placed at the place where you want to get clickable text/icon of the shopping cart. <span slot="checkoutShoppingCart">Checkout</span> should be placed between the checkout-shopping-cart tag.

Info

This component does not change the DOM.

...
  <ul class="menu-wrapper__items">
    <li class="menu-wrapper__item">
      <checkout-shopping-cart>
        <span slot="checkoutShoppingCart">Checkout</span>
      </checkout-shopping-cart>
    </li>
    <li class="menu-wrapper__item"><a href="#" target="_blank">projectPartner</a></li>
    ...
  </ul>
...

Checkout Core

This is the main web component. The previous two will not work without it. It handles all events coming from other components. Interacts with the backend. It also contains the flow of adding an item to the cart and checkout flow.

Usage notes and requirements

Before using the webComponent you need to load its script checkout-core.js.

<script src="/path/or/url/to/checkout-core.js"></script>

Since this component works with the backend and due to the fact that we can work with different versions of the backend environment, we need to configure it correctly. To do this, the component has a property config. Using this property, we need to pass a configuration object that has the following structure:

{
    subscriptionKey: string;
    profileUrl: string;
    marketplaceUrl: string;
    refreshTokenExpirationTimeInDays: number;
    forceToAuth: boolean;
    assetsPrefix: string;
    stripeInteractionStrategy: string;
    orderFulfillmentUrl: string;
    numberOfProfileMergingAttempts: number; // by default 3
    delayBetweenProfileMergingAttempts: number; // by default 500 milliseconds
    shortDelay: number; // delay in milliseconds between requests during shortDelayDuration
    longDelay: number; // delay in milliseconds between requests after shortDelayDuration period
    shortDelayDuration: number; // duration in milliseconds for frequent requests
    timeout: number; // stop observation after the timeout (milliseconds)
    orderInactivityDuration: number; // clear order, product, productVariant state after mentioned time of inactivity (milliseconds)
}

and result should be like this:

  ...
  <checkout-core config="`
    {
      'subscriptionKey': 'realSUbscriptionKeyForTheParticularEnvironment';
      'profileUrl': 'https://path/to/profile/api/url';
      'marketplaceUrl': 'https://path/to/marketplace/api/url';
      'refreshTokenExpirationTimeInDays': 10,
      'forceToAuth': false, // whether the webcomponent should require user authentication or can it work as a guest
      'assetsPrefix': 'path/to/static/files' or 'https://some.url.cdn.storage',
      'stripeInteractionStrategy': 'dev' | 'test' | 'prod', // we don't have stripe impl for dev ENV. So for correct handling this step we need to provide this parameter.
      'orderFulfillmentUrl': 'https://api.discover.swiss/dev/orderfulfillment', // used only for DEV ENV for handling payment step, you can omit this param for any other ENV
      'numberOfProfileMergingAttempts': 3
      'delayBetweenProfileMergingAttempts': 500
    }
  `">
  <div slot="stripe-payment-element" id="stripe-payment-element-id">
    stripe-payment-element isn't mounted
  </div>
  </checkout-core>
</body>

Info

This component does not change the DOM.

To simplify component testing, we have implemented a default config, which contains the configuration for interacting with the test environment. Therefore, it is possible to omit the config parameter. In this case, there will be an interaction with the test environment.

Info

You can provide partial configuration. In this case, all fields that you omit will be taken from the default configuration.

Info

Note that you should avoid any caching of these endpoints (neither HTTP cache nor service workers):

'profileUrl': 'https://path/to/profile/api/url';
'marketplaceUrl': 'https://path/to/marketplace/api/url';
'orderFulfillmentUrl': 'https://api.discover.swiss/dev/orderfulfillment'; // used only for DEV ENV for handling payment step, you can

  ...
  <checkout-core>
    <div slot="stripe-payment-element" id="stripe-payment-element-id">
      stripe-payment-element isn't mounted
    </div>
  </checkout-core>
</body>

Styling

By default, the default discover.swiss color scheme is used (for light and dark modes) whose structure and color values can be seen below.

{
  ...
  style: {
        light: {
            "--primary-100": "#212121",
            '--primary-90': '#373737',
            '--primary-80': '#4d4d4d',
            '--primary-70': '#646464',
            '--primary-60': '#707070',
            '--primary-50': '#909090',
            '--primary-40': '#a6a6a6',
            '--primary-30': '#bcbcbc',
            '--primary-20': '#d3d3d3',
            '--primary-10': '#dddddd',
            '--primary-5': '#f0f0f0',
            '--primary-0': '#ffffff',
            '--accent-dark': '#b12527',
            '--accent-100': '#d02c2e',
            '--accent-70': '#db6a6f',
            '--accent-60': '#e38082',
            '--accent-30': '#e9a8ac',
            '--accent-secondary-dark': '#006610',
            '--accent-secondary-100':  '#008315',
            '--main-font': `'HK Grotesk', serif`,
            '--btn-text-color-disabled': '#707070',
            '--btn-confirmation-text-color': '#008315',
            '--btn-confirmation-text-color-hover': '#006610',
            '--btn-confirmation-text-color-disabled': '#707070',
            '--btn-primary-text-color': '#ffffff',
            '--btn-primary-text-color-disabled': '#ffffff',
            '--btn-primary-confirmation-text-color': '#ffffff',
        },
        dark: {
            "--primary-100": '#ffffff',
            '--primary-90': '#f0f0f0',
            '--primary-80': '#dddddd',
            '--primary-70': '#d3d3d3',
            '--primary-60': '#bcbcbc',
            '--primary-50': '#a6a6a6',
            '--primary-40': '#909090',
            '--primary-30': '#707070',
            '--primary-20': '#646464',
            '--primary-10': '#4d4d4d',
            '--primary-5': '#373737',
            '--primary-0': '#212121',
            '--accent-dark': '#b12527',
            '--accent-100': '#d02c2e',
            '--accent-70': '#db6a6f',
            '--accent-60': '#e38082',
            '--accent-30': '#e9a8ac',
            '--accent-secondary-dark': '#006610',
            '--accent-secondary-100':  '#008315',
            '--main-font': `'HK Grotesk', serif`,
            '--btn-text-color-disabled': '#909090',
            '--btn-confirmation-text-color': '#008315',
            '--btn-confirmation-text-color-hover': '#006610',
            '--btn-confirmation-text-color-disabled': '#909090',
            '--btn-primary-text-color': '#ffffff',
            '--btn-primary-text-color-disabled': '#ffffff',
            '--btn-primary-confirmation-text-color': '#ffffff',
        }
    }
    ...
}

Currently only hexadecimal color representation is supported. If you want to change any of the colors, then just add these values to your config. The existing values will be replaced with yours.

Example: I want to change few values (not only colors but font family as well) in this config for light and dark theme:

  <checkout-core config="`
    {
      'subscriptionKey': 'realSUbscriptionKeyForTheParticularEnvironment',
      'profileUrl': 'https://path/to/profile/api/url',
      'marketplaceUrl': 'https://path/to/marketplace/api/url',
      'refreshTokenExpirationTimeInDays': 10,
      'forceToAuth': false, // whether the webcomponent should require user authentication or can it work as a guest
      'assetsPrefix': 'path/to/static/files' or 'https://some.url.cdn.storage',
      'stripeInteractionStrategy': 'dev' | 'test' | 'prod', // we don't have stripe impl for dev ENV. So for correct handling this step we need to provide this parameter.
      'orderFulfillmentUrl': 'https://api.discover.swiss/dev/orderfulfillment', // used only for DEV ENV for handling payment step, you can omit this param for any other ENV
      'numberOfProfileMergingAttempts': 3,
      'delayBetweenProfileMergingAttempts': 500,
      style: {
        light: {
            '--accent-secondary-dark': '#007510',
            '--accent-secondary-100':  '#008525',
            '--main-font': `'Georgia', serif`,
            '--btn-text-color-disabled': '#757575',
        },
        dark: {
            '--accent-secondary-dark': '#007750',
            '--accent-secondary-100':  '#008950',
            '--main-font': `'Georgia', serif`,
            '--btn-text-color-disabled': '#959595',
    }
    }
  `">
  <div slot="stripe-payment-element" id="stripe-payment-element-id">
    stripe-payment-element isn't mounted
  </div>
  </checkout-core>
</body>

As you can see we can omit colors that we don't wan't to change.

NOTE: This component does not change the DOM

Authentication

Guests or authorized users can interact with components.

If the user is not authorized, then at the first call to the api that requires user identification (for example, when viewing product variants), a guest token is created and recorded in the local storage.

dsGuestProfileToken: 'token'
dsRefreshGuestProfileToken: 'refresh_token'
This happens automatically and does not require any action from the user.

User authorization is also supported. In this case, the user must independently obtain an authorization token and pass it to the checkout-core component as the "autnToken" parameter:

<checkout-core auth-token="some_token" ...></checkout-core>
Web components can also fire authorization-related events that must be handled by the parent application. The list of events:

  • dsRefreshAuthTokenReq - this event fires when the web components detect that authToken has expired before adding the authToken to the request. In this case, you need to update the authToken and pass the updated version as a parameter to the checkout-core component;
  • dsForceAuthReq - this event fires when the user clicks on the login button inside the web components. In this case, the parent application should prompt the user to log in, and then pass the authorization token to the checkout-core;

Events

Web components can fire such events:

  • dsOpenProductDetails - this event fires when user clicks on the product name inside shopping cart;

Web components can respond to such events:

  • dsSendCloseShoppingCartEvent - web components listen for this event and the cart will be closed when it is received;

Language

The web components support English and German languages, all the necessary translations are already contained within the web components. To select a language, you should pass "language" parameter to the checkout-core component:

    <checkout-core language="de or en" ...></checkout-core>
If the language parameter is not passed, then the browser language is taken if it is English or German, otherwise the default language is German.

Required 3rd party fonts

Current webComponents design uses HT Groteks font. Due to webComponents restrictions we need to add this font somehow. We suggest to add in head section link to cdn with the font.

<link href="http://fonts.cdnfonts.com/css/hk-groteks" rel="stylesheet">

Working example

Warning

To successfully complete the entire path from adding an item to the cart to placing an order with payment in TEST ENV, you need to open the page through the https connection (http protocol or open a file locally directly from the FS). Otherwise, the payment step will not work. These are the limitations of the payment system.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./checkout-core.js"></script>
    <script src="https://cdn-test.discover.swiss/webcomponents/checkout/checkout-product-selector-0.js"></script>
    <script src="https://cdn-test.discover.swiss/webcomponents/checkout/checkout-product-variant-selector-0.js"></script>
    <script src="https://cdn-test.discover.swiss/webcomponents/checkout/checkout-shopping-cart-0.js"></script>
</head>
<body>
    <p>checkout-core</p>
    <checkout-core config='
      {
        "assetsPrefix": "https://cdn-test.discover.swiss/webcomponents/checkout/assets",
        "forceToAuth": false,
        "orderFulfillmentUrl": "https://api.discover.swiss/dev/orderfulfillment",
        "marketplaceUrl": "https://api.discover.swiss/dev/market",
        "profileUrl": "https://api.discover.swiss/dev/profile",
        "refreshTokenExpirationTimeInDays": 10,
        "stripeInteractionStrategy": "dev",
        "subscriptionKey": "d458b1d3733b43c09744517ab030a753"
      }
    '>
      <div slot="stripe-payment-element" id="stripe-payment-element-id">
        stripe-payment-element isn't mounted
      </div>
    </checkout-core>


    <p>Checkout-select-variant</p>
    <checkout-product-selector>
      <button id="nova_zurichcard" slot="productBtn">ADD TO BASKET</button>
    </checkout-product-selector>


    <br><br>
    <checkout-shopping-cart>
      <span slot="checkoutShoppingCart">Checkout shopping cart</span>
    </checkout-shopping-cart>

    <p>Checkout product variant selector</p>
    <checkout-product-variant-selector
      language="de"
      product-id="shopify_6544202104961"
      show-description="true"
      show-title="true"
      config='
        {
          "assetsPrefix": "https://cdn-test.discover.swiss/webcomponents/checkout/assets/"
        }
      '>
    </checkout-product-variant-selector>
</body>
</html>

Last update: February 3, 2023 10:23:01