Django集成Stripe Webhook异常:时而201时而500,求解决方案
解决Django+Stripe Webhook部署后不稳定的问题
核心问题定位
你遇到的500错误大概率是两个原因叠加:耗时任务阻塞Webhook响应导致Stripe超时重试,或者服务器时间与Stripe不同步引发签名验证失败。以下是针对性的修复方案:
1. 异步处理PDF生成与邮件发送
Stripe要求Webhook在10秒内返回200,而生成PDF+发邮件属于耗时操作,直接在视图中执行必然导致超时。必须把这部分逻辑异步化:
方案:用Celery实现异步任务
首先安装Celery和依赖(以Redis作为消息中间件为例):
pip install celery redis
定义异步任务(tasks.py)
from celery import shared_task from django.core.mail import EmailMessage from django.template.loader import render_to_string import pdfkit from your_app.models import Order # 替换为你的订单模型 @shared_task def send_order_confirmation(customer_email, session_id): # 根据Stripe会话ID获取订单数据 order = Order.objects.get(stripe_session_id=session_id) # 渲染PDF HTML模板 pdf_html = render_to_string('order_confirmation.html', {'order': order}) # 生成PDF(需提前安装wkhtmltopdf) pdf_content = pdfkit.from_string(pdf_html, False) # 发送带附件的邮件 email = EmailMessage( subject='您的订单已确认', body='请查收附件中的订单详情', from_email='noreply@yourdomain.com', to=[customer_email] ) email.attach(f'order_{order.id}.pdf', pdf_content, 'application/pdf') email.send()
修改Webhook视图,立刻返回200
from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt import stripe from django.conf import settings from .tasks import send_order_confirmation stripe.api_key = settings.STRIPE_SECRET_KEY @csrf_exempt def stripe_webhook(request): payload = request.body sig_header = request.META.get('HTTP_STRIPE_SIGNATURE') event = None # 验证Stripe签名 try: event = stripe.Webhook.construct_event( payload, sig_header, settings.STRIPE_WEBHOOK_SECRET ) except (ValueError, stripe.error.SignatureVerificationError): return HttpResponse(status=400) # 触发异步任务,不阻塞响应 if event['type'] == 'checkout.session.completed': session = event['data']['object'] send_order_confirmation.delay(session['customer_email'], session['id']) # 立刻返回200,告知Stripe事件已接收 return HttpResponse(status=200)
2. 修复服务器时间同步问题
Stripe签名验证要求服务器时间与Stripe官方时间差不超过5分钟,否则会直接验证失败返回500。
同步服务器时间(以Ubuntu为例)
# 安装NTP时间同步服务 sudo apt update && sudo apt install ntp # 启动并设置开机自启 sudo systemctl start ntp sudo systemctl enable ntp # 检查同步状态 ntpq -p
如果是CentOS/RHEL,把apt换成yum,服务名改为ntpd即可。
3. 部署环境排查与优化
Nginx配置检查
确保Webhook请求被正确转发,且未修改请求体(Stripe签名依赖原始请求体):
location /stripe/webhook/ { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 禁止修改请求体和头部 proxy_pass_request_body on; proxy_pass_request_headers on; }
Gunicorn优化
调整worker数量避免请求堆积,建议设置为2*CPU核心数+1:
gunicorn --workers=3 --bind=127.0.0.1:8000 your_project.wsgi:application
查看错误日志定位具体问题
在Django的settings.py中配置错误日志:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'ERROR', 'class': 'logging.FileHandler', 'filename': '/var/log/django/stripe_errors.log', }, }, 'loggers': { 'django': { 'handlers': ['file'], 'level': 'ERROR', 'propagate': True, }, }, }
查看日志文件,能精准定位500错误的根源(比如wkhtmltopdf未安装、邮件服务器配置错误等)。
内容的提问来源于stack exchange,提问作者TSG16
相关产品推荐
相关产品推荐

