from flask import request, jsonify, current_app from . import api_bp from .license import require_admin import os # 系统设置配置项映射 CONFIG_MAPPING = { # 基本设置 'site_name': 'SITE_NAME', 'admin_email': 'ADMIN_EMAIL', 'frontend_domain': 'FRONTEND_DOMAIN', 'max_failed_attempts': 'MAX_FAILED_ATTEMPTS', 'lockout_minutes': 'LOCKOUT_MINUTES', 'max_unbind_times': 'MAX_UNBIND_TIMES', 'auth_secret_key': 'AUTH_SECRET_KEY', # 安全设置 'secret_key': 'SECRET_KEY', 'session_cookie_secure': 'SESSION_COOKIE_SECURE', 'session_cookie_httponly': 'SESSION_COOKIE_HTTPONLY', 'session_cookie_samesite': 'SESSION_COOKIE_SAMESITE', # 卡密设置 'license_key_length': 'LICENSE_KEY_LENGTH', 'license_key_prefix': 'LICENSE_KEY_PREFIX', 'trial_prefix': 'TRIAL_PREFIX', 'offline_cache_days': 'OFFLINE_CACHE_DAYS', # API设置 'api_version': 'API_VERSION', 'items_per_page': 'ITEMS_PER_PAGE', # 文件上传设置 'max_content_length': 'MAX_CONTENT_LENGTH', 'upload_folder': 'UPLOAD_FOLDER', # 会话设置 'session_lifetime_hours': 'SESSION_LIFETIME_HOURS', # 记住我设置 'remember_cookie_duration': 'REMEMBER_COOKIE_DURATION_DAYS', # 特殊处理 'remember_cookie_secure': 'REMEMBER_COOKIE_SECURE', 'remember_cookie_httponly': 'REMEMBER_COOKIE_HTTPONLY', 'remember_cookie_samesite': 'REMEMBER_COOKIE_SAMESITE', # 日志设置 'log_level': 'LOG_LEVEL', # 支付设置 'alipay_app_id': 'ALIPAY_APP_ID', 'alipay_private_key': 'ALIPAY_PRIVATE_KEY', 'alipay_public_key': 'ALIPAY_PUBLIC_KEY', 'alipay_alipay_public_key': 'ALIPAY_ALIPAY_PUBLIC_KEY', 'alipay_gateway': 'ALIPAY_GATEWAY', 'alipay_sign_type': 'ALIPAY_SIGN_TYPE', 'alipay_charset': 'ALIPAY_CHARSET', 'alipay_version': 'ALIPAY_VERSION', 'alipay_notify_url': 'ALIPAY_NOTIFY_URL', 'alipay_return_url': 'ALIPAY_RETURN_URL', 'alipay_timeout_express': 'ALIPAY_TIMEOUT_EXPRESS', 'payment_enabled': 'PAYMENT_ENABLED' } @require_admin @api_bp.route('/settings/test-payment', methods=['POST']) def test_payment(): """测试支付功能""" try: # 获取当前配置 config = current_app.config # 检查支付功能是否启用 if not config.get('PAYMENT_ENABLED'): return jsonify({'success': False, 'message': '支付功能未启用'}), 400 # 检查支付宝配置 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: return jsonify({'success': False, 'message': f'缺少支付宝配置: {", ".join(missing_configs)}'}), 400 # 创建测试订单 try: from app.utils.alipay import AlipayHelper from app.models import Order import time import random # 初始化支付宝助手 alipay_helper = AlipayHelper(current_app) # 生成测试订单号 test_order_number = f"TEST{int(time.time())}{random.randint(100, 999)}" # 创建支付链接 notify_url = config.get('ALIPAY_NOTIFY_URL') or f"{request.url_root.strip('/')}/api/v1/pay/alipay/notify" return_url = config.get('ALIPAY_RETURN_URL') or f"{request.url_root.strip('/')}/payment/result" payment_url = alipay_helper.create_payment_url( order_number=test_order_number, amount=0.01, # 测试金额 subject='支付功能测试', notify_url=notify_url, return_url=return_url ) current_app.logger.info(f"支付功能测试成功,订单号: {test_order_number}") return jsonify({ 'success': True, 'message': '支付功能测试成功!', 'payment_url': payment_url, 'order_number': test_order_number }) except Exception as e: current_app.logger.error(f"创建支付链接失败: {str(e)}") return jsonify({'success': False, 'message': f'创建支付链接失败: {str(e)}'}), 400 except Exception as e: current_app.logger.error(f"测试支付功能失败: {str(e)}") return jsonify({'success': False, 'message': '服务器内部错误'}), 500 @require_admin @api_bp.route('/settings/test-alipay', methods=['POST']) def test_alipay_config(): """测试支付宝配置""" try: data = request.get_json() if not data: return jsonify({'success': False, 'message': '请求数据为空'}), 400 # 获取配置参数 alipay_app_id = data.get('alipay_app_id') alipay_private_key = data.get('alipay_private_key') alipay_public_key = data.get('alipay_public_key') alipay_alipay_public_key = data.get('alipay_alipay_public_key') alipay_gateway = data.get('alipay_gateway', 'https://openapi.alipay.com/gateway.do') # 验证必填项 if not all([alipay_app_id, alipay_private_key, alipay_public_key, alipay_alipay_public_key]): return jsonify({'success': False, 'message': '请填写完整的支付宝配置信息'}), 400 # 验证基本参数 if not alipay_app_id or len(alipay_app_id) < 10: return jsonify({'success': False, 'message': '无效的APP_ID'}), 400 # 验证密钥格式 if 'BEGIN' not in alipay_private_key or 'END' not in alipay_private_key: return jsonify({'success': False, 'message': '私钥格式不正确'}), 400 if 'BEGIN' not in alipay_public_key or 'END' not in alipay_public_key: return jsonify({'success': False, 'message': '公钥格式不正确'}), 400 if 'BEGIN' not in alipay_alipay_public_key or 'END' not in alipay_alipay_public_key: return jsonify({'success': False, 'message': '支付宝公钥格式不正确'}), 400 # 如果所有验证通过,返回成功 return jsonify({ 'success': True, 'message': '支付宝配置测试成功!', 'details': { 'app_id': alipay_app_id, 'gateway': alipay_gateway, 'sign_type': 'RSA2' } }) except Exception as e: current_app.logger.error(f"测试支付宝配置失败: {str(e)}") return jsonify({'success': False, 'message': '服务器内部错误'}), 500 @require_admin @api_bp.route('/settings', methods=['POST']) def save_settings(): """保存系统设置""" try: data = request.get_json() if not data: return jsonify({'success': False, 'message': '请求数据为空'}), 400 # 获取当前应用配置 app_config = current_app.config # 更新配置项 updated_configs = {} for key, value in data.items(): if key in CONFIG_MAPPING: config_key = CONFIG_MAPPING[key] # 类型转换 if key in ['max_failed_attempts', 'lockout_minutes', 'max_unbind_times', 'license_key_length', 'offline_cache_days', 'items_per_page', 'session_lifetime_hours', 'remember_cookie_duration']: value = int(value) elif key in ['session_cookie_secure', 'session_cookie_httponly', 'remember_cookie_secure', 'remember_cookie_httponly']: # 转换布尔值 value = value is True or value == 'True' or value == 'true' elif key == 'max_content_length': # 转换为字节 value = int(value) * 1024 * 1024 elif key == 'session_lifetime_hours': # 转换为秒 value = int(value) * 3600 elif key in ['alipay_timeout_express']: # 支付超时时间,转换为分钟 value = int(value) elif key in ['payment_enabled']: # 支付开关 value = value is True or value == 'True' or value == 'true' elif key in ['alipay_sign_type', 'alipay_charset', 'alipay_version']: # 支付相关字符串配置 pass # 保持原值 # 注意:密钥类配置(私钥、公钥等)不进行类型转换,直接保存 # 更新配置 app_config[config_key] = value updated_configs[config_key] = value # 特殊处理会话生命周期 if 'SESSION_LIFETIME_HOURS' in updated_configs: from datetime import timedelta app_config['PERMANENT_SESSION_LIFETIME'] = timedelta(seconds=updated_configs['SESSION_LIFETIME_HOURS']) # 特殊处理记住我持续时间 if 'REMEMBER_COOKIE_DURATION_DAYS' in updated_configs: from datetime import timedelta app_config['REMEMBER_COOKIE_DURATION'] = timedelta(days=updated_configs['REMEMBER_COOKIE_DURATION_DAYS']) # 特殊处理SECRET_KEY if 'SECRET_KEY' in updated_configs: # 更新应用的SECRET_KEY app_config['SECRET_KEY'] = updated_configs['SECRET_KEY'] return jsonify({ 'success': True, 'message': '设置保存成功', 'updated_configs': updated_configs }) except Exception as e: current_app.logger.error(f"保存设置失败: {str(e)}") return jsonify({'success': False, 'message': '服务器内部错误'}), 500