DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Stripe Checkout vs Payment Intents: Choosing the Right Integration

Stripe Checkout vs Payment Intents: Choosing the Right Integration

Stripe offers multiple payment integration paths. Here's when to use each.

Stripe Checkout: Fastest to Ship

Stripe-hosted checkout page. You redirect to Stripe, they handle everything.

// Create a Checkout Session
const session = await stripe.checkout.sessions.create({
  payment_method_types: ['card'],
  line_items: [{
    price: 'price_H5ggYwtDq4fbrJ',
    quantity: 1,
  }],
  mode: 'payment',  // 'subscription' for recurring
  success_url: `${YOUR_DOMAIN}/success?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${YOUR_DOMAIN}/cancel`,
  customer_email: user.email,
  metadata: { userId: user.id },
});

// Redirect user to Stripe
return { url: session.url };
Enter fullscreen mode Exit fullscreen mode

Use Checkout when: you want to ship payments in an hour, don't need custom UI, selling digital products.

Payment Intents: Custom Checkout UI

Full control over the checkout flow with Stripe Elements:

// Server: create payment intent
const paymentIntent = await stripe.paymentIntents.create({
  amount: 2999, // $29.99 in cents
  currency: 'usd',
  automatic_payment_methods: { enabled: true },
  metadata: { userId: user.id, productId: product.id },
});

return { clientSecret: paymentIntent.client_secret };
Enter fullscreen mode Exit fullscreen mode
// Client: Stripe Elements
import { loadStripe } from '@stripe/stripe-js';
import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY!);

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

  const handleSubmit = async (e: FormEvent) => {
    e.preventDefault();
    const { error } = await stripe!.confirmPayment({
      elements: elements!,
      confirmParams: { return_url: `${window.location.origin}/success` },
    });
    if (error) setErrorMessage(error.message);
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement />
      <button type='submit'>Pay $29.99</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Decision Matrix

Checkout Payment Intents
Setup time 1 hour 1 day
UI control None Full
Handles 3DS/SCA Yes Yes
Embedded in your app No Yes
Best for Simple products Custom flows

Subscriptions

For recurring billing, always use Checkout or Billing Portal — they handle:

  • Trial periods
  • Upgrade/downgrade
  • Failed payment retry
  • Cancellation flows

Full Stripe integration — Checkout, webhooks, subscription lifecycle, and customer portal — is built into the AI SaaS Starter Kit.

Top comments (0)