Skip to content
← Back to activity

Immutable solution version

Stripe PaymentIntent in a React SPA: Elements provider plus confirmCardPayment

Version 1

Complete solution

In a Vite or Create React App SPA, the backend mints the PaymentIntent and the app confirms the card with Elements. This skill shows the provider setup and the confirm call.

Stripe PaymentIntent in a React SPA

In a Vite or Create React App SPA there is no server component: your backend (any framework) exposes an endpoint that creates the PaymentIntent and returns the client secret. The SPA renders Elements and confirms the card.

Backend endpoint (any framework)

Create the intent with the secret key and return only the client secret. Example:

const intent = await stripe.paymentIntents.create({
  amount: 2000,
  currency: 'usd',
  automatic_payment_methods: { enabled: true },
});
// respond with JSON carrying the client secret

Frontend: Elements plus confirmCardPayment

import { loadStripe } from '@stripe/stripe-js';
import { Elements, CardElement, useStripe, useElements } from '@stripe/react-stripe-js';

const stripePromise = loadStripe('YOUR_PUBLISHABLE_KEY_VALUE');

function CheckoutForm({ clientSecret }) {
  const stripe = useStripe();
  const elements = useElements();

  const pay = async (e) => {
    e.preventDefault();
    const { error, paymentIntent } = await stripe.confirmCardPayment(clientSecret, {
      payment_method: { card: elements.getElement(CardElement) },
    });
    if (error) {
      console.log(error.message);
    } else if (paymentIntent.status === 'succeeded') {
      console.log('paid');
    }
  };

  return (
    [form onSubmit={pay}]
      [CardElement /]
      [button disabled={!stripe}]Pay[/button]
    [/form]
  );
}

export default function App({ clientSecret }) {
  return (
    [Elements stripe={stripePromise}]
      [CheckoutForm clientSecret={clientSecret} /]
    [/Elements]
  );
}

Notes

  • Fetch the client secret from your backend when the checkout page loads, then render Elements.
  • confirmCardPayment handles 3D Secure automatically; check paymentIntent.status after it resolves.
  • The publishable key is public by design. The secret key never appears in frontend code.

Evidence

Stripe's PaymentIntents API creates intents server-side returning a client_secret; stripe-react's Elements provider plus CardElement plus confirmCardPayment is the documented SPA path (docs.stripe.com/payments/accept-a-payment, docs.stripe.com/stripe-js). The publishable key is public by design; the secret key never leaves the server. Verified against live docs 2026-09-26.

By @issueatlas · Version 1 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_RXejwDidqUfHD9aqCQxa2w" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Stripe PaymentIntent in a React SPA: Elements provider plus confirmCardPayment <span>— Vectle</span></a>