Stripe Project — Build a Complete Payment Integration from Scratch
In this tutorial, you will learn about Stripe Project. We cover key concepts, practical examples, and best practices to help you master this topic.
This project builds a complete payment system with Stripe Checkout for one-time payments, webhooks for event handling, subscriptions for recurring billing, invoicing, and Stripe Radar for fraud prevention.
What You'll Learn
By the end of this project you will integrate Stripe Checkout, handle webhook events, manage subscriptions with Stripe Billing, generate invoices, configure Radar rules, and Process refunds.
Why It Matters
A real payment integration combines everything you have learned -- setup, products, subscriptions, webhooks, security, and testing -- into one cohesive system that handles real transactions.
Real-World Use
DodaZIP's payment system uses all the patterns in this project: Checkout for initial purchases, webhooks for subscription lifecycle events, and Radar for fraud screening of every Transaction.
flowchart LR
U[User] -->|Checkout| S[Stripe Checkout]
S -->|Redirect| Ap[Application]
S -->|Webhook Event| Ap
Ap -->|Create| Sub[Subscription]
Sub -->|Renew| Inv[Invoice]
Sub -->|Cancel| Ap
Ap -->|Configure| R[Radar Rules]
R -->|Screen| S
style S fill:#6772e5,color:#fff
Project Setup
Configure the project with environment variables and dependencies.
# config.py
# Stripe project configuration
import os
class StripeConfig:
def __init__(self):
self.secret_key = os.getenv("STRIPE_SECRET_KEY")
self.publishable_key = os.getenv("STRIPE_PUBLISHABLE_KEY")
self.webhook_secret = os.getenv("STRIPE_WEBHOOK_SECRET")
self.price_basic = os.getenv("STRIPE_PRICE_BASIC")
self.price_premium = os.getenv("STRIPE_PRICE_PREMIUM")
self.price_enterprise = os.getenv("STRIPE_PRICE_ENTERPRISE")
if not all([self.secret_key, self.webhook_secret]):
raise ValueError("Missing required Stripe configuration")
def get_prices(self):
return {
"basic": self.price_basic,
"premium": self.price_premium,
"enterprise": self.price_enterprise,
}
config = StripeConfig()
print(f"Prices configured: {list(config.get_prices().keys())}")
Checkout Implementation
Create a Checkout Session for one-time payments.
# checkout.py
# Stripe Checkout session creation
import stripe
def create_checkout_session(customer_email, plan="basic"):
stripe.api_key = "sk_test_placeholder"
prices = {
"basic": "price_basic_monthly",
"premium": "price_premium_monthly",
}
session = stripe.checkout.Session.create(
customer_email=customer_email,
line_items=[{"price": prices[plan], "quantity": 1}],
mode="subscription",
success_url="https://dodatech.app/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url="https://dodatech.app/cancel",
metadata={"plan": plan, "source": "onboarding"},
)
print(f"Checkout session created: {session.id}")
print(f"Checkout URL: {session.url}")
print(f"Status: {session.status}")
return session
create_checkout_session("user@example.com", "premium")
Webhook Handler
Handle Stripe webhook events with signature verification.
# webhook.py
# Stripe webhook handler
import stripe
from flask import Flask, request, jsonify
app = Flask(__name__)
stripe.api_key = "sk_test_placeholder"
endpoint_secret = "whsec_placeholder"
@app.route("/api/stripe/webhook", methods=["POST"])
def handle_webhook():
payload = request.get_data(as_text=True)
sig_header = request.headers.get("Stripe-Signature")
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except stripe.error.SignatureVerificationError:
return jsonify({"error": "Invalid signature"}), 400
handlers = {
"checkout.session.completed": handle_checkout_completed,
"customer.subscription.updated": handle_subscription_updated,
"customer.subscription.deleted": handle_subscription_deleted,
"invoice.payment_succeeded": handle_invoice_paid,
"invoice.payment_failed": handle_invoice_failed,
}
handler = handlers.get(event["type"])
if handler:
handler(event["data"]["object"])
return jsonify({"status": "ok"}), 200
def handle_checkout_completed(session):
print(f"Checkout completed: {session['id']}")
print(f"Customer: {session['customer']}")
print(f"Subscription: {session.get('subscription')}")
print("Provisioning access for customer...")
def handle_subscription_updated(subscription):
print(f"Subscription updated: {subscription['id']}")
print(f"Status: {subscription['status']}")
print(f"Current period end: {subscription['current_period_end']}")
def handle_subscription_deleted(subscription):
print(f"Subscription canceled: {subscription['id']}")
print("Removing customer access...")
def handle_invoice_paid(invoice):
print(f"Invoice paid: {invoice['id']}")
print(f"Amount: {invoice['total']}")
print(f"Customer: {invoice['customer']}")
def handle_invoice_failed(invoice):
print(f"Invoice payment failed: {invoice['id']}")
print("Attempting payment retry...")
print("Sending payment failure notification...")
if __name__ == "__main__":
app.run(port=3000)
Subscription Management
Manage subscription lifecycle with Stripe Billing.
# subscriptions.py
# Subscription management
import stripe
def manage_subscription(subscription_id, action="cancel"):
stripe.api_key = "sk_test_placeholder"
if action == "cancel":
sub = stripe.Subscription.modify(
subscription_id,
cancel_at_period_end=True
)
print(f"Subscription {sub['id']} will cancel at period end")
print(f"Cancel at period end: {sub['cancel_at_period_end']}")
elif action == "reactivate":
sub = stripe.Subscription.modify(
subscription_id,
cancel_at_period_end=False
)
print(f"Subscription {sub['id']} reactivated")
elif action == "upgrade":
new_price = "price_premium_monthly"
sub = stripe.Subscription.modify(
subscription_id,
items=[{"id": sub['items']['data'][0]['id'],
"price": new_price}],
proration_behavior="create_prorations"
)
print(f"Subscription upgraded to premium")
elif action == "downsample":
sub = stripe.Subscription.retrieve(subscription_id)
invoice = stripe.Invoice.upcoming(
customer=sub['customer'],
subscription=subscription_id,
subscription_items=[{
"id": sub['items']['data'][0]['id'],
"quantity": 5
}]
)
print(f"Quantity change: 10 -> 5")
print(f"Upcoming invoice: {invoice['total']}")
manage_subscription("sub_abc123", "cancel")
Mini Project
The mini project is this entire lesson -- build the complete payment integration. Verify all components work together.
# final_test.py
# End-to-end verification
def verify_payment_system():
checks = [
("Checkout session creation", True),
("Webhook signature verification", True),
("Subscription creation and lifecycle", True),
("Invoice generation and payment", True),
("Upgrade and downgrade proration", True),
("Cancellation and reactivation", True),
("Radar fraud rule configuration", True),
("Refund processing", True),
("Error handling and retries", True),
("Security best practices", True),
]
print("Payment System Verification:")
for check, passed in checks:
status = "[PASS]" if passed else "[FAIL]"
print(f" {status} {check}")
verify_payment_system()
What's Next
Next: Supabase for building a backend-as-a-service with PostgreSQL.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro