Setting Up Stripe in Django and Managing Payment Flows
The next step is to get your Django project ready for payment processing when you have a conceptual understanding of how Stripe operates. Although handling API requests is supported by the official Stripe Python SDK (stripe), how you organize it in a Django project is just as important. In order to maintain your Django project secure, scalable, and clean, you must arrange and structure the payment logic. This section concentrates on theory.
✅ Installing Stripe Python SDK and Configuring API Keys in Django
Stripe offers a well-documented Python SDK that works beautifully with Django. You install it using pip:
pip install stripe
But the installation is just the beginning. In Django, you typically want to store your Stripe API keys securely and avoid hardcoding them anywhere in your codebase.
Best practice is to store them in your environment and load them into settings.py
like so:
# settings.py
STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY")
STRIPE_PUBLISHABLE_KEY = os.getenv("STRIPE_PUBLISHABLE_KEY")
You then set them in your .env
or directly in your environment. This keeps your secrets safe while allowing easy separation between development, staging and production environments.
Within your Django views or services where Stripe is used, you initialize the library:
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
This step must happen before any Stripe operation like creating a payment or session.
💸 Creating Payments (One-Time and Recurring)
Stripe supports both one-time payments (e.g., a digital product) and recurring payments (e.g., a monthly subscription). In Django terms, you decide the type of payment in your view logic and call the appropriate Stripe API.
One-Time Payment (Basic Flow)
- A product is selected by the user.
- A
PaymentIntent
is created on the server. - The frontend confirms the payment using Stripe Elements or Checkout.
- Stripe handles authentication (3D Secure, etc.).
- The webhook is triggered to confirm the payment status.
Recurring Payment (Subscription)
- A customer is created or retrieved.
- A
Price
andProduct
is defined in Stripe Dashboard or via API. - A
Subscription
is created for the customer. - The first payment is made, and subsequent ones are automated.
- Webhooks notify your Django backend about payment success/failure.
Both of these flows involve Stripe managing the actual card details securely, while your Django backend mostly creates the appropriate Stripe objects and listens for events.
In your Django database, you’d usually mirror this logic with models like:
Customer
: Links a DjangoUser
to a Stripecustomer_id
Payment
: Stores a record of each payment with amount, status, and payment methodSubscription
: Optional model to track recurring billing and its state
🧭 Using Stripe Checkout and Payment Intents with Django Views
Stripe Checkout and Payment Intents are two of the most common ways to process payments with Stripe.
Stripe Checkout:
This is the simplest method and highly recommended when starting out. Stripe hosts the entire UI, handles validation, 3D Secure, and even collects billing/shipping addresses.
Your Django view would look like:
- Accept request (POST or AJAX)
- Call
stripe.checkout.Session.create(...)
- Redirect the user to the session URL
- Handle success/cancel URLs in your Django app
Checkout is ideal for clean separation and quick implementation.
Payment Intents + Stripe Elements:
This method is more advanced but gives full control over the UI. You’d use Stripe Elements (a frontend JS library) to collect card data and confirm the payment.
Django's role here:
- Serve the page with the Elements script embedded
- Create a
PaymentIntent
via an API view - Receive confirmation from the frontend after Stripe processes the card
- Handle final status via webhook
This is great for apps that need deeply customized payment experiences but requires careful CSRF and frontend-backend communication handling.