| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- <?php
- namespace App\Module\Mex\Logic;
- use App\Module\Fund\Services\FundService;
- use App\Module\Fund\Enums\FUND_TYPE;
- use App\Module\Fund\Enums\FUND_CURRENCY_TYPE;
- use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
- use App\Module\GameItems\Services\ItemService;
- use App\Module\Mex\Logic\MexTransactionLogic;
- use App\Module\Mex\Logic\MexWarehouseLogic;
- use App\Module\Mex\Logic\FundLogic;
- use App\Module\Mex\Enums\TransactionType;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- /**
- * 农贸市场账户流转逻辑
- *
- * 处理用户与仓库账户之间的资金和物品流转
- * 仓库账户USER_ID为15,调控账户USER_ID为16
- * 支持多币种交易,默认使用钻石币种
- */
- class MexAccountLogic
- {
- // 仓库账户ID
- const WAREHOUSE_USER_ID = 15;
- // 调控账户ID
- const REGULATION_USER_ID = 16;
- /**
- * 处理用户卖出订单的账户流转
- * 用户卖出:资金从仓库转出到用户、物品从用户转入仓库
- *
- * @param int $userId 用户ID
- * @param int $itemId 商品ID
- * @param int $quantity 数量
- * @param string $price 单价
- * @param string $totalAmount 总金额
- * @param int $orderId 订单ID
- * @param FUND_CURRENCY_TYPE|null $currencyType 币种类型,默认使用钻石
- * @return array 操作结果
- */
- public static function processSellOrder(int $userId, int $itemId, int $quantity, string $price, string $totalAmount, int $orderId, ?FUND_CURRENCY_TYPE $currencyType = null): array
- {
- try {
- DB::beginTransaction();
- // 获取币种类型,默认使用钻石
- $currencyType = $currencyType ?? FundLogic::getDefaultCurrency();
- // 获取对应的账户类型
- $availableAccountType = FundLogic::getAvailableAccountType($currencyType);
- if (!$availableAccountType) {
- DB::rollBack();
- return ['success' => false, 'message' => '不支持的币种类型'];
- }
- // 1. 验证用户是否有足够的物品
- $checkResult = ItemService::checkItemQuantity($userId, $itemId, $quantity);
- if (!$checkResult->success) {
- DB::rollBack();
- return ['success' => false, 'message' => $checkResult->message];
- }
- // 2. 从用户扣除物品
- $consumeResult = ItemService::consumeItem($userId, $itemId, null, $quantity, [
- 'reason' => 'mex_sell',
- 'order_id' => $orderId,
- 'remark' => "农贸市场卖出物品,订单ID:{$orderId}"
- ]);
- if (!$consumeResult['success']) {
- DB::rollBack();
- return ['success' => false, 'message' => '扣除用户物品失败:' . ($consumeResult['message'] ?? '未知错误')];
- }
- // 3. 给仓库账户添加物品
- $addResult = ItemService::addItem(self::WAREHOUSE_USER_ID, $itemId, $quantity, [
- 'reason' => 'mex_warehouse_buy',
- 'source_type' => REWARD_SOURCE_TYPE::MEX_BUY,
- 'source_id' => $orderId,
- 'order_id' => $orderId,
- 'remark' => "农贸市场仓库收购物品,订单ID:{$orderId}"
- ]);
- if (!$addResult['success']) {
- DB::rollBack();
- return ['success' => false, 'message' => '仓库添加物品失败:' . ($addResult['message'] ?? '未知错误')];
- }
- // 4. 从仓库账户转出资金给用户
- $warehouseFundService = new FundService(self::WAREHOUSE_USER_ID, $availableAccountType->value);
- $precision = $currencyType->getPrecision();
- $fundAmount = (int)bcmul($totalAmount, bcpow('10', $precision), 0); // 根据币种精度转换
- $transferResult = $warehouseFundService->trade(
- $userId,
- $fundAmount,
- 'mex_sell',
- $orderId,
- "农贸市场卖出收款,订单ID:{$orderId}"
- );
- if (is_string($transferResult)) {
- DB::rollBack();
- return ['success' => false, 'message' => '资金转移失败:' . $transferResult];
- }
- // 5. 更新仓库统计
- $warehouseResult = MexWarehouseLogic::addStock($itemId, $quantity, $totalAmount);
- if (!$warehouseResult) {
- DB::rollBack();
- return ['success' => false, 'message' => '更新仓库统计失败'];
- }
- // 6. 创建成交记录
- $transactionResult = MexTransactionLogic::createTransaction([
- 'sell_order_id' => $orderId,
- 'buyer_id' => self::WAREHOUSE_USER_ID,
- 'seller_id' => $userId,
- 'item_id' => $itemId,
- 'currency_type' => $currencyType->value,
- 'quantity' => $quantity,
- 'price' => $price,
- 'total_amount' => $totalAmount,
- 'transaction_type' => TransactionType::USER_SELL,
- 'is_admin_operation' => false,
- ]);
- if (!$transactionResult) {
- DB::rollBack();
- return ['success' => false, 'message' => '创建成交记录失败'];
- }
- DB::commit();
- return [
- 'success' => true,
- 'message' => '卖出订单处理成功',
- 'transaction_id' => $transactionResult->id,
- 'fund_transfer' => $transferResult,
- 'item_consume' => $consumeResult,
- 'warehouse_add' => $addResult
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('Mex卖出订单处理失败', [
- 'user_id' => $userId,
- 'item_id' => $itemId,
- 'quantity' => $quantity,
- 'order_id' => $orderId,
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString()
- ]);
- return ['success' => false, 'message' => '系统错误:' . $e->getMessage()];
- }
- }
- /**
- * 处理用户买入订单的账户流转
- * 用户买入:资金从用户转入仓库、物品从仓库转出到用户
- *
- * @param int $userId 用户ID
- * @param int $itemId 商品ID
- * @param int $quantity 数量
- * @param string $price 单价
- * @param string $totalAmount 总金额
- * @param int $orderId 订单ID
- * @param FUND_CURRENCY_TYPE|null $currencyType 币种类型,默认使用钻石
- * @return array 操作结果
- */
- public static function processBuyOrder(int $userId, int $itemId, int $quantity, string $price, string $totalAmount, int $orderId, ?FUND_CURRENCY_TYPE $currencyType = null): array
- {
- try {
- DB::beginTransaction();
- // 获取币种类型,默认使用钻石
- $currencyType = $currencyType ?? FundLogic::getDefaultCurrency();
- // 获取对应的账户类型
- $availableAccountType = FundLogic::getAvailableAccountType($currencyType);
- if (!$availableAccountType) {
- DB::rollBack();
- return ['success' => false, 'message' => '不支持的币种类型'];
- }
- // 1. 验证仓库是否有足够的物品
- if (!MexWarehouseLogic::checkStockSufficient($itemId, $quantity)) {
- DB::rollBack();
- return ['success' => false, 'message' => '仓库库存不足'];
- }
- // 2. 验证用户是否有足够的资金
- $userFundService = new FundService($userId, $availableAccountType->value);
- $precision = $currencyType->getPrecision();
- $fundAmount = (int)bcmul($totalAmount, bcpow('10', $precision), 0); // 根据币种精度转换
- if ($userFundService->balance() < $fundAmount) {
- DB::rollBack();
- return ['success' => false, 'message' => '用户资金不足'];
- }
- // 3. 从用户转出资金到仓库
- $transferResult = $userFundService->trade(
- self::WAREHOUSE_USER_ID,
- $fundAmount,
- 'mex_buy',
- $orderId,
- "农贸市场买入付款,订单ID:{$orderId}"
- );
- if (is_string($transferResult)) {
- DB::rollBack();
- return ['success' => false, 'message' => '资金转移失败:' . $transferResult];
- }
- // 4. 从仓库扣除物品
- $consumeResult = ItemService::consumeItem(self::WAREHOUSE_USER_ID, $itemId, null, $quantity, [
- 'reason' => 'mex_warehouse_sell',
- 'order_id' => $orderId,
- 'remark' => "农贸市场仓库出售物品,订单ID:{$orderId}"
- ]);
- if (!$consumeResult['success']) {
- DB::rollBack();
- return ['success' => false, 'message' => '仓库扣除物品失败:' . ($consumeResult['message'] ?? '未知错误')];
- }
- // 5. 给用户添加物品
- $addResult = ItemService::addItem($userId, $itemId, $quantity, [
- 'reason' => 'mex_buy',
- 'source_type' => REWARD_SOURCE_TYPE::MEX_BUY,
- 'source_id' => $orderId,
- 'order_id' => $orderId,
- 'remark' => "农贸市场买入物品,订单ID:{$orderId}"
- ]);
- if (!$addResult['success']) {
- DB::rollBack();
- return ['success' => false, 'message' => '用户添加物品失败:' . ($addResult['message'] ?? '未知错误')];
- }
- // 6. 更新仓库统计
- $warehouseResult = MexWarehouseLogic::reduceStock($itemId, $quantity, $totalAmount);
- if (!$warehouseResult) {
- DB::rollBack();
- return ['success' => false, 'message' => '更新仓库统计失败'];
- }
- // 7. 创建成交记录
- $transactionResult = MexTransactionLogic::createTransaction([
- 'buy_order_id' => $orderId,
- 'buyer_id' => $userId,
- 'seller_id' => self::WAREHOUSE_USER_ID,
- 'item_id' => $itemId,
- 'currency_type' => $currencyType->value,
- 'quantity' => $quantity,
- 'price' => $price,
- 'total_amount' => $totalAmount,
- 'transaction_type' => TransactionType::USER_BUY,
- 'is_admin_operation' => false,
- ]);
- if (!$transactionResult) {
- DB::rollBack();
- return ['success' => false, 'message' => '创建成交记录失败'];
- }
- DB::commit();
- return [
- 'success' => true,
- 'message' => '买入订单处理成功',
- 'transaction_id' => $transactionResult->id,
- 'fund_transfer' => $transferResult,
- 'item_consume' => $consumeResult,
- 'user_add' => $addResult
- ];
- } catch (\Exception $e) {
- DB::rollBack();
- Log::error('Mex买入订单处理失败', [
- 'user_id' => $userId,
- 'item_id' => $itemId,
- 'quantity' => $quantity,
- 'order_id' => $orderId,
- 'error' => $e->getMessage(),
- 'trace' => $e->getTraceAsString()
- ]);
- return ['success' => false, 'message' => '系统错误:' . $e->getMessage()];
- }
- }
- /**
- * 检查仓库账户资金余额
- *
- * @param FUND_CURRENCY_TYPE|null $currencyType 币种类型,默认使用钻石
- * @return int 余额(按币种精度存储的整数)
- */
- public static function getWarehouseFundBalance(?FUND_CURRENCY_TYPE $currencyType = null): int
- {
- $currencyType = $currencyType ?? FundLogic::getDefaultCurrency();
- $availableAccountType = FundLogic::getAvailableAccountType($currencyType);
- if (!$availableAccountType) {
- return 0;
- }
- $warehouseFundService = new FundService(self::WAREHOUSE_USER_ID, $availableAccountType->value);
- return $warehouseFundService->balance();
- }
- /**
- * 检查调控账户资金余额
- *
- * @param FUND_CURRENCY_TYPE|null $currencyType 币种类型,默认使用钻石
- * @return int 余额(按币种精度存储的整数)
- */
- public static function getRegulationFundBalance(?FUND_CURRENCY_TYPE $currencyType = null): int
- {
- $currencyType = $currencyType ?? FundLogic::getDefaultCurrency();
- $availableAccountType = FundLogic::getAvailableAccountType($currencyType);
- if (!$availableAccountType) {
- return 0;
- }
- $regulationFundService = new FundService(self::REGULATION_USER_ID, $availableAccountType->value);
- return $regulationFundService->balance();
- }
- }
|