Django集成Stripe时Checkout Session的payment_intent为null问题求助
问题
我已成功创建Stripe Checkout Session,但查看payment_intent值时发现其为null。我需要将该值保存至Order对象,以便在支付成功的处理视图中关联对应订单。
创建Checkout Session的视图代码
@csrf_exempt def create_checkout_session(request,id): request_data = json.loads(request.body) order = Order.objects.filter(id = id).last() stripe.api_key = PaymentConfig.objects.all().last().stripe_secret_key checkout_session = stripe.checkout.Session.create( # Customer Email is optional, # It is not safe to accept email directly from the client side customer_email=request_data['email'], payment_method_types=['card'], line_items=[ { 'price_data': { 'currency': str(order.amount_type.lower()), 'product_data': { 'name': order.plan.title, }, 'unit_amount': int(order.amount * 100), }, 'quantity': 1, } ], mode='payment', success_url=request.build_absolute_uri( reverse('paymentsuccess') ) + "?session_id={CHECKOUT_SESSION_ID}", cancel_url=request.build_absolute_uri(reverse('paymentfailed')), ) order.stripe_payment_intent = checkout_session['payment_intent'] print(payment_intent) -- **null value** order.save() return JsonResponse({'sessionId':checkout_session.id})
支付成功处理视图代码
class PaymentSuccessView(TemplateView): template_name = "v3/payment-successful.html" def get(self, request, *args, **kwargs): session_id = request.GET.get('session_id') if session_id is None: return HttpResponseNotFound() stripe.api_key = PaymentConfig.objects.all().last().stripe_secret_key session = stripe.checkout.Session.retrieve(session_id) order = get_object_or_404(Order, stripe_payment_intent=session.payment_intent) --**HERE** call=AfterPaymentBackend(request, order.id) ctx = { 'order':order, 'siteInfo':Company.objects.all().last() } return render(request, self.template_name, ctx)
我已尝试咨询ChatGPT、谷歌搜索,甚至部署后测试,问题仍未解决,请问我忽略了什么?
解决方案
核心原因
创建Checkout Session的瞬间,payment_intent字段确实为null——这是Stripe的正常机制:该字段仅在用户完成支付后才会生成并填充到会话对象中,会话创建阶段不会提前生成。
修正方案
方案1:改用Session ID直接关联订单(快速解决)
- 在Order模型中新增
stripe_session_id字段(存储Checkout Session的ID) - 修改创建会话的代码,保存Session ID而非
payment_intent:
# 创建会话后替换原有赋值逻辑 order.stripe_session_id = checkout_session.id order.save()
- 支付成功视图中通过Session ID查询订单:
# 替换支付成功视图的查询逻辑 session = stripe.checkout.Session.retrieve(session_id) order = get_object_or_404(Order, stripe_session_id=session_id)
方案2:通过Webhook获取Payment Intent(生产环境推荐)
Webhook是Stripe官方推荐的支付状态同步方式,可靠性更高:
- 在Stripe后台配置
checkout.session.completed事件的Webhook端点,获取Webhook密钥 - 编写Webhook处理视图:
@csrf_exempt def stripe_webhook(request): stripe.api_key = PaymentConfig.objects.all().last().stripe_secret_key payload = request.body sig_header = request.META.get('HTTP_STRIPE_SIGNATURE') endpoint_secret = "你的Stripe Webhook密钥" try: event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret) except (ValueError, stripe.error.SignatureVerificationError): return HttpResponse(status=400) if event['type'] == 'checkout.session.completed': session = event['data']['object'] # 通过metadata获取订单ID(需在创建会话时传入) order_id = session['metadata']['order_id'] order = Order.objects.get(id=order_id) # 此时session['payment_intent']已存在 order.stripe_payment_intent = session['payment_intent'] order.save() # 执行支付成功后的业务逻辑 AfterPaymentBackend(request, order.id) return HttpResponse(status=200)
- 创建Checkout Session时添加metadata传递订单ID:
checkout_session = stripe.checkout.Session.create( # 原有参数保持不变 metadata={ 'order_id': str(order.id) }, )
额外注意事项
- 禁止依赖前端传递的信息关联订单,必须使用Stripe返回的可靠标识(Session ID或Webhook事件数据)
- 生产环境必须验证Webhook签名,防止伪造请求
内容的提问来源于stack exchange,提问作者Proud Wadhwa
相关产品推荐
相关产品推荐

