ai_v/services/alipay_service.py
24024 acaa5d4fd8 fix(payment): 增加支付回调签名验证日志及异常处理
- 在支付宝同步回调(payment_return)中添加详细日志记录
- 添加同步回调缺少签名参数的错误处理
- 同步回调中移除sign和sign_type再进行签名验证
- 同步回调异常捕获,返回500错误并记录详细异常信息
- 在支付宝异步通知(payment_notify)中添加详细日志记录
- 异步通知缺少签名参数时返回fail并记录错误日志
- 异步通知验证签名失败或交易状态异常时返回fail并记录错误日志
- 异步通知中增加已处理订单状态跳过处理并返回success的逻辑
- 异步通知异常捕获时回滚数据库事务并返回fail
- 支付宝服务(AlipayService)的签名验证方法增加日志记录和异常捕获
- 签名验证时移除不参与验证的sign和sign_type字段,防止验证错误
2026-01-14 19:48:00 +08:00

82 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from alipay import AliPay
from flask import current_app
import os
import logging
logger = logging.getLogger(__name__)
class AlipayService:
def __init__(self):
self.app_id = current_app.config.get('ALIPAY_APP_ID')
self.private_key = current_app.config.get('ALIPAY_APP_PRIVATE_KEY')
self.public_key = current_app.config.get('ALIPAY_PUBLIC_KEY')
self.return_url = current_app.config.get('ALIPAY_RETURN_URL')
self.notify_url = current_app.config.get('ALIPAY_NOTIFY_URL')
self.debug = current_app.config.get('ALIPAY_DEBUG', True)
def get_alipay_client(self):
"""获取支付宝客户端实例"""
return AliPay(
appid=self.app_id,
app_notify_url=self.notify_url,
app_private_key_string=self.private_key,
alipay_public_key_string=self.public_key,
sign_type="RSA2",
debug=self.debug
)
def create_order_url(self, out_trade_no, total_amount, subject):
"""生成支付链接 (电脑网站支付)"""
alipay = self.get_alipay_client()
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=out_trade_no,
total_amount=str(total_amount),
subject=subject,
return_url=self.return_url,
notify_url=self.notify_url
)
# 拼接支付网关 (使用最新的支付宝沙箱域名)
gateway = "https://openapi-sandbox.dl.alipaydev.com/gateway.do" if self.debug else "https://openapi.alipay.com/gateway.do"
return f"{gateway}?{order_string}"
def verify_notify(self, data, signature):
"""验证通知签名"""
try:
logger.info(f"开始验证支付宝签名,数据: {data}")
logger.info(f"签名值: {signature}")
# 验证必要参数
if not signature:
logger.error("签名为空")
return False
if not data:
logger.error("数据为空")
return False
# 创建数据副本,避免修改原数据
verify_data = data.copy()
# 移除sign和sign_type这两个字段不参与验证
verify_data.pop('sign', None)
verify_data.pop('sign_type', None)
alipay = self.get_alipay_client()
result = alipay.verify(verify_data, signature)
if result:
logger.info("签名验证成功")
else:
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}")
return result
except Exception as e:
logger.error(f"验证签名时发生异常: {str(e)}", exc_info=True)
return False