Skip to content

Stripe Payment Element — Building Secure Payment Forms with Pre-Built UI

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Stripe Payment Element. We cover key concepts, practical examples, and best practices to help you master this topic.

The Stripe Payment Element is a pre-built UI component that renders a dynamic payment form supporting cards, wallets, bank transfers, and local payment methods based on the customer's location and device.

What You'll Learn

  • How to set up Stripe Payment Element
  • How to customize the payment form appearance
  • How to handle payment confirmation and errors

Why It Matters

Building a custom payment form requires PCI SAQ Compliance, handling multiple payment methods, and managing complex validation. The Payment Element handles all of this automatically, reducing integration time from weeks to hours while maintaining full Stripe compliance.

Real-World Use

DodaTech's checkout page uses Payment Element with Apple Pay, Google Pay, and card support. The element automatically shows Apple Pay on Safari iOS devices, Google Pay on Android Chrome, and a card form on desktop. No code changes were needed when Stripe added SEPA support.

import stripe
from flask import Flask, render_template, jsonify, request

stripe.api_key = 'sk_test_...'

@app.route('/create-payment-intent', methods=['POST'])
def create_payment_intent():
    intent = stripe.PaymentIntent.create(
        amount=2999,  # $29.99
        currency='usd',
        automatic_payment_methods={'enabled': True}
    )
    return jsonify({'clientSecret': intent.client_secret})
// Client-side code
const stripe = Stripe('pk_test_...');

async function initialize() {
  const response = await fetch('/create-payment-intent', { method: 'POST' });
  const { clientSecret } = await response.json();

  const appearance = {
    theme: 'stripe',
    variables: {
      colorPrimary: '#2563eb',
      colorBackground: '#ffffff',
      colorText: '#1f2937',
      borderRadius: '8px'
    }
  };

  const elements = stripe.elements({ appearance, clientSecret });
  const paymentElement = elements.create('payment');
  paymentElement.mount('#payment-element');
}

async function handleSubmit(e) {
  e.preventDefault();
  const { error } = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: 'https://dodatech.com/checkout/complete'
    }
  });

  if (error) {
    showError(error.message);
  }
}

Custom Fonts and Themes

const appearance = {
  theme: 'night',
  labels: 'floating',
  variables: {
    fontFamily: '"Inter", system-ui, sans-serif',
    colorPrimary: '#2563eb',
    colorBackground: '#1f2937',
    colorText: '#f9fafb',
    borderRadius: '8px'
  },
  rules: {
    '.Label': { fontWeight: '600' },
    '.Input': { border: '1px solid #374151' },
    '.Tab': { border: '1px solid #374151' }
  }
};

const elements = stripe.elements({ appearance, clientSecret });

Common Mistakes

1. Not Using Automatic Payment Methods

Manual payment method configuration misses newly supported methods. Enable automatic_payment_methods for future-proof integration.

2. Storing clientSecret on the Client

The clientSecret should be fetched from your server at checkout time, not embedded in JavaScript bundles.

3. Ignoring the return_url

After payment confirmation, the customer is redirected to the return_url. This page must handle both successful and failed payments.

4. Not Handling Payment Method Changes

When the customer changes payment methods, re-fetch the clientSecret if the amount changes.

5. Skipping Loading States

The Payment Element takes time to load. Show a loading state while elements.mount() is pending.

Practice Questions

  1. What is the Stripe Payment Element?
  2. How does automatic_payment_methods work?
  3. How do you customize the Payment Element appearance?
  4. What happens after confirmPayment succeeds?
  5. How do you handle payment errors?

Answers

  1. A pre-built UI component for secure payment forms. 2. It dynamically shows available payment methods based on the customer. 3. Using the appearance object with theme, variables, and rules. 4. The customer is redirected to the return_url. 5. The error object from confirmPayment contains the error message.

Challenge

Build a complete payment page with Payment Element that supports cards and wallets, handles the redirect to a confirmation page, displays payment success or failure, and works on mobile and desktop.

FAQ

What is Stripe Payment Element?

A pre-built UI component that renders the appropriate payment form based on the customer.

Is Payment Element PCI compliant?

Yes. Card details go directly to Stripe, never to your server.

What payment methods does Payment Element support?

Cards, Apple Pay, Google Pay, bank transfers, wallets, and local methods.

Can I customize the Payment Element appearance?

Yes, using the appearance object with theme, variables, and CSS-like rules.

How do I test Payment Element?

Use Stripe test card numbers like 4242424242424242.

Mini Project

Build a subscription checkout page that: creates a PaymentIntent or SetupIntent on the server, renders Payment Element on the client with custom branding, handles the post-payment redirect, and displays a confirmation page with subscription details.

What's Next

  • Learn about Stripe Embedded Checkout for quick integration
  • Explore SetupIntent for saving payment methods
  • Continue to subscription management with trials and proration

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro