如何检测用户在Stripe结账页面触发cancel_url的行为?
Stripe结账取消行为的检测方案
针对你提出的「用户未填写结账表单直接点击返回按钮触发cancel_url」的检测需求,可通过以下步骤实现:
1. 修改Cancel URL,携带Session ID
首先在创建Checkout Session时,给cancel_url添加session_id参数,这样用户取消跳转回来后,你能获取到对应的Stripe会话信息:
# 原代码修改处 cancel_url=domain + 'cancelled?session_id={CHECKOUT_SESSION_ID}',
2. 编写Cancel页面的处理视图
在你的Django项目中创建对应cancelled的视图函数,通过Session ID查询Stripe会话详情,判断用户是否有填写支付表单的行为:
def stripe_cancelled(request): stripe.api_key = settings.STRIPE_SECRET_KEY session_id = request.GET.get('session_id') # 无Session ID时直接跳转回余额页 if not session_id: return HttpResponseRedirect(f'/profiles/{request.user.username}/balance/') try: session = stripe.checkout.Session.retrieve(session_id) transaction_id = session['metadata']['transactionID'] transaction = Transaction.objects.get(id=transaction_id) # 判断用户是否未触碰支付表单:无Payment Intent或未尝试过支付 payment_intent_id = session.get('payment_intent') if not payment_intent_id: # 完全未填写表单就取消 transaction.status = 'cancelled_unfilled' print("用户未填写支付表单直接取消") else: payment_intent = stripe.PaymentIntent.retrieve(payment_intent_id) # 检查是否有过支付尝试 if payment_intent['status'] == 'requires_payment_method' and not payment_intent['attempted']: transaction.status = 'cancelled_unfilled' print("用户未提交支付表单就取消") else: # 用户填写了表单但取消,标记为普通取消 transaction.status = 'cancelled' transaction.save() # 可添加通知逻辑 add_notification(request.user, 'payment_cancelled', 'balance') except (stripe.error.StripeError, Transaction.DoesNotExist): # 处理异常,直接跳转 pass return HttpResponseRedirect(f'/profiles/{request.user.username}/balance/')
3. 补充Webhook监听超时场景
除了用户主动点击取消,还需处理「用户打开结账页面后未操作超时」的情况,在Webhook中监听checkout.session.expired事件:
def stripe_webhook(request): # 原有代码... # Handle the checkout.session.completed event if event['type'] == 'checkout.session.completed': # 原有成功逻辑... # 新增超时事件处理 elif event['type'] == 'checkout.session.expired': session = event['data']['object'] try: userObject = User.objects.get(username=session['client_reference_id']) transaction = Transaction.objects.get(id=session['metadata']['transactionID']) transaction.status = 'expired' transaction.save() add_notification(userObject, 'payment_expired', 'balance') except (User.DoesNotExist, Transaction.DoesNotExist): pass return HttpResponse(status=200)
核心判断逻辑说明
- 无Payment Intent:用户打开结账页面后完全未触碰支付表单,Stripe不会生成Payment Intent
- Payment Intent未尝试支付:用户可能填写了部分表单但未提交支付,此时
attempted字段为False,状态为requires_payment_method
内容的提问来源于stack exchange,提问作者vladimir
相关产品推荐
相关产品推荐

