| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- <?php
- namespace Controllers;
- use Libs\ResponseLib;
- use Models\CprModel;
- use Models\OrderbookModel;
- use Models\OrderbookTransferModel;
- use Models\PaymentModel;
- use Models\TokenModel;
- use Models\WalletModel;
- use Psr\Http\Message\ServerRequestInterface;
- use Respect\Validation\Exceptions\ValidationException;
- use Respect\Validation\Validator as val;
- use Services\TokenTransferService;
- class OrderbookTransferController
- {
- private PaymentModel $paymentModel;
- private WalletModel $walletModel;
- private OrderbookTransferModel $orderbookTransferModel;
- private TokenTransferService $tokenTransferService;
- private TokenModel $tokenModel;
- private CprModel $cprModel;
- public function __construct()
- {
- $this->paymentModel = new PaymentModel();
- $this->walletModel = new WalletModel();
- $this->orderbookTransferModel = new OrderbookTransferModel();
- $this->tokenTransferService = new TokenTransferService();
- $this->tokenModel = new TokenModel();
- $this->cprModel = new CprModel();
- }
- public function __invoke(ServerRequestInterface $request)
- {
- $body = json_decode((string)$request->getBody(), true) ?? [];
- try {
- val::key('external_id', val::stringType()->notEmpty())
- ->key('token_external_id', val::stringType()->notEmpty())
- ->assert($body);
- } catch (ValidationException $e) {
- return ResponseLib::sendFail('Validation failed: ' . $e->getFullMessage(), [], 'E_VALIDATE')->withStatus(400);
- }
- $externalId = trim((string)$body['external_id']);
- $tokenExternalId = trim((string)$body['token_external_id']);
- $companyId = (int)($request->getAttribute('api_company_id') ?? 0);
- if ($companyId <= 0) {
- return ResponseLib::sendFail('Empresa autenticada não encontrada', [], 'E_VALIDATE')->withStatus(401);
- }
- try {
- $payment = $this->paymentModel->findByExternalId($externalId);
- } catch (\Throwable $e) {
- return ResponseLib::sendFail('Falha ao consultar pagamento: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
- }
- if (!$payment) {
- return ResponseLib::sendFail('Pagamento não encontrado', ['external_id' => $externalId], 'E_NOT_FOUND')->withStatus(404);
- }
- if ((int)$payment['status_id'] !== PaymentModel::STATUS_COMPLETED) {
- return ResponseLib::sendFail('Pagamento ainda não concluído', ['external_id' => $externalId, 'status_id' => $payment['status_id']], 'E_PAYMENT_PENDING')->withStatus(409);
- }
- try {
- $orderbook = $this->orderbookTransferModel->getByTokenExternalId($tokenExternalId);
- } catch (\Throwable $e) {
- return ResponseLib::sendFail('Falha ao consultar orderbook: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
- }
- if (!$orderbook) {
- return ResponseLib::sendFail('Orderbook não encontrado', ['token_external_id' => $tokenExternalId], 'E_NOT_FOUND')->withStatus(404);
- }
- $tokenId = (int)($orderbook['token_id'] ?? 0);
- if ($tokenId <= 0) {
- return ResponseLib::sendFail('Orderbook sem token associado', [], 'E_ORDERBOOK_TOKEN')->withStatus(409);
- }
- try {
- $token = $this->tokenModel->findById($tokenId);
- } catch (\Throwable $e) {
- return ResponseLib::sendFail('Falha ao carregar token vinculado: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
- }
- if (!$token) {
- return ResponseLib::sendFail('Token associado ao orderbook não encontrado', ['token_id' => $tokenId], 'E_TOKEN_NOT_FOUND')->withStatus(404);
- }
- $cprId = (int)($token['cpr_id'] ?? 0);
- if ($cprId <= 0) {
- return ResponseLib::sendFail('Token não está vinculado a uma CPR', ['token_id' => $tokenId], 'E_CPR_NOT_FOUND')->withStatus(409);
- }
- if ((int)$orderbook['company_id'] !== $companyId) {
- return ResponseLib::sendFail('Orderbook não pertence à empresa autenticada', [], 'E_FORBIDDEN')->withStatus(403);
- }
- if ((int)$orderbook['status_id'] === OrderbookModel::STATUS_COMPLETED) {
- return ResponseLib::sendOk([
- 'orderbook_id' => (int)$orderbook['orderbook_id'],
- 'token_external_id' => $tokenExternalId,
- 'message' => 'Orderbook já transferido anteriormente',
- ], 'S_TOKEN_ALREADY_TRANSFERRED');
- }
- try {
- $wallet = $this->walletModel->getPrimaryWalletByCompanyId($companyId);
- } catch (\Throwable $e) {
- return ResponseLib::sendFail('Falha ao consultar carteira da empresa: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
- }
- if (!$wallet || empty($wallet['wallet_address'])) {
- return ResponseLib::sendFail('Carteira da empresa não encontrada', [], 'E_WALLET_NOT_FOUND')->withStatus(404);
- }
- $serverAddress = $this->resolveServerAddress();
- try {
- $transferResult = $this->tokenTransferService->transferFrom($serverAddress, (string)$wallet['wallet_address'], $tokenExternalId);
- $this->orderbookTransferModel->markCompleted((int)$orderbook['orderbook_id']);
- $this->cprModel->updateCompanyId($cprId, $companyId);
- } catch (\Throwable $e) {
- return ResponseLib::sendFail('Falha ao transferir token: ' . $e->getMessage(), [], 'E_TRANSFER')->withStatus(500);
- }
- return ResponseLib::sendOk([
- 'orderbook_id' => (int)$orderbook['orderbook_id'],
- 'token_external_id' => $tokenExternalId,
- 'destination_address' => (string)$wallet['wallet_address'],
- 'transfer_output' => $transferResult['output'] ?? '',
- 'transfer_error' => $transferResult['error'] ?? '',
- ], 'S_TOKEN_TRANSFERRED');
- }
- private function resolveServerAddress(): string
- {
- $address = $_ENV['SERVER_WALLET_ADDRESS'] ?? $_ENV['EASY_ADMIM_PUBLIC_KEY'] ?? '';
- $trimmed = trim((string)$address);
- if ($trimmed === '') {
- throw new \RuntimeException('Endereço do servidor (SERVER_WALLET_ADDRESS) não configurado.');
- }
- return $trimmed;
- }
- }
|