Django电商Buy Now支付后Payment DoesNotExist错误解决问询
问题解决:Buy Now支付后出现Payment匹配不存在错误
问题现象
电商网站集成Razorpay支付,购物车结算逻辑正常,但点击Buy Now按钮完成支付后,跳转至/buy_now_payment_done/时抛出错误:DoesNotExist at /buy_now_payment_done/ Payment matching query does not exist。
错误原因分析
- BuyNow视图Payment对象创建逻辑漏洞:当Razorpay订单创建状态不是
created时,payment变量未初始化就执行save(),导致可能生成无效Payment记录;即使状态正常,若save()不在if块内,也可能出现数据不匹配情况。 - 回调URL缺失prod_id参数:
buynow_payment_done视图需要prod_id获取商品,但当前回调未传递该参数,不仅会导致订单创建失败,还可能间接引发Payment查询异常。 - 未处理Payment查询失败场景:直接使用
get()查询Payment,一旦order_id不匹配就抛出未捕获的DoesNotExist异常。
修复步骤
1. 修复BuyNow视图的Payment创建逻辑
修改views.py中的BuyNow类,确保仅在Razorpay订单创建成功时才保存Payment记录:
class BuyNow(View): def get(self, request): product_id = request.GET.get('prod_id') product = get_object_or_404(Product, id=product_id) user = request.user address = Customer.objects.filter(user=user) discounted_price = product.discounted_price shipping_amount = 40.00 total_amount = discounted_price + shipping_amount razorpay_amount = int(total_amount * 100) client = razorpay.Client(auth=("rzp_test_NqHIxmro5EHkHO", "PVE3M1msR3vfdwEcVlFuMWVX")) data = {'amount' : razorpay_amount, 'currency' : 'INR', 'receipt': 'order_rcptid_12', 'payment_capture' : '1'} payment_response = client.order.create(data=data) order_id = payment_response['id'] order_status = payment_response['status'] payment = None if order_status == 'created': payment = Payment( user=user, amount=total_amount, razorpay_order_id=order_id, razorpay_payment_status=order_status, ) payment.save() # 仅订单创建成功时保存Payment # 处理订单创建失败的情况 if not payment: messages.error(request, "支付订单创建失败,请重试") return redirect('product-detail', pk=product_id) total_item_in_cart = len(Cart.objects.filter(user=request.user)) if request.user.is_authenticated else 0 return render(request, 'app/buynow_checkout.html', { 'product': product, 'discounted_price': discounted_price, 'shipping_amount': shipping_amount, 'total_amount': total_amount, 'razorpay_amount':razorpay_amount, 'address':address, 'total_item_in_cart':total_item_in_cart, 'payment':payment.id, 'order_id':order_id # 确保模板能获取到order_id })
2. 修复buynow_checkout.html的回调URL,补充prod_id参数
修改buynow_checkout.html中的handler函数,在跳转URL中加入商品ID:
<script> var options = { "key": 'rzp_test_NqHIxmro5EHkHO', "amount": "{{ razorpay_amount }}", "currency": "INR", "name": "Tech - Store Ecomm", "description": "Test Transaction", "order_id": "{{order_id}}", "handler": function (response){ var form = document.getElementById('buynow_payment_form') window.location.href = `http://127.0.0.1:8000/buy_now_payment_done?order_id=${response.razorpay_order_id}&payment_id=${response.razorpay_payment_id}&custid=${form.elements["custid"].value}&prod_id={{ product.id }}` }, "theme": { "color": "#1f19e0" } }; var rzp1 = new Razorpay(options); rzp1.on('payment.failed', function (response){ alert(response.error.description); }); document.getElementById('rzp-button2').onclick = function(e){ rzp1.open(); e.preventDefault(); } </script>
3. 增强buynow_payment_done视图的健壮性
使用get_object_or_404替代get(),并验证所有必要参数:
@login_required def buynow_payment_done(request): order_id = request.GET.get('order_id') payment_id = request.GET.get('payment_id') custid = request.GET.get('custid') product_id = request.GET.get('prod_id') # 验证必要参数是否齐全 if not all([order_id, payment_id, custid, product_id]): messages.error(request, "无效的支付请求") return redirect('home') user = request.user customer = get_object_or_404(Customer, id=custid) # 增加user过滤,确保查询的是当前用户的Payment记录 payment = get_object_or_404(Payment, razorpay_order_id=order_id, user=user) payment.paid = True payment.razorpay_payment_id = payment_id payment.save() product = get_object_or_404(Product, id=product_id) order = OrderPlaced(user=user, customer=customer, product=product, quantity=1, payment=payment) order.save() messages.success(request, '支付成功,您的订单已提交') return redirect('orders')
4. 同步修复checkout视图的同类问题(可选)
checkout视图存在相同的Payment保存逻辑漏洞,建议同步修复:
class checkout(View): def get(self,request): user = request.user add = Customer.objects.filter(user=user) cart_items = Cart.objects.filter(user=user) famount = 0 for p in cart_items: value = p.quantity * p.product.discounted_price famount = famount+value totalamount = famount + 40 razorpay_amount = int(totalamount * 100) client = razorpay.Client(auth=("rzp_test_NqHIxmro5EHkHO", "PVE3M1msR3vfdwEcVlFuMWVX")) data = {'amount' : razorpay_amount, 'currency' : 'INR', 'receipt': 'order_rcptid_12', 'payment_capture' : '1'} payment_response = client.order.create(data=data) order_id = payment_response['id'] order_status = payment_response['status'] payment = None if order_status == 'created': payment = Payment( user=user, amount=totalamount, razorpay_order_id=order_id, razorpay_payment_status=order_status, ) payment.save() if not payment: messages.error(request, "支付订单创建失败,请重试") return redirect('cart') total_item_in_cart = len(Cart.objects.filter(user=request.user)) if request.user.is_authenticated else 0 return render(request, 'app/checkout.html',locals())
内容的提问来源于stack exchange,提问作者Prajwal Kamde
相关产品推荐
相关产品推荐

