You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 08:30:47