> ## Documentation Index
> Fetch the complete documentation index at: https://docs.komerza.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Checkout

> Process orders and redirect customers to hosted checkout

## Overview

The `checkout()` function creates an order from the current basket and automatically redirects the customer to Komerza's hosted checkout page to complete payment.

<Note>
  The checkout function validates the basket, creates an order, and
  **automatically redirects** to the payment page. No manual redirect handling
  needed.
</Note>

## Basic Usage

```javascript theme={null}
const response = await komerza.checkout(emailAddress, couponCode);
```

### Parameters

<ParamField path="emailAddress" type="string" required>
  Customer's email address for the order. Must be a valid email format.
</ParamField>

<ParamField path="couponCode" type="string">
  Optional coupon/discount code to apply to the order. Must be 3-32 characters
  if provided.
</ParamField>

### Returns

Returns a Promise that resolves to `ApiResponse<Order>`:

```typescript theme={null}
interface ApiResponse<Order> {
  success: boolean; // Whether the order was created
  message?: string; // Error message if failed
  invalidFields?: Array<{
    // Validation errors if any
    fieldName: string;
    reason: string;
  }>;
  data?: Order; // Order details if successful
}
```

<Note>
  If `success` is `true`, the browser will automatically redirect to the
  checkout page. The response is mainly useful for error handling.
</Note>

## Validation

The checkout function performs validation before creating the order:

**Basket Validation:**

* Basket cannot be empty
* All items must have valid product and variant IDs

**Email Validation:**

* Must be a valid email address format

**Coupon Validation (if provided):**

* Must be at least 3 characters
* Cannot exceed 32 characters

## Simple Example

```javascript theme={null}
// Checkout button handler
async function handleCheckout() {
  const email = document.getElementById("email").value;
  const coupon = document.getElementById("coupon").value;

  try {
    const response = await komerza.checkout(email, coupon);

    // Only executes if checkout failed (no redirect occurred)
    if (!response.success) {
      alert(response.message || "Checkout failed");
    }
  } catch (error) {
    console.error("Checkout error:", error);
    alert("An error occurred during checkout");
  }
}
```

## Complete Example with Validation

```html theme={null}
<!DOCTYPE html>
<html>
  <head>
    <title>Checkout</title>
    <script src="https://cdn.komerza.com/komerza.min.js"></script>
    <style>
      .error {
        color: red;
        font-size: 14px;
      }
      .field-error {
        border-color: red;
      }
    </style>
  </head>
  <body>
    <div id="checkout-form">
      <h2>Checkout</h2>

      <div id="cart-summary"></div>

      <form onsubmit="handleCheckout(event)">
        <div>
          <label for="email">Email Address *</label>
          <input
            type="email"
            id="email"
            required
            placeholder="your@email.com"
          />
          <div id="email-error" class="error"></div>
        </div>

        <div>
          <label for="coupon">Coupon Code (optional)</label>
          <input
            type="text"
            id="coupon"
            placeholder="Enter coupon code"
            minlength="3"
            maxlength="32"
          />
          <div id="coupon-error" class="error"></div>
        </div>

        <button type="submit" id="checkout-btn">Complete Purchase</button>
      </form>
    </div>

    <script>
      // Initialize
      komerza.init("your-store-id");

      // Display cart summary
      function updateCartSummary() {
        const basket = komerza.getBasket();
        const count = komerza.getBasketItemCount();

        if (count === 0) {
          document.getElementById("cart-summary").innerHTML = `
          <p class="error">Your cart is empty</p>
        `;
          document.getElementById("checkout-btn").disabled = true;
          return;
        }

        document.getElementById("cart-summary").innerHTML = `
        <p>${count} item(s) in cart</p>
      `;
      }

      // Handle checkout
      async function handleCheckout(event) {
        event.preventDefault();

        // Clear previous errors
        document.getElementById("email-error").textContent = "";
        document.getElementById("coupon-error").textContent = "";
        document.getElementById("email").classList.remove("field-error");
        document.getElementById("coupon").classList.remove("field-error");

        const email = document.getElementById("email").value.trim();
        const coupon = document.getElementById("coupon").value.trim();

        // Basic client-side validation
        if (!email) {
          document.getElementById("email-error").textContent =
            "Email is required";
          return;
        }

        // Disable button and show loading
        const btn = document.getElementById("checkout-btn");
        const originalText = btn.textContent;
        btn.disabled = true;
        btn.textContent = "Processing...";

        try {
          // Create backup before checkout
          komerza.createBasketBackup();

          // Attempt checkout
          const response = await komerza.checkout(email, coupon || undefined);

          // If we reach here, checkout failed (no redirect happened)
          if (!response.success) {
            // Handle validation errors
            if (response.invalidFields) {
              response.invalidFields.forEach((field) => {
                const errorEl = document.getElementById(
                  `${field.fieldName}-error`
                );
                const inputEl = document.getElementById(field.fieldName);

                if (errorEl) errorEl.textContent = field.reason;
                if (inputEl) inputEl.classList.add("field-error");
              });
            } else {
              // General error
              alert(response.message || "Checkout failed. Please try again.");
            }

            // Restore basket from backup
            komerza.restoreBasketFromBackup();
          }
        } catch (error) {
          console.error("Checkout error:", error);
          alert("An unexpected error occurred. Please try again.");

          // Restore basket from backup
          komerza.restoreBasketFromBackup();
        } finally {
          // Re-enable button
          btn.disabled = false;
          btn.textContent = originalText;
        }
      }

      // Initialize display
      updateCartSummary();
    </script>
  </body>
</html>
```

## Error Handling

Common error scenarios and how to handle them:

### Empty Basket

```javascript theme={null}
const response = await komerza.checkout(email);

if (!response.success && response.message === "Basket is empty") {
  alert("Please add items to your cart before checking out");
}
```

### Validation Errors

```javascript theme={null}
const response = await komerza.checkout(email, coupon);

if (!response.success && response.invalidFields) {
  response.invalidFields.forEach((field) => {
    console.log(`${field.fieldName}: ${field.reason}`);
    // Display error next to the relevant form field
  });
}
```

### General Errors

```javascript theme={null}
try {
  await komerza.checkout(email, coupon);
} catch (error) {
  // Network error or other exception
  console.error("Checkout failed:", error);
  alert("Could not complete checkout. Please check your connection.");
}
```

## Response Object

The `Order` object in the response contains:

```typescript theme={null}
interface Order {
  id: string; // Order ID
  status: string; // Order status (e.g., "pending")
  amount: number; // Total amount
  amountPaid: number; // Amount paid so far
  currencyCode: string; // Currency (e.g., "USD")
  gateway: string; // Payment gateway used
  items: LineItem[]; // Order line items
  customer: {
    emailAddress: string;
    countryCode: string;
  };
  gatewayMetadata?: {
    clientSecret?: string; // Payment URL/secret
    transactionId?: string;
    // ... other gateway-specific fields
  };
  coupon?: {
    code: string;
    percentageDecrease?: number;
    netDecrease: number;
  };
  dateCreated: string; // ISO 8601 timestamp
}
```

## Affiliate Tracking

The checkout function automatically includes affiliate tracking if an affiliate cookie (`kmrza_ref`) is present:

```javascript theme={null}
// Affiliate ID is automatically read from cookies
// No manual handling required
await komerza.checkout(email);
```

The affiliate cookie is set when customers visit your store through an affiliate link.

## Best Practices

**Validate before submission** - Check email format client-side for instant feedback

**Create basket backups** - Save basket state before checkout to restore if payment fails

**Disable during processing** - Prevent double-submissions by disabling the checkout button

**Handle all error cases** - Account for empty basket, validation errors, and network failures

**Show loading states** - Display progress indicators while checkout is processing

**Don't auto-clear basket** - The basket persists after checkout - clear it manually after payment confirmation if needed

## Next Steps

<CardGroup cols={2}>
  <Card title="Basket Management" icon="cart-shopping" href="/storefront/basket">
    Learn how to manage cart items
  </Card>

  <Card title="Products" icon="box" href="/storefront/products">
    Display and fetch product information
  </Card>
</CardGroup>
