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

在Django中实现Stripe支付成功后更新广告过期日期

实现支付成功后延长广告有效期的方案

步骤1:配置Stripe Webhook端点

在Stripe后台创建Webhook端点,接收checkout.session.completed事件(该事件会在用户支付成功后触发)。端点URL设置为你的Django应用的API路径,比如/api/stripe/webhook/,开发环境可借助ngrok等工具让路径能被公网访问。

步骤2:创建Webhook处理视图

添加处理Stripe Webhook的视图,先验证事件合法性,再提取广告ID并更新有效期:

import stripe
from django.conf import settings
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework.views import APIView
from .models import Advertise
from datetime import timedelta

stripe.api_key = settings.STRIPE_SECRET_KEY

@method_decorator(csrf_exempt, name='dispatch')
class StripeWebhookView(APIView):
    def post(self, request, *args, **kwargs):
        payload = request.body
        sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')
        event = None

        try:
            event = stripe.Webhook.construct_event(
                payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
            )
        except ValueError:
            # 无效payload
            return HttpResponse(status=400)
        except stripe.error.SignatureVerificationError:
            # 无效签名
            return HttpResponse(status=400)

        # 处理支付成功事件
        if event['type'] == 'checkout.session.completed':
            session = event['data']['object']
            adv_id = session['metadata']['adv_id']
            try:
                adv = Advertise.objects.get(id=adv_id)
                # 延长30天有效期,可按需调整天数
                adv.expiration_date += timedelta(days=30)
                adv.save()
            except Advertise.DoesNotExist:
                # 广告不存在时可记录日志或做其他处理
                pass

        return HttpResponse(status=200)

步骤3:配置URL路由

在项目的urls.py中添加Webhook路由:

from django.urls import path
from .views import StripeCheckoutView, StripeWebhookView

urlpatterns = [
    # 其他路由...
    path('checkout/<int:pk>/', StripeCheckoutView.as_view(), name='stripe-checkout'),
    path('stripe/webhook/', StripeWebhookView.as_view(), name='stripe-webhook'),
]

步骤4:优化现有Checkout视图

去掉重复的广告查询,明确metadata键名,同时优化错误处理:

class StripeCheckoutView(APIView):
    def post(self, request, *args, **kwargs):
        adv_id = self.kwargs["pk"]
        try:
            adv = Advertise.objects.get(id=adv_id)
            checkout_session = stripe.checkout.Session.create(
                line_items=[
                    {
                        'price_data': {
                            'currency':'usd',
                             'unit_amount': 50 * 100,
                             'product_data':{
                                 'name': adv.description,
                             }
                        },
                        'quantity': 1,
                    },
                ],
                metadata={
                    "adv_id": adv.id  # 明确命名为adv_id,避免歧义
                },
                mode='payment',
                success_url=settings.SITE_URL + f'?success=true&adv_id={adv.id}',
                cancel_url=settings.SITE_URL + '?canceled=true',
            )
            return redirect(checkout_session.url)
        except Advertise.DoesNotExist:
            return Response({'msg': '广告不存在'}, status=404)
        except Exception as e:
            return Response({'msg':'创建Stripe会话时出错','error':str(e)}, status=500)

额外注意事项

  • Webhook可靠性:不能依赖前端success_url跳转更新有效期,用户可能中途关闭页面或网络异常导致前端无法触发,Webhook是Stripe主动通知应用,稳定性更高。
  • 过期广告处理:若广告已过期,可根据需求选择从当前日期延长:
    from datetime import date
    if adv.expiration_date < date.today():
        adv.expiration_date = date.today() + timedelta(days=30)
    else:
        adv.expiration_date += timedelta(days=30)
    
  • 日志记录:建议在Webhook中添加日志,方便后续排查问题,可使用Django自带的logging模块。

内容的提问来源于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 01:05:18