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

Django集成Stripe支付遇Webhook签名缺失及邮件未发送问题求助

Django Stripe支付问题排查方案

一、Webhook "Missing stripe signature" 错误排查

  • 验证签名密钥与请求头获取方式
    • 确保使用Stripe控制台生成的Webhook专属签名密钥(格式为whsec_xxx),而非普通API密钥
    • Django中需从request.META.get('HTTP_STRIPE_SIGNATURE')获取签名头,注意是大写前缀HTTP_,不能直接用request.headers.get('Stripe-Signature')(部分WSGI服务器会转换头格式)
  • 必须使用原始请求体验证
    • 禁止使用request.POST或request.data(Django会自动解析请求体,破坏签名验证的原始数据),直接读取request.body作为payload传入stripe.Webhook.construct_event
  • 调整时间窗口(可选)
    • 若请求存在延迟,可在construct_event中增加tolerance参数放宽时间限制,例如tolerance=600(10分钟)
  • 确认端点配置
    • 检查Stripe控制台中Webhook端点URL与本地/线上部署的URL完全一致,本地开发需用ngrok等工具暴露公网可访问的地址

正确Webhook视图示例:

import stripe
from django.http import HttpResponse
from django.views.decorators.http import require_POST

stripe.api_key = "你的Stripe API密钥"
WEBHOOK_SECRET = "你的Webhook签名密钥"

@require_POST
def stripe_webhook(request):
    payload = request.body
    sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')
    event = None

    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, WEBHOOK_SECRET
            # 可选:放宽时间限制
            # tolerance=600
        )
    except ValueError:
        return HttpResponse(status=400)
    except stripe.error.SignatureVerificationError:
        return HttpResponse(status=400)

    # 绑定业务逻辑
    if event['type'] == 'checkout.session.completed':
        handle_checkout_session(event['data']['object'])

    return HttpResponse(status=200)

二、handle_checkout_session未发送邮件排查

  • 确认函数是否被触发
    • 在函数开头添加日志输出,例如用Django logger或print语句,查看是否有执行记录
    • 登录Stripe控制台查看Webhook事件日志,确认checkout.session.completed事件已成功送达你的端点,且返回200状态码
  • 检查邮件配置与代码
    • 验证settings.py中的邮件配置是否正确(EMAIL_HOST、EMAIL_PORT、EMAIL_HOST_USER、EMAIL_HOST_PASSWORD等),可先测试发送一封测试邮件确认配置有效
    • 移除send_mail中的fail_silently=True,强制抛出异常,排查是否有邮件发送错误被静默吞掉
    • 确认从checkout session中获取的收件邮箱(如session['customer_email'])不为空,避免因无收件人导致邮件不发送

排查用handle_checkout_session示例:

import logging
from django.core.mail import send_mail

logger = logging.getLogger(__name__)

def handle_checkout_session(session):
    logger.debug("开始处理支付会话: %s", session.id)
    customer_email = session.get('customer_email')
    
    if not customer_email:
        logger.error("支付会话%s未获取到用户邮箱", session.id)
        return
    
    try:
        send_mail(
            '支付成功通知',
            '你的订单已完成支付,感谢支持!',
            'noreply@yourdomain.com',
            [customer_email],
            fail_silently=False,  # 关闭静默失败,抛出异常便于排查
        )
        logger.info("支付通知邮件已发送至: %s", customer_email)
    except Exception as e:
        logger.error("发送邮件失败: %s", str(e))
        raise  # 抛出异常,避免静默失败导致无法发现问题

内容的提问来源于stack exchange,提问作者Yekpahi Prince

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 20:33:20