| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- <?php
- namespace App\Module\Mex\Validators;
- use App\Module\GameItems\Logics\ItemQuantity;
- use App\Module\Fund\Services\FundService;
- use App\Module\Fund\Enums\FUND_CURRENCY_TYPE;
- use App\Module\Mex\Logic\FundLogic;
- use UCore\Validator;
- use Uraus\Kku\Common\MEX_DIRECTION;
- use Illuminate\Support\Facades\Log;
- /**
- * 农贸市场订单验证器
- *
- * 验证订单创建的各种条件,包括资金、物品数量等
- * 支持多币种验证,默认使用钻石币种
- */
- class MexOrderValidator extends Validator
- {
- /**
- * 验证订单创建条件
- *
- * @param mixed $value 交易方向
- * @param array $data 所有数据
- * @return bool 验证是否通过
- */
- public function validate(mixed $value, array $data): bool
- {
- $direction = (int)$value;
- // 从 args 获取字段名
- $userIdKey = $this->args[0] ?? 'user_id';
- $itemIdKey = $this->args[1] ?? 'itemId';
- $numKey = $this->args[2] ?? 'num';
- $priceKey = $this->args[3] ?? 'price';
- $currencyTypeKey = $this->args[4] ?? 'currency_type'; // 新增币种字段
- $userId = $data[$userIdKey] ?? null;
- $itemId = $data[$itemIdKey] ?? null;
- $quantity = $data[$numKey] ?? null;
- $price = $data[$priceKey] ?? null;
- $currencyTypeValue = $data[$currencyTypeKey] ?? null;
- if (!$userId || !$itemId || !$quantity || !$price) {
- $this->addError('订单参数不完整');
- return false;
- }
- // 解析币种类型
- $currencyType = null;
- if ($currencyTypeValue !== null) {
- $currencyType = FUND_CURRENCY_TYPE::tryFrom($currencyTypeValue);
- }
- // 如果没有指定币种或币种无效,使用默认币种(钻石)
- $currencyType = $currencyType ?? FundLogic::getDefaultCurrency();
- try {
- if ($direction === MEX_DIRECTION::SELL) {
- return $this->validateSellOrder($userId, $itemId, $quantity, $price);
- } elseif ($direction === MEX_DIRECTION::BUY) {
- return $this->validateBuyOrder($userId, $itemId, $quantity, $price, $currencyType);
- } else {
- $this->addError('无效的交易方向');
- return false;
- }
- } catch (\Exception $e) {
- Log::error('农贸市场订单验证失败', [
- 'user_id' => $userId,
- 'item_id' => $itemId,
- 'quantity' => $quantity,
- 'price' => $price,
- 'direction' => $direction,
- 'currency_type' => $currencyType?->value,
- 'error' => $e->getMessage()
- ]);
- $this->addError('订单验证时发生错误');
- return false;
- }
- }
- /**
- * 验证卖出订单
- *
- * @param int $userId 用户ID
- * @param int $itemId 物品ID
- * @param int $quantity 数量
- * @param float $price 价格
- * @return bool
- */
- private function validateSellOrder(int $userId, int $itemId, int $quantity, float $price): bool
- {
- // 验证用户是否拥有足够的物品
- if (!$this->validateUserItemQuantity($userId, $itemId, $quantity)) {
- return false;
- }
- return true;
- }
- /**
- * 验证买入订单
- *
- * @param int $userId 用户ID
- * @param int $itemId 物品ID
- * @param int $quantity 数量
- * @param float $price 价格
- * @param FUND_CURRENCY_TYPE|null $currencyType 币种类型,默认使用钻石
- * @return bool
- */
- private function validateBuyOrder(int $userId, int $itemId, int $quantity, float $price, ?FUND_CURRENCY_TYPE $currencyType = null): bool
- {
- // 计算所需资金
- $totalCost = $quantity * $price;
- // 验证用户是否有足够的资金(使用指定币种)
- if (!$this->validateUserFundBalance($userId, $totalCost, $currencyType)) {
- return false;
- }
- return true;
- }
- /**
- * 验证用户物品数量(检查可用数量,排除已冻结的物品)
- *
- * @param int $userId 用户ID
- * @param int $itemId 物品ID
- * @param int $requiredQuantity 需要的数量
- * @return bool
- */
- private function validateUserItemQuantity(int $userId, int $itemId, int $requiredQuantity): bool
- {
- // 使用ItemService获取可用数量(排除已冻结的物品)
- $availableQuantity = \App\Module\GameItems\Services\ItemService::getAvailableQuantity($userId, $itemId);
- if ($availableQuantity < $requiredQuantity) {
- $this->addError("可用物品数量不足,当前可用 {$availableQuantity} 个,需要 {$requiredQuantity} 个");
- return false;
- }
- return true;
- }
- /**
- * 验证用户资金余额
- * 使用Fund模块的验证器进行数额验证,信任Fund模块的数据处理
- *
- * @param int $userId 用户ID
- * @param float $requiredAmount 需要的金额
- * @param FUND_CURRENCY_TYPE|null $currencyType 币种类型,默认使用钻石
- * @return bool
- */
- private function validateUserFundBalance(int $userId, float $requiredAmount, ?FUND_CURRENCY_TYPE $currencyType = null): bool
- {
- // 获取币种类型,默认使用钻石
- $currencyType = $currencyType ?? FundLogic::getDefaultCurrency();
- // 获取对应的可用账户类型
- $availableAccountType = FundLogic::getAvailableAccountType($currencyType);
- if (!$availableAccountType) {
- $this->addError('不支持的币种类型');
- return false;
- }
- // 使用Fund模块的FundService进行资金验证,信任Fund模块的数据处理
- $fundService = new FundService($userId, $availableAccountType->value);
- $balance = $fundService->balance();
- // 直接比较,不进行精度转换,信任Fund模块的数据处理
- if ($balance < $requiredAmount) {
- $this->addError("资金不足,当前{$currencyType->name}余额 {$balance},需要 {$requiredAmount}");
- return false;
- }
- return true;
- }
- }
|