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:
-
Stripe Account Setup: Create a Stripe account (or sign in) at stripe.com and switch to sandbox mode for testing.
-
Product Creation: Create a sample product in the Stripe dashboard, specifying a one-off payment and a price (e.g., €10).
-
API Keys and Price ID: Obtain the Stripe public key, secret key, and the price ID of the product from the Stripe dashboard.
-
Environment Setup: Create an
.envfile to store the API keys securely:STRIPE_PUBLIC_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx -
Python Environment: Set up a Python virtual environment (using
venv,virtualenv, oruv) and install the necessary packages:stripe,flask, andpython-dotenv. -
Flask Application (main.py):
- Import necessary modules:
stripe,flask,render_template,redirect,url_for,os, andload_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.htmltemplate 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 withprice(price ID) andquantity(1).mode:payment.success_url: A URL that redirects to the/successendpoint with asession_idparameter (filled by Stripe).cancel_url: A URL that redirects to the/cancelendpoint.
- Redirects the user to the Stripe checkout session URL.
- GET: Renders an
/success: Retrieves the session ID from the URL, retrieves the checkout session usingstripe.checkout.Session.retrieve(session_id), and checks thepayment_status. Ifpaid, displays a success message; otherwise, redirects to/cancel./cancel: Displays a "Payment Cancelled" message.
- Run the Flask application:
app.run().
- Import necessary modules:
-
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:
- Django Project Setup: Create a Django project named "shop" and two apps: "accounts" (for authentication) and "products" (for product management and payments).
- User Authentication (accounts app):
- Views (views.py):
- Create a
SignupViewusingCreateViewfromdjango.views.generic, specifying theUserCreationForm, template name (registration/signup.html), andsuccess_url(redirect to login).
- Create a
- URLs (urls.py):
- Define URL patterns for signup (
/signup/) and logout (/logout/) usingpathfromdjango.urlsandLogoutViewfromdjango.contrib.auth.views. Include all default Django authentication URLs usinginclude('django.contrib.auth.urls').
- Define URL patterns for signup (
- Templates (templates/registration/):
- Create
signup.htmlandlogin.htmltemplates with forms for user registration and login, including CSRF tokens.
- Create
- Settings (settings.py):
- Add "accounts" and "products" to
INSTALLED_APPS. - Set
LOGIN_REDIRECT_URL(e.g.,/products/) andLOGOUT_REDIRECT_URL(e.g.,/accounts/login/).
- Add "accounts" and "products" to
- Views (views.py):
- Product Management and Payments (products app):
- Models (models.py):
- Define an
Ordermodel with the following fields:user: AForeignKeyto the Django user model (settings.AUTH_USER_MODEL) withon_delete=models.CASCADEandrelated_name='orders'.stripe_session_id: ACharFieldto store the Stripe session ID (unique, nullable, blank).amount: AnIntegerFieldto store the amount in cents.created_at: ADateTimeFieldwithauto_now_add=True.paid: ABooleanFieldindicating whether the order is paid (default:False).
- Define an
- Views (views.py):
- Import necessary modules:
stripe,settings,redirect,reverse,HttpResponse,csrf_exempt, andlogin_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
productsview (decorated with@login_required) to handle product display and payment processing.- GET: Retrieves price objects using
stripe.Price.retrieve(pid)for each price ID inPRICE_IDSand renders aproducts/products.htmltemplate with the price objects. - POST:
- Retrieves the price ID from the POST request.
- Creates a new
Orderobject withuser,stripe_session_id(empty initially),amount(0 initially), andpaid(False). - Creates a Stripe checkout session using
stripe.checkout.Session.create(), specifying:line_items: A list containing a dictionary withprice(price ID) andquantity(1).mode:payment.success_url: A URL that redirects to the/products/endpoint withsuccess=1andsession_idparameters.cancel_url: A URL that redirects to the/products/endpoint withcancelled=1.metadata: A dictionary containing theorder_id(primary key of theOrderobject).
- Updates the
Orderobject with thecheckout_session.idandcheckout_session.amount_total. - Redirects the user to the Stripe checkout session URL.
- GET: Retrieves price objects using
- Import necessary modules:
- URLs (urls.py):
- Define a URL pattern for the
/products/endpoint, mapping it to theproductsview.
- Define a URL pattern for the
- Templates (templates/products/):
- Create a
products.htmltemplate with:- A form for logging out the user.
- Conditional messages based on the
successorcancelledquery 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.
- Create a
- Models (models.py):
- Webhooks (views.py):
- Define a
stripe_webhookview (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.completedevent:- Extract the session object from the event data.
- Retrieve the
order_idfrom the session metadata. - Filter the
Orderobjects to find the order with the matchingorder_idandpaid=False. - Update the
Orderobject to setpaid=True. - Return an
HttpResponsewith a 200 status code.
- Define a URL pattern for the
/stripe/webhook/endpoint, mapping it to thestripe_webhookview.
- Define a
- Stripe CLI and Webhook Setup:
- Install the Stripe CLI and log in.
- Use
stripe listen --forward-to localhost:8000/stripe/webhookto forward Stripe events to the local development server. - Trigger a
checkout.session.completedevent usingstripe trigger checkout_session.completed --add checkout_session:metadata.order_id=1(replace1with 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:
- User Profile (accounts app/models.py):
- Create a
Profilemodel with a one-to-one relationship to the Django user model (models.OneToOneField) and ais_premiumboolean field (default:False). - Create a
signals.pyfile to automatically create aProfileinstance whenever a new user is created.
- Create a
- Subscription Model (products app/models.py):
- Replace the
Ordermodel with aSubscriptionmodel with the following fields:user: AForeignKeyto the Django user model.stripe_subscription_id: ACharFieldto store the Stripe subscription ID.status: ACharFieldto store the subscription status (default: "active").current_period_end: ADateTimeFieldto store the end date of the current billing period (nullable).
- Replace the
- Subscription Logic (products app/views.py):
- Modify the
productsview to usemode='subscription'when creating the Stripe checkout session. - Pass the user ID as the
client_reference_idin themetadataof the checkout session. - Modify the
stripe_webhookview to handle the following events:checkout.session.completed:- Retrieve the
subscription_idandclient_reference_idfrom 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
Subscriptionobject in the database with theuser,stripe_subscription_id,status, andcurrent_period_end. - Set the
is_premiumfield of the user's profile toTrue.
- Retrieve the
customer.subscription.updated:- Update the
Subscriptionobject in the database with the newstatusandcurrent_period_endfrom the event data.
- Update the
customer.subscription.deletedandinvoice.payment_failed:- Retrieve the
Subscriptionobject from the database. - Set the
statusto "cancelled". - Set the
is_premiumfield of the user's profile toFalse.
- Retrieve the
- Modify the
- Cancellation Endpoint (products app/views.py):
- Create a
cancel_subscriptionview (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).
- Create a
- Stripe Dashboard Configuration:
- Update the webhook in the Stripe dashboard to listen to the following events:
checkout.session.completedcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_failed
- Update the webhook in the Stripe dashboard to listen to the following events:
- User Profile (accounts app/models.py):
- 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.





