- 在支付宝同步回调(payment_return)中添加详细日志记录 - 添加同步回调缺少签名参数的错误处理 - 同步回调中移除sign和sign_type再进行签名验证 - 同步回调异常捕获,返回500错误并记录详细异常信息 - 在支付宝异步通知(payment_notify)中添加详细日志记录 - 异步通知缺少签名参数时返回fail并记录错误日志 - 异步通知验证签名失败或交易状态异常时返回fail并记录错误日志 - 异步通知中增加已处理订单状态跳过处理并返回success的逻辑 - 异步通知异常捕获时回滚数据库事务并返回fail - 支付宝服务(AlipayService)的签名验证方法增加日志记录和异常捕获 - 签名验证时移除不参与验证的sign和sign_type字段,防止验证错误
82 lines
3.0 KiB
Python
82 lines
3.0 KiB
Python
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
|