如何将JavaScript支付结果对象发送至Django后端处理
问题:将JavaScript支付API的结果发送至Django后端处理
我正在使用IntaSend的JavaScript支付API处理订阅支付,目前已经能在控制台打印支付的COMPLETE/FAILED/IN-PROGRESS状态结果,但不知道如何把这些results数据传递给Django的subscription视图,完成后续的支付状态更新、订阅激活等处理。
相关代码
1. Django视图(Subscription.py)
@csrf_exempt @login_required(login_url='login') def subscription(request): user = request.user user_organization = OrganizationUser.objects.get(user=user) company = Company.objects.filter(name = user_organization.organization.name).first() today = datetime.date.today() form = CompanyForm(request.POST) subscription = Subscription.objects.all() if user_organization.is_admin == True: context = {'user_organization': user_organization, 'form': form, 'subscription': subscription, 'company': company, 'today': today,} return render(request, 'registration/subscription.html', context) else: return HttpResponse('You are not authorised to view this page')
2. 前端模板(Subscription.html)
{% block content %} <div class="columns is-centered"> <div class="column is-5 box"> {% if company.paid_till < today %} <form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} <div class="content"> <h1 class="title is-4"> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Account is not active </h1> Your company <strong>{{user_organization.organization}}</strong> is not active. Please renew the subscription.<br> </div> {% else %} <p class="label">We have great subcription options for you. Choose from our list either for monthly or annual plans</p><br> {% endif %} <h2>Subscription Packages</h2><br> <div class="select"> <select name="search" hx-get="{% url 'searched-subs' %}" hx-target="#searched-subs" hx-trigger="change" hx-swap="innerHTML" onchange="updateButtonDataAmount(event)" > <option value="select-a-plan">Select A Plan</option> <option value="7.99">Starter - Monthly ($7.99/Month)</option> <option value="79.00">Starter - Annually ($79.00/Year)</option> <option value="49.90">Business - Monthly ($49.90/Month)</option> <option value="499.00">Business - Annually ($499.00/Year)</option> </select> </form> </div><br><br> <div id="searched-subs"></div><br><br> <button class="intaSendPayButton button is-btn-mycolor is-fullwidth" data-amount="10" data-currency="KES" data-email="{{ user.email }}" data-first_name="{{ user.first_name }}" data-last_name="{{ user.last_name }}" data-country="KE"> Pay Now </button><br> </div> </div> <script> new window.IntaSend({ publicAPIKey: "publishing-key", live: false //set to true when going live }) .on("COMPLETE", (results) => console.log("Payment in COMPLETE status", results)) .on("FAILED", (results) => console.log("Payment in FAILED status", results)) .on("IN-PROGRESS", (results) => console.log("Payment in progress status", results)) </script> {% endblock %}
解决方案:前端传支付结果到后端的具体步骤
1. 改造Django视图,支持接收支付结果
更新subscription视图,新增POST请求处理逻辑,用来接收前端的支付数据并处理业务:
from django.http import JsonResponse import json import datetime @login_required(login_url='login') def subscription(request): user = request.user user_organization = OrganizationUser.objects.get(user=user) company = Company.objects.filter(name=user_organization.organization.name).first() today = datetime.date.today() subscription = Subscription.objects.all() if request.method == 'POST': # 解析前端发送的支付结果 payment_results = request.POST.get('payment_results') plan_type = request.POST.get('plan_type') if payment_results: data = json.loads(payment_results) # 根据支付状态处理业务逻辑 if data.get('status') == 'COMPLETE': # 根据套餐类型更新订阅到期时间 if plan_type == 'monthly': company.paid_till = today + datetime.timedelta(days=30) elif plan_type == 'annual': company.paid_till = today + datetime.timedelta(days=365) company.save() # 返回处理结果给前端 return JsonResponse({'status': 'success', 'message': 'Payment processed'}) # GET请求逻辑保持不变 form = CompanyForm() if user_organization.is_admin: context = { 'user_organization': user_organization, 'form': form, 'subscription': subscription, 'company': company, 'today': today } return render(request, 'registration/subscription.html', context) else: return HttpResponse('You are not authorised to view this page')
关键点:
- 移除
@csrf_exempt,改用Django默认CSRF验证(前端需传递CSRF Token) - 新增POST分支,解析前端传递的JSON格式支付结果
- 根据支付状态更新公司订阅到期时间,可根据实际业务调整逻辑
2. 更新前端JS,在支付回调中发送请求
修改模板中的JavaScript部分,在支付状态回调里通过fetch把结果发送给后端:
<script> // 获取Django生成的CSRF Token function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken'); // 记录用户选择的套餐类型(月度/年度) let selectedPlanType = ''; function updateButtonDataAmount(event) { const selectedValue = event.target.value; const button = document.querySelector('.intaSendPayButton'); button.dataset.amount = selectedValue; // 根据金额判断套餐类型 if (selectedValue === '7.99' || selectedValue === '49.90') { selectedPlanType = 'monthly'; } else if (selectedValue === '79.00' || selectedValue === '499.00') { selectedPlanType = 'annual'; } } new window.IntaSend({ publicAPIKey: "publishing-key", live: false //set to true when going live }) .on("COMPLETE", (results) => { console.log("Payment in COMPLETE status", results); // 发送支付结果到后端 fetch("{% url 'subscription' %}", { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRFToken': csrftoken }, body: new URLSearchParams({ 'payment_results': JSON.stringify(results), 'plan_type': selectedPlanType }) }) .then(response => response.json()) .then(data => { console.log('Backend response:', data); // 支付成功后刷新页面,展示更新后的订阅状态 window.location.reload(); }) .catch(error => console.error('Error sending data:', error)); }) .on("FAILED", (results) => { console.log("Payment in FAILED status", results); // 发送失败结果到后端记录 fetch("{% url 'subscription' %}", { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRFToken': csrftoken }, body: new URLSearchParams({ 'payment_results': JSON.stringify(results), 'plan_type': selectedPlanType }) }) .catch(error => console.error('Error sending failed payment data:', error)); }) .on("IN-PROGRESS", (results) => { console.log("Payment in progress status", results); // 可选:将进行中状态发送到后端记录 }) </script>
关键点:
- 新增
getCookie函数获取CSRF Token,确保POST请求通过Django验证 - 完善
updateButtonDataAmount函数,记录用户选择的套餐类型,方便后端计算到期时间 - 在每个支付状态回调中,用
fetch发送POST请求,传递支付结果和套餐类型 - 支付成功后刷新页面,让用户看到最新的订阅状态
内容的提问来源于stack exchange,提问作者Vince Matinde
相关产品推荐
相关产品推荐

