You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django项目中添加支付功能以延长广告过期时间

实现Django广告延期支付功能的完整指导

看起来你已经搭好了广告的基础功能,现在要加支付延期的逻辑对吧?我会从支付流程设计、代码实现到回调处理一步步给你讲清楚,咱们用Stripe作为示例支付服务商(国内场景用支付宝/微信的话,核心思路完全一致)。


1. 先梳理核心流程

用户发起延期请求 → 后端生成支付订单 → 用户完成支付 → 支付服务商回调后端 → 后端验证支付成功 → 更新广告的expiration_date


2. 第一步:添加支付相关模型

首先在你的models.py里新增一个Payment模型,用来记录支付记录,方便后续对账和追溯:

from django.db import models
from django.conf import settings
from .models import Advertise  # 导入你的广告模型

class Payment(models.Model):
    PAYMENT_STATUS_CHOICES = (
        ('PENDING', '待支付'),
        ('SUCCESS', '支付成功'),
        ('FAILED', '支付失败'),
    )
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    advertise = models.ForeignKey(Advertise, on_delete=models.CASCADE, related_name='payments')
    extend_days = models.IntegerField(default=30)  # 默认延长30天,也可支持用户自定义
    amount = models.FloatField()  # 支付金额,比如10元
    status = models.CharField(max_length=20, choices=PAYMENT_STATUS_CHOICES, default='PENDING')
    transaction_id = models.CharField(max_length=255, null=True, blank=True)  # 支付服务商的交易ID
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user.username} - {self.advertise.category} - {self.status}"

执行以下命令创建数据表:

python manage.py makemigrations
python manage.py migrate

3. 第二步:集成支付服务商(以Stripe为例)

先安装Stripe的Python SDK:

pip install stripe

在settings.py里配置Stripe密钥:

STRIPE_SECRET_KEY = "你的Stripe私密密钥"
STRIPE_PUBLISHABLE_KEY = "你的Stripe公钥"
STRIPE_WEBHOOK_SECRET = "你的Stripe Webhook密钥"  # 后续回调验证用

4. 第三步:写生成支付订单的API视图

这个视图负责接收用户的延期请求,生成Stripe支付会话,返回给前端唤起支付弹窗:

import stripe
from django.conf import settings
from django.utils import timezone
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from .models import Advertise, Payment

stripe.api_key = settings.STRIPE_SECRET_KEY

class AdvertiseExtendPaymentView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, advertise_id):
        # 验证用户是否是广告所有者
        try:
            advertise = Advertise.objects.get(id=advertise_id, owner=request.user)
        except Advertise.DoesNotExist:
            return Response({"error": "广告不存在或你无操作权限"}, status=status.HTTP_404_NOT_FOUND)
        
        # 可根据需求自定义延长天数和金额(比如按天数计费)
        extend_days = request.data.get('extend_days', 30)
        amount = 10.0  # 示例:延长30天收费10元,也可改为extend_days * 0.33
        
        # 创建本地支付记录
        payment = Payment.objects.create(
            user=request.user,
            advertise=advertise,
            extend_days=extend_days,
            amount=amount
        )

        # 生成Stripe支付会话
        session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            line_items=[{
                'price_data': {
                    'currency': 'usd',  # 替换为你需要的货币,如cny
                    'product_data': {
                        'name': f'广告延期{extend_days}天',
                    },
                    'unit_amount': int(amount * 100),  # Stripe以"分"为单位
                },
                'quantity': 1,
            }],
            mode='payment',
            success_url=f"https://你的域名/api/payment/success/{payment.id}/",  # 支付成功回调地址
            cancel_url="https://你的域名/api/payment/cancel/",  # 取消支付跳转地址
            metadata={'payment_id': payment.id}  # 传递本地支付ID给Stripe,方便回调识别
        )

        return Response({"session_id": session.id, "publishable_key": settings.STRIPE_PUBLISHABLE_KEY}, status=status.HTTP_200_OK)

5. 第四步:处理支付成功的回调

这个视图是给Stripe调用的,用来验证支付状态并更新广告过期时间:

class PaymentSuccessView(APIView):
    def post(self, request):
        # 验证Stripe回调签名,防止伪造请求
        payload = request.body
        sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')
        
        try:
            event = stripe.Webhook.construct_event(
                payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
            )
        except (ValueError, stripe.error.SignatureVerificationError):
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # 处理支付成功事件
        if event['type'] == 'checkout.session.completed':
            session = event['data']['object']
            payment_id = session['metadata']['payment_id']
            payment = Payment.objects.get(id=payment_id)

            # 更新支付记录状态
            payment.status = 'SUCCESS'
            payment.transaction_id = session['payment_intent']
            payment.save()

            # 延长广告过期时间
            advertise = payment.advertise
            advertise.expiration_date = advertise.expiration_date + timezone.timedelta(days=payment.extend_days)
            advertise.save()

        return Response({"status": "success"}, status=status.HTTP_200_OK)

6. 额外注意事项

  • 权限加固:始终验证操作广告的用户是所有者,避免越权操作。
  • 时区问题:使用Django的timezone模块处理日期,避免跨时区导致的过期时间错误。
  • 支付失败处理:可新增PaymentCancelView处理支付取消/失败的情况,更新Payment状态为FAILED。
  • 前端交互:前端拿到session_id后,用Stripe.js加载支付弹窗,支付成功后提示用户或自动刷新广告列表。
  • 测试环境:Stripe提供测试信用卡号(如4242 4242 4242 4242),可用来快速测试支付流程。

如果用支付宝/微信支付,核心逻辑完全一致,只是支付订单生成、回调验证的API调用不同而已。

内容的提问来源于stack exchange,提问作者Yussef Raouf Abdelmisih

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:40:37