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

Django电商Stripe支付成功后仪表盘无记录及Webhook无响应问题

Django电商集成Stripe支付异常排查

问题现象

  • 按Stripe官方文档完成集成后,用户填写支付表单后跳转至成功页面,但Stripe仪表盘无对应支付记录
  • 已在结账页面加载Stripe JS,并完整传递商品信息,不确定集成流程是否存在遗漏
  • 新增Stripe Webhook监听后,完成结账流程无任何响应:既未触发checkout.session.completed事件,也未返回错误信息

相关代码

Checkout视图函数

@login_required(login_url='core:login_register')
def checkout(request):
    user_profile = request.user.userprofile
    cart = get_object_or_404(Cart, user=user_profile)
    total_price = cart.calculate_total_price()
    has_existing_billing_address = Address.objects.filter(user=user_profile).exists()
    form = CheckoutForm(request.POST or None)

    if request.method == 'POST' and form.is_valid():
        order, _ = Checkout.objects.get_or_create(user=user_profile, cart=cart)
        default_billing_address = form.cleaned_data['use_default_billing_address']

        if default_billing_address:
            billing_address = Address.objects.filter(user=user_profile, default=True).first()
            order.billing_address = billing_address
        else:
            new_billing_address = Address(
                user=user_profile,
                street_address=form.cleaned_data['street_address'],
                apartment_address=form.cleaned_data['apartment_address'],
                zip_code=form.cleaned_data['zip_code'],
                country=form.cleaned_data['country'],
                default=True
            )
            new_billing_address.save()
            order.billing_address = new_billing_address

        order.save()
        payment_method = form.cleaned_data.get('payment_method')

        if payment_method:
            return redirect('core:payment', payment_method='card')

    context = {
        'total_price': total_price,
        'form': form,
        'has_existing_billing_address': has_existing_billing_address,
        'STRIPE_API_KEY': settings.STRIPE_SECRET_KEY,
    }
    return render(request, 'checkout.html', context)

Payment视图函数

@login_required(login_url='core:login_register')
def payment(request, payment_method):
    user_profile = request.user.userprofile
    cart = get_object_or_404(Cart, user=user_profile)
    billing_address_exists = Address.objects.filter(user=user_profile).exists()
    cart_items = cart.items.all()
    if not billing_address_exists:
        return redirect('core:checkout')
    
    line_items = [{
        'price_data': {
            'currency': 'usd',
            'product_data': {
                'name': item.product.title,
            },
            'unit_amount': int(item.product.price * 100),
        },
        'quantity': item.quantity,
    } for item in cart_items]

    try:
            session = stripe.checkout.Session.create(
                payment_method_types=[payment_method],
                line_items=line_items,
                mode='payment',
                customer_creation = 'always',
                success_url=request.build_absolute_uri(reverse('core:success')),
                cancel_url=request.build_absolute_uri(reverse('core:cancel')),
            )

            return redirect(session.url)
    
    except stripe.error.StripeError as e:
        return HttpResponse(f"Stripe Error: {str(e)}")
    
    except Exception as e:
        return HttpResponse(f"An error occurred: {str(e)}")

排查与解决步骤

1. 环境与密钥验证

  • 确认是否混用测试/生产密钥:测试密钥生成的支付记录仅出现在测试仪表盘,需切换对应环境查看
  • 核对settings.STRIPE_SECRET_KEY是否与Stripe后台对应环境的密钥完全一致

2. 支付会话有效性排查

  • 在payment视图中添加日志,打印session.id,直接在Stripe仪表盘搜索该ID,确认会话是否被成功创建
  • 检查success_url是否为公开可访问地址(本地开发需用ngrok等工具暴露端口),Stripe不允许回调至localhost未暴露的地址
  • 验证line_items中unit_amount是否为有效正整数(代码中已转换为分单位,需确认item.product.price是否为合法数值)

3. Webhook配置修复

  • 检查Stripe后台Webhook端点配置:URL需公开可访问,且已勾选checkout.session.completed事件
  • 确认Webhook签名密钥配置正确,Django视图中已正确验证Stripe签名(常见错误:未获取原始请求体、签名密钥不匹配)
  • 本地开发时使用Stripe CLI转发事件测试:
    stripe listen --forward-to localhost:8000/your-webhook-endpoint/
    
  • 排查Django中间件是否修改了请求体,导致签名验证失败(如部分中间件会自动解析JSON,需跳过Webhook端点的解析)

4. 支付流程完整性确认

  • 在success视图中通过会话ID查询支付状态,避免仅跳转成功页就判定支付完成:
    def success(request):
        session_id = request.GET.get('session_id')
        if session_id:
            session = stripe.checkout.Session.retrieve(session_id)
            if session.payment_status == 'paid':
                # 处理订单更新、库存扣减等逻辑
                pass
        return render(request, 'success.html')
    
  • 确认使用Stripe官方测试卡完成支付(如4242 4242 4242 4242,过期日期选未来月份,CVV任意3位)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:28:08