Răsfoiți Sursa

feat(unit-payment-account): valida chave e registra webhook ao salvar; remove ao limpar

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ebagabee 4 săptămâni în urmă
părinte
comite
d35f41cde7
1 a modificat fișierele cu 66 adăugiri și 4 ștergeri
  1. 66 4
      app/Services/UnitPaymentAccountService.php

+ 66 - 4
app/Services/UnitPaymentAccountService.php

@@ -2,10 +2,18 @@
 
 namespace App\Services;
 
+use App\Exceptions\AsaasException;
 use App\Models\UnitPaymentAccount;
+use App\Services\Integrations\Asaas\AsaasWebhookService;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Validation\ValidationException;
 
 class UnitPaymentAccountService
 {
+    public function __construct(
+        protected AsaasWebhookService $webhookService,
+    ) {}
+
     public function getByUnitId(int $unitId): ?UnitPaymentAccount
     {
         return UnitPaymentAccount::where('unit_id', $unitId)->first();
@@ -14,7 +22,8 @@ public function getByUnitId(int $unitId): ?UnitPaymentAccount
     /**
      * Cria/atualiza a conta de pagamento da unidade.
      *
-     * Quando a chave vem vazia, a integração é considerada limpa (status pending).
+     * Ao informar uma chave: valida na Asaas e registra o webhook (síncrono e
+     * estrito — chave inválida bloqueia). Ao limpar: remove o webhook (best-effort).
      */
     public function upsertAsaasApiKey(int $unitId, ?string $apiKey): UnitPaymentAccount
     {
@@ -23,12 +32,65 @@ public function upsertAsaasApiKey(int $unitId, ?string $apiKey): UnitPaymentAcco
 
         $model = UnitPaymentAccount::firstOrNew(['unit_id' => $unitId]);
 
-        $model->asaas_api_key = $hasKey ? $apiKey : null;
-        $model->status        = $hasKey ? UnitPaymentAccount::STATUS_ACTIVE : UnitPaymentAccount::STATUS_PENDING;
-        $model->onboarded_at  = $hasKey ? ($model->onboarded_at ?? now()) : null;
+        if (!$hasKey) {
+            $this->removeWebhook($model);
+
+            $model->asaas_api_key    = null;
+            $model->asaas_webhook_id = null;
+            $model->status           = UnitPaymentAccount::STATUS_PENDING;
+            $model->onboarded_at     = null;
+            $model->save();
+
+            return $model->fresh();
+        }
+
+        // Reenvio da mesma chave já configurada: mantém como está.
+        if ($model->exists && $model->asaas_api_key === $apiKey && $model->asaas_webhook_id) {
+            return $model->fresh();
+        }
+
+        try {
+            $this->webhookService->validateKey($apiKey);
+        } catch (AsaasException $e) {
+            throw ValidationException::withMessages([
+                'asaas_api_key' => 'Chave Asaas inválida ou sem permissão. Verifique e tente novamente.',
+            ]);
+        }
+
+        // Troca de chave: remove o webhook antigo antes de registrar o novo.
+        $this->removeWebhook($model);
+
+        try {
+            $webhookId = $this->webhookService->register($apiKey);
+        } catch (AsaasException $e) {
+            Log::error("Falha ao registrar webhook Asaas da unidade {$unitId}: " . $e->getMessage());
+            throw ValidationException::withMessages([
+                'asaas_api_key' => 'Não foi possível registrar o webhook na Asaas. Tente novamente.',
+            ]);
+        }
 
+        $model->asaas_api_key    = $apiKey;
+        $model->asaas_webhook_id = $webhookId;
+        $model->status           = UnitPaymentAccount::STATUS_ACTIVE;
+        $model->onboarded_at     = $model->onboarded_at ?? now();
         $model->save();
 
         return $model->fresh();
     }
+
+    /**
+     * Remove o webhook atual da conta (ignora erros — best-effort).
+     */
+    private function removeWebhook(UnitPaymentAccount $model): void
+    {
+        if (!$model->asaas_api_key || !$model->asaas_webhook_id) {
+            return;
+        }
+
+        try {
+            $this->webhookService->delete($model->asaas_api_key, $model->asaas_webhook_id);
+        } catch (\Throwable $e) {
+            Log::warning("Não foi possível remover webhook Asaas da unidade {$model->unit_id}: " . $e->getMessage());
+        }
+    }
 }