Django类视图集成Razorpay回调URL出现CSRF token缺失报错如何解决
问题1:为视图POST方法豁免CSRF token校验的实现
可以任选以下两种方案之一:
方案1:直接装饰类视图
在views.py中导入装饰器,给类视图的dispatch方法添加csrf_exempt装饰即可:
from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator # 新增装饰器 @method_decorator(csrf_exempt, name='dispatch') class BuyCoinPageView(LoginRequiredMixin, View): # 原有代码保持不变 def get(self, request, *args, **kwargs): client = razorpay.Client(auth=("scretKey", "secretKey")) data = { "amount": 10000, "currency": "INR", "receipt": "order_rcptid_11" } payment = client.order.create(data=data) print('Razor Pay - ', payment['id']) return render(request, "pricing-page.html", {'payment': payment}) def post(self, request, *args, **kwargs): data = request.POST print(data) # 注意:生产环境必须在此处添加Razorpay签名校验逻辑,防止伪造请求 return render(request, "pricing-page.html")
方案2:在路由中配置豁免
不需要修改视图代码,直接在urls.py中给对应路由的视图函数包裹csrf_exempt即可:
from django.views.decorators.csrf import csrf_exempt from .views import BuyCoinPageView urlpatterns = [ # 其他路由 path('buy-coin/', csrf_exempt(BuyCoinPageView.as_view()), name='buy_coin'), ]
问题2:Razorpay JS配置添加CSRF token到回调请求的实现
可以实现,更推荐使用自定义handler回调的方式,无需豁免CSRF校验,安全性更高:
删除原JS配置中的callback_url参数,新增handler回调手动发起携带CSRF token的POST请求,修改后的代码如下:
<a href="#" id="rzp-button1" class="btn-buy">Buy Now</a> <script src="https://checkout.razorpay.com/v1/checkout.js"></script> <script> var options = { "key": "rzp_test_hwAkAHZlKJdgee", "amount": "50000", "currency": "INR", "name": "Acme Corp", "description": "Test Transaction", "image": "https://example.com/your_logo", "order_id": "{{payment.id}}", // 删掉原来的callback_url配置 "prefill": { "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", "contact": "9999999999" }, "notes": { "address": "Razorpay Corporate Office" }, "theme": { "color": "#3399cc" }, // 新增自定义handler "handler": function (response) { // 构造表单提交 const form = document.createElement('form'); form.method = 'POST'; form.action = "{% url 'buy_coin' %}"; // 添加CSRF token参数 const csrfInput = document.createElement('input'); csrfInput.type = 'hidden'; csrfInput.name = 'csrfmiddlewaretoken'; csrfInput.value = '{{ csrf_token }}'; form.appendChild(csrfInput); // 添加Razorpay返回的支付结果参数 Object.keys(response).forEach(key => { const input = document.createElement('input'); input.type = 'hidden'; input.name = key; input.value = response[key]; form.appendChild(input); }); document.body.appendChild(form); form.submit(); } }; var rzp1 = new Razorpay(options); document.getElementById('rzp-button1').onclick = function(e){ rzp1.open(); e.preventDefault(); } </script>
如果要继续使用原生callback_url,也可以将CSRF token拼接到URL的查询参数中,如"callback_url": "{% url 'buy_coin' %}?csrfmiddlewaretoken={{ csrf_token }}",但Django默认不会从查询参数读取CSRF token,需要额外修改校验逻辑,不推荐使用。
内容的提问来源于stack exchange,提问作者Cipher
相关产品推荐
相关产品推荐

