Browse Source

feat(company-payment-account): endpoints para a matriz configurar a própria chave Asaas

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ebagabee 4 weeks ago
parent
commit
47af112e21

+ 32 - 0
app/Http/Controllers/CompanyPaymentAccountController.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\CompanyPaymentAccountRequest;
+use App\Http\Resources\CompanyPaymentAccountResource;
+use App\Services\CompanyPaymentAccountService;
+use Illuminate\Http\JsonResponse;
+
+class CompanyPaymentAccountController extends Controller
+{
+    public function __construct(
+        protected CompanyPaymentAccountService $service,
+    ) {}
+
+    public function show(): JsonResponse
+    {
+        return $this->successResponse(
+            payload: new CompanyPaymentAccountResource($this->service->current()),
+        );
+    }
+
+    public function upsert(CompanyPaymentAccountRequest $request): JsonResponse
+    {
+        $item = $this->service->upsertAsaasApiKey($request->validated('asaas_api_key'));
+
+        return $this->successResponse(
+            payload: new CompanyPaymentAccountResource($item),
+            message: __('messages.updated'),
+        );
+    }
+}

+ 15 - 0
app/Http/Requests/CompanyPaymentAccountRequest.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CompanyPaymentAccountRequest extends FormRequest
+{
+    public function rules(): array
+    {
+        return [
+            'asaas_api_key' => 'present|nullable|string|max:500',
+        ];
+    }
+}

+ 26 - 0
app/Http/Resources/CompanyPaymentAccountResource.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+/**
+ * Nunca expõe a api_key em texto puro: apenas se está configurada e mascarada.
+ */
+class CompanyPaymentAccountResource extends JsonResource
+{
+    public function toArray(Request $request): array
+    {
+        $key = $this->asaas_api_key;
+
+        return [
+            'status'               => $this->status ?? 'pending',
+            'asaas_configured'     => filled($key),
+            'asaas_api_key_masked' => filled($key)
+                ? str_repeat('•', 8) . mb_substr($key, -4)
+                : null,
+            'onboarded_at'         => $this->onboarded_at?->format('Y-m-d H:i:s'),
+        ];
+    }
+}

+ 89 - 0
app/Services/CompanyPaymentAccountService.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace App\Services;
+
+use App\Exceptions\AsaasException;
+use App\Models\CompanyPaymentAccount;
+use App\Services\Integrations\Asaas\AsaasWebhookService;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Validation\ValidationException;
+
+/**
+ * Conta Asaas da franqueadora (matriz). Linha única, editável pela UI —
+ * a franqueadora pode trocar a própria chave sem depender do .env nem do suporte.
+ */
+class CompanyPaymentAccountService
+{
+    public function __construct(
+        protected AsaasWebhookService $webhookService,
+    ) {}
+
+    public function current(): CompanyPaymentAccount
+    {
+        return CompanyPaymentAccount::current();
+    }
+
+    public function upsertAsaasApiKey(?string $apiKey): CompanyPaymentAccount
+    {
+        $apiKey = $apiKey !== null ? trim($apiKey) : null;
+        $hasKey = $apiKey !== null && $apiKey !== '';
+
+        $model = CompanyPaymentAccount::current();
+
+        if (!$hasKey) {
+            $this->removeWebhook($model);
+
+            $model->asaas_api_key    = null;
+            $model->asaas_webhook_id = null;
+            $model->status           = CompanyPaymentAccount::STATUS_PENDING;
+            $model->onboarded_at     = null;
+            $model->save();
+
+            return $model->fresh();
+        }
+
+        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.',
+            ]);
+        }
+
+        $this->removeWebhook($model);
+
+        try {
+            $webhookId = $this->webhookService->register($apiKey);
+        } catch (AsaasException $e) {
+            Log::error('Falha ao registrar webhook Asaas da matriz: ' . $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           = CompanyPaymentAccount::STATUS_ACTIVE;
+        $model->onboarded_at     = $model->onboarded_at ?? now();
+        $model->save();
+
+        return $model->fresh();
+    }
+
+    private function removeWebhook(CompanyPaymentAccount $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 matriz: ' . $e->getMessage());
+        }
+    }
+}

+ 9 - 0
routes/authRoutes/company_payment_account.php

@@ -0,0 +1,9 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+use App\Http\Controllers\CompanyPaymentAccountController;
+
+Route::controller(CompanyPaymentAccountController::class)->prefix('company-payment-account')->group(function () {
+    Route::get('/', 'show')->middleware('permission:integrations,view');
+    Route::post('/', 'upsert')->middleware('permission:integrations,edit');
+});