Skip to main content
Payment Elements is a React SDK that renders the payment-method form for one payment intent and confirms it from the browser. Your server creates the intent and hands the clientSecret to the page; the SDK does the rest. You keep full control of the surrounding checkout UI, including the email, name, and billing-address fields. Requires React 18 or 19.

Overview

  1. Your server calls POST /payments/payment-intent and returns the clientSecret to the browser. The secret is scoped to that one intent and is only issued on the create response; the SDK uses it both to load the intent and to confirm the payment on the buyer’s behalf.
  2. Wrap your checkout in <PaymentProvider clientSecret={...}>, render <PaymentElement /> where the payment-method form should appear, and render the required <BrandingElement />.
  3. Collect email, name, and billing address in your own fields, then call confirm() from usePaymentElements().
  4. Treat the result as “the buyer is done”, not “the payment settled”. Fulfill from your server when the intent’s status becomes succeeded, via the payments.payment_intent.updated webhook.

Components

<PaymentProvider>

Loads the payment intent for the given clientSecret and provides state to everything inside it. Render one provider per payment intent. The provider is safe to render on the server: it emits non-interactive placeholders until it runs in the browser.

<PaymentElement>

The payment-method form. Renders the card input and any wallets enabled for your account. Billing details are not collected here; you own those fields and pass them to confirm(). The element reports its completeness to the provider, which drives canConfirm.

<BrandingElement>

Renders the required payment-processing attribution.
<BrandingElement /> is required. It must be rendered inside the <PaymentProvider> on every page that renders <PaymentElement />. Payments from pages that omit it will be blocked. Place it near your pay button.

React hooks

usePaymentElements()

Returns the current PaymentInitializationState. Must be called inside a <PaymentProvider>. The state is a discriminated union on state: In the 'ready' state:
  • canConfirm: booleantrue once the buyer has filled in a complete payment method. Bind your pay button’s disabled to !canConfirm.
  • confirm(input): Promise<PaymentResult> — see Static methods.
  • fetchUpdates(): Promise<void> — see Static methods.

Static methods

Available on the 'ready' state returned by usePaymentElements().

confirm()

Tokenizes the payment method, confirms the intent, and runs any buyer step (such as 3-D Secure) inline. Resolves to a PaymentResult once the buyer is done or the attempt failed. Takes a single object with the buyer details you collected. Missing or malformed fields are rejected before any network call with a validation_error listing each offending field.
string
required
Buyer’s email.
string
required
Buyer’s name as it appears on the card.
object
required
Billing address for the payment method.
string
https:// URL the buyer is sent back to if a payment method requires a full-page redirect. Provide it if you enable wallets or redirect-based methods.

fetchUpdates()

Reloads the intent’s current amount, currency, and allowed payment methods. Call it after your server changes the intent (for example after applying a discount) so the form reflects the new amount, and after a payment_intent_updated error before asking the buyer to confirm again. Overlapping calls share one request.

Results and errors

PaymentResult

confirm() never throws for payment outcomes; it resolves to exactly one of: Repeated confirm() calls for the same intent while one is in flight share the same pending promise.

PaymentError

Initialization errors

When usePaymentElements() returns state: 'error', error is a PaymentInitializationError:

Full example

Gotchas

  • processing is not success. Confirmation resolving means the buyer’s part is over. Settlement happens asynchronously; the only signal to fulfill on is the intent’s status reaching succeeded, read from your server. Never grant goods or services based on a browser-side result alone.
  • Declines are retryable in place. A payment_method_declined result returns the intent to pending, so the buyer can enter another card and confirm() again without a new intent.
  • After an api_error, check before retrying. The attempt may still hold the intent’s processing lock. Read the intent from your server; if it is pending, the buyer can retry.
  • Redirect-based methods. If the payment method sends the buyer to another page, confirm() resolves processing at the moment of handoff and the buyer returns to returnUrl. Treat that landing page like any other post-checkout page: wait for the webhook.
  • One intent per provider. To switch intents, render a new <PaymentProvider> with the new clientSecret; state does not carry over.