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

Django接收Stripe订阅扣费失败webhook时出现MultiValueDictKeyError报错

报错原因

从回溯信息可以定位到错误出现在zebra/views.py第38行,代码直接从request.POST中读取request_data字段,而当前Stripe发送的webhook请求不会携带该表单字段,因此触发MultiValueDictKeyError异常。
你使用的django-zebra库已经多年停止维护,适配的是非常早期的Stripe API版本,和当前Stripe webhook的请求格式不兼容。

解决方案

方案1:替换为自定义Stripe webhook视图(更稳定,推荐)

直接废弃django-zebra的内置webhook视图,自己实现逻辑适配当前Stripe的请求格式,示例代码如下:

import json
import stripe
from django.conf import settings
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

stripe.api_key = settings.STRIPE_SECRET_KEY
webhook_secret = settings.STRIPE_WEBHOOK_SECRET

@require_POST
@csrf_exempt
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
        )
    except ValueError:
        # 无效payload
        return HttpResponse(status=400)
    except stripe.error.SignatureVerificationError:
        # 签名验证失败
        return HttpResponse(status=403)

    # 处理订阅扣费失败事件
    if event['type'] == 'invoice.payment_failed':
        payment_failed_event = event['data']['object']
        # 此处写入你的业务逻辑,例如给用户发送通知、标记订阅失效状态等
        pass

    return HttpResponse(status=200)

修改urls.py里的webhook路由,指向你自己实现的这个视图即可。

方案2:临时修复django-zebra源码(仅应急使用,不推荐)

找到报错的zebra/views.py文件,把第38行的取值逻辑修改为直接读取请求体:

# 注释原有错误逻辑
# request_data = json.loads(request.POST["request_data"])
# 替换为以下代码
request_data = json.loads(request.body)

该方案属于第三方库源码魔改,后续升级库时修改会被覆盖,仅适合临时应急使用。

注意事项

  • 生产环境必须开启Stripe webhook签名校验,避免伪造请求触发业务逻辑
  • 处理webhook事件时不要加入过长的同步逻辑,Stripe有请求超时限制,超时会触发重复回调

内容的提问来源于stack exchange,提问作者Aditya Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:54:07