الانتقال إلى المحتوى الرئيسي

مستودع GitHub

نموذج كامل لـ FastAPI + مدفوعات دودي

نظرة عامة

يوفر نموذج FastAPI نقطة انطلاق جاهزة للإنتاج لدمج مدفوعات دودي مع بايثون الخلفية الخاصة بك. يتضمن هذا القالب معالجة جلسات الدفع، والتحقق من الويب هوك، ودمج بوابة العملاء، وأنماط API غير المتزامنة لمساعدتك في البدء في قبول المدفوعات بسرعة.
يستخدم هذا النموذج FastAPI مع أنماط async/await، وPydantic للتحقق، وdodopayments SDK بايثون لدمج API بسلاسة.

الميزات

  • إعداد سريع - ابدأ في أقل من 5 دقائق
  • دعم غير متزامن - مبني على أنماط async/await الأصلية لـ FastAPI
  • جلسات الدفع - تدفق دفع مُعد مسبقًا باستخدام SDK بايثون
  • معالجة الويب هوك - نقطة نهاية ويب هوك آمنة مع التحقق من التوقيع
  • بوابة العملاء - إنشاء جلسات بوابة العملاء بسهولة
  • أمان النوع - تحقق كامل من Pydantic وتلميحات النوع
  • تكوين البيئة - إعداد متغيرات البيئة الجاهزة للاستخدام

المتطلبات المسبقة

قبل أن تبدأ، تأكد من أن لديك:
  • بايثون 3.9+ (موصى به: بايثون 3.11+)
  • pip أو uv لإدارة الحزم
  • حساب مدفوعات دودي (للوصول إلى مفاتيح API وWebhook من لوحة التحكم)

بدء سريع

1

استنساخ المستودع

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

إنشاء بيئة افتراضية

قم بإعداد بيئة بايثون معزولة:
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

قم بالتسجيل في مدفوعات دودي واحصل على بيانات اعتمادك من لوحة التحكم:
تأكد من أنك في وضع الاختبار أثناء التطوير!
5

تكوين متغيرات البيئة

قم بإنشاء ملف .env في الدليل الجذر:
cp .env.example .env
قم بتحديث القيم باستخدام بيانات اعتماد مدفوعات دودي الخاصة بك:
.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 التفاعلية!
يجب أن ترى واجهة Swagger الخاصة بـ FastAPI مع جميع نقاط النهاية المتاحة جاهزة للاختبار.

هيكل المشروع

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معالجة ويب هوك مدفوعات دودي
/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))

معالجة الويب هوك

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

أحداث الويب هوك

يظهر النموذج كيفية التعامل مع أحداث الويب هوك الشائعة:
الحدثالوصف
payment.succeededتم إكمال الدفع بنجاح
payment.failedفشل محاولة الدفع
subscription.activeالاشتراك نشط الآن
subscription.cancelledتم إلغاء الاشتراك
refund.succeededتم معالجة الاسترداد بنجاح
أضف منطق عملك داخل معالج الويب هوك لـ:
  • تحديث أذونات المستخدم في قاعدة البيانات الخاصة بك
  • إرسال رسائل تأكيد عبر البريد الإلكتروني
  • توفير الوصول إلى المنتجات الرقمية
  • تتبع التحليلات والقياسات

اختبار الويب هوك محليًا

للتطوير المحلي، استخدم أدوات مثل ngrok لفتح خادمك المحلي:
ngrok http 8000
قم بتحديث عنوان URL للويب هوك في لوحة تحكم مدفوعات دودي:
https://your-ngrok-url.ngrok.io/webhook

النشر

دوكر

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 الإنتاج من لوحة التحكم
  • قم بتحديث عنوان URL للويب هوك إلى نطاق الإنتاج الخاص بك
  • قم بتمكين HTTPS لجميع نقاط النهاية

استكشاف الأخطاء وإصلاحها

تأكد من تنشيط بيئتك الافتراضية وتثبيت التبعيات:
source venv/bin/activate
pip install -r requirements.txt
الأسباب الشائعة:
  • معرف المنتج غير صالح - تحقق من أنه موجود في لوحة تحكم دودي الخاصة بك
  • مفتاح API أو إعداد البيئة غير صحيح في .env
  • تحقق من سجلات FastAPI للحصول على رسائل خطأ مفصلة
للاختبار المحلي، استخدم ngrok لفتح خادمك:
ngrok http 8000
قم بتحديث عنوان URL للويب هوك في لوحة تحكم دودي إلى عنوان URL الخاص بـ ngrok. تأكد من تحديث ملف .env الخاص بك بمفتاح التحقق الصحيح للويب هوك.
  • تأكد من أن DODO_PAYMENTS_WEBHOOK_KEY تم تعيينه بشكل صحيح في .env
  • تحقق من أنك تستخدم جسم الطلب الخام للتحقق من التوقيع
  • تحقق من أنك تقرأ رأس webhook-signature بشكل صحيح

تعرف على المزيد

الدعم

تحتاج إلى مساعدة بشأن النموذج؟