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

