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

# Checkout

> The payment step: Stripe Embedded Checkout or Payment Element for a client secret, or a pay button for any other checkout result.

`Checkout` renders the payment step of a checkout your backend created: Stripe's form for a client secret, or a pay button for a checkout result.

**When to use**

* The step after [`CheckoutButton`](/sdks/react/components/checkout-button) or [`PricingTable`](/sdks/react/components/pricing-table) returns a Stripe client secret.
* A payment page that resumes a checkout your backend already created.
* A pay button for a Razorpay, hosted or processing checkout, with or without `BillingProvider`.

`Checkout` does not need `BillingProvider`.

**Light**

![Checkout pay button for a checkout result, labelled Pay \$29.00, light theme](https://mintcdn.com/nozle-d78f01d8/Ae2cAgwEfN_SPqzG/images/react/components/checkout/light.png?fit=max\&auto=format\&n=Ae2cAgwEfN_SPqzG\&q=85\&s=1fd4c4dda1f22a9448e98b4426179f35)

**Dark**

![Checkout pay button for a checkout result, labelled Pay \$29.00, dark theme](https://mintcdn.com/nozle-d78f01d8/Ae2cAgwEfN_SPqzG/images/react/components/checkout/dark.png?fit=max\&auto=format\&n=Ae2cAgwEfN_SPqzG\&q=85\&s=a5ae5e8e0003842630d9c527dcf63951)

**Minimal**

![Checkout pay button for a checkout result, labelled Pay \$29.00, minimal theme](https://mintcdn.com/nozle-d78f01d8/Ae2cAgwEfN_SPqzG/images/react/components/checkout/minimal.png?fit=max\&auto=format\&n=Ae2cAgwEfN_SPqzG\&q=85\&s=035cf51763cae97ba7c7a157faa60b61)

**Neobrutal**

![Checkout pay button for a checkout result, labelled Pay \$29.00, neobrutal theme](https://mintcdn.com/nozle-d78f01d8/Ae2cAgwEfN_SPqzG/images/react/components/checkout/neobrutal.png?fit=max\&auto=format\&n=Ae2cAgwEfN_SPqzG\&q=85\&s=852727c04b7025b6124692f2a72e7090)

**Nozle**

![Checkout pay button for a checkout result, labelled Pay \$29.00, nozle theme](https://mintcdn.com/nozle-d78f01d8/Ae2cAgwEfN_SPqzG/images/react/components/checkout/nozle.png?fit=max\&auto=format\&n=Ae2cAgwEfN_SPqzG\&q=85\&s=0e506bf2902901ea6fd5efa6af058ce3)

**Nozle Dark**

![Checkout pay button for a checkout result, labelled Pay \$29.00, nozleDark theme](https://mintcdn.com/nozle-d78f01d8/Ae2cAgwEfN_SPqzG/images/react/components/checkout/nozle-dark.png?fit=max\&auto=format\&n=Ae2cAgwEfN_SPqzG\&q=85\&s=324de27041c4725c5b7e146dc57aa626)

The screenshots show the pay button of a checkout result. Stripe's own form takes its look from Stripe and is not shown.

## Importing Checkout

```tsx theme={null}
import {
  Checkout,
  useCheckout,
  type CheckoutResult,
} from '@nozle-js/react'
```

## Rendering Checkout

Pass a Stripe client secret and your Stripe publishable key:

```tsx components/pay-step.tsx theme={null}
export function PayStep({ clientSecret }: { clientSecret: string }) {
  return (
    <Checkout
      clientSecret={clientSecret}
      publishableKey="pk_live_stripe..."
      returnUrl="https://app.example.com/settings/billing"
      onSuccess={(paymentIntentId) => console.log('paid', paymentIntentId)}
      onError={(error) => console.error(error.message)}
    />
  )
}
```

A `cs_` Checkout Session secret, which Nozle returns for plan and invoice checkout, mounts Stripe Embedded Checkout. Any other Stripe secret mounts Payment Element, themed from your `appearance`, with a loading placeholder and its own submit button.

> [!WARNING]
>
> Stripe webhooks decide whether the subscription is active. `onSuccess`, `onComplete` and the return page are interface signals; reload billing status before you show success.

## Data

`Checkout` takes either a Stripe client secret or a `checkout` result in the `CheckoutResult` shape that `createCheckout` returns:

```tsx theme={null}
const result: CheckoutResult = {
  type: 'razorpay',
  checkout_id: 'chk_123',
  key_id: 'rzp_live_...',
  order_id: 'order_123',
  amount_cents: 2900,
  currency: 'INR',
}

export function ResumePayment() {
  return <Checkout checkout={result} submitLabel="Pay ₹29.00" />
}
```

See [checkout result types](/sdks/react/hooks#checkout-result-types).

### Live data

The client secret comes from `onStripeClientSecret` of [`CheckoutButton`](/sdks/react/components/checkout-button), [`PricingTable`](/sdks/react/components/pricing-table) or [`UpgradeButton`](/sdks/react/components/upgrade-button), or from `fetchClientSecret` of [`useCheckoutSession`](/sdks/react/hooks#usecheckoutsession). Your Stripe publishable key is your own; Nozle does not return it.

```tsx theme={null}
import { useState } from 'react'
import { CheckoutButton } from '@nozle-js/react'

export function BuyPro() {
  const [clientSecret, setClientSecret] = useState<string | null>(null)
  if (clientSecret) return <Checkout clientSecret={clientSecret} publishableKey="pk_live_stripe..." />
  return <CheckoutButton planCode="pro" onStripeClientSecret={setClientSecret} />
}
```

A `stripe` result passed as `checkout` is mounted with Stripe only when it carries a client secret and `publishable_key`. Nozle does not return `publishable_key`, so pass a Stripe client secret with `clientSecret` and `publishableKey` instead; a `stripe` result without them shows "Payment setup is incomplete. Contact support to continue."

## Examples

### Pay button for a checkout result

With `checkout`, the component renders a pay button that handles Razorpay, hosted, processing, completed and scheduled results. It reads `verifyCheckout` and `getCheckoutStatus` from its props first (React `0.10.0` and later), then from `BillingProvider`.

![Checkout pay button for a checkout result, labelled Pay \$29.00, light theme](https://mintcdn.com/nozle-d78f01d8/Ae2cAgwEfN_SPqzG/images/react/components/checkout/light.png?fit=max\&auto=format\&n=Ae2cAgwEfN_SPqzG\&q=85\&s=1fd4c4dda1f22a9448e98b4426179f35)

```tsx theme={null}
import type { CheckoutStatus, RazorpayVerification } from '@nozle-js/react'

const post = async (path: string, body: object): Promise<CheckoutStatus> => {
  const response = await fetch(path, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
  if (!response.ok) throw new Error(`Request failed: ${response.status}`)
  return response.json()
}

export function ResumePayment({ result }: { result: CheckoutResult }) {
  return (
    <Checkout
      checkout={result}
      submitLabel="Pay ₹29.00"
      verifyCheckout={(checkoutId: string, verification: RazorpayVerification) =>
        post('/api/billing/checkout/verify', { checkoutId, ...verification })
      }
      getCheckoutStatus={(checkoutId: string) => post('/api/billing/checkout/status', { checkoutId })}
      onComplete={() => console.log('done')}
      onDismiss={() => console.log('closed')}
    />
  )
}
```

### Your own pay button

To place your own pay button in the Payment Element form, pass it as `children` and call `useCheckout()` in it. `children` replaces the built-in submit button.

```tsx theme={null}
function PayButton() {
  const { confirmPayment, isProcessing, error } = useCheckout()
  return (
    <>
      <button type="button" onClick={() => void confirmPayment()} disabled={isProcessing}>
        {isProcessing ? 'Paying…' : 'Pay now'}
      </button>
      {error && <p role="alert">{error.message}</p>}
    </>
  )
}

export function CustomPay({ clientSecret }: { clientSecret: string }) {
  return (
    <Checkout clientSecret={clientSecret} publishableKey="pk_live_stripe...">
      <PayButton />
    </Checkout>
  )
}
```

## API reference

`Checkout` takes one of two sets of props.

### With a Stripe client secret

**clientSecret** `string` *required*

The Stripe client secret. A `cs_` Checkout Session secret mounts Embedded Checkout; any other secret mounts Payment Element.

**publishableKey** `string` *required*

Your Stripe publishable key.

**stripeAccount** `string`

Stripe Connect account ID passed to Stripe.

**returnUrl** `string`

Where Stripe returns the customer after a payment that needs a redirect (Payment Element). Defaults to the current URL.

**submitLabel** `string` (default: Pay now)

Text of the Payment Element submit button. It reads "Processing..." while the payment is confirmed.

**onSuccess** `(paymentIntentId: string) =\> void`

Payment Element only. Fires when the PaymentIntent succeeds without a redirect and receives its ID.

**onComplete** `() =\> void`

Embedded Checkout only. Fires when the session completes without a redirect. It does not fire when the session redirects to its return URL, which is how Nozle creates sessions.

**onError** `(error: Error) =\> void`

Fires when the payment fails and receives Stripe's error, or "Payment could not be confirmed. Check its status before retrying." when confirming throws. The message also shows under the form.

**onReady** `() =\> void`

Payment Element only. Fires when the form can be used; a loading placeholder shows until then.

**children** `ReactNode`

Payment Element only. Replaces the submit button. Call `useCheckout()` inside it. Defaults to a submit button.

**className** `string`

Class name on the root element.

**style** `CSSProperties`

Inline styles on the root element.

**appearance** `Appearance`

Theme for the wrapper, also mapped onto Payment Element: primary, background, text and danger colours, corner radius and font. A dark card colour picks Stripe's `night` theme. Embedded Checkout uses the branding of your Stripe account. Defaults to the provider's.

### With a checkout result

**checkout** `CheckoutResult` *required*

A result from `createCheckout` or from a checkout status call.

**submitLabel** `string` (default: Pay now)

Text of the pay button. It reads "Processing…" while it runs.

**returnUrl** `string`

Passed on to Stripe when the result is mounted with Stripe. Defaults to the current URL.

**verifyCheckout** `(checkoutId, verification) =\> Promise\<CheckoutStatus\>`

Checks a Razorpay payment on your backend. Required for Razorpay. Defaults to the provider's.

**getCheckoutStatus** `(checkoutId) =\> Promise\<CheckoutStatus\>`

Reads the checkout status on your backend, polled up to 30 times, one second apart. Required for `processing` results. Defaults to the provider's.

**onSuccess** `(paymentId: string) =\> void`

Fires when a Razorpay payment is captured and fulfilled and receives the payment ID; `onComplete` fires after it.

**onComplete** `() =\> void`

Fires when the checkout completes, including `completed` and `scheduled` results.

**onProcessing** `(status: CheckoutStatus) =\> void`

Fires while payment confirmation is pending and receives the status.

**onDismiss** `() =\> void`

Fires when the customer closes Razorpay without paying.

**onError** `(error: Error) =\> void`

Fires when the payment fails and receives the error. The message also shows under the button.

**className** `string`

Class name on the root element.

**appearance** `Appearance`

Theme, variables and element overrides. Defaults to the provider's. See [Appearance](/sdks/react/styling).

### `useCheckout`

Call `useCheckout()` only inside `children` of the Payment Element form; it throws outside `Checkout`. It is not [`useCheckoutSession`](/sdks/react/hooks#usecheckoutsession), which creates a checkout.

**confirmPayment** `() =\> Promise\<void\>`

Confirms the payment.

**isProcessing** `boolean`

`true` while the payment is confirmed.

**error** `Error | null`

The last payment error.

### States

| State | What shows |
| - | - |
| Payment Element loading | A loading placeholder until the form can be used. |
| Confirming the payment | "Processing..." on the submit button, or "Processing…" on the pay button. |
| Waiting for payment confirmation | "Payment is processing. Confirmation may take a little while." |
| Payment failed | The error message under the form or button. |
| `stripe` result without client secret and `publishable_key` | "Payment setup is incomplete. Contact support to continue." |

`Checkout` shows [Powered by Nozle](/sdks/react/components/powered-by-nozle) below the form, unless it is inside another component that already shows it.

### Appearance

> **Element keys**
>
> `checkout` (root), `checkout__submit` (the submit or pay button), `checkout__error`.
>
> Style them with `appearance.elements`. See [Elements](/sdks/react/styling#elements).

## Related

> **[CheckoutButton](/sdks/react/components/checkout-button)**
>
> Starts checkout and returns the client secret.

> **[PlanChangeControl](/sdks/react/components/plan-change-control)**
>
> Renders Checkout for a paid upgrade.

> **[Stripe](/integrations/stripe)**
>
> Connect Stripe to Nozle.

> **[Razorpay](/integrations/razorpay)**
>
> Connect Razorpay to Nozle.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.