Skip to content

Stripe Project — Build a Complete Payment Integration from Scratch

DodaTech Updated 2026-06-28 3 min read

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