# -*- coding: utf-8 -*- """ 支付宝支付工具类 """ from alipay import AliPay from flask import current_app from datetime import datetime class AlipayHelper: """支付宝支付助手类""" def __init__(self, app=None): """ 初始化支付宝客户端 :param app: Flask应用实例 """ self.alipay = None if app: self.init_app(app) def init_app(self, app): """ 初始化支付宝配置 :param app: Flask应用实例 """ config = app.config # 检查必要的配置 required_configs = [ 'ALIPAY_APP_ID', 'ALIPAY_PRIVATE_KEY', 'ALIPAY_PUBLIC_KEY', 'ALIPAY_ALIPAY_PUBLIC_KEY' ] missing_configs = [cfg for cfg in required_configs if not config.get(cfg)] if missing_configs: raise ValueError(f"缺少必要的支付宝配置: {', '.join(missing_configs)}") # 初始化支付宝客户端 self.alipay = AliPay( appid=config['ALIPAY_APP_ID'], app_private_key=config['ALIPAY_PRIVATE_KEY'], alipay_public_key=config['ALIPAY_ALIPAY_PUBLIC_KEY'], sign_type=config.get('ALIPAY_SIGN_TYPE', 'RSA2'), charset=config.get('ALIPAY_CHARSET', 'utf-8'), gateway=config.get('ALIPAY_GATEWAY', 'https://openapi.alipay.com/gateway.do') ) def create_payment_url(self, order_number, amount, subject, notify_url, return_url): """ 创建支付宝支付链接 :param order_number: 订单号 :param amount: 支付金额 :param subject: 支付主题 :param notify_url: 异步通知URL :param return_url: 同步返回URL :return: 支付链接 """ if not self.alipay: raise ValueError("支付宝客户端未初始化") # 构建订单参数 order_params = { 'out_trade_no': order_number, # 商户订单号 'total_amount': str(amount), # 订单总金额 'subject': subject, # 订单标题 'body': f'订单{order_number}的支付', # 订单描述 'product_code': 'FAST_INSTANT_TRADE_PAY', # 产品代码 } # 生成支付链接 payment_url = self.alipay.trade_page_pay( total_amount=str(amount), subject=subject, out_trade_no=order_number, return_url=return_url, notify_url=notify_url ) # 构建完整的支付URL gateway = self.alipay.gateway full_payment_url = f"{gateway}?{payment_url}" return full_payment_url def create_wap_payment_url(self, order_number, amount, subject, notify_url, return_url): """ 创建手机网站支付链接 :param order_number: 订单号 :param amount: 支付金额 :param subject: 支付主题 :param notify_url: 异步通知URL :param return_url: 同步返回URL :return: 支付链接 """ if not self.alipay: raise ValueError("支付宝客户端未初始化") # 生成支付链接 payment_url = self.alipay.trade_wap_pay( total_amount=str(amount), subject=subject, out_trade_no=order_number, return_url=return_url, notify_url=notify_url ) # 构建完整的支付URL gateway = self.alipay.gateway full_payment_url = f"{gateway}?{payment_url}" return full_payment_url def query_order_status(self, order_number): """ 查询订单支付状态 :param order_number: 订单号 :return: 订单状态信息 """ if not self.alipay: raise ValueError("支付宝客户端未初始化") try: result = self.alipay.alipay_trade_query( out_trade_no=order_number ) return result except Exception as e: current_app.logger.error(f"查询支付宝订单状态失败: {str(e)}") return None def verify_notification(self, data, signature): """ 验证支付宝异步通知签名 :param data: 通知数据 :param signature: 签名 :return: 验证结果 """ if not self.alipay: raise ValueError("支付宝客户端未初始化") try: # 验证签名 return self.alipay.verify(data, signature) except Exception as e: current_app.logger.error(f"验证支付宝通知签名失败: {str(e)}") return False def verify_trade_status(self, notify_data): """ 验证交易状态 :param notify_data: 通知数据 :return: 验证结果和交易状态 """ if not self.alipay: raise ValueError("支付宝客户端未初始化") try: # 验证签名 if not self.alipay.verify(notify_data, notify_data.get('sign')): return False, None # 检查交易状态 trade_status = notify_data.get('trade_status') if trade_status in ['TRADE_SUCCESS', 'TRADE_FINISHED']: return True, trade_status else: return False, trade_status except Exception as e: current_app.logger.error(f"验证支付宝交易状态失败: {str(e)}") return False, None def get_trade_state(self, order_number): """ 获取交易状态 :param order_number: 订单号 :return: 交易状态 """ result = self.query_order_status(order_number) if not result: return None # 根据支付宝返回的状态码判断 code = result.get('code') if code == '10000': # 接口调用成功 trade_status = result.get('trade_status') if trade_status == 'TRADE_SUCCESS': return 'SUCCESS' elif trade_status == 'TRADE_FINISHED': return 'FINISHED' elif trade_status == 'TRADE_CLOSED': return 'CLOSED' elif trade_status == 'WAIT_BUYER_PAY': return 'WAIT_PAY' elif code == '40004': # 业务处理失败 return 'NOT_EXIST' return None