|
|
@@ -10,6 +10,7 @@ use App\Module\Game\Models\GameConsumeItem;
|
|
|
use App\Module\GameItems\Services\ItemService;
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
+use UCore\Db\Helper;
|
|
|
use UCore\Dto\Res;
|
|
|
|
|
|
/**
|
|
|
@@ -19,6 +20,7 @@ use UCore\Dto\Res;
|
|
|
*/
|
|
|
class ConsumeService
|
|
|
{
|
|
|
+
|
|
|
/**
|
|
|
* 检查用户是否满足消耗组的条件
|
|
|
*
|
|
|
@@ -30,6 +32,9 @@ class ConsumeService
|
|
|
{
|
|
|
try {
|
|
|
// 获取消耗组
|
|
|
+ /**
|
|
|
+ * @var GameConsumeGroup $consumeGroup
|
|
|
+ */
|
|
|
$consumeGroup = is_numeric($consumeGroupCode)
|
|
|
? GameConsumeGroup::find($consumeGroupCode)
|
|
|
: GameConsumeGroup::where('code', $consumeGroupCode)->first();
|
|
|
@@ -48,18 +53,23 @@ class ConsumeService
|
|
|
// 检查每个消耗项
|
|
|
foreach ($consumeItems as $item) {
|
|
|
$checkResult = self::checkConsumeItem($userId, $item);
|
|
|
+
|
|
|
if (!$checkResult['success']) {
|
|
|
return Res::error($checkResult['message'], $checkResult);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return Res::success();
|
|
|
+ // 所有条件都满足,返回成功; 返回消耗组信息
|
|
|
+ return Res::success('',
|
|
|
+ ConsumeGroupService::consumeItems2Array($consumeItems)
|
|
|
+ );
|
|
|
} catch (\Exception $e) {
|
|
|
Log::error('检查消耗条件失败', [
|
|
|
- 'user_id' => $userId,
|
|
|
+ 'user_id' => $userId,
|
|
|
'consume_group' => $consumeGroupCode,
|
|
|
- 'error' => $e->getMessage()
|
|
|
+ 'error' => $e->getMessage()
|
|
|
]);
|
|
|
+
|
|
|
return Res::error('检查消耗条件时发生错误: ' . $e->getMessage());
|
|
|
|
|
|
}
|
|
|
@@ -74,16 +84,22 @@ class ConsumeService
|
|
|
* @param int $sourceId 消耗来源ID
|
|
|
* @return Res 执行结果
|
|
|
*/
|
|
|
- public static function executeConsume(int $userId, $consumeGroupCode, string $source, int $sourceId = 0): Res
|
|
|
+ public static function executeConsume(int $userId, $consumeGroupCode, string $source, int $sourceId = 0, $check = true): Res
|
|
|
{
|
|
|
- // 先检查是否满足消耗条件
|
|
|
- $checkResult = self::checkConsume($userId, $consumeGroupCode);
|
|
|
- if (!$checkResult->success) {
|
|
|
- return $checkResult;
|
|
|
+ if ($check) {
|
|
|
+ // 先检查是否满足消耗条件
|
|
|
+ $checkResult = self::checkConsume($userId, $consumeGroupCode);
|
|
|
+ if (!$checkResult->success) {
|
|
|
+ return $checkResult;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
+ Helper::check_tr();
|
|
|
// 获取消耗组
|
|
|
+ /**
|
|
|
+ * @var GameConsumeGroup $consumeGroup
|
|
|
+ */
|
|
|
$consumeGroup = is_numeric($consumeGroupCode)
|
|
|
? GameConsumeGroup::find($consumeGroupCode)
|
|
|
: GameConsumeGroup::where('code', $consumeGroupCode)->first();
|
|
|
@@ -92,37 +108,35 @@ class ConsumeService
|
|
|
$consumeItems = $consumeGroup->consumeItems;
|
|
|
|
|
|
// 开始事务
|
|
|
- DB::beginTransaction();
|
|
|
+
|
|
|
|
|
|
// 执行每个消耗项
|
|
|
foreach ($consumeItems as $item) {
|
|
|
$consumeResult = self::executeConsumeItem($userId, $item, $source, $sourceId);
|
|
|
if (!$consumeResult['success']) {
|
|
|
DB::rollBack();
|
|
|
+
|
|
|
return Res::error($consumeResult['message'], $consumeResult);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 提交事务
|
|
|
- DB::commit();
|
|
|
|
|
|
return Res::success('消耗执行成功', [
|
|
|
'consume_group' => [
|
|
|
- 'id' => $consumeGroup->id,
|
|
|
+ 'id' => $consumeGroup->id,
|
|
|
'code' => $consumeGroup->code,
|
|
|
'name' => $consumeGroup->name
|
|
|
- ]
|
|
|
+ ],
|
|
|
+ 'list' => ConsumeGroupService::consumeItems2Array($consumeItems)
|
|
|
]);
|
|
|
} catch (\Exception $e) {
|
|
|
- // 回滚事务
|
|
|
- DB::rollBack();
|
|
|
|
|
|
Log::error('执行消耗失败', [
|
|
|
- 'user_id' => $userId,
|
|
|
+ 'user_id' => $userId,
|
|
|
'consume_group' => $consumeGroupCode,
|
|
|
- 'source' => $source,
|
|
|
- 'source_id' => $sourceId,
|
|
|
- 'error' => $e->getMessage()
|
|
|
+ 'source' => $source,
|
|
|
+ 'source_id' => $sourceId,
|
|
|
+ 'error' => $e->getMessage()
|
|
|
]);
|
|
|
|
|
|
return Res::error('执行消耗时发生错误: ' . $e->getMessage());
|
|
|
@@ -141,24 +155,26 @@ class ConsumeService
|
|
|
switch ($consumeItem->consume_type) {
|
|
|
case CONSUME_TYPE::ITEM->value:
|
|
|
$result = self::checkItemConsume($userId, $consumeItem);
|
|
|
+
|
|
|
// 将 Res 对象转换为数组格式
|
|
|
return [
|
|
|
- 'success' => $result->success,
|
|
|
- 'message' => $result->message,
|
|
|
- 'item_id' => $result->data['item_id'] ?? null,
|
|
|
+ 'success' => $result->success,
|
|
|
+ 'message' => $result->message,
|
|
|
+ 'item_id' => $result->data['item_id'] ?? null,
|
|
|
'required' => $result->data['required'] ?? null,
|
|
|
- 'actual' => $result->data['actual'] ?? null
|
|
|
+ 'actual' => $result->data['actual'] ?? null
|
|
|
];
|
|
|
|
|
|
case CONSUME_TYPE::FUND_CONFIG->value:
|
|
|
$result = self::checkFundConfigConsume($userId, $consumeItem);
|
|
|
+
|
|
|
// 将 Res 对象转换为数组格式
|
|
|
return [
|
|
|
- 'success' => $result->success,
|
|
|
- 'message' => $result->message,
|
|
|
+ 'success' => $result->success,
|
|
|
+ 'message' => $result->message,
|
|
|
'fund_config_id' => $result->data['fund_config_id'] ?? null,
|
|
|
- 'required' => $result->data['required'] ?? null,
|
|
|
- 'actual' => $result->data['actual'] ?? null
|
|
|
+ 'required' => $result->data['required'] ?? null,
|
|
|
+ 'actual' => $result->data['actual'] ?? null
|
|
|
];
|
|
|
|
|
|
case CONSUME_TYPE::CURRENCY->value:
|
|
|
@@ -186,22 +202,24 @@ class ConsumeService
|
|
|
switch ($consumeItem->consume_type) {
|
|
|
case CONSUME_TYPE::ITEM->value:
|
|
|
$result = self::executeItemConsume($userId, $consumeItem, $source, $sourceId);
|
|
|
+
|
|
|
// 将 Res 对象转换为数组格式
|
|
|
return [
|
|
|
- 'success' => $result->success,
|
|
|
- 'message' => $result->message,
|
|
|
- 'item_id' => $result->data['item_id'] ?? null,
|
|
|
+ 'success' => $result->success,
|
|
|
+ 'message' => $result->message,
|
|
|
+ 'item_id' => $result->data['item_id'] ?? null,
|
|
|
'quantity' => $result->data['quantity'] ?? null
|
|
|
];
|
|
|
|
|
|
case CONSUME_TYPE::FUND_CONFIG->value:
|
|
|
$result = self::executeFundConfigConsume($userId, $consumeItem, $source, $sourceId);
|
|
|
+
|
|
|
// 将 Res 对象转换为数组格式
|
|
|
return [
|
|
|
- 'success' => $result->success,
|
|
|
- 'message' => $result->message,
|
|
|
+ 'success' => $result->success,
|
|
|
+ 'message' => $result->message,
|
|
|
'fund_config_id' => $result->data['fund_config_id'] ?? null,
|
|
|
- 'amount' => $result->data['amount'] ?? null
|
|
|
+ 'amount' => $result->data['amount'] ?? null
|
|
|
];
|
|
|
|
|
|
case CONSUME_TYPE::CURRENCY->value:
|
|
|
@@ -224,11 +242,11 @@ class ConsumeService
|
|
|
*/
|
|
|
protected static function checkItemConsume(int $userId, GameConsumeItem $consumeItem): Res
|
|
|
{
|
|
|
- $itemId = $consumeItem->target_id;
|
|
|
+ $itemId = $consumeItem->target_id;
|
|
|
$quantity = $consumeItem->quantity;
|
|
|
|
|
|
// 获取用户物品
|
|
|
- $userItems = ItemService::getUserItems($userId, ['item_id' => $itemId]);
|
|
|
+ $userItems = ItemService::getUserItems($userId, [ 'item_id' => $itemId ]);
|
|
|
|
|
|
// 计算用户拥有的物品总数
|
|
|
$totalQuantity = 0;
|
|
|
@@ -239,9 +257,9 @@ class ConsumeService
|
|
|
// 检查数量是否足够
|
|
|
if ($totalQuantity < $quantity) {
|
|
|
return Res::error("物品数量不足,需要 {$quantity},实际 {$totalQuantity}", [
|
|
|
- 'item_id' => $itemId,
|
|
|
+ 'item_id' => $itemId,
|
|
|
'required' => $quantity,
|
|
|
- 'actual' => $totalQuantity
|
|
|
+ 'actual' => $totalQuantity
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
@@ -260,7 +278,7 @@ class ConsumeService
|
|
|
protected static function checkFundConfigConsume(int $userId, GameConsumeItem $consumeItem): Res
|
|
|
{
|
|
|
$fundConfigId = $consumeItem->target_id;
|
|
|
- $amount = $consumeItem->quantity;
|
|
|
+ $amount = $consumeItem->quantity;
|
|
|
|
|
|
// 获取用户账户
|
|
|
$account = FundLogic::get_account($userId, $fundConfigId);
|
|
|
@@ -276,8 +294,8 @@ class ConsumeService
|
|
|
if ($account->balance < $amount) {
|
|
|
return Res::error("账户余额不足,需要 {$amount},实际 {$account->balance}", [
|
|
|
'fund_config_id' => $fundConfigId,
|
|
|
- 'required' => $amount,
|
|
|
- 'actual' => $account->balance
|
|
|
+ 'required' => $amount,
|
|
|
+ 'actual' => $account->balance
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
@@ -299,7 +317,7 @@ class ConsumeService
|
|
|
try {
|
|
|
// 获取用户代币账户
|
|
|
$fundService = new \App\Module\Fund\Services\FundService($userId, $fundId);
|
|
|
- $account = $fundService->getAccount();
|
|
|
+ $account = $fundService->getAccount();
|
|
|
|
|
|
// 检查账户是否存在
|
|
|
if (!$account) {
|
|
|
@@ -314,11 +332,11 @@ class ConsumeService
|
|
|
$balance = $account->balance;
|
|
|
if ($balance < $amount) {
|
|
|
return [
|
|
|
- 'success' => false,
|
|
|
- 'message' => "代币账户余额不足,需要 {$amount},实际 {$balance}",
|
|
|
- 'fund_id' => $fundId,
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => "代币账户余额不足,需要 {$amount},实际 {$balance}",
|
|
|
+ 'fund_id' => $fundId,
|
|
|
'required' => $amount,
|
|
|
- 'actual' => $balance
|
|
|
+ 'actual' => $balance
|
|
|
];
|
|
|
}
|
|
|
|
|
|
@@ -346,28 +364,28 @@ class ConsumeService
|
|
|
*/
|
|
|
protected static function executeItemConsume(int $userId, GameConsumeItem $consumeItem, string $source, int $sourceId): Res
|
|
|
{
|
|
|
- $itemId = $consumeItem->target_id;
|
|
|
+ $itemId = $consumeItem->target_id;
|
|
|
$quantity = $consumeItem->quantity;
|
|
|
|
|
|
// 消耗物品
|
|
|
$result = ItemService::consumeItem($userId, $itemId, null, $quantity, [
|
|
|
'source_type' => $source,
|
|
|
- 'source_id' => $sourceId,
|
|
|
- 'details' => [
|
|
|
- 'consume_item_id' => $consumeItem->id,
|
|
|
+ 'source_id' => $sourceId,
|
|
|
+ 'details' => [
|
|
|
+ 'consume_item_id' => $consumeItem->id,
|
|
|
'consume_group_id' => $consumeItem->group_id
|
|
|
]
|
|
|
]);
|
|
|
|
|
|
if (!$result['success']) {
|
|
|
return Res::error($result['message'] ?? '物品消耗失败', [
|
|
|
- 'item_id' => $itemId,
|
|
|
+ 'item_id' => $itemId,
|
|
|
'quantity' => $quantity
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
return Res::success('物品消耗成功', [
|
|
|
- 'item_id' => $itemId,
|
|
|
+ 'item_id' => $itemId,
|
|
|
'quantity' => $quantity
|
|
|
]);
|
|
|
}
|
|
|
@@ -386,7 +404,7 @@ class ConsumeService
|
|
|
protected static function executeFundConfigConsume(int $userId, GameConsumeItem $consumeItem, string $source, int $sourceId): Res
|
|
|
{
|
|
|
$fundConfigId = $consumeItem->target_id;
|
|
|
- $amount = -$consumeItem->quantity; // 负数表示消耗
|
|
|
+ $amount = -$consumeItem->quantity; // 负数表示消耗
|
|
|
|
|
|
// 构建备注
|
|
|
$remark = "消耗组:{$consumeItem->group_id},来源:{$source}";
|
|
|
@@ -406,15 +424,16 @@ class ConsumeService
|
|
|
|
|
|
if ($result !== true) {
|
|
|
$errorMessage = is_string($result) ? $result : '账户资金消耗失败';
|
|
|
+
|
|
|
return Res::error($errorMessage, [
|
|
|
'fund_config_id' => $fundConfigId,
|
|
|
- 'amount' => abs($amount)
|
|
|
+ 'amount' => abs($amount)
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
return Res::success('账户资金消耗成功', [
|
|
|
'fund_config_id' => $fundConfigId,
|
|
|
- 'amount' => abs($amount)
|
|
|
+ 'amount' => abs($amount)
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
@@ -431,7 +450,7 @@ class ConsumeService
|
|
|
protected static function checkCurrencyConsume(int $userId, GameConsumeItem $consumeItem): array
|
|
|
{
|
|
|
$currencyId = $consumeItem->target_id;
|
|
|
- $amount = $consumeItem->quantity;
|
|
|
+ $amount = $consumeItem->quantity;
|
|
|
|
|
|
try {
|
|
|
// 获取该币种的所有账户种类
|
|
|
@@ -439,22 +458,22 @@ class ConsumeService
|
|
|
|
|
|
if ($fundConfigs->isEmpty()) {
|
|
|
return [
|
|
|
- 'success' => false,
|
|
|
- 'message' => "币种不存在或没有关联的账户种类",
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => "币种不存在或没有关联的账户种类",
|
|
|
'currency_id' => $currencyId
|
|
|
];
|
|
|
}
|
|
|
|
|
|
// 获取用户所有与该币种相关的账户
|
|
|
$fundConfigIds = $fundConfigs->pluck('id')->toArray();
|
|
|
- $accounts = \App\Module\Fund\Models\FundModel::where('user_id', $userId)
|
|
|
+ $accounts = \App\Module\Fund\Models\FundModel::where('user_id', $userId)
|
|
|
->whereIn('fund_id', $fundConfigIds)
|
|
|
->get();
|
|
|
|
|
|
if ($accounts->isEmpty()) {
|
|
|
return [
|
|
|
- 'success' => false,
|
|
|
- 'message' => "用户没有该币种的账户",
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => "用户没有该币种的账户",
|
|
|
'currency_id' => $currencyId
|
|
|
];
|
|
|
}
|
|
|
@@ -465,23 +484,23 @@ class ConsumeService
|
|
|
// 检查余额是否足够
|
|
|
if ($totalBalance < $amount) {
|
|
|
return [
|
|
|
- 'success' => false,
|
|
|
- 'message' => "币种总余额不足,需要 {$amount},实际 {$totalBalance}",
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => "币种总余额不足,需要 {$amount},实际 {$totalBalance}",
|
|
|
'currency_id' => $currencyId,
|
|
|
- 'required' => $amount,
|
|
|
- 'actual' => $totalBalance
|
|
|
+ 'required' => $amount,
|
|
|
+ 'actual' => $totalBalance
|
|
|
];
|
|
|
}
|
|
|
|
|
|
return [
|
|
|
- 'success' => true,
|
|
|
- 'message' => '币种总余额足够',
|
|
|
+ 'success' => true,
|
|
|
+ 'message' => '币种总余额足够',
|
|
|
'accounts' => $accounts->toArray()
|
|
|
];
|
|
|
} catch (\Exception $e) {
|
|
|
return [
|
|
|
- 'success' => false,
|
|
|
- 'message' => '检查币种消耗异常: ' . $e->getMessage(),
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => '检查币种消耗异常: ' . $e->getMessage(),
|
|
|
'currency_id' => $currencyId
|
|
|
];
|
|
|
}
|
|
|
@@ -502,7 +521,7 @@ class ConsumeService
|
|
|
protected static function executeCurrencyConsume(int $userId, GameConsumeItem $consumeItem, string $source, int $sourceId): array
|
|
|
{
|
|
|
// todo 需要优化,迁移到Fund中
|
|
|
- $currencyId = $consumeItem->target_id;
|
|
|
+ $currencyId = $consumeItem->target_id;
|
|
|
$amountToConsume = $consumeItem->quantity;
|
|
|
|
|
|
try {
|
|
|
@@ -513,7 +532,7 @@ class ConsumeService
|
|
|
}
|
|
|
|
|
|
// 获取该币种的所有账户种类
|
|
|
- $fundConfigs = \App\Module\Fund\Models\FundConfigModel::where('currency_id', $currencyId)->get();
|
|
|
+ $fundConfigs = \App\Module\Fund\Models\FundConfigModel::where('currency_id', $currencyId)->get();
|
|
|
$fundConfigIds = $fundConfigs->pluck('id')->toArray();
|
|
|
|
|
|
// 获取用户所有与该币种相关的账户
|
|
|
@@ -525,7 +544,7 @@ class ConsumeService
|
|
|
// 开始事务
|
|
|
\Illuminate\Support\Facades\DB::beginTransaction();
|
|
|
|
|
|
- $remainingAmount = $amountToConsume;
|
|
|
+ $remainingAmount = $amountToConsume;
|
|
|
$consumedAccounts = [];
|
|
|
|
|
|
// 依次从各个账户中扣除
|
|
|
@@ -556,18 +575,19 @@ class ConsumeService
|
|
|
|
|
|
if ($result !== true) {
|
|
|
\Illuminate\Support\Facades\DB::rollBack();
|
|
|
+
|
|
|
return [
|
|
|
- 'success' => false,
|
|
|
- 'message' => is_string($result) ? $result : "从账户 {$account->fund_id} 扣除失败",
|
|
|
- 'currency_id' => $currencyId,
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => is_string($result) ? $result : "从账户 {$account->fund_id} 扣除失败",
|
|
|
+ 'currency_id' => $currencyId,
|
|
|
'fund_config_id' => $account->fund_id,
|
|
|
- 'amount' => $amountToDeduct
|
|
|
+ 'amount' => $amountToDeduct
|
|
|
];
|
|
|
}
|
|
|
|
|
|
$consumedAccounts[] = [
|
|
|
'fund_config_id' => $account->fund_id,
|
|
|
- 'amount' => $amountToDeduct
|
|
|
+ 'amount' => $amountToDeduct
|
|
|
];
|
|
|
|
|
|
$remainingAmount -= $amountToDeduct;
|
|
|
@@ -578,10 +598,10 @@ class ConsumeService
|
|
|
\Illuminate\Support\Facades\DB::commit();
|
|
|
|
|
|
return [
|
|
|
- 'success' => true,
|
|
|
- 'message' => '币种消耗成功',
|
|
|
- 'currency_id' => $currencyId,
|
|
|
- 'amount' => $amountToConsume,
|
|
|
+ 'success' => true,
|
|
|
+ 'message' => '币种消耗成功',
|
|
|
+ 'currency_id' => $currencyId,
|
|
|
+ 'amount' => $amountToConsume,
|
|
|
'consumed_accounts' => $consumedAccounts
|
|
|
];
|
|
|
} catch (\Exception $e) {
|
|
|
@@ -591,11 +611,12 @@ class ConsumeService
|
|
|
}
|
|
|
|
|
|
return [
|
|
|
- 'success' => false,
|
|
|
- 'message' => '币种消耗异常: ' . $e->getMessage(),
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => '币种消耗异常: ' . $e->getMessage(),
|
|
|
'currency_id' => $currencyId,
|
|
|
- 'amount' => $amountToConsume
|
|
|
+ 'amount' => $amountToConsume
|
|
|
];
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
}
|