Skip to main content

Merchant Setup

A merchant is any business or platform integrating checkout into their website — for example, an online store selling clothing or a booking site for events.

The Merchant Tools Library determines whether a user can complete checkout directly on the merchant site using an embedded wallet experience.

When embedded checkout is available, the user remains on the merchant domain and authenticates using passkeys (cross-domain) through an embedded wallet iframe.

When embedded checkout is not available, the integration automatically falls back to a redirect-based checkout flow hosted on the wallet domain.

Overview Flow

Architecture Overview

The integration consists of three components:

Merchant Domain

Hosts the checkout experience and controls the checkout flow.

Responsibilities:

  • Launch discovery
  • Generate or retrieve a merchantTrustId
  • Launch embedded checkout
  • Handle fallback redirects
  • Persist embedded checkout status

Discovery Page

A lightweight page hosted on the wallet domain.

The discovery page determines whether embedded checkout is supported in the current browser and device environment.

Because passkey availability must be evaluated from the wallet origin, discovery must run on the wallet domain.

Wallet Checkout

Handles authentication, signing, and transaction approval.

Depending on the discovery result, checkout is displayed:

  • Inside an embedded iframe
  • As a full-page wallet redirect

Integration

Step 1: Run Discovery

Load a hidden iframe that points to the wallet-hosted discovery page.

The discovery page:

  • Calls Wallet SDK discover method
  • Evaluates passkey availability
  • Returns a DiscoveryResult using postMessage

Possible values for the flow field are:

ResultDescription
EMBEDEmbedded checkout is supported
REDIRECTEmbedded checkout is not recommended
Recommended

Merchants can use the LoginID Merchant Tools library to perform discovery instead of manually creating a hidden iframe and handling postMessage communication.

import { LoginIDMerchantCheckout } from "@loginid/checkout-merchant";

const result = await LoginIDMerchantCheckout.discover("https://wallet/discover");

if (result.flow === "EMBED") {
// Launch embedded checkout
}

Step 2: Generate or Retrieve a merchantTrustId

Before starting checkout, the merchant must provide a merchantTrustId.

The merchantTrustId is an identifier that links a wallet account.

What is merchantTrustId?

A merchantTrustId is a cryptographic identifier that links a wallet account to a browser that has successfully completed passkey registration.

It serves two purposes:

  • Account Association — it allows the wallet to determine which wallet account the checkout belongs to.
  • Possession — it proves that the browser participating in the checkout is the same browser that previously registered the passkey.

The merchantTrustId is passed from the merchant domain to the wallet domain during checkout. It is cryptographically signed and bound to the browser where passkey registration occurred, allowing the wallet to verify both account association and possession of the browser that originally registered the passkey.

Terminology Update

merchantTrustId was previously called checkoutId. These terms refer to the same identifier. Older documentation, code samples, or integrations may still use the name checkoutId.

How is a merchantTrustId Generated?

  1. The merchant generates a browser-bound key pair using the Web Crypto API.
  2. The private key is stored as a non-exportable key in IndexedDB.
  3. The browser signs a checkout payload using the stored private key.
  4. The JWS header contains a fingerprint or identifier for the associated public key.
  5. The resulting JWS becomes the merchantTrustId.
  6. The wallet validates the signature and uses the public key fingerprint to resolve the associated account.
Recommended

The LoginID Merchant Tools library can generate, store, and reuse the browser-bound key material and automatically create a valid merchantTrustId.

import { LoginIDMerchantCheckout } from "@loginid/checkout-merchant";

// Generates a new merchantTrustId if one does not exist,
// otherwise signs and returns the existing merchantTrustId.
const merchantTrustId = await LoginIDMerchantCheckout.getMerchantTrustId();

This approach ensures that only the browser that originally completed passkey registration can generate valid merchantTrustId signatures.

Step 3: Start Checkout

After discovery completes:

Embedded Path

If:

result.flow === "EMBED"

then:

  1. Create checkout iframe
  2. Load wallet checkout page
  3. Send merchantTrustId via postMessage
  4. Provide merchantTrustId to the Wallet SDK beginFlow method
  5. Complete authentication and signing inside iframe

Redirect Path

If embedded checkout is unavailable:

  1. Redirect user to wallet checkout
  2. Provide merchantTrustId to the Wallet SDK beginFlow method
  3. Complete authentication on wallet domain

Optimizing Returning Users

After a successful embedded checkout, persist a flag on the merchant domain:

localStorage.setItem("lid-checkout", "true");

This indicates that the user previously completed an embedded checkout on this browser and likely has passkey support available.

Future Visits

If the flag exists:

  • Skip discovery
  • Launch embedded checkout immediately

If the flag does not exist:

  • Run discovery
  • Result determines the best checkout experience

This optimization reduces page load time and avoids unnecessary discovery requests for returning users.

Sequence Diagram

Example Implementations

Here are somes examples of how your setup might look on the merchant side:

info

There are two ways to integrate:

  • With LoginID Merchant Library – Recommended for most merchants. Offers built-in utilities for managing:
    • merchantTrustId
    • iframe messaging
    • discovery
  • Without LoginID Merchant Library – Use this if you need full control or want to integrate directly without relying on the library.

Select the tab below based on your preferred approach.

Here is a sample from our checkout demo that uses a custom approach for communicating with the iframe and
handling the transfer of the merchantTrustId.

This approach doesn't rely on the Merchant library directly.

See the implementation details here.

info

Need help integrating secure embedded checkout on your merchant domain? Reach out to our support team at support@loginid.io for personalized assistance.

tip

Having issues? Visit our troubleshooting section for common questions and solutions.