target_id; $amount = $consumeItem->quantity * $multiplier; // 使用倍数计算所需金额 try { // 获取该币种的所有账户种类 $fundConfigs = \App\Module\Fund\Models\FundConfigModel::where('currency_id', $currencyId)->get(); if ($fundConfigs->isEmpty()) { return [ 'success' => false, 'message' => "币种不存在或没有关联的账户种类", 'currency_id' => $currencyId ]; } // 获取用户所有与该币种相关的账户 $fundConfigIds = $fundConfigs->pluck('id')->toArray(); $accounts = \App\Module\Fund\Models\FundModel::where('user_id', $userId) ->whereIn('fund_id', $fundConfigIds) ->get(); if ($accounts->isEmpty()) { return [ 'success' => false, 'message' => "用户没有该币种的账户", 'currency_id' => $currencyId ]; } // 计算总余额 $totalBalance = $accounts->sum('balance'); // 检查余额是否足够 if ($totalBalance < $amount) { return [ 'success' => false, 'message' => "币种总余额不足,需要 {$amount},实际 {$totalBalance}", 'currency_id' => $currencyId, 'required' => $amount, 'actual' => $totalBalance ]; } return [ 'success' => true, 'message' => '币种总余额足够', 'currency_id' => $currencyId, 'required' => $amount, 'actual' => $totalBalance, 'accounts' => $accounts->toArray() ]; } catch (\Exception $e) { return [ 'success' => false, 'message' => '检查币种消耗异常: ' . $e->getMessage(), 'currency_id' => $currencyId ]; } } public static function process(int $userId, GameConsumeItem $consumeItem, string $source, int $sourceId,$multiplier): Res { // todo 需要优化,迁移到Fund中 $currencyId = $consumeItem->target_id; $amountToConsume = $consumeItem->quantity * $multiplier; // 使用倍数计算实际消耗金额 try { // 先检查是否有足够的余额(使用相同的倍数) $checkResult = self::checkCurrencyConsume($userId, $consumeItem, $multiplier); if (!$checkResult['success']) { return $checkResult; } // 获取该币种的所有账户种类 $fundConfigs = \App\Module\Fund\Models\FundConfigModel::where('currency_id', $currencyId)->get(); $fundConfigIds = $fundConfigs->pluck('id')->toArray(); // 获取用户所有与该币种相关的账户 $accounts = \App\Module\Fund\Models\FundModel::where('user_id', $userId) ->whereIn('fund_id', $fundConfigIds) ->orderBy('fund_id') // 按账户种类ID排序,通常可用账户ID较小 ->get(); // 验证事务是否已开启(由调用者负责事务管理) \UCore\Db\Helper::check_tr(); $remainingAmount = $amountToConsume; $consumedAccounts = []; // 依次从各个账户中扣除 foreach ($accounts as $account) { if ($remainingAmount <= 0) { break; } $accountBalance = $account->balance; $amountToDeduct = min($accountBalance, $remainingAmount); if ($amountToDeduct > 0) { // 构建备注 $remark = "币种消耗:{$currencyId},消耗组:{$consumeItem->group_id},来源:{$source}"; if ($sourceId > 0) { $remark .= ",ID:{$sourceId}"; } if ($multiplier != 1.0) { $remark .= ",倍数:{$multiplier}"; } // 从当前账户扣除 $result = FundLogic::handle( $userId, $account->fund_id->value, -$amountToDeduct, // 负数表示消耗 FUND_LOG_TYPE::TRADE, $sourceId, $remark ); if ($result !== true) { return [ 'success' => false, 'message' => is_string($result) ? $result : "从账户 {$account->fund_id} 扣除失败", 'currency_id' => $currencyId, 'fund_config_id' => $account->fund_id, 'amount' => $amountToDeduct ]; } $consumedAccounts[] = [ 'fund_config_id' => $account->fund_id, 'amount' => $amountToDeduct ]; $remainingAmount -= $amountToDeduct; } } return [ 'success' => true, 'message' => '币种消耗成功', 'currency_id' => $currencyId, 'amount' => $amountToConsume, 'consumed_accounts' => $consumedAccounts ]; } catch (\Exception $e) { return [ 'success' => false, 'message' => '币种消耗异常: ' . $e->getMessage(), 'currency_id' => $currencyId, 'amount' => $amountToConsume ]; } } }