Stripe Integration in Python - Full Tutorial with Flask & Django

NeuralNineAbout 10 min readAug 9, 2025Watch original
THE SUMMARYAI-generated

Key Concepts

Stripe integration, Python, Flask, Django, payments, subscriptions, API keys, price IDs, webhooks, user authentication, database management, Stripe CLI, ngrok, user profiles, premium membership, event handling.

Stripe Integration in Python: A Comprehensive Guide

This video tutorial provides a detailed walkthrough of integrating Stripe for payments and subscriptions into Python applications using Flask and Django. The content is structured into three segments: a minimal Flask proof of concept, a Django application with user authentication and individual product purchases, and a Django application with subscription management.

1. Flask Proof of Concept: Minimal Payment Integration

  • Goal: To create a basic Flask application with a single button that allows users to make a payment via Stripe and be redirected to a success or cancel page.
  • Process:
    1. Stripe Account Setup: Create a Stripe account (or sign in) at stripe.com and switch to sandbox mode for testing.

    2. Product Creation: Create a sample product in the Stripe dashboard, specifying a one-off payment and a price (e.g., €10).

    3. API Keys and Price ID: Obtain the Stripe public key, secret key, and the price ID of the product from the Stripe dashboard.

    4. Environment Setup: Create an .env file to store the API keys securely:

      STRIPE_PUBLIC_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
      STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
      
    5. Python Environment: Set up a Python virtual environment (using venv, virtualenv, or uv) and install the necessary packages: stripe, flask, and python-dotenv.

    6. Flask Application (main.py):

      • Import necessary modules: stripe, flask, render_template, redirect, url_for, os, and load_dotenv.
      • Load environment variables using load_dotenv().
      • Set the Stripe API key: stripe.api_key = os.getenv("STRIPE_SECRET_KEY").
      • Create a Flask application instance: app = Flask(__name__).
      • Define three routes:
        • / (Home): Handles both GET and POST requests.
          • GET: Renders an index.html template with a "Purchase" button.
          • POST: Initiates a Stripe checkout session.
            • Retrieves the price ID.
            • Retrieves the price object using stripe.Price.retrieve(price_id).
            • Creates a checkout session using stripe.checkout.Session.create(), specifying:
              • line_items: A list containing a dictionary with price (price ID) and quantity (1).
              • mode: payment.
              • success_url: A URL that redirects to the /success endpoint with a session_id parameter (filled by Stripe).
              • cancel_url: A URL that redirects to the /cancel endpoint.
            • Redirects the user to the Stripe checkout session URL.
        • /success: Retrieves the session ID from the URL, retrieves the checkout session using stripe.checkout.Session.retrieve(session_id), and checks the payment_status. If paid, displays a success message; otherwise, redirects to /cancel.
        • /cancel: Displays a "Payment Cancelled" message.
      • Run the Flask application: app.run().
    7. HTML Template (index.html): A simple HTML file with a heading and a form containing a "Purchase" button that submits a POST request to the / route.

  • Example: The video demonstrates a successful payment using test credit card details (e.g., 42424242...).
  • Key Takeaway: This section provides a foundational understanding of how to integrate Stripe for basic payment processing in a Flask application.

2. Django Application: User Authentication and Product Purchases

  • Goal: To build a Django application with user registration, login, and the ability for users to purchase individual items, tracking orders in the database.
  • Process:
    1. Django Project Setup: Create a Django project named "shop" and two apps: "accounts" (for authentication) and "products" (for product management and payments).
    2. User Authentication (accounts app):
      • Views (views.py):
        • Create a SignupView using CreateView from django.views.generic, specifying the UserCreationForm, template name (registration/signup.html), and success_url (redirect to login).
      • URLs (urls.py):
        • Define URL patterns for signup (/signup/) and logout (/logout/) using path from django.urls and LogoutView from django.contrib.auth.views. Include all default Django authentication URLs using include('django.contrib.auth.urls').
      • Templates (templates/registration/):
        • Create signup.html and login.html templates with forms for user registration and login, including CSRF tokens.
      • Settings (settings.py):
        • Add "accounts" and "products" to INSTALLED_APPS.
        • Set LOGIN_REDIRECT_URL (e.g., /products/) and LOGOUT_REDIRECT_URL (e.g., /accounts/login/).
    3. Product Management and Payments (products app):
      • Models (models.py):
        • Define an Order model with the following fields:
          • user: A ForeignKey to the Django user model (settings.AUTH_USER_MODEL) with on_delete=models.CASCADE and related_name='orders'.
          • stripe_session_id: A CharField to store the Stripe session ID (unique, nullable, blank).
          • amount: An IntegerField to store the amount in cents.
          • created_at: A DateTimeField with auto_now_add=True.
          • paid: A BooleanField indicating whether the order is paid (default: False).
      • Views (views.py):
        • Import necessary modules: stripe, settings, redirect, reverse, HttpResponse, csrf_exempt, and login_required.
        • Load the Stripe secret key from the environment: stripe.api_key = settings.STRIPE_SECRET_KEY.
        • Define a list of price IDs: PRICE_IDS = ["price_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"].
        • Create a products view (decorated with @login_required) to handle product display and payment processing.
          • GET: Retrieves price objects using stripe.Price.retrieve(pid) for each price ID in PRICE_IDS and renders a products/products.html template with the price objects.
          • POST:
            • Retrieves the price ID from the POST request.
            • Creates a new Order object with user, stripe_session_id (empty initially), amount (0 initially), and paid (False).
            • Creates a Stripe checkout session using stripe.checkout.Session.create(), specifying:
              • line_items: A list containing a dictionary with price (price ID) and quantity (1).
              • mode: payment.
              • success_url: A URL that redirects to the /products/ endpoint with success=1 and session_id parameters.
              • cancel_url: A URL that redirects to the /products/ endpoint with cancelled=1.
              • metadata: A dictionary containing the order_id (primary key of the Order object).
            • Updates the Order object with the checkout_session.id and checkout_session.amount_total.
            • Redirects the user to the Stripe checkout session URL.
      • URLs (urls.py):
        • Define a URL pattern for the /products/ endpoint, mapping it to the products view.
      • Templates (templates/products/):
        • Create a products.html template with:
          • A form for logging out the user.
          • Conditional messages based on the success or cancelled query parameters in the request.
          • A form for buying products, iterating over the prices (price objects) and displaying a button for each product with the price ID as the button's name and value.
    4. Webhooks (views.py):
      • Define a stripe_webhook view (decorated with @csrf_exempt) to handle Stripe webhook events.
      • Load the Stripe webhook secret from the environment: webhook_secret = settings.STRIPE_WEBHOOK_SECRET.
      • Retrieve the payload and signature from the request.
      • Construct the event using stripe.Webhook.construct_event(), verifying the signature with the webhook secret.
      • Handle the checkout.session.completed event:
        • Extract the session object from the event data.
        • Retrieve the order_id from the session metadata.
        • Filter the Order objects to find the order with the matching order_id and paid=False.
        • Update the Order object to set paid=True.
        • Return an HttpResponse with a 200 status code.
      • Define a URL pattern for the /stripe/webhook/ endpoint, mapping it to the stripe_webhook view.
    5. Stripe CLI and Webhook Setup:
      • Install the Stripe CLI and log in.
      • Use stripe listen --forward-to localhost:8000/stripe/webhook to forward Stripe events to the local development server.
      • Trigger a checkout.session.completed event using stripe trigger checkout_session.completed --add checkout_session:metadata.order_id=1 (replace 1 with the actual order ID).
      • Alternatively, set up a webhook in the Stripe dashboard, but this requires a publicly accessible URL (e.g., using ngrok).
  • Example: The video demonstrates a user registering, logging in, purchasing a product, and the webhook updating the order status in the database to "paid."
  • Key Takeaway: This section demonstrates how to build a more robust Django application with user authentication, product purchases, and webhook integration for reliable payment status updates.

3. Django Application: Subscription Management

  • Goal: To implement subscription management in the Django application, allowing users to subscribe to a service and handle subscription cancellations and other events.
  • Process:
    1. User Profile (accounts app/models.py):
      • Create a Profile model with a one-to-one relationship to the Django user model (models.OneToOneField) and a is_premium boolean field (default: False).
      • Create a signals.py file to automatically create a Profile instance whenever a new user is created.
    2. Subscription Model (products app/models.py):
      • Replace the Order model with a Subscription model with the following fields:
        • user: A ForeignKey to the Django user model.
        • stripe_subscription_id: A CharField to store the Stripe subscription ID.
        • status: A CharField to store the subscription status (default: "active").
        • current_period_end: A DateTimeField to store the end date of the current billing period (nullable).
    3. Subscription Logic (products app/views.py):
      • Modify the products view to use mode='subscription' when creating the Stripe checkout session.
      • Pass the user ID as the client_reference_id in the metadata of the checkout session.
      • Modify the stripe_webhook view to handle the following events:
        • checkout.session.completed:
          • Retrieve the subscription_id and client_reference_id from the event data.
          • Retrieve the user object using the client_reference_id.
          • Retrieve the subscription object from Stripe using the subscription_id.
          • Create or update a Subscription object in the database with the user, stripe_subscription_id, status, and current_period_end.
          • Set the is_premium field of the user's profile to True.
        • customer.subscription.updated:
          • Update the Subscription object in the database with the new status and current_period_end from the event data.
        • customer.subscription.deleted and invoice.payment_failed:
          • Retrieve the Subscription object from the database.
          • Set the status to "cancelled".
          • Set the is_premium field of the user's profile to False.
    4. Cancellation Endpoint (products app/views.py):
      • Create a cancel_subscription view (decorated with @login_required) to allow users to cancel their subscription.
      • Retrieve the active subscription for the user.
      • Use stripe.Subscription.modify() to cancel the subscription at the end of the current billing period (cancel_at_period_end=True).
    5. Stripe Dashboard Configuration:
      • Update the webhook in the Stripe dashboard to listen to the following events:
        • checkout.session.completed
        • customer.subscription.updated
        • customer.subscription.deleted
        • invoice.payment_failed
  • Example: The video demonstrates a user subscribing to a service, the webhook updating the user's profile to "premium," and the user cancelling the subscription, which eventually removes the "premium" status.
  • Key Takeaway: This section provides a comprehensive guide to implementing subscription management with Stripe in a Django application, including handling various subscription events and allowing users to cancel their subscriptions.

Notable Quotes

  • "You want to create a sandbox because you don't want to actually charge um proper credit cards and actually do proper payments. You want to simulate the environment."
  • "This is something that Stripe is going to fill uh itself. So, this is something that we pass here as a placeholder, but it's going to be filled by Stripe, not by our Python application."
  • "We don't want to rely just on redirects to uh success and cancel endpoints."

Technical Terms and Concepts

  • Stripe: A payment processing platform that allows businesses to accept online payments.
  • API Keys: Secret and public keys used to authenticate with the Stripe API.
  • Price ID: A unique identifier for a specific price of a product or subscription in Stripe.
  • Webhooks: HTTP callbacks that are triggered by events in Stripe, allowing applications to react to changes in real-time.
  • Flask: A micro web framework for Python.
  • Django: A high-level Python web framework.
  • Virtual Environment: An isolated environment for Python projects to manage dependencies.
  • CSRF Token: A security measure to prevent cross-site request forgery attacks.
  • ngrok: A tool that exposes local servers to the internet.
  • Stripe CLI: A command-line interface for interacting with the Stripe API.
  • Metadata: Additional information that can be attached to Stripe objects, such as checkout sessions.
  • One-to-One Field: A Django model field that creates a one-to-one relationship between two models.
  • Foreign Key: A Django model field that creates a many-to-one relationship between two models.

Logical Connections

The tutorial progresses logically from a simple payment integration to a more complex subscription management system. Each section builds upon the previous one, introducing new concepts and techniques as needed. The use of webhooks is emphasized as a crucial component for reliable payment and subscription management.

Data, Research Findings, or Statistics

The video does not present any specific data, research findings, or statistics.

Synthesis/Conclusion

This tutorial provides a comprehensive guide to integrating Stripe into Python applications using Flask and Django. It covers the essential steps for setting up a Stripe account, creating products and subscriptions, handling payments, managing user authentication, and reacting to Stripe events using webhooks. The tutorial emphasizes the importance of using a sandbox environment for testing and provides practical examples of how to implement various payment and subscription scenarios. The use of webhooks is highlighted as a critical component for building reliable and robust payment and subscription systems.

AI summaries can miss context or contain errors. Check important details against the original video.

Go a little deeper.

Have a question about this video? Load its transcript to open the video chat.