Browse Source

fix the orderbook transfer

gdias 1 week ago
parent
commit
6278e1453b

+ 9 - 2
controllers/OrderbookPaymentController.php

@@ -52,8 +52,15 @@ class OrderbookPaymentController
             return ResponseLib::sendFail('Valor do token inválido', ['orderbook_id' => $orderbookId], 'E_TOKEN_VALUE')->withStatus(422);
         }
 
+        $tokenExternalId = trim((string)($order['token_external_id'] ?? ''));
+        if ($tokenExternalId === '') {
+            return ResponseLib::sendFail('Orderbook sem token externo associado', ['orderbook_id' => $orderbookId], 'E_TOKEN_NOT_FOUND')->withStatus(409);
+        }
+
+        $paymentFlag = sprintf('orderbook:%d;token:%s', $orderbookId, $tokenExternalId);
+
         try {
-            $paymentData = $this->paymentService->initiatePayment((int)round($tokenValue * 100));
+            $paymentData = $this->paymentService->initiatePayment((int)round($tokenValue * 100), $paymentFlag);
         } catch (\Throwable $e) {
             return ResponseLib::sendFail('Falha ao iniciar pagamento: ' . $e->getMessage(), [], 'E_PAYMENT')->withStatus(500);
         }
@@ -63,7 +70,7 @@ class OrderbookPaymentController
             'payment_id' => $paymentData['payment_id'],
             'payment_code' => $paymentData['payment_code'],
             'payment_external_id' => $paymentData['payment_external_id'],
-            'token_external_id' => (string)($order['token_external_id'] ?? ''),
+            'token_external_id' => $tokenExternalId,
         ], 'S_ORDERBOOK_PAYMENT');
     }
 }

+ 49 - 14
controllers/OrderbookTransferController.php

@@ -23,9 +23,15 @@ class OrderbookTransferController
     private TokenModel $tokenModel;
     private CprModel $cprModel;
     private OrderbookModel $orderbookModel;
+    private \PDO $pdo;
 
     public function __construct()
     {
+        if (!isset($GLOBALS['pdo']) || !$GLOBALS['pdo'] instanceof \PDO) {
+            throw new \RuntimeException('Global PDO connection not initialized');
+        }
+
+        $this->pdo = $GLOBALS['pdo'];
         $this->paymentModel = new PaymentModel();
         $this->walletModel = new WalletModel();
         $this->orderbookTransferModel = new OrderbookTransferModel();
@@ -79,6 +85,36 @@ class OrderbookTransferController
             return ResponseLib::sendFail('Orderbook não encontrado', ['token_external_id' => $tokenExternalId], 'E_NOT_FOUND')->withStatus(404);
         }
 
+        if ((int)$orderbook['status_id'] !== OrderbookModel::STATUS_OPEN) {
+            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');
+            }
+
+            return ResponseLib::sendFail(
+                'Orderbook não está disponível para transferência',
+                ['orderbook_id' => (int)$orderbook['orderbook_id'], 'status_id' => $orderbook['status_id']],
+                'E_ORDERBOOK_STATUS'
+            )->withStatus(409);
+        }
+
+        $paymentFlag = trim((string)($payment['payment_flag'] ?? ''));
+        $expectedFlag = sprintf('orderbook:%d;token:%s', (int)$orderbook['orderbook_id'], $tokenExternalId);
+        if ($paymentFlag === '' || $paymentFlag !== $expectedFlag) {
+            return ResponseLib::sendFail(
+                'Pagamento não vinculado ao orderbook informado',
+                [
+                    'external_id' => $externalId,
+                    'payment_flag' => $paymentFlag,
+                    'expected' => $expectedFlag,
+                ],
+                'E_PAYMENT_MISMATCH'
+            )->withStatus(409);
+        }
+
         $tokenId = (int)($orderbook['token_id'] ?? 0);
         if ($tokenId <= 0) {
             return ResponseLib::sendFail('Orderbook sem token associado', [], 'E_ORDERBOOK_TOKEN')->withStatus(409);
@@ -109,14 +145,6 @@ class OrderbookTransferController
             return ResponseLib::sendFail('Carteira da empresa não encontrada', [], 'E_WALLET_NOT_FOUND')->withStatus(404);
         }
 
-        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');
-        }
-
         $serverAddress = $this->resolveServerAddress();
 
         try {
@@ -131,17 +159,24 @@ class OrderbookTransferController
         }
 
         try {
-            $this->orderbookModel->updateWalletId((int)$orderbook['orderbook_id'], (int)$wallet['wallet_id']);
-        } catch (\Throwable $e) {
-            return ResponseLib::sendFail('Falha ao registrar comprador no orderbook: ' . $e->getMessage(), [], 'E_ORDERBOOK_UPDATE')->withStatus(500);
-        }
+            $this->pdo->beginTransaction();
 
-        try {
+            $this->orderbookModel->updateWalletId((int)$orderbook['orderbook_id'], (int)$wallet['wallet_id']);
             $this->orderbookTransferModel->markCompleted((int)$orderbook['orderbook_id']);
             $this->tokenModel->updateWalletId($tokenId, (int)$wallet['wallet_id']);
             $this->cprModel->updateCompanyId($cprId, $companyId);
+
+            $this->pdo->commit();
         } catch (\Throwable $e) {
-            return ResponseLib::sendFail('Falha ao atualizar registros após transferência: ' . $e->getMessage(), [], 'E_TRANSFER_PERSIST')->withStatus(500);
+            if ($this->pdo->inTransaction()) {
+                $this->pdo->rollBack();
+            }
+
+            return ResponseLib::sendFail(
+                'Falha ao atualizar registros após transferência: ' . $e->getMessage(),
+                [],
+                'E_TRANSFER_PERSIST'
+            )->withStatus(500);
         }
 
         return ResponseLib::sendOk([

+ 15 - 0
controllers/WooviWebhookController.php

@@ -43,6 +43,14 @@ class WooviWebhookController
             return ResponseLib::sendFail('status inválido', [], 'E_VALIDATE')->withStatus(400);
         }
 
+        if (!$this->isPaidStatus($status)) {
+            return ResponseLib::sendOk([
+                'correlation_id' => $correlationId,
+                'status' => $status,
+                'updated' => false,
+            ], 'S_WEBHOOK_IGNORED');
+        }
+
         try {
             $payment = $this->paymentModel->findByExternalId($correlationId);
         } catch (\Throwable $e) {
@@ -64,6 +72,13 @@ class WooviWebhookController
             'correlation_id' => $correlationId,
             'status' => $status,
             'status_id' => 1,
+            'updated' => true,
         ], 'S_PAYMENT_UPDATED');
     }
+
+    private function isPaidStatus(string $status): bool
+    {
+        $normalized = strtoupper(trim($status));
+        return in_array($normalized, ['PAID', 'COMPLETED', 'CONFIRMED', 'APPROVED'], true);
+    }
 }

+ 2 - 2
services/PaymentService.php

@@ -19,7 +19,7 @@ class PaymentService
         $this->wooviCliPath = $wooviCliPath ?? $this->resolveWooviCliPath();
     }
 
-    public function initiatePayment(int $value): array
+    public function initiatePayment(int $value, ?string $paymentFlag = null): array
     {
         if ($value <= 0) {
             throw new \InvalidArgumentException('Payment value must be greater than zero');
@@ -35,7 +35,7 @@ class PaymentService
             $userId,
             null,
             '',
-            ''
+            $paymentFlag ?? ''
         );
 
         return [

+ 13 - 5
services/TokenTransferService.php

@@ -35,17 +35,25 @@ class TokenTransferService
         );
 
         $result = BashExecutor::run($command, 120);
+        $stdout = trim((string)($result['output'] ?? ''));
+        $stderr = trim((string)($result['error'] ?? ''));
+
+        $combinedOutput = trim(implode("\n", array_filter([$stdout, $stderr])));
+
         if (($result['exitCode'] ?? 1) !== 0) {
-            $message = $result['error'] ?: $result['output'] ?: 'Unknown easycli error';
+            $message = $combinedOutput !== '' ? $combinedOutput : 'Unknown easycli error';
             throw new \RuntimeException('easycli transfer failed: ' . $message);
         }
 
-        $output = trim((string)($result['output'] ?? ''));
-        $txHash = $this->extractHashFromOutput($output);
+        if ($combinedOutput !== '' && preg_match('/execution\s+reverted/i', $combinedOutput)) {
+            throw new \RuntimeException('easycli transfer failed: ' . $combinedOutput);
+        }
+
+        $txHash = $this->extractHashFromOutput($combinedOutput);
 
         return [
-            'output' => $output,
-            'error' => trim((string)($result['error'] ?? '')),
+            'output' => $stdout,
+            'error' => $stderr,
             'tx_hash' => $txHash,
         ];
     }