# Transfer模块手续费功能使用指南 > 更新时间: 2025-06-19 03:43 > 模块: Transfer > 功能: 手续费系统 > 维护状态: 🔄 持续维护中 FeeService 增加 ,‘转移’方法用于将手续费转移到指定用户, 参数 :appid(出钱的), 目标用户ID(收钱的),金额(钱数), 订单ID(划转依据) ## 概述 Transfer模块现已支持转入/转出手续费功能,可以为每个划转应用配置不同的手续费率、最低手续费和最高手续费。手续费系统支持灵活的配置选项,包括费率设置、限额控制、账户指定等功能,满足不同业务场景的需求。 ### 主要特性 - ✅ **灵活费率配置** - 支持转入/转出分别设置手续费率 - ✅ **限额控制** - 支持最低/最高手续费限制 - ✅ **账户指定** - 可指定手续费收取账户 - ✅ **自动计算** - 订单创建时自动计算和扣除手续费 - ✅ **统计分析** - 提供完整的手续费统计功能 - ✅ **向后兼容** - 兼容现有订单,默认手续费为0 ## 数据库字段说明 ### 应用配置表 (kku_transfer_apps) | 字段名 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | fee_in_rate | DECIMAL(5,4) | 0.0000 | 转入手续费率(0.0000-1.0000) | | fee_out_rate | DECIMAL(5,4) | 0.0000 | 转出手续费率(0.0000-1.0000) | | fee_in_min | DECIMAL(15,4) | 0.0000 | 转入最低手续费 | | fee_in_max | DECIMAL(15,4) | 0.0000 | 转入最高手续费(0为不限制) | | fee_out_min | DECIMAL(15,4) | 0.0000 | 转出最低手续费 | | fee_out_max | DECIMAL(15,4) | 0.0000 | 转出最高手续费(0为不限制) | | fee_account_uid | INT | 1 | 手续费收取账户UID(默认为1) | ### 订单表 (kku_transfer_orders) | 字段名 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | fee_rate | DECIMAL(5,4) | 0.0000 | 使用的手续费率 | | fee_amount | DECIMAL(15,4) | 0.0000 | 手续费金额 | | actual_amount | DECIMAL(15,4) | 0.0000 | 实际到账金额(扣除手续费后) | ### 字段详细说明 #### 应用配置字段 - **fee_in_rate / fee_out_rate**: 手续费率,范围0.0000-1.0000,对应0%-100% - **fee_in_min / fee_out_min**: 最低手续费,确保即使按比例计算很低也有最低收费 - **fee_in_max / fee_out_max**: 最高手续费,0表示不限制,大于0时生效 - **fee_account_uid**: 手续费收取账户,必须是有效的Fund账户UID #### 订单记录字段 - **fee_rate**: 创建订单时使用的实际手续费率 - **fee_amount**: 计算得出的手续费金额 - **actual_amount**: 扣除手续费后的实际到账金额 ## 手续费计算规则 ### 计算公式 手续费计算遵循以下步骤: 1. **按比例计算**: `手续费 = 金额 × 手续费率` 2. **最低限制**: `if (手续费 < 最低手续费) 手续费 = 最低手续费` 3. **最高限制**: `if (最高手续费 > 0 && 手续费 > 最高手续费) 手续费 = 最高手续费` 4. **实际到账**: `实际到账金额 = 原金额 - 手续费` ### 计算逻辑说明 - **费率优先**: 首先按照配置的费率计算基础手续费 - **最低保障**: 确保手续费不低于设定的最低值 - **最高限制**: 防止手续费过高,保护用户利益 - **精度处理**: 使用bcmath函数确保计算精度 - **零费率处理**: 当费率为0时,手续费为0,实际到账等于原金额 ### 计算示例 假设应用配置: - 转出手续费率: 1% (0.0100) - 最低手续费: 0.50 - 最高手续费: 10.00 不同金额的手续费计算: | 转出金额 | 按比例计算 | 应用限制后 | 实际到账 | 说明 | |----------|------------|------------|----------|------| | 10.00 | 0.10 | 0.50 (最低) | 9.50 | 触发最低限制 | | 100.00 | 1.00 | 1.00 | 99.00 | 正常计算 | | 1500.00 | 15.00 | 10.00 (最高) | 1490.00 | 触发最高限制 | | 0.00 | 0.00 | 0.50 (最低) | -0.50 | 零金额也收最低费 | ### 特殊情况处理 1. **零金额订单**: 即使金额为0,也会收取最低手续费 2. **费率为0**: 当费率设置为0时,不收取任何手续费 3. **最高费率**: 费率可以设置为100%(1.0000),但受最高限额约束 4. **负数处理**: 系统会验证金额为正数,负数订单会被拒绝 ## API使用示例 ### 1. 计算手续费 ```php use App\Module\Transfer\Services\TransferService; // 计算转出手续费 $feeInfo = TransferService::calculateOutFee( transferAppId: 1, amount: '100.00' ); // 返回结果 [ 'fee_rate' => 0.0100, // 手续费率 'fee_amount' => '1.0000', // 手续费金额 'actual_amount' => '99.0000' // 实际到账金额 ] // 计算转入手续费 $feeInfo = TransferService::calculateInFee( transferAppId: 1, amount: '100.00' ); ``` ### 2. 创建订单(自动计算手续费) ```php // 转出订单 - 手续费会自动计算并从用户账户扣除 $result = TransferService::createTransferOut( transferAppId: 1, userId: 12345, amount: '100.00', password: 'user_password' ); // 转入订单 - 手续费会自动计算,用户收到扣除手续费后的金额 $result = TransferService::createTransferIn( transferAppId: 1, userId: 12345, businessId: 'BIZ_001', amount: '100.00' ); ``` ### 3. 获取手续费配置 ```php $config = TransferService::getFeeConfig(transferAppId: 1); // 返回结果 [ 'in' => [ 'rate' => 0.0050, // 转入费率 0.5% 'min' => 0.1000, // 最低 0.1 'max' => 5.0000, // 最高 5.0 'enabled' => true // 是否启用 ], 'out' => [ 'rate' => 0.0100, // 转出费率 1.0% 'min' => 0.2000, // 最低 0.2 'max' => 10.0000, // 最高 10.0 'enabled' => true // 是否启用 ], 'account_uid' => 999 // 手续费收取账户 ] ``` ### 4. 获取手续费统计 ```php // 获取所有应用的手续费统计 $stats = TransferService::getFeeStatistics(); // 获取指定应用和时间范围的统计 $stats = TransferService::getFeeStatistics( appId: 1, startDate: '2025-06-01', endDate: '2025-06-30' ); // 返回结果 [ 'total_orders' => 150, // 总订单数 'total_fee' => 125.50, // 总手续费 'avg_fee_rate' => 0.0075, // 平均费率 'in_orders' => 80, // 转入订单数 'in_fee' => 60.25, // 转入手续费 'out_orders' => 70, // 转出订单数 'out_fee' => 65.25, // 转出手续费 ] // 获取应用的手续费收入统计 $income = TransferService::getAppFeeIncome( appId: 1, days: 30 ); ``` ### 5. 批量手续费计算 ```php // 批量计算多个金额的手续费 $amounts = ['100.00', '200.00', '500.00']; $feeResults = []; foreach ($amounts as $amount) { $feeResults[] = TransferService::calculateOutFee( transferAppId: 1, amount: $amount ); } // 预估手续费总额 $totalFee = array_sum(array_column($feeResults, 'fee_amount')); ``` ### 6. 手续费配置验证 ```php // 验证手续费配置是否合理 $validation = TransferService::validateFeeConfig([ 'fee_rate' => 0.0150, // 1.5% 'fee_min' => 0.10, // 最低0.1 'fee_max' => 50.00, // 最高50 ]); if ($validation['valid']) { echo "配置有效"; } else { echo "配置错误: " . $validation['message']; } ``` ## 资金流向说明 ### 转出订单资金流向 1. **用户账户** → **目标账户** (实际到账金额,扣除手续费后) 2. **用户账户** → **手续费账户** (手续费金额) ``` 用户余额: 1000.00 转出金额: 100.00 手续费: 1.00 实际转出: 99.00 执行后: - 用户余额: 899.00 (扣除 100.00) - 目标账户: +99.00 (实际到账) - 手续费账户: +1.00 ``` ### 转入订单资金流向 1. **来源账户** → **用户账户** (实际到账金额,扣除手续费后) 2. **来源账户** → **手续费账户** (手续费金额) ``` 来源账户余额: 1000.00 转入金额: 100.00 手续费: 1.00 实际到账: 99.00 执行后: - 来源账户余额: 900.00 (扣除 100.00) - 用户账户: +99.00 (实际到账) - 手续费账户: +1.00 ``` ### 默认手续费账户 - **默认账户UID**: 1 - **使用规则**: 如果应用未配置 `fee_account_uid` 或配置为0,系统自动使用账户UID 1收取手续费 - **配置优先级**: 应用配置的手续费账户 > 默认账户UID 1 ## 配置示例 ### 1. 数据库配置 ```sql -- 配置应用手续费 UPDATE kku_transfer_apps SET fee_in_rate = 0.0050, -- 转入手续费 0.5% fee_out_rate = 0.0100, -- 转出手续费 1.0% fee_in_min = 0.1000, -- 转入最低手续费 0.1 fee_in_max = 10.0000, -- 转入最高手续费 10 fee_out_min = 0.2000, -- 转出最低手续费 0.2 fee_out_max = 20.0000, -- 转出最高手续费 20 fee_account_uid = 1 -- 手续费收取账户 WHERE keyname = 'game_app'; ``` ### 2. 模型使用 ```php use App\Module\Transfer\Models\TransferApp; $app = TransferApp::find(1); // 检查是否启用手续费 if ($app->isFeeEnabled('out')) { echo "转出手续费已启用"; } // 计算手续费 $feeInfo = $app->calculateOutFee('100.00'); echo "手续费: {$feeInfo['fee_amount']}"; echo "实际到账: {$feeInfo['actual_amount']}"; ``` ### 3. 订单信息 ```php use App\Module\Transfer\Models\TransferOrder; $order = TransferOrder::find(1); // 检查是否有手续费 if ($order->hasFee()) { echo "手续费率: {$order->getFeeRatePercentAttribute()}"; echo "手续费金额: {$order->getFeeAmountTextAttribute()}"; echo "实际到账: {$order->getActualAmountTextAttribute()}"; } ``` ## 注意事项 ### 配置限制 1. **手续费率范围**: 0.0000 - 1.0000 (0% - 100%) 2. **最低手续费**: 不能为负数,建议设置合理的最低值 3. **最高手续费**: 0表示不限制,大于0时生效 4. **手续费账户**: 必须是有效的Fund账户UID,默认为1 5. **精度处理**: 所有金额计算使用4位小数精度 6. **向后兼容**: 现有订单的手续费字段默认为0 ### 业务规则 7. **费率生效**: 手续费配置修改后立即生效,不影响已创建订单 8. **账户余额**: 确保手续费收取账户有足够权限接收资金 9. **用户提示**: 建议在用户界面明确显示手续费信息 10. **异常处理**: 手续费计算失败时应有明确的错误提示 ### 安全考虑 11. **权限控制**: 手续费配置修改需要管理员权限 12. **审计日志**: 所有手续费配置变更应记录日志 13. **监控报警**: 设置手续费异常监控和报警机制 14. **数据校验**: 严格验证手续费配置参数的合法性 ## 监控和报警 ### 1. 手续费异常监控 ```sql -- 查找手续费异常高的订单 SELECT id, transfer_app_id, amount, fee_rate, fee_amount, created_at FROM kku_transfer_orders WHERE fee_rate > 0.1000 -- 手续费率超过10% OR fee_amount > amount * 0.1 -- 手续费超过金额的10% ORDER BY created_at DESC; ``` ### 2. 手续费收入统计 ```sql -- 手续费收入日报 SELECT DATE(created_at) as date, COUNT(*) as orders, SUM(fee_amount) as total_fee, AVG(fee_rate) as avg_rate FROM kku_transfer_orders WHERE status = 100 AND fee_amount > 0 AND created_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) GROUP BY DATE(created_at) ORDER BY date DESC; ``` ## 最佳实践 ### 配置策略 1. **合理设置费率**: 根据业务需求和市场情况设置合理的手续费率 2. **设置限制**: 使用最低和最高手续费限制保护用户利益 3. **分级配置**: 可考虑根据用户等级或交易量设置不同费率 4. **定期调整**: 根据业务发展和成本变化定期调整费率 ### 运营管理 5. **监控收入**: 定期监控手续费收入和异常情况 6. **账户管理**: 确保手续费收取账户有足够的权限和安全性 7. **用户提示**: 在用户界面明确显示手续费信息和计算方式 8. **透明度**: 提供手续费计算器供用户预估费用 ### 技术实施 9. **性能优化**: 手续费计算应高效,避免影响订单创建性能 10. **缓存策略**: 对手续费配置进行适当缓存,减少数据库查询 11. **异步处理**: 手续费统计可采用异步处理,避免阻塞主流程 12. **数据备份**: 定期备份手续费相关数据,确保数据安全 ### 合规要求 13. **法规遵循**: 确保手续费设置符合相关法律法规 14. **用户协议**: 在用户协议中明确说明手续费政策 15. **变更通知**: 手续费政策变更应提前通知用户 16. **争议处理**: 建立手续费争议处理机制 ## 故障排除 ### 常见问题 1. **手续费计算错误**: 检查应用配置和计算逻辑 2. **手续费未收取**: 检查fee_account_uid配置 3. **余额不足**: 确保来源账户有足够余额 4. **精度问题**: 使用bcmath函数进行精确计算 ### 调试方法 ```php // 调试手续费计算 $app = TransferApp::find(1); $feeInfo = $app->calculateOutFee('100.00'); var_dump($feeInfo); // 检查订单手续费信息 $order = TransferOrder::find(1); echo "原金额: {$order->amount}"; echo "手续费: {$order->fee_amount}"; echo "实际金额: {$order->actual_amount}"; // 验证手续费配置 $app = TransferApp::find(1); echo "转出费率: " . ($app->fee_out_rate * 100) . "%"; echo "最低费用: {$app->fee_out_min}"; echo "最高费用: " . ($app->fee_out_max > 0 ? $app->fee_out_max : '不限制'); // 测试不同金额的手续费 $testAmounts = ['10.00', '100.00', '1000.00']; foreach ($testAmounts as $amount) { $fee = TransferService::calculateOutFee(1, $amount); echo "金额: {$amount}, 手续费: {$fee['fee_amount']}, 实际: {$fee['actual_amount']}"; } ``` ## 相关文档 - [Transfer模块设计文档](README.md) - 了解模块整体架构 - [API使用指南](API_USAGE.md) - 学习API调用方法 - [数据库设计文档](DATABASE.md) - 查看完整的表结构 - [汇率概念说明](EXCHANGE_RATE_CONCEPT.md) - 了解汇率计算规则 --- > 文档创建时间: 2025-06-15 > 最后更新时间: 2025-06-19 03:43 > 维护状态: 🔄 持续维护中 > 如有疑问请联系开发团队