Skip to content

Stripe Checkout Session: Hosted Payment Pages for Quick Integration

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Stripe Checkout Session: Hosted Payment Pages for Quick Integration. We cover key concepts, practical examples, and best practices to help you master this topic.

Stripe Checkout Session creates a hosted payment page that handles the entire checkout flow — card entry, 3D Secure, address collection, and redirect back to your app.

What You'll Learn

How to create Checkout Sessions for one-time and subscription payments, customize branding, handle success/cancel URLs, collect customer information, and fulfill orders via Webhook.

Why It Matters

Checkout Sessions eliminate the need to build and maintain a payment form UI. DodaTech uses Checkout for all customer-facing payments, reducing frontend payment code by 80%.

Real-World Use

A customer clicks "Subscribe" on dodatech.com/pricing. The server creates a Checkout Session, redirects the customer to checkout.stripe.com, they enter card details, and are redirected back on completion.

flowchart LR
    A["User Clicks\nSubscribe"] --> B["Server Creates\nCheckout Session"]
    B --> C["Redirect to\ncheckout.stripe.com"]
    C --> D["Customer\nPays"]
    D --> E["Redirect Back\nSuccess URL"]
    D --> F["Webhook\ncheckout.session.completed"]
    F --> G["Fulfill\nOrder"]
    style A fill:#dbeafe,stroke:#2563eb
    style B fill:#6772e5,color:#fff
    style C fill:#fef3c7,stroke:#d97706
    style F fill:#bbf7d0,stroke:#16a34a

Creating a One-Time Payment Session

import stripe
stripe.api_key = os.environ["STRIPE_SECRET_KEY"]

def create_checkout_session_one_time(price_id, customer_email):
    session = stripe.checkout.Session.create(
        success_url="https://dodatech.com/success?session_id={CHECKOUT_SESSION_ID}",
        cancel_url="https://dodatech.com/pricing",
        mode="payment",
        line_items=[{
            "price": price_id,
            "quantity": 1
        }],
        customer_email=customer_email,
        metadata={"source": "pricing_page"}
    )

    print(f"Checkout Session: {session.id}")
    print(f"URL: {session.url}")
    print(f"Mode: {session.mode}")

    return session.url

url = create_checkout_session_one_time("price_123abc", "alice@example.com")
# Expected output:
# Checkout Session: cs_test_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
# URL: https://checkout.stripe.com/c/pay/cs_test_a1b2c...

Subscription Checkout

def create_checkout_session_subscription(price_id, customer_email):
    session = stripe.checkout.Session.create(
        success_url="https://dodatech.com/success?session_id={CHECKOUT_SESSION_ID}",
        cancel_url="https://dodatech.com/pricing",
        mode="subscription",
        line_items=[{
            "price": price_id,
            "quantity": 1
        }],
        customer_email=customer_email,
        subscription_data={
            "metadata": {"plan_tier": "pro"},
            "trial_period_days": 14
        },
        allow_promotion_codes=True,
        automatic_tax={"enabled": True}
    )

    print(f"Subscription checkout: {session.id}")
    print(f"Free trial: 14 days")
    return session.url

Custom Branding

# Configure in Stripe Dashboard:
# Settings > Branding
# - Icon: 128x128 PNG
# - Logo: up to 512px wide
# - Primary color: hex code
# - Background color

# These apply automatically to all Checkout Sessions
# No code changes needed

session = stripe.checkout.Session.create(
    success_url="https://dodatech.com/success",
    cancel_url="https://dodatech.com/pricing",
    mode="subscription",
    line_items=[{"price": "price_123", "quantity": 1}],
    # Stripe applies your branding automagically
)

Customer Information Collection

def create_session_with_customer_info(price_id):
    session = stripe.checkout.Session.create(
        success_url="https://dodatech.com/success",
        cancel_url="https://dodatech.com/pricing",
        mode="subscription",
        line_items=[{"price": price_id, "quantity": 1}],
        phone_number_collection={"enabled": True},
        shipping_address_collection={
            "allowed_countries": ["US", "CA", "GB", "DE", "FR"]
        },
        billing_address_collection="required",
        metadata={"source": "enterprise_page"}
    )
    print(f"Session with address collection: {session.id}")
    return session

Common Mistakes

1. Hardcoding Success/Cancel URLs

Always include {CHECKOUT_SESSION_ID} in the success URL. Stripe replaces it with the session ID, letting your success page verify and display order details.

2. Using mode="payment" for Subscriptions

Setting mode="payment" creates a one-time charge, not a subscription. Use mode="subscription" with recurring prices.

3. Forgetting to Listen for Webhooks

The redirect might not reach your app (ad blocker, browser crash). Always use webhooks to fulfill orders, not the redirect callback.

4. Not Testing the Full Flow

Test the complete flow: create session, go through checkout, verify webhook fires, check fulfillment. Don't assume it works — test each step.

5. Ignoring Payment Method Options

By default, Checkout shows all enabled methods. Limit to relevant methods with payment_method_types to reduce confusion.

Practice Questions

  1. What is the difference between Checkout Session and PaymentIntent?
  2. How do you handle order fulfillment when the customer may not return after redirect?
  3. What happens if the customer closes the browser during checkout?
  4. How do you add a trial period to a subscription?

Answers:

  1. Checkout Session creates a hosted payment page that returns a PaymentIntent or Subscription behind the scenes. PaymentIntent is the raw API without a UI.
  2. Use webhooks (checkout.session.completed) for fulfillment. Don't rely on the success redirect. The webhook fires regardless of redirect.
  3. The payment may still complete. Stripe sends the webhook. Your system should handle incomplete sessions gracefully.
  4. Set subscription_data.trial_period_days on the Checkout Session. The card isn't charged until the trial ends.

Challenge: Build a complete subscription checkout: create a price in Stripe Dashboard, build a Checkout Session with 14-day trial and promotion codes, redirect customer, verify webhook handling, and redirect to success page with session details.

FAQ

Can I customize the Checkout Session URL domain?

Checkout pages are hosted on checkout.stripe.com. Use Stripe Payment Links if you need custom domains.

What currencies does Checkout support?

Checkout supports 135+ currencies. The currency is determined by the price object.

Can I collect shipping addresses in Checkout?

Yes, enable shipping_address_collection with allowed countries.

Does Checkout support coupons?

Yes, set allow_promotion_codes: true to let customers enter coupon codes during checkout.

How do I test Checkout Sessions?

Create sessions with test API keys and use test card numbers. 4242424242424242 for successful payment, 4000002500003155 for 3D Secure.

Mini Project

Build a complete subscription purchase flow: create a price in Stripe Dashboard, build a Checkout Session with 14-day trial, redirect customer, handle success/cancel URLs, implement webhook fulfillment for checkout.session.completed, and verify end-to-end with test cards.

What's Next

Subscriptions — manage recurring billing and subscription lifecycle.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro