FEE_TRANSFER_USAGE.md 5.1 KB

FeeService 转移方法使用说明

概述

FeeService 新增了 transfer 方法,用于将手续费从指定应用的手续费账户转移到目标用户账户。

方法签名

/**
 * 转移手续费到指定用户
 *
 * 将手续费从指定应用的手续费账户转移到目标用户账户
 *
 * @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. 基本使用

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. 在业务流程中使用

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. 批量处理

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

相关配置

确保应用表中正确配置了手续费账户:

-- 设置应用的手续费收取账户
UPDATE kku_transfer_apps 
SET fee_account_uid = 1 
WHERE id = 1;

如果fee_account_uid为0或NULL,系统会自动使用默认账户UID 1。