FEE_USAGE.md 14 KB

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. 计算手续费

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. 创建订单(自动计算手续费)

// 转出订单 - 手续费会自动计算并从用户账户扣除
$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. 获取手续费配置

$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. 获取手续费统计

// 获取所有应用的手续费统计
$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. 批量手续费计算

// 批量计算多个金额的手续费
$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. 手续费配置验证

// 验证手续费配置是否合理
$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. 数据库配置

-- 配置应用手续费
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. 模型使用

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. 订单信息

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

业务规则

  1. 费率生效: 手续费配置修改后立即生效,不影响已创建订单
  2. 账户余额: 确保手续费收取账户有足够权限接收资金
  3. 用户提示: 建议在用户界面明确显示手续费信息
  4. 异常处理: 手续费计算失败时应有明确的错误提示

安全考虑

  1. 权限控制: 手续费配置修改需要管理员权限
  2. 审计日志: 所有手续费配置变更应记录日志
  3. 监控报警: 设置手续费异常监控和报警机制
  4. 数据校验: 严格验证手续费配置参数的合法性

监控和报警

1. 手续费异常监控

-- 查找手续费异常高的订单
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. 手续费收入统计

-- 手续费收入日报
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. 定期调整: 根据业务发展和成本变化定期调整费率

运营管理

  1. 监控收入: 定期监控手续费收入和异常情况
  2. 账户管理: 确保手续费收取账户有足够的权限和安全性
  3. 用户提示: 在用户界面明确显示手续费信息和计算方式
  4. 透明度: 提供手续费计算器供用户预估费用

技术实施

  1. 性能优化: 手续费计算应高效,避免影响订单创建性能
  2. 缓存策略: 对手续费配置进行适当缓存,减少数据库查询
  3. 异步处理: 手续费统计可采用异步处理,避免阻塞主流程
  4. 数据备份: 定期备份手续费相关数据,确保数据安全

合规要求

  1. 法规遵循: 确保手续费设置符合相关法律法规
  2. 用户协议: 在用户协议中明确说明手续费政策
  3. 变更通知: 手续费政策变更应提前通知用户
  4. 争议处理: 建立手续费争议处理机制

故障排除

常见问题

  1. 手续费计算错误: 检查应用配置和计算逻辑
  2. 手续费未收取: 检查fee_account_uid配置
  3. 余额不足: 确保来源账户有足够余额
  4. 精度问题: 使用bcmath函数进行精确计算

调试方法

// 调试手续费计算
$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']}";
}

相关文档


文档创建时间: 2025-06-15 最后更新时间: 2025-06-19 03:43 维护状态: 🔄 持续维护中 如有疑问请联系开发团队