Prechádzať zdrojové kódy

Merge branch 'main' of ssh://git.mixtech.dev.br:22622/TooEasy/backend-php

gdias 3 týždňov pred
rodič
commit
74c1a554db

+ 13 - 3
bin/setup

@@ -175,9 +175,19 @@ WHERE c.company_name = 'LumyonTech'
 SQL
 
 run_psql "${DB_NAME}" -v ON_ERROR_STOP=1 <<SQL
-INSERT INTO "status" (status_status)
-SELECT 'PENDING'
-WHERE NOT EXISTS (SELECT 1 FROM "status" WHERE status_status = 'PENDING');
+INSERT INTO "status" (status_id, status_status) VALUES
+    (0, 'PENDING'),
+    (1, 'CONFIRMED'),
+    (2, 'EXPIRED')
+ON CONFLICT (status_id) DO UPDATE
+    SET status_status = EXCLUDED.status_status;
+SQL
+
+run_psql "${DB_NAME}" -v ON_ERROR_STOP=1 <<SQL
+SELECT setval(
+    pg_get_serial_sequence('"status"', 'status_id'),
+    GREATEST((SELECT COALESCE(MAX(status_id), 0) FROM "status"), 1)
+);
 SQL
 
 run_psql "${DB_NAME}" -v ON_ERROR_STOP=1 <<SQL

+ 0 - 0
controllers/PixQRController.php


+ 41 - 31
controllers/WooviWebhookController.php

@@ -3,10 +3,18 @@
 namespace Controllers;
 
 use Libs\ResponseLib;
+use Models\PaymentModel;
 use Psr\Http\Message\ServerRequestInterface;
 
 class WooviWebhookController
 {
+    private PaymentModel $paymentModel;
+
+    public function __construct()
+    {
+        $this->paymentModel = new PaymentModel();
+    }
+
     public function __invoke(ServerRequestInterface $request)
     {
         $rawBody = (string)$request->getBody();
@@ -14,46 +22,48 @@ class WooviWebhookController
             $rawBody = (string)file_get_contents('php://input');
         }
 
-        $record = [
-            'received_at' => (new \DateTimeImmutable('now', new \DateTimeZone('UTC')))->format(DATE_ATOM),
-            'headers' => $this->normalizeHeaders($request->getHeaders()),
-            'raw_body' => $rawBody,
-        ];
+        $payload = json_decode($rawBody, true);
+        if (!is_array($payload)) {
+            return ResponseLib::sendFail('Payload inválido', [], 'E_VALIDATE')->withStatus(400);
+        }
 
-        $fileName = sprintf(
-            'woovi_webhook_%s_%s.txt',
-            (new \DateTimeImmutable('now'))->format('Ymd_His'),
-            bin2hex(random_bytes(4))
-        );
+        $charge = $payload['charge'] ?? null;
+        if (!is_array($charge)) {
+            return ResponseLib::sendFail('Charge inválida', [], 'E_VALIDATE')->withStatus(400);
+        }
+
+        $correlationId = $charge['correlationID'] ?? null;
+        $status = $charge['status'] ?? null;
 
-        $filePath = dirname(__DIR__) . '/bin/' . $fileName;
+        if (!is_string($correlationId) || $correlationId === '') {
+            return ResponseLib::sendFail('correlationID inválido', [], 'E_VALIDATE')->withStatus(400);
+        }
+
+        if (!is_string($status) || $status === '') {
+            return ResponseLib::sendFail('status inválido', [], 'E_VALIDATE')->withStatus(400);
+        }
 
         try {
-            $encoded = json_encode($record, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
-            if ($encoded === false) {
-                $encoded = $rawBody;
-            }
-            file_put_contents($filePath, $encoded, LOCK_EX);
+            $payment = $this->paymentModel->findByExternalId($correlationId);
         } catch (\Throwable $e) {
-            return ResponseLib::sendFail('Falha ao salvar webhook: ' . $e->getMessage(), [], 'E_INTERNAL')->withStatus(500);
+            return ResponseLib::sendFail('Falha ao consultar pagamento: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
         }
 
-        return ResponseLib::sendOk([
-            'stored_file' => basename($filePath),
-        ], 'S_WEBHOOK_SAVED');
-    }
+        if (!$payment) {
+            return ResponseLib::sendFail('Pagamento não encontrado', ['correlation_id' => $correlationId], 'E_NOT_FOUND')->withStatus(404);
+        }
 
-    /**
-     * @param array<string, array<int, string>> $headers
-     * @return array<string, string>
-     */
-    private function normalizeHeaders(array $headers): array
-    {
-        $normalized = [];
-        foreach ($headers as $name => $values) {
-            $normalized[$name] = implode(', ', $values);
+        try {
+            $this->paymentModel->updateStatusId((int)$payment['payment_id'], 1);
+        } catch (\Throwable $e) {
+            return ResponseLib::sendFail('Falha ao atualizar pagamento: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500);
         }
 
-        return $normalized;
+        return ResponseLib::sendOk([
+            'payment_id' => (int)$payment['payment_id'],
+            'correlation_id' => $correlationId,
+            'status' => $status,
+            'status_id' => 1,
+        ], 'S_PAYMENT_UPDATED');
     }
 }

+ 22 - 0
models/PaymentModel.php

@@ -62,4 +62,26 @@ class PaymentModel
 
         return $record ?: null;
     }
+
+    public function findByExternalId(string $paymentExternalId): ?array
+    {
+        $stmt = $this->pdo->prepare(
+            'SELECT * FROM "payment" WHERE payment_external_id = :external_id LIMIT 1'
+        );
+        $stmt->execute(['external_id' => $paymentExternalId]);
+        $record = $stmt->fetch(\PDO::FETCH_ASSOC);
+
+        return $record ?: null;
+    }
+
+    public function updateStatusId(int $paymentId, int $statusId): void
+    {
+        $stmt = $this->pdo->prepare(
+            'UPDATE "payment" SET status_id = :status_id WHERE payment_id = :payment_id'
+        );
+        $stmt->execute([
+            'status_id' => $statusId,
+            'payment_id' => $paymentId,
+        ]);
+    }
 }