---
title: Payment component
description: Render native Lockerverse checkout for a catalog selection.
sidebar:
  order: 2
---

```tsx
import { LockerversePayment } from "@lockerverse/react/payment";
import "@lockerverse/react/payment.css";
```

## Required properties

| Property | Type | Description |
| --- | --- | --- |
| `widget` | `UseLockerverseWidgetResult` | Result from `useLockerverseWidget` |
| `selection` | `LockerversePaymentSelectionItem[]` | Products to quote and pay |

## Payment properties

```ts
type LockerversePaymentProps = {
  widget: UseLockerverseWidgetResult;
  selection: LockerversePaymentSelectionItem[];
  branding?: {
    accentColor?: string;
    imageUrl?: string | null;
    name: string;
  };
  metadata?: Record<string, string>;
  initialCustomFieldValues?: Record<string, boolean | string | string[]>;
  style?: LockerverseStyle;
  theme?: "dark" | "light";
  resumePayment?: {
    connectedAccountId: string | null;
    paymentReference: string;
  } | null;
  onPaymentComplete?: (payment: LockerversePaymentCompletion) => void;
  onPaymentRecoveryChange?: (recovery: LockerversePaymentRecovery | null) => void;
  onPaymentUncertain?: (payment: LockerversePaymentUncertain) => void;
};
```

The component also accepts `<section>` properties and `className`. See [Theming](/react/theming) for the shared typed CSS tokens.

## Completion

```tsx
import type { LockerversePaymentCompletion } from "@lockerverse/react/payment";

const widget = useLockerverseWidget({
  communitySlug: "your-community",
  widgetSlug: "your-widget",
});

const handlePaymentComplete = (payment: LockerversePaymentCompletion) => {
  const admissionItems = payment.lineItems?.filter(
    (item) => item.fulfillmentType === "event_admission"
  );
  console.info("Payment complete; admission item count", admissionItems?.length ?? 0);
};

<LockerversePayment
  onPaymentComplete={handlePaymentComplete}
  selection={selection}
  widget={widget}
/>
```

Use `onPaymentComplete` as the confirmed success signal. A direct completion
includes the normalized customer `email` and authoritative `lineItems`. A
completion recovered after reload has `null` for both fields.

## Recovery

Store `onPaymentRecoveryChange` and pass it back through `resumePayment` after reload. Keep `onPaymentUncertain` unresolved.

## Prefill custom fields

Pass configured field IDs to `initialCustomFieldValues`:

```tsx
<LockerversePayment
  widget={widget}
  selection={selection}
  initialCustomFieldValues={{
    field_muw2q7vx_sf7r94: "Autographed basketball",
  }}
/>
```

The form reads these values when a checkout form starts. Buyers can edit them;
parent re-renders and price refreshes do not overwrite their edits. To apply a
new set of initial values, start a new form with a new React `key`. This also
resets the other form inputs.

Text and textarea fields take strings. A checkbox takes a boolean. Radio and
select fields take an option ID. Checkboxes and multi-select fields take arrays
of option IDs. Unknown fields, wrong value types, and unknown options are
ignored. Only fields for the selected products are used. Required-field
validation and server validation still apply.

`LockerverseDonateLauncher` accepts the same property. For live control over
individual values and a custom submission flow, use the
[payment primitives](/react/payment-primitives) with the Core SDK.
