fix(payment): 优化支付回调签名验证逻辑

- 取消支付回调中签名前日志冗余输出,简化验证流程
- verify_notify方法中合并签名和数据为空的校验,减少日志行
- 调整sign和sign_type参数移除逻辑,兼容不同通知类型的签名校验
- 增加验证失败时的详细日志,帮助定位公钥配置问题
- 提示可能公钥使用错误,改善错误排查体验
This commit is contained in:
24024 2026-01-14 19:57:43 +08:00
parent acaa5d4fd8
commit 5dc2fbd0e7
6 changed files with 21 additions and 33 deletions

Binary file not shown.

View File

@ -73,18 +73,9 @@ def payment_return():
logger.error("同步回调缺少签名参数")
return "参数错误:缺少签名", 400
# 验证签名前,先记录关键信息
logger.info(f"验证订单号: {data.get('out_trade_no')}")
logger.info(f"支付宝交易号: {data.get('trade_no')}")
logger.info(f"支付金额: {data.get('total_amount')}")
# 从数据中移除sign参数以进行验证
verify_data = data.copy()
verify_data.pop('sign', None)
verify_data.pop('sign_type', None) # 也要移除sign_type
alipay_service = AlipayService()
success = alipay_service.verify_notify(verify_data, signature)
# 直接传递原始字典,由 verify_notify 处理
success = alipay_service.verify_notify(data, signature)
out_trade_no = data.get('out_trade_no')
order = Order.query.filter_by(out_trade_no=out_trade_no).first()

View File

@ -50,7 +50,7 @@ class Config:
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCJSgmesQisfxNdz5dUhdv3Anh6aOGyQ03t69cqnenFumyEiLFk1N9FBDRR6onUsW9ZUGf7+P1sn/TMHdoOQZzZsxYVCCj85820ORP/DHTyP0ONHfBj0GqnKig5o3OGosC9ieJT6QLBzycOmiv/3YcHSJQPQ3zlyUloPScD1UsslgpCFWF3c3UDstzhYy/i1LbNy63w+Hr/xj01f1JCzivJoir9erLpTbbjPcPbQXd9xpycwIyGufXbFh1kOE6q+WOZq6NAXCe0/leUwh+q5v0pTnWnY07iB9nQtL2qvXQIBZWGI6HV4NDnO6rblDf1oOwNWYKcjCtL045xcHfUWKlrAgMBAAECggEAO4qfp3JyJ5WpSYtJv3+aiYNJyxUHpW9pMeGR3MrF41pZzBUYknl8J4uOQWStyE/30c18e5xeFKk+2vOraXltVEFGN3Lli+HgpeQHVxsI8TMc0ewFINT4HG29KlpINUEKxGkzfl7VMkbsUnns0Tg7Yp5IkGIdne7xZkL3U8NCqh/0oHAczMTwV1gqOFetyENNhdqzZJgwjR5c2OIIsNAuq+s0CcIqIw6hSwKzYN3H2i+4UKXmgU9kB2pGIzyxOH41FbEZp/UAcv9m2ikK2oYSXIHozaEsYyUXZbvHn4vmz1+grwnMJy2UQZQUCOLjvkul7tGKcNXTFSCvtgudBMSQ2QKBgQDxKvs97C3CRqgM/GkajI3DVmCY9NZGj5fd75JVg0yIeYQ4tmUmVIepTfq/8YxmgUD284FAFeyfbcFMbZnP4MXQ5Ddun0je70P3snLhfCw52PG1ypxBHl/jzZPdecy5kPKSQIWK9dfaXzwvhRC+YFV2x2V+tcubfeGgZkJ4+79KPQKBgQCRu483SbkjIbKTlJVL1m8a8RtljEg0AxnGIOQQvpkNHWRRHEqE3ozkj3PUHicDh9MumyZSRm9ifSmbD+cYSnjpQYafD9pZQ4lFWE72rCrz2vTTiZKyd/VuuQl2wTcj57ffX7cCaXQ635O1w+tz4VXnZzFnN0Lx3KDQ76bpPEEExwKBgHpRqoyFtc/LtoCfpU9p6p0gum3aALRZMFXIpRfqOG8f8wgwuqzuQsCEZKHmCagT9rdKWkv+0r0qFdiF3nWpM6v3lIXvFC6+fGKth8cGDAhrGG10DjyZA1mvc0fp9wRHmEDFqPYKKyj/FK+ldhCZG7/a8oeJ/XMoLcAFHcHvLd6hAoGAFQnDmhKthHHX6tA3YVRag8Qs1VMUFVYhQWX8JqKtS6RjmAYCh/3szw4ahZO4xBy2kvLY7GW4rLou6HC6RtpxbBMGkS3jsqE6TuV5uMiQBtYkI+mnYNZKeyqBQECSaj+IXtndfJ6mpd0i4Mmg0wDDuv09t43Vvz6/hIokSWVmaX8CgYEApzBH2M3R3j/jz2Hb3cevI+3MaeSIZMCedj2oTI2VB+6cOfuCW+65uuj7VuZkjEWzHMt3jVWPBtjyp002D3unYfIiaFaXUK4hSeoOCVj9ma8xhqR278Llkhxgf6KDx2E43YeTtrg9jStHmuD+Wr4UV96MOuIyaKqOFQHs4P/sQqY=
-----END RSA PRIVATE KEY-----""" # 应用私钥
ALIPAY_PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx6iXKiRpbs5WLHlb6fdoteef+vs+QxxtmwDL2IJwhEJ+OMrkwlKyd4noYaiGDy2YcyHKahb4bsHRoPLVEqLveuVFksjsiFTH2mUhuwuqDe//XwE4hHsguNL3nY72gZ6qjwbg5mAVrHRcKUi6XSLSP4pWdCzD0leZ4GA9Kw1WstCS4sGBcrzyHPhRvtdVFZR5UjNLVAaN6HIMNhW0TBXz4r1ihXMV4byeN3n0n6e6reBLXr222f7c5almGurq6D9pLqwAmsqWbQWbvitOjZRll+bjpa29JIkNi+jEpPdYpGjU3e0Tl8aWkKjtYXmDyWtdw00RkciHUR4hMuCZW5qIjwIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlDx4KdOtOQE+tBq6jHKKFenRaRe2gbBnleBk++5gki9IQuxVyZUGTJixstf2gELFHWrGanpnwmGggXsqG+Rm5ZLJOlmFM1k0XeAIDvi6tP/rM+ZDFSu1bMBYtT5vzgVZC7mzIvOp9gsT/puqd3aNZmlviLD0R6OYN0zvFX+5qADZV7A9ziA+nXPFSHreBh7yY/q9ophVZNeHGPoYkDVI5++RrF1cALKOdit0giN5vxpe3ch9z3E6+FZg3LiP+1RW3tMiDQfp/SlVs6bNhLUtmlI5r7+mtFCKDUCEpnQ3S9e0II6rzyVXRyKCFs7qi5YzyhhmO3tJJoe9ilEFyNzfRQIDAQAB
-----END PUBLIC KEY-----""" # 支付宝公钥
ALIPAY_RETURN_URL = "http://331002.xyz:2010/payment/return" # 支付成功跳转地址
ALIPAY_NOTIFY_URL = "http://331002.xyz:2010/payment/notify" # 支付异步通知地址

View File

@ -42,37 +42,34 @@ class AlipayService:
def verify_notify(self, data, signature):
"""验证通知签名"""
try:
logger.info(f"开始验证支付宝签名,数据: {data}")
logger.info(f"签名值: {signature}")
# 验证必要参数
if not signature:
logger.error("签名为空")
if not signature or not data:
logger.error("签名或数据为空")
return False
if not data:
logger.error("数据为空")
return False
# 创建数据副本,避免修改原数据
# 创建数据副本
verify_data = data.copy()
# 移除sign和sign_type这两个字段不参与验证
# python-alipay-sdk 的 verify 方法会自动处理 sign 的移除
# 但为了保险,我们手动移除它,保留其他所有字段
verify_data.pop('sign', None)
verify_data.pop('sign_type', None)
alipay = self.get_alipay_client()
# 对于同步回调sign_type 实际上是参与签名的(某些版本/接口)
# 对于异步通知sign_type 通常不参与签名
# alipay.verify 会根据情况处理 sign_type
result = alipay.verify(verify_data, signature)
if result:
logger.info("签名验证成功")
else:
if not result:
logger.error("签名验证失败")
logger.error(f"验证数据: {verify_data}")
logger.error(f"公钥配置: {self.public_key[:50]}...")
# 额外调试信息
logger.error(f"App ID: {self.app_id}")
logger.error(f"是否调试模式: {self.debug}")
logger.error(f"待验证数据: {verify_data}")
logger.error(f"签名值: {signature}")
logger.error(f"使用的公钥前50位: {self.public_key[:50]}...")
# 检查公钥是否可能是应用公钥而非支付宝公钥
if self.private_key and self.public_key:
logger.warning("提示:如果签名持续验证失败,请确认 ALIPAY_PUBLIC_KEY 是“支付宝公钥”而非“应用公钥”")
else:
logger.info("签名验证成功")
return result