Stripe Best Practices

Apply and integrate best practices for Stripe payments and billing workflows

Stripe Best Practices is a community skill for integrating Stripe payment processing into applications, covering checkout sessions, subscription management, webhook handling, error management, and PCI compliance patterns for secure payment workflows.

What Is This?

Overview

Stripe Best Practices provides patterns for building secure and reliable payment integrations with Stripe APIs. It covers Checkout Session creation for one-time payments and subscription signups with hosted payment pages, subscription lifecycle management including trials, upgrades, downgrades, and cancellation flows, webhook endpoint implementation for processing asynchronous events like payment confirmations and failures, error handling with retry logic and idempotency keys for reliable payment operations, and Payment Intent workflows for custom checkout experiences. The skill enables developers to build payment flows that handle edge cases gracefully while maintaining PCI compliance through Stripe hosted fields.

Who Should Use This

This skill serves backend developers integrating Stripe payments into web applications, SaaS teams building subscription billing with plan management, and engineers implementing marketplace payment flows with Stripe Connect.

Why Use It?

Problems It Solves

Payment integration requires handling many edge cases including card declines, expired cards, and network failures. Subscription billing involves complex state transitions between trial, active, past due, and canceled states. Processing webhook events reliably needs signature verification, idempotent handling, and retry logic. Maintaining PCI compliance while providing a custom checkout experience demands proper use of Stripe hosted elements.

Core Highlights

Checkout builder creates hosted payment pages with line items and tax calculation. Subscription manager handles plan changes, proration, and billing cycle adjustments. Webhook processor verifies signatures and routes events to handlers idempotently. Error handler categorizes Stripe errors and applies appropriate retry strategies.

How to Use It?

Basic Usage

import stripe
import os

stripe.api_key = os.environ[
    'STRIPE_SECRET_KEY']

def create_checkout(
        price_id: str,
        customer_email: str) -> str:
    session = stripe.checkout\
        .Session.create(
            mode='subscription',
            customer_email=customer_email,
            line_items=[{
                'price': price_id,
                'quantity': 1}],
            success_url=(
                'https://app.example.com'
                '/success?session_id='
                '{CHECKOUT_SESSION_ID}'),
            cancel_url=(
                'https://app.example.com'
                '/pricing'))
    return session.url

def get_subscription(
        sub_id: str) -> dict:
    sub = stripe.Subscription.retrieve(
        sub_id)
    return {
        'id': sub.id,
        'status': sub.status,
        'plan': sub['items']
            ['data'][0]['price']['id'],
        'current_period_end':
            sub.current_period_end}

Real-World Examples

import stripe
from flask import Flask, request, jsonify

app = Flask(__name__)
endpoint_secret = os.environ[
    'STRIPE_WEBHOOK_SECRET']

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.get_data()
    sig = request.headers.get(
        'Stripe-Signature')
    try:
        event = stripe.Webhook\
            .construct_event(
                payload, sig,
                endpoint_secret)
    except stripe.error\
            .SignatureVerificationError:
        return jsonify(
            error='Invalid sig'), 400

    if event['type'] == (
            'invoice.payment_succeeded'):
        invoice = event['data']['object']
        handle_payment_success(
            invoice['subscription'],
            invoice['amount_paid'])
    elif event['type'] == (
            'invoice.payment_failed'):
        invoice = event['data']['object']
        handle_payment_failure(
            invoice['subscription'],
            invoice['attempt_count'])
    elif event['type'] == (
            'customer.subscription'
            '.deleted'):
        sub = event['data']['object']
        handle_cancellation(sub['id'])

    return jsonify(received=True), 200

def handle_payment_success(
        sub_id: str, amount: int):
    print(f'Payment: {sub_id}, '
          f'{amount / 100:.2f}')

Advanced Tips

Use idempotency keys on all payment creation requests to prevent duplicate charges from network retries. Implement webhook event deduplication by tracking processed event IDs in your database. Use Stripe Test Clocks to simulate subscription lifecycle events including renewals, trials, and failures during development.

When to Use It?

Use Cases

Build a SaaS billing system with monthly and annual subscription plans, trial periods, and plan upgrades. Create a marketplace payment flow using Stripe Connect for splitting payments between platform and sellers. Implement a donation platform with one-time and recurring payment options.

Related Topics

Payment processing, subscription billing, webhook handling, PCI compliance, and e-commerce integration.

Important Notes

Requirements

Stripe account with API keys configured. Python with the stripe package installed. HTTPS endpoint accessible from the internet for webhook delivery. Use Stripe CLI for local webhook testing during development.

Usage Recommendations

Do: verify webhook signatures on every event to prevent spoofed requests. Use Stripe Checkout or Elements for payment form rendering to maintain PCI compliance. Store Stripe customer and subscription IDs in your database for reference.

Don't: log or store raw credit card numbers or CVV values anywhere in your application. Process webhooks synchronously with long-running operations that may cause timeout failures. Rely solely on client-side redirect for payment confirmation without webhook verification.

Limitations

Stripe webhook delivery is at-least-once, meaning handlers must be idempotent to avoid duplicate processing. Some Stripe features like Tax and Billing Portal have additional pricing. Regional payment method support varies and may require additional configuration for specific countries. Currency handling needs careful decimal precision management for different currencies.