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

Razor Pay支付成功但未调用callback_url问题求助

排查Razorpay callback_url未触发及redirect:true导致支付失败的问题

核心问题1:callback_url未触发的原因

你配置了前端handler函数,Razorpay的默认逻辑是优先执行前端handler,而非触发callback_url的跳转/回调。只要存在handler,Razorpay就会跳过callback_url的自动调用。

核心问题2:添加redirect:true后支付失败的常见原因

1. callback_url不是绝对URL

Razorpay要求callback_url必须是完整的http/https开头的绝对地址,你用{% url 'PaymentSuccess' %}生成的是相对路径(比如/payment-success/),Razorpay服务器无法解析这个相对路径,导致回调失败,进而触发支付失败。

2. 后端视图未配置正确的请求方法或CSRF豁免

Razorpay的callback是POST请求,且不会携带Django的CSRF Token。如果你的PaymentSuccess视图没有开启POST支持,或者没有添加@csrf_exempt装饰器,Django会直接拦截请求,返回403 Forbidden,导致Razorpay判定支付失败。

3. 签名验证缺失(隐性问题)

即使callback_url触发,若未验证Razorpay的签名,业务逻辑会存在安全风险,同时部分场景下Razorpay会因为回调处理异常判定失败。


具体修复步骤

步骤1:修正callback_url为绝对URL

在Django模板中,使用request.build_absolute_uri生成完整URL:

var options = {
    "key": data.razorpay_key,
    "amount": data.amount,
    "currency": data.currency,
    "name": "BusinessCard4U",
    "image": "{{websitelogo.image.url}}",
    "description": "Payment for digital card subscription",
    "order_id": data.razorpay_order_id,
    // 替换为绝对URL
    "callback_url": "{{ request.build_absolute_uri|add:payment_success_path }}",
    // 若依赖callback_url自动跳转,移除handler函数
    // "handler": function (response){...},
    "theme": {
        "color": "#5EB9F0"
    },
};

注:如果保留handler,需要在handler中手动跳转,但必须先完成签名验证

步骤2:修复后端视图配置

给PaymentSuccess视图添加POST支持和CSRF豁免,并实现签名验证:

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, HttpResponseMethodNotAllowed
import hmac
import hashlib

@csrf_exempt
def PaymentSuccess(request):
    if request.method != 'POST':
        return HttpResponseMethodNotAllowed(['POST'])
    
    # 从请求中获取Razorpay返回的参数
    razorpay_order_id = request.POST.get('razorpay_order_id')
    razorpay_payment_id = request.POST.get('razorpay_payment_id')
    razorpay_signature = request.POST.get('razorpay_signature')
    
    # 验证签名(必须步骤,防止伪造请求)
    secret_key = b'YOUR_RAZORPAY_SECRET_KEY'  # 替换为你的密钥
    message = f"{razorpay_order_id}|{razorpay_payment_id}".encode()
    generated_signature = hmac.new(secret_key, message, hashlib.sha256).hexdigest()
    
    if generated_signature == razorpay_signature:
        # 签名验证通过,处理你的业务逻辑(比如更新订单状态)
        return HttpResponse("Payment Verified Successfully")
    else:
        # 签名验证失败,拒绝处理
        return HttpResponse("Invalid Payment Signature", status=400)

步骤3:调整handler与callback_url的逻辑

  • 如果依赖自动跳转:移除handler函数,添加redirect: true参数,此时Razorpay会在支付成功后自动跳转到callback_url。
  • 如果需要保留前端handler:在handler中完成签名验证后,手动跳转到后端接口:
"handler": function (response){
    // 先验证签名(前端验证仅作辅助,必须后端再次验证)
    var orderId = response.razorpay_order_id;
    var paymentId = response.razorpay_payment_id;
    var signature = response.razorpay_signature;
    
    // 调用后端接口验证签名,验证通过后跳转
    fetch('/verify-signature/', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({
            order_id: orderId,
            payment_id: paymentId,
            signature: signature
        })
    }).then(res => res.json())
      .then(data => {
          if(data.success){
              window.location.href = "{{ request.build_absolute_uri|add:payment_success_path }}";
          }
      });
},

步骤4:查看Razorpay后台日志定位问题

如果仍然失败,登录Razorpay后台,找到对应订单的失败详情,里面会明确标注回调失败的原因(比如403、404、500等),根据错误码进一步排查。


内容的提问来源于stack exchange,提问作者Proud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:29:56