跳转到主要内容

GitHub 仓库

完整的 FastAPI + Dodo Payments 模板

概述

FastAPI 模板为将 Dodo Payments 集成到您的 Python 后端提供了一个生产就绪的起点。此模板包括结账会话处理、Webhook 验证、客户门户集成和异步 API 模式,帮助您快速开始接受支付。
此模板使用 FastAPI 的 async/await 模式,使用 Pydantic 进行验证,并使用 dodopayments Python SDK 进行无缝 API 集成。

特性

  • 快速设置 - 在 5 分钟内开始
  • 异步支持 - 使用 FastAPI 的原生 async/await 模式构建
  • 结账会话 - 使用 Python SDK 预配置的结账流程
  • Webhook 处理 - 带有签名验证的安全 Webhook 端点
  • 客户门户 - 轻松创建客户门户会话
  • 类型安全 - 完整的 Pydantic 验证和类型提示
  • 环境配置 - 准备使用的环境变量设置

先决条件

在开始之前,请确保您拥有:
  • Python 3.9+(推荐:Python 3.11+)
  • pipuv 进行包管理
  • Dodo Payments 账户(以从仪表板访问 API 和 Webhook 密钥)

快速开始

1

克隆仓库

git clone https://github.com/dodopayments/fastapi-boilerplate.git
cd fastapi-boilerplate
2

创建虚拟环境

设置一个隔离的 Python 环境:
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
或者使用 uv 进行更快的依赖管理:
uv venv
source .venv/bin/activate
3

安装依赖

pip install -r requirements.txt
或者使用 uv:
uv pip install -r requirements.txt
4

获取 API 凭证

Dodo Payments 注册并从仪表板获取您的凭证:
确保在开发时处于 测试模式
5

配置环境变量

在根目录中创建一个 .env 文件:
cp .env.example .env
用您的 Dodo Payments 凭证更新值:
.env
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_WEBHOOK_KEY=your_webhook_signing_key_here
DODO_PAYMENTS_ENVIRONMENT=test_mode
切勿将您的 .env 文件提交到版本控制。它已包含在 .gitignore 中。
6

运行开发服务器

uvicorn main:app --reload
打开 http://localhost:8000/docs 查看交互式 API 文档!
您应该看到 FastAPI 的 Swagger UI,所有可用的端点都准备好进行测试。

项目结构

fastapi-boilerplate/
├── main.py                 # FastAPI application entry point
├── routers/
│   ├── checkout.py         # Checkout session endpoints
│   ├── webhook.py          # Webhook handler endpoint
│   └── customer_portal.py  # Customer portal endpoints
├── config.py               # Environment configuration
├── requirements.txt        # Python dependencies
├── .env.example            # Environment template
└── README.md

API 端点

该模板包括以下预配置的端点:
端点方法描述
/checkoutPOST创建新的结账会话
/webhookPOST处理 Dodo Payments Webhook
/customer-portalPOST生成客户门户 URL

代码示例

创建结账会话

from fastapi import APIRouter, HTTPException
from dodopayments import AsyncDodoPayments
from pydantic import BaseModel
from config import settings

router = APIRouter()
dodo = AsyncDodoPayments(
    bearer_token=settings.DODO_PAYMENTS_API_KEY,
    environment=settings.DODO_PAYMENTS_ENVIRONMENT
)

class CheckoutRequest(BaseModel):
    product_id: str
    quantity: int = 1
    customer_email: str | None = None
    customer_name: str | None = None

@router.post("/checkout")
async def create_checkout(request: CheckoutRequest):
    try:
        session = await dodo.checkout_sessions.create(
            product_cart=[{
                "product_id": request.product_id,
                "quantity": request.quantity
            }],
            customer={
                "email": request.customer_email,
                "name": request.customer_name
            } if request.customer_email else None,
            return_url="http://localhost:8000/success"
        )
        return {"checkout_url": session.url, "session_id": session.session_id}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))

处理 Webhook

from fastapi import APIRouter, Request, HTTPException
import hmac
import hashlib
from config import settings

router = APIRouter()

def verify_webhook_signature(payload: bytes, signature: str) -> bool:
    expected = hmac.new(
        settings.DODO_PAYMENTS_WEBHOOK_KEY.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

@router.post("/webhook")
async def handle_webhook(request: Request):
    payload = await request.body()
    signature = request.headers.get("webhook-signature", "")
    
    if not verify_webhook_signature(payload, signature):
        raise HTTPException(status_code=401, detail="Invalid signature")
    
    event = await request.json()
    event_type = event.get("type")
    
    match event_type:
        case "payment.succeeded":
            # Handle successful payment
            payment_id = event["data"]["payment_id"]
            print(f"Payment succeeded: {payment_id}")
            
        case "subscription.active":
            # Handle subscription activation
            subscription_id = event["data"]["subscription_id"]
            print(f"Subscription activated: {subscription_id}")
            
        case "refund.succeeded":
            # Handle refund
            refund_id = event["data"]["refund_id"]
            print(f"Refund processed: {refund_id}")
    
    return {"status": "received"}

客户门户集成

from fastapi import APIRouter, HTTPException
from dodopayments import AsyncDodoPayments
from pydantic import BaseModel
from config import settings

router = APIRouter()
dodo = AsyncDodoPayments(
    bearer_token=settings.DODO_PAYMENTS_API_KEY,
    environment=settings.DODO_PAYMENTS_ENVIRONMENT
)

class PortalRequest(BaseModel):
    customer_id: str

@router.post("/customer-portal")
async def create_portal_session(request: PortalRequest):
    try:
        session = await dodo.customers.create_customer_portal(
            customer_id=request.customer_id
        )
        return {"portal_url": session.url}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))

Webhook 事件

该模板演示了处理常见 Webhook 事件:
事件描述
payment.succeeded支付成功完成
payment.failed支付尝试失败
subscription.active订阅现已激活
subscription.cancelled订阅已取消
refund.succeeded退款成功处理
在 Webhook 处理程序中添加您的业务逻辑:
  • 更新数据库中的用户权限
  • 发送确认电子邮件
  • 提供对数字产品的访问
  • 跟踪分析和指标

本地测试 Webhook

对于本地开发,使用 ngrok 来暴露您的本地服务器:
ngrok http 8000
在您的 Dodo Payments 仪表板 中更新 Webhook URL:
https://your-ngrok-url.ngrok.io/webhook

部署

Docker

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
构建并运行:
docker build -t fastapi-dodo .
docker run -p 8000:8000 --env-file .env fastapi-dodo

生产注意事项

在部署到生产之前:
  • DODO_PAYMENTS_ENVIRONMENT 切换到 live_mode
  • 使用仪表板中的生产 API 密钥
  • 将 Webhook URL 更新为您的生产域名
  • 为所有端点启用 HTTPS

故障排除

确保您的虚拟环境已激活并安装了依赖:
source venv/bin/activate
pip install -r requirements.txt
常见原因:
  • 无效的产品 ID - 验证它在您的 Dodo 仪表板中存在
  • 错误的 API 密钥或 .env 中的环境设置
  • 检查 FastAPI 日志以获取详细错误消息
对于本地测试,使用 ngrok 来暴露您的服务器:
ngrok http 8000
在您的 Dodo 仪表板 中将 Webhook URL 更新为 ngrok URL。确保使用正确的 Webhook 验证密钥更新您的 .env 文件。
  • 确保 DODO_PAYMENTS_WEBHOOK_KEY 在您的 .env 中正确设置
  • 验证您是否使用原始请求体进行签名验证
  • 检查您是否正确读取 webhook-signature

了解更多

支持

需要有关模板的帮助吗?