Django+Braintree支付按钮无法跳转至payment-done视图问题
问题分析与修复方案
核心问题1:模板中表单代码被错误包裹在代码块标签内
你的process.html模板里,把实际需要渲染的<form>和<script>代码放在了<pre><code>标签中,这会导致浏览器将这些内容显示为纯文本代码,而非可交互的HTML元素。用户点击的只是文本里的"Pay now!",而非真正的按钮,自然不会触发后续支付逻辑。
修复方法:
移除模板中的<pre><code>标签,直接保留<form>和<script>代码:
{% extends "shop/base.html" %} {% block title %} Pay by credit card {% endblock %} {% block sidenavigation %} {% endblock %} {% block content %} <h1>Pay by credit card</h1> <form method="post" autocomplete="off"> {% if braintree_error %} <div class="alert alert-danger fade in"> <button class="close" data-dismiss="alert">×</button> {{ braintree_error|safe }} </div> {% endif %} <div class="braintree-notifications"></div> <div id="braintree-dropin"></div> <input style="background-color: #0783ca" id="submit-button" class="btn btn-success btn-lg btn-block" type="button" value="Pay now!"/> </form> <script> var braintree_client_token = "{{ client_token}}"; var button = document.querySelector('#submit-button'); braintree.dropin.create({ authorization: "{{client_token}}", container: '#braintree-dropin', card: { cardholderName: { required: false } } }, function (createErr, instance) { button.addEventListener('click', function () { instance.requestPaymentMethod(function (err, payload) { $.ajax({ type: 'POST', url: '{% url "payment:process" %}', data: { 'paymentMethodNonce': payload.nonce, 'csrfmiddlewaretoken': '{{ csrf_token }}' } }).done(function (result) { // 根据后端响应跳转页面 window.location.href = result.redirect_url; }).fail(function() { // 处理请求失败情况,跳转到取消页面 window.location.href = '{% url "payment:canceled" %}'; }); }); }); }); </script> {% endblock %}
核心问题2:AJAX请求未处理后端的跳转响应
后端视图在支付成功/失败后返回redirect(),但AJAX请求不会自动处理这种响应(浏览器仅在同步请求时执行跳转)。需要修改后端返回JSON格式的跳转地址,让前端JS主动执行页面跳转。
修复后端视图payment_process:
from django.http import JsonResponse from django.urls import reverse def payment_process(request): """处理支付的视图""" order_id = request.session.get('order_id') order = get_object_or_404(Order, id=order_id) total_cost = order.get_total_cost() if request.method == 'POST': nonce = request.POST.get('paymentMethodNonce', None) # 先检查客户创建是否成功 customer_kwargs = { "first_name": order.first_name, "last_name": order.last_name, "email": order.email } customer_create = gateway.customer.create(customer_kwargs) if not customer_create.is_success: # 客户创建失败,返回跳转地址 return JsonResponse({'success': False, 'redirect_url': reverse('payment:canceled')}) customer_id = customer_create.customer.id # 创建交易 result = gateway.transaction.sale({ 'amount': f'{total_cost:.2f}', 'payment_method_nonce': nonce, 'options': { 'submit_for_settlement': True } }) if result.is_success: order.paid = True order.braintree_id = result.transaction.id order.save() # 返回成功跳转地址 return JsonResponse({'success': True, 'redirect_url': reverse('payment:done')}) else: # 返回失败跳转地址 return JsonResponse({'success': False, 'redirect_url': reverse('payment:canceled')}) else: client_token = gateway.client_token.generate() return render( request, 'payment/process.html', { 'order': order, 'client_token': client_token } )
额外优化点
- 增加客户创建失败的判断,避免无效交易请求
- AJAX请求添加
fail回调,处理网络异常等情况,确保用户能被引导到对应页面
内容的提问来源于stack exchange,提问作者Remo
相关产品推荐
相关产品推荐

