Python中Razorpay webhook支付回调签名验证失败如何解决
Razorpay webhook签名验证失败问题解决方案
核心问题原因
Razorpay的webhook签名是基于发送的原始未修改请求载荷生成,你之前的错误全部来自载荷处理环节:
- 使用
json.dumps处理request.json/request.data时,会重新排序JSON键、修改空格/分隔符格式,生成的内容和Razorpay发送的原始载荷不一致,直接导致签名校验失败 request.data本身是bytes类型,直接传入json.dumps会触发类型不兼容的序列化错误- 你最后用
request.data.decode('utf-8')传入验证得到None属于正常结果:Razorpay官方SDK的verify_webhook_signature方法验证通过时无返回值,只有验证失败才会抛出SignatureVerificationError异常,你误以为None是错误,实际此时已经校验通过。
正确实现代码
import razorpay # 以下以Flask框架为例,其他框架仅需调整原始请求体的获取方式即可 from flask import request # 需和Razorpay webhook配置页填写的密钥完全一致,注意无多余空格、大小写匹配 WEBHOOK_SECRET = "abc" # 你的Razorpay商户认证信息 RAZORPAY_KEY = "xyz" RAZORPAY_SECRET = "pqr" client = razorpay.Client(auth=(RAZORPAY_KEY, RAZORPAY_SECRET)) def handle_razorpay_webhook(): # 获取请求头中的签名 webhook_signature = request.headers.get('X-Razorpay-Signature') if not webhook_signature: return {"status": "error", "msg": "缺少签名头"}, 400 try: # 直接传入解码后的原始请求体,不要做任何JSON序列化/格式化操作 client.utility.verify_webhook_signature( request.data.decode('utf-8'), webhook_signature, WEBHOOK_SECRET ) # 校验通过,此处编写你的业务逻辑,例如修改订单状态、触发发货流程等 print("签名验证通过,支付状态有效") return {"status": "success"}, 200 except razorpay.errors.SignatureVerificationError: # 校验失败,直接拦截非法请求 print("签名验证失败,请求非法") return {"status": "error", "msg": "签名验证失败"}, 403
其他注意事项
- 若使用Django框架,原始请求体用
request.body.decode('utf-8')获取即可,逻辑完全一致 - 绝对不要对原始请求体做任何修改、格式化、重新序列化操作,必须直接使用Razorpay发送的原始字符串内容
- 若校验仍然失败,优先核对webhook密钥是否和后台配置完全一致,不要复制到多余的空格、换行符
内容的提问来源于stack exchange,提问作者Jasmine
相关产品推荐
相关产品推荐

