|
|
@@ -0,0 +1,221 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\OpenAPI\Handlers\Fund;
|
|
|
+
|
|
|
+use App\Module\OpenAPI\Handlers\BaseHandler;
|
|
|
+use App\Module\OpenAPI\Services\ScopeService;
|
|
|
+use App\Module\OpenAPI\Services\DeveloperAccountService;
|
|
|
+use App\Module\OpenAPI\Enums\SCOPE_TYPE;
|
|
|
+use App\Module\OpenAPI\Validations\DiamondWithdrawValidation;
|
|
|
+use App\Module\Fund\Services\FundService;
|
|
|
+use App\Module\Fund\Enums\FUND_TYPE;
|
|
|
+use App\Module\Fund\Enums\FUND_CURRENCY_TYPE;
|
|
|
+use Illuminate\Http\JsonResponse;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 钻石提取Handler
|
|
|
+ *
|
|
|
+ * 处理开发者从用户账户提取钻石的业务逻辑
|
|
|
+ * 资金流向:用户钻石账户 -> 开发者提取账户
|
|
|
+ */
|
|
|
+class DiamondWithdrawHandler extends BaseHandler
|
|
|
+{
|
|
|
+ public function __construct(ScopeService $scopeService)
|
|
|
+ {
|
|
|
+ parent::__construct($scopeService);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取所需的权限范围
|
|
|
+ *
|
|
|
+ * @return SCOPE_TYPE[]
|
|
|
+ */
|
|
|
+ public function getRequiredScopes(): array
|
|
|
+ {
|
|
|
+ return [SCOPE_TYPE::FUND_WITHDRAW];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理钻石提取请求
|
|
|
+ *
|
|
|
+ * @param array $data 请求数据
|
|
|
+ * @param array $context 上下文信息
|
|
|
+ * @return JsonResponse
|
|
|
+ */
|
|
|
+ protected function process(array $data, array $context = []): JsonResponse
|
|
|
+ {
|
|
|
+ // 使用验证类进行数据验证
|
|
|
+ $validation = new DiamondWithdrawValidation($data);
|
|
|
+ $validation->validate();
|
|
|
+
|
|
|
+ if ($validation->isFail()) {
|
|
|
+ return $this->errorResponse('参数验证失败', $validation->getErrors(), 422);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取验证后的数据
|
|
|
+ $safeData = $validation->getSafeData();
|
|
|
+ $sourceUserId = $safeData['user_id'];
|
|
|
+ $amount = $safeData['amount'];
|
|
|
+ $remark = $safeData['remark'] ?? '开发者提取钻石';
|
|
|
+ $orderId = $safeData['order_id'] ?? null;
|
|
|
+
|
|
|
+ // 获取应用信息
|
|
|
+ $app = $this->getApp($context);
|
|
|
+ if (!$app) {
|
|
|
+ return $this->errorResponse('无法获取应用信息', null, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ DB::beginTransaction();
|
|
|
+
|
|
|
+ // 检查开发者账户是否存在
|
|
|
+ $accountCheck = DeveloperAccountService::checkDeveloperAccounts($app);
|
|
|
+ if (!$accountCheck['withdraw_account_exists']) {
|
|
|
+ // 自动创建开发者账户
|
|
|
+ $createResult = DeveloperAccountService::createDeveloperAccounts($app);
|
|
|
+ if (!$createResult['success']) {
|
|
|
+ DB::rollBack();
|
|
|
+ return $this->errorResponse('创建开发者账户失败', $createResult['message'], 500);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取开发者提取账户用户ID
|
|
|
+ $withdrawUserId = DeveloperAccountService::getWithdrawUserId($app->id);
|
|
|
+
|
|
|
+ // 检查源用户钻石账户余额
|
|
|
+ $sourceFundService = new FundService($sourceUserId, FUND_TYPE::FUND2->value);
|
|
|
+ $sourceAccount = $sourceFundService->getAccount();
|
|
|
+
|
|
|
+ if (!$sourceAccount) {
|
|
|
+ DB::rollBack();
|
|
|
+ return $this->errorResponse('用户钻石账户不存在', null, 404);
|
|
|
+ }
|
|
|
+
|
|
|
+ $sourceBalance = $sourceFundService->balance();
|
|
|
+ if ($sourceBalance < $amount) {
|
|
|
+ DB::rollBack();
|
|
|
+ return $this->errorResponse('用户钻石账户余额不足', [
|
|
|
+ 'required' => $amount,
|
|
|
+ 'available' => $sourceBalance
|
|
|
+ ], 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保开发者提取账户存在
|
|
|
+ $withdrawFundService = new FundService($withdrawUserId, FUND_TYPE::FUND2->value);
|
|
|
+ $withdrawAccount = $withdrawFundService->getAccount();
|
|
|
+ if (!$withdrawAccount) {
|
|
|
+ // 初始化开发者提取账户
|
|
|
+ $initResult = $withdrawFundService->admin(FUND_TYPE::FUND2, 0, 1, '初始化开发者提取账户');
|
|
|
+ if (is_string($initResult)) {
|
|
|
+ DB::rollBack();
|
|
|
+ return $this->errorResponse('初始化提取账户失败', $initResult, 500);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 执行转账:从用户钻石账户转到开发者提取账户
|
|
|
+ $transferResult = $sourceFundService->transfer(
|
|
|
+ $withdrawUserId,
|
|
|
+ $amount,
|
|
|
+ $remark . ($orderId ? " (订单号: {$orderId})" : '')
|
|
|
+ );
|
|
|
+
|
|
|
+ if (is_string($transferResult)) {
|
|
|
+ DB::rollBack();
|
|
|
+ return $this->errorResponse('提取转账失败', $transferResult, 500);
|
|
|
+ }
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+
|
|
|
+ // 记录操作日志
|
|
|
+ $this->logAction('diamond.withdraw', [
|
|
|
+ 'app_id' => $app->id,
|
|
|
+ 'source_user_id' => $sourceUserId,
|
|
|
+ 'withdraw_user_id' => $withdrawUserId,
|
|
|
+ 'amount' => $amount,
|
|
|
+ 'order_id' => $orderId,
|
|
|
+ 'transfer_id' => $transferResult->transferId,
|
|
|
+ ], $context);
|
|
|
+
|
|
|
+ // 获取提取后的账户信息
|
|
|
+ $sourceAccountInfo = $sourceFundService->getAccount();
|
|
|
+ $withdrawAccountInfo = $withdrawFundService->getAccount();
|
|
|
+
|
|
|
+ $responseData = [
|
|
|
+ 'transfer_id' => $transferResult->transferId,
|
|
|
+ 'order_id' => $orderId,
|
|
|
+ 'amount' => $amount,
|
|
|
+ 'currency_type' => FUND_CURRENCY_TYPE::ZUANSHI->value,
|
|
|
+ 'currency_name' => FUND_CURRENCY_TYPE::ZUANSHI->getCurrencyName(),
|
|
|
+ 'from_account' => [
|
|
|
+ 'user_id' => $sourceUserId,
|
|
|
+ 'account_type' => '用户钻石账户',
|
|
|
+ 'balance_after' => $sourceAccountInfo ? $sourceAccountInfo->balance : 0,
|
|
|
+ ],
|
|
|
+ 'to_account' => [
|
|
|
+ 'user_id' => $withdrawUserId,
|
|
|
+ 'account_type' => '开发者提取账户',
|
|
|
+ 'balance_after' => $withdrawAccountInfo ? $withdrawAccountInfo->balance : 0,
|
|
|
+ ],
|
|
|
+ 'remark' => $remark,
|
|
|
+ 'created_at' => $transferResult->createdAt,
|
|
|
+ ];
|
|
|
+
|
|
|
+ return $this->successResponse('钻石提取成功', $responseData);
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ DB::rollBack();
|
|
|
+
|
|
|
+ Log::error('钻石提取失败', [
|
|
|
+ 'app_id' => $app->id,
|
|
|
+ 'source_user_id' => $sourceUserId,
|
|
|
+ 'amount' => $amount,
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ 'trace' => $e->getTraceAsString()
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return $this->errorResponse('提取处理失败', $e->getMessage(), 500);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取开发者提取账户余额信息
|
|
|
+ *
|
|
|
+ * @param array $data 请求数据
|
|
|
+ * @param array $context 上下文信息
|
|
|
+ * @return JsonResponse
|
|
|
+ */
|
|
|
+ public function getWithdrawAccountBalance(array $data, array $context = []): JsonResponse
|
|
|
+ {
|
|
|
+ // 获取应用信息
|
|
|
+ $app = $this->getApp($context);
|
|
|
+ if (!$app) {
|
|
|
+ return $this->errorResponse('无法获取应用信息', null, 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取开发者账户信息
|
|
|
+ $accountInfo = DeveloperAccountService::getDeveloperAccountInfo($app);
|
|
|
+
|
|
|
+ $responseData = [
|
|
|
+ 'app_id' => $app->id,
|
|
|
+ 'app_name' => $app->name,
|
|
|
+ 'withdraw_account' => $accountInfo['withdraw_account'],
|
|
|
+ 'currency_type' => FUND_CURRENCY_TYPE::ZUANSHI->value,
|
|
|
+ 'currency_name' => FUND_CURRENCY_TYPE::ZUANSHI->getCurrencyName(),
|
|
|
+ 'precision' => FUND_CURRENCY_TYPE::ZUANSHI->getPrecision(),
|
|
|
+ ];
|
|
|
+
|
|
|
+ return $this->successResponse('获取提取账户余额成功', $responseData);
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error('获取提取账户余额失败', [
|
|
|
+ 'app_id' => $app->id,
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return $this->errorResponse('获取账户信息失败', $e->getMessage(), 500);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|