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
相关产品推荐
相关产品推荐

