在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
相关产品推荐
相关产品推荐

