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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:01:10