|
|
@@ -2,9 +2,11 @@
|
|
|
|
|
|
namespace App\Services\Integrations\Asaas;
|
|
|
|
|
|
+use App\Exceptions\AsaasException;
|
|
|
use App\Models\Unit;
|
|
|
use App\Models\UnitPaymentAccount;
|
|
|
use Exception;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
class AsaasAccountService
|
|
|
{
|
|
|
@@ -27,6 +29,13 @@ public function ensureSubaccount(Unit $unit): UnitPaymentAccount
|
|
|
throw new Exception("A unidade {$unit->fantasy_name} não possui um CNPJ cadastrado. O CNPJ é obrigatório para criar a subconta.");
|
|
|
}
|
|
|
|
|
|
+ // Garante a chave de criptografia ANTES de chamar o Asaas. Sem APP_KEY, o
|
|
|
+ // POST cria a subconta lá, mas o save local falha ao encriptar a apiKey
|
|
|
+ // (cast 'encrypted') -> subconta órfã: apiKey perdida e e-mail/CNPJ travados.
|
|
|
+ if (empty(config('app.key'))) {
|
|
|
+ throw new Exception("APP_KEY não configurada. Abortando antes de criar a subconta no Asaas para evitar conta órfã (Unidade {$unit->id}).");
|
|
|
+ }
|
|
|
+
|
|
|
$payload = [
|
|
|
'name' => $unit->fantasy_name ?? $unit->social_reason ?? 'Unidade Ginástica do Cérebro',
|
|
|
'email' => $unit->email,
|
|
|
@@ -40,17 +49,53 @@ public function ensureSubaccount(Unit $unit): UnitPaymentAccount
|
|
|
'incomeValue' => 10000.00, // Renda/Faturamento exigido pelo Asaas
|
|
|
];
|
|
|
|
|
|
- $response = $this->client->post('/accounts', $payload);
|
|
|
+ try {
|
|
|
+ $response = $this->client->post('/accounts', $payload);
|
|
|
+ } catch (AsaasException $e) {
|
|
|
+ // Colisão de e-mail (400): diagnostica se a conta é SUA (órfã, recuperável
|
|
|
+ // só pelo painel) ou EXTERNA (e-mail em uso fora do seu parent -> trocar e-mail).
|
|
|
+ if ($e->getCode() === 400 && str_contains($e->getMessage(), 'já está em uso')) {
|
|
|
+ $this->logEmailCollision($unit);
|
|
|
+ }
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
|
|
|
return UnitPaymentAccount::updateOrCreate(
|
|
|
['unit_id' => $unit->id],
|
|
|
[
|
|
|
'asaas_account_id' => $response['id'],
|
|
|
'asaas_wallet_id' => $response['walletId'],
|
|
|
+ // Cast 'encrypted' do model encripta no save; e SyncStudentChargeJob
|
|
|
+ // espera mais uma camada manual. Mantém o encryptString para casar.
|
|
|
'asaas_api_key' => \Illuminate\Support\Facades\Crypt::encryptString($response['apiKey']),
|
|
|
'status' => 'ACTIVE',
|
|
|
'onboarded_at' => now(),
|
|
|
]
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Loga, no erro de e-mail em uso, se a conta colidente pertence ao seu parent
|
|
|
+ * (subconta órfã) ou é externa — para acelerar o diagnóstico.
|
|
|
+ */
|
|
|
+ private function logEmailCollision(Unit $unit): void
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ $accounts = $this->client->get('/accounts', ['email' => $unit->email])['data'] ?? [];
|
|
|
+
|
|
|
+ if (count($accounts) > 0) {
|
|
|
+ Log::warning("Asaas: e-mail {$unit->email} já é uma SUBCONTA SUA (órfã). Recuperável só pelo painel/encerramento.", [
|
|
|
+ 'unit_id' => $unit->id,
|
|
|
+ 'asaas_account_id' => $accounts[0]['id'] ?? null,
|
|
|
+ 'wallet_id' => $accounts[0]['walletId'] ?? null,
|
|
|
+ ]);
|
|
|
+ } else {
|
|
|
+ Log::warning("Asaas: e-mail {$unit->email} está em uso em conta EXTERNA (fora do seu parent). Cadastre a unidade com outro e-mail.", [
|
|
|
+ 'unit_id' => $unit->id,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ } catch (\Throwable $t) {
|
|
|
+ // Diagnóstico é best-effort: nunca mascara o erro original do POST.
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|