# FeeService 转移方法使用说明 ## 概述 FeeService 新增了 `transfer` 方法,用于将手续费从指定应用的手续费账户转移到目标用户账户。 ## 方法签名 ```php /** * 转移手续费到指定用户 * * 将手续费从指定应用的手续费账户转移到目标用户账户 * * @param int $appId 出钱的应用ID(从该应用的手续费账户扣除) * @param int $targetUserId 目标用户ID(收钱的) * @param float $amount 金额(钱数) * @param int $orderId 订单ID(划转依据) * @param string $transferType 转移类型(默认为'fee_transfer') * @return bool|string 成功返回true,失败返回错误信息 */ public static function transfer(int $appId, int $targetUserId, float $amount, int $orderId, string $transferType = 'fee_transfer') ``` ## 参数说明 - **$appId**: 应用ID,从该应用配置的手续费账户中扣除资金 - **$targetUserId**: 目标用户ID,接收转移资金的用户 - **$amount**: 转移金额,必须大于0 - **$orderId**: 订单ID,作为转移的依据和日志记录 - **$transferType**: 转移类型,用于标识转移的业务类型(默认为'fee_transfer') ## 使用示例 ### 1. 基本使用 ```php use App\Module\Transfer\Services\FeeService; // 从应用ID为1的手续费账户转移10元到用户ID为123的账户(使用默认转移类型) $result = FeeService::transfer( appId: 1, targetUserId: 123, amount: 10.0, orderId: 12345 ); if ($result === true) { echo "手续费转移成功"; } else { echo "转移失败: " . $result; } // 使用自定义转移类型 $result = FeeService::transfer( appId: 1, targetUserId: 123, amount: 10.0, orderId: 12345, transferType: 'refund' ); ``` ### 2. 在业务流程中使用 ```php use App\Module\Transfer\Services\FeeService; use App\Module\Transfer\Models\TransferApp; use App\Module\Transfer\Models\TransferOrder; // 获取订单信息 $order = TransferOrder::find($orderId); $app = $order->transferApp; // 计算需要返还的手续费 $refundAmount = $order->fee_amount * 0.5; // 返还50%手续费 // 执行手续费转移 $result = FeeService::transfer( appId: $app->id, targetUserId: $order->user_id, amount: $refundAmount, orderId: $order->id, transferType: 'fee_refund' ); if ($result === true) { // 记录返还日志 logger()->info("手续费返还成功", [ 'order_id' => $order->id, 'user_id' => $order->user_id, 'refund_amount' => $refundAmount ]); } else { // 处理失败情况 logger()->error("手续费返还失败", [ 'order_id' => $order->id, 'error' => $result ]); } ``` ### 3. 批量处理 ```php use App\Module\Transfer\Services\FeeService; $transfers = [ ['app_id' => 1, 'user_id' => 123, 'amount' => 10.0, 'order_id' => 1001, 'type' => 'fee_refund'], ['app_id' => 1, 'user_id' => 124, 'amount' => 15.0, 'order_id' => 1002, 'type' => 'bonus'], ['app_id' => 2, 'user_id' => 125, 'amount' => 8.0, 'order_id' => 1003, 'type' => 'compensation'], ]; $results = []; foreach ($transfers as $transfer) { $result = FeeService::transfer( appId: $transfer['app_id'], targetUserId: $transfer['user_id'], amount: $transfer['amount'], orderId: $transfer['order_id'], transferType: $transfer['type'] ); $results[] = [ 'order_id' => $transfer['order_id'], 'success' => $result === true, 'error' => $result === true ? null : $result ]; } // 统计结果 $successCount = count(array_filter($results, fn($r) => $r['success'])); $failCount = count($results) - $successCount; echo "成功: {$successCount}, 失败: {$failCount}"; ``` ## 错误处理 方法可能返回以下错误信息: - `"转移金额必须大于0"` - 金额参数无效 - `"应用不存在"` - 指定的应用ID不存在 - `"目标用户不存在"` - 指定的用户ID不存在 - `"not-sufficient-funds ..."` - 手续费账户余额不足 - `"手续费转移异常: ..."` - 其他系统异常 ## 工作原理 1. **参数验证**: 检查金额、应用ID、用户ID的有效性 2. **账户获取**: 通过应用配置获取手续费收取账户UID(默认为1) 3. **资金转移**: 使用Fund模块的trade方法执行资金转移 4. **日志记录**: 记录转移成功或失败的详细日志 5. **异常处理**: 捕获并记录任何异常情况 ## 注意事项 1. **事务安全**: 方法内部使用Fund模块的trade方法,该方法会自动处理事务 2. **日志记录**: 所有转移操作都会记录详细日志,便于审计和调试 3. **权限控制**: 方法不进行权限检查,调用方需要自行控制访问权限 4. **金额精度**: 使用Fund模块的精度控制,确保金额计算准确 5. **账户配置**: 依赖应用的fee_account_uid配置,未配置时使用默认账户UID 1 ## 相关配置 确保应用表中正确配置了手续费账户: ```sql -- 设置应用的手续费收取账户 UPDATE kku_transfer_apps SET fee_account_uid = 1 WHERE id = 1; ``` 如果fee_account_uid为0或NULL,系统会自动使用默认账户UID 1。