| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- <?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);
- }
- }
- }
|