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

Django+Stripe支付success_url本地正常生产环境报400错误求助

Django + Stripe 生产环境支付成功页返回400 Bad Request错误

问题描述

本地环境下集成Stripe支付的Django网站功能正常,支付成功后能正常跳转至order_complete页面并加载会话数据,但部署到AWS Elastic Beanstalk后,支付成功页返回**Bad Request(400)**错误。Webhook已正确配置并能捕获所有Stripe事件,仅成功页加载失败。


相关代码

charges视图(生成Stripe会话)

def charges(request, order_id):
  try:
    cart_items = CartItem.objects.filter(user=request.user)
    domain = settings.DOMAIN_NAME
    if settings.DEBUG:
      domain = "http://127.0.0.1:8000/"   
    session = stripe.checkout.Session.create(
      customer_email=request.user.email,
      payment_method_types=['card'],
      line_items=[{
        'price_data': {
          'product_data': {
            'name': cart_item.product.product_name,
          },
          'unit_amount_decimal': cart_item.product.price*100,
          'currency': 'usd',
        },
        'quantity': cart_item.quantity,
        'tax_rates': [tax_rate.id],
      } for cart_item in cart_items],
      metadata={
         "orderID": order_id
      },
      mode='payment',
      success_url=domain + 'orders/order_complete?session_id={CHECKOUT_SESSION_ID}',
      cancel_url=domain + 'orders/order_incomplete?session_id={CHECKOUT_SESSION_ID}',
    )
    # Pass the session ID to the template
    return JsonResponse({
       "id": session.id
    })
  except stripe.error.InvalidRequestError as e:
    # Handle the specific InvalidRequestError exception
    print(f"Invalid request error: {e.param}")
  except stripe.error.StripeError as e:
    # Handle other Stripe-related errors
    print(f"Stripe error: {e}")
  except stripe.error.ValueError as e:
    print(f"Stripe error: {e}")
  except Exception as e:
    # Handle other general exceptions
    return JsonResponse({'error': str(e)}) 

order_complete视图(渲染成功页)

def order_complete(request):
   session_id = request.GET.get('session_id')
   session = stripe.checkout.Session.retrieve(session_id)
   order_number = session["metadata"]["orderID"]
   transID = session["id"]

   try:
      order = Order.objects.get(order_number=order_number, is_ordered=True)
      ordered_products = OrderProduct.objects.filter(order_id=order.id)
      payment = Payment.objects.get(payment_id=transID)

      context = {
          'order': order,
          'ordered_products': ordered_products,
          'order_number': order.order_number,
          'transID': payment.payment_id,
          'payment': payment,
      }
      return render(request, "orders/order_complete.html", context)
   except (Payment.DoesNotExist, Order.DoesNotExist):
      return redirect('home')

order_complete.html模板

{% block content %}
    
<div class="container" style="margin-top: 50px; text-align:center">
    <i class="fas fa-check-circle" style="font-size: 72px;margin-bottom: 20px;color: #28A745;"></i>
    <h2 class="text-center">Payment Successful</h2>
    <br>
    <div class="text-center">
        <a href="{% url 'store' %}" class="btn btn-success">Shop more</a>
    </div>
</div>

<div class="container" style="margin: 0 auto;width: 50%;padding: 50px;background: #f1f1f1;margin-top: 50px;margin-bottom: 50px;">
    <div class="row invoice row-printable">
        <div class="col-md-12">
            <!-- col-lg-12 start here -->
            <div class="panel panel-default plain" id="dash_0">
                <!-- Start .panel -->
                <div class="panel-body p30">
                    <div class="row">
                        <!-- Start .row -->
                        <div class="col-lg-6">
                            <!-- col-lg-6 start here -->
                            <div class="invoice-logo"><img src="{% static '/images/logo.png' %}" alt="Invoice logo" style="max-height: 40px;"></div>
                        </div>
                        <!-- col-lg-6 end here -->
                        <div class="col-lg-6">
                            <!-- col-lg-6 start here -->
                            <div class="invoice-from">
                                <ul class="list-unstyled text-right">
                                    <li><strong>Invoiced To</strong></li>
                                    <li>{{order.full_name}}</li>
                                    <li>{{order.full_address}}</li>
                                    <li>{{order.city}}, {{order.state}} {{order.zip}}</li>
                                </ul>
                            </div>
                        </div>
                        <!-- col-lg-6 end here -->
                        <div class="col-lg-12">
                            <!-- col-lg-12 start here -->
                            <div class="invoice-details mt25">
                                <div class="well">
                                    <ul class="list-unstyled mb0">
                                        <li><strong>Order:</strong> #{{order_number}}</li>
                                        <li><strong>Transaction ID:</strong> {{transID}}</li>
                                        <li><strong>Order Date:</strong> {{order.created_at}}</li>
                                        <li><strong>Status:</strong> {{order.status}}</li>
                                    </ul>
                                </div>
                            </div>

                            <div class="invoice-items">
                                <div class="table-responsive" style="overflow: hidden; outline: none;" tabindex="0">
                                    <table class="table table-bordered">
                                        <thead>
                                            <tr>
                                                <th class="per70 text-center">Products</th>
                                                <th class="per5 text-center">Qty</th>
                                                <th class="per25 text-center">Total</th>
                                            </tr>
                                        </thead>
                                        <tbody>
                                          {% for item in ordered_products %}
                                            <tr>
                                                <td>{{item.product.product_name}}
                                                  <p class="text-muted small">
                                                            {% if item.variations.all %}
                                                                {% for i in item.variations.all %}
                                                                    {{ i.variation_category | capfirst }} : {{ i.variation_value | capfirst }} <br>
                                                                {% endfor %}
                                                            {% endif %}
                                                        </p>
                                                </td>
                                                <td class="text-center">{{item.quantity}}</td>
                                                <td class="text-center">${{item.product_price}}</td>
                                            </tr>
                                          {% endfor %}
                                        </tbody>
                                        <tfoot>
                                            <tr>
                                                <th colspan="2" class="text-right">Sub Total:</th>
                                                <th class="text-center">${{order.sub_total}} </th>
                                            </tr>
                                            <tr>
                                                <th colspan="2" class="text-right">Tax:</th>
                                                <th class="text-center">${{order.tax}} </th>
                                            </tr>

                                            <tr>
                                                <th colspan="2" class="text-right">Order Total:</th>
                                                <th class="text-center">${{order.order_total}} </th>
                                            </tr>
                                        </tfoot>
                                    </table>
                                </div>
                            </div>
                            <div class="invoice-footer mt25">
                                <p class="text-center">Thank you for shopping with us!</p>
                            </div>
                        </div>
                        <!-- col-lg-12 end here -->
                    </div>
                    <!-- End .row -->
                </div>
            </div>
            <!-- End .panel -->
        </div>
        <!-- col-lg-12 end here -->
    </div>
    </div>

{% endblock content %}

排查方向与解决方案

1. 生产环境DOMAIN_NAME配置问题

  • 检查settings.DOMAIN_NAME是否包含正确的HTTPS协议前缀,生产环境必须使用HTTPS,否则Stripe跳转时会出现协议不匹配的请求错误。
  • 确保DOMAIN_NAME末尾无多余斜杠,避免生成的success_url出现//orders/...的格式错误。

2. Stripe密钥与会话参数验证

  • 确认生产环境使用的是Stripe生产密钥,而非测试密钥,否则stripe.checkout.Session.retrieve(session_id)会因权限问题抛出异常。
  • 在order_complete视图中添加日志打印session_id,验证Stripe跳转时参数是否完整传递。

3. Django安全设置拦截

  • 虽然order_complete是GET请求,但生产环境中Django的SECURE_BROWSER_XSS_FILTER等安全设置可能拦截请求,可临时添加@csrf_exempt装饰器测试是否解决问题,后续再调整CSRF白名单确保安全。

4. AWS Elastic Beanstalk环境配置

  • 检查Elastic Beanstalk负载均衡器是否配置了有效HTTPS证书,确保请求能正常转发到Django应用。
  • 确认Elastic Beanstalk环境变量中正确设置了Stripe生产密钥和DOMAIN_NAME,避免配置缺失导致的错误。

5. 订单状态同步延迟

  • Webhook捕获事件后可能存在数据库写入延迟,导致order_complete视图查询时Order或Payment记录尚未创建。可在视图中添加重试逻辑,或在Webhook处理函数中确保订单状态更新完成后再允许访问成功页。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:45:00