Chuyển đến nội dung chính

Kho lưu trữ GitHub

Mẫu FastAPI + Dodo Payments hoàn chỉnh

Tổng quan

Mẫu FastAPI cung cấp một điểm khởi đầu sẵn sàng cho sản xuất để tích hợp Dodo Payments với backend Python của bạn. Mẫu này bao gồm xử lý phiên thanh toán, xác minh webhook, tích hợp cổng khách hàng và các mẫu API bất đồng bộ để giúp bạn bắt đầu chấp nhận thanh toán nhanh chóng.
Mẫu này sử dụng FastAPI với các mẫu async/await, Pydantic để xác thực, và dodopayments SDK Python để tích hợp API liền mạch.

Tính năng

  • Cài đặt nhanh - Bắt đầu trong chưa đầy 5 phút
  • Hỗ trợ bất đồng bộ - Được xây dựng với các mẫu async/await của FastAPI
  • Phiên thanh toán - Quy trình thanh toán được cấu hình sẵn sử dụng SDK Python
  • Xử lý Webhook - Điểm cuối webhook an toàn với xác minh chữ ký
  • Cổng khách hàng - Tạo phiên cổng khách hàng dễ dàng
  • An toàn kiểu - Xác thực Pydantic đầy đủ và gợi ý kiểu
  • Cấu hình môi trường - Cài đặt biến môi trường sẵn sàng sử dụng

Điều kiện tiên quyết

Trước khi bắt đầu, hãy đảm bảo bạn đã có:
  • Python 3.9+ (khuyến nghị: Python 3.11+)
  • pip hoặc uv để quản lý gói
  • Tài khoản Dodo Payments (để truy cập API và Webhook Keys từ bảng điều khiển)

Bắt đầu nhanh

1

Nhân bản kho lưu trữ

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

Tạo Môi Trường Ảo

Thiết lập một môi trường Python tách biệt:
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
Hoặc sử dụng uv để quản lý phụ thuộc nhanh hơn:
uv venv
source .venv/bin/activate
3

Cài đặt Phụ thuộc

pip install -r requirements.txt
Hoặc với uv:
uv pip install -r requirements.txt
4

Lấy Thông tin API

Đăng ký tại Dodo Payments và lấy thông tin xác thực của bạn từ bảng điều khiển:
Hãy chắc chắn rằng bạn đang ở Chế độ thử nghiệm trong khi phát triển!
5

Cấu hình Biến Môi Trường

Tạo một .env file trong thư mục gốc:
cp .env.example .env
Cập nhật các giá trị với thông tin xác thực Dodo Payments của bạn:
.env
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_WEBHOOK_KEY=your_webhook_signing_key_here
DODO_PAYMENTS_ENVIRONMENT=test_mode
Không bao giờ cam kết file .env của bạn vào kiểm soát phiên bản. Nó đã được bao gồm trong .gitignore.
6

Chạy Máy Chủ Phát Triển

uvicorn main:app --reload
Mở http://localhost:8000/docs để xem tài liệu API tương tác!
Bạn sẽ thấy Swagger UI của FastAPI với tất cả các điểm cuối có sẵn sẵn sàng để thử nghiệm.

Cấu trúc Dự án

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

Các Điểm Cuối API

Mẫu này bao gồm các điểm cuối được cấu hình sẵn sau:
Điểm cuốiPhương thứcMô tả
/checkoutPOSTTạo một phiên thanh toán mới
/webhookPOSTXử lý webhook Dodo Payments
/customer-portalPOSTTạo URL cổng khách hàng

Ví dụ Mã

Tạo một Phiên Thanh Toán

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))

Xử lý Webhooks

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"}

Tích hợp Cổng Khách Hàng

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))

Sự Kiện Webhook

Mẫu này minh họa việc xử lý các sự kiện webhook phổ biến:
Sự kiệnMô tả
payment.succeededThanh toán đã hoàn thành thành công
payment.failedNỗ lực thanh toán thất bại
subscription.activeĐăng ký hiện đang hoạt động
subscription.cancelledĐăng ký đã bị hủy
refund.succeededHoàn tiền đã được xử lý thành công
Thêm logic kinh doanh của bạn bên trong trình xử lý webhook để:
  • Cập nhật quyền người dùng trong cơ sở dữ liệu của bạn
  • Gửi email xác nhận
  • Cung cấp quyền truy cập vào sản phẩm kỹ thuật số
  • Theo dõi phân tích và số liệu

Kiểm Tra Webhooks Tại Địa Phương

Để phát triển tại địa phương, sử dụng các công cụ như ngrok để mở rộng máy chủ địa phương của bạn:
ngrok http 8000
Cập nhật URL webhook trong Bảng điều khiển Dodo Payments:
https://your-ngrok-url.ngrok.io/webhook

Triển Khai

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"]
Xây dựng và chạy:
docker build -t fastapi-dodo .
docker run -p 8000:8000 --env-file .env fastapi-dodo

Cân Nhắc Sản Xuất

Trước khi triển khai vào sản xuất:
  • Chuyển DODO_PAYMENTS_ENVIRONMENT sang live_mode
  • Sử dụng khóa API sản xuất từ bảng điều khiển
  • Cập nhật URL webhook đến miền sản xuất của bạn
  • Bật HTTPS cho tất cả các điểm cuối

Khắc Phục Sự Cố

Đảm bảo môi trường ảo của bạn đã được kích hoạt và các phụ thuộc đã được cài đặt:
source venv/bin/activate
pip install -r requirements.txt
Nguyên nhân phổ biến:
  • ID sản phẩm không hợp lệ - xác minh rằng nó tồn tại trong bảng điều khiển Dodo của bạn
  • Khóa API hoặc cài đặt môi trường sai trong .env
  • Kiểm tra nhật ký FastAPI để biết thông điệp lỗi chi tiết
Để thử nghiệm tại địa phương, sử dụng ngrok để mở rộng máy chủ của bạn:
ngrok http 8000
Cập nhật URL webhook trong bảng điều khiển Dodo đến URL ngrok. Hãy chắc chắn cập nhật file .env của bạn với khóa xác minh webhook chính xác.
  • Đảm bảo DODO_PAYMENTS_WEBHOOK_KEY được thiết lập đúng trong .env
  • Xác minh rằng bạn đang sử dụng thân yêu cầu thô để xác minh chữ ký
  • Kiểm tra rằng bạn đang đọc tiêu đề webhook-signature một cách chính xác

Tìm Hiểu Thêm

Hỗ Trợ

Cần giúp đỡ với mẫu này?