HOME


Mini Shell 1.0
DIR: /home/cardxfeb/public_html/app/Http/Controllers/Webhooks/
Upload File :
Current File : //home/cardxfeb/public_html/app/Http/Controllers/Webhooks/BrasilWebhookController.php
<?php

namespace App\Http\Controllers\Webhooks;

use App\Http\Controllers\Controller;
use App\Models\Vcard;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;

/**
 * Webhook handler for Brazilian payments (Asaas / PIX)
 * Route: POST /webhooks/brasil
 *
 * Asaas docs: https://docs.asaas.com/reference/webhooks
 */
class BrasilWebhookController extends Controller
{
    public function handle(Request $request): JsonResponse
    {
        // Validate Asaas token signature
        $token = $request->header('asaas-access-token')
               ?? $request->header('x-asaas-token');

        $expectedToken = config('services.asaas.webhook_token');

        if ($expectedToken && $token !== $expectedToken) {
            Log::warning('[BrasilWebhook] Invalid token: ' . $token);
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        $payload = $request->all();
        $event   = $payload['event'] ?? '';

        Log::info('[BrasilWebhook] Event: ' . $event, [
            'payment_id'    => $payload['payment']['id'] ?? null,
            'external_ref'  => $payload['payment']['externalReference'] ?? null,
        ]);

        return match ($event) {
            'PAYMENT_CONFIRMED',
            'PAYMENT_RECEIVED'  => $this->handlePaymentConfirmed($payload),
            'PAYMENT_OVERDUE'   => $this->handlePaymentOverdue($payload),
            'PAYMENT_DELETED',
            'PAYMENT_REFUNDED'  => $this->handlePaymentRefunded($payload),
            default              => response()->json(['status' => 'event_ignored']),
        };
    }

    private function handlePaymentConfirmed(array $payload): JsonResponse
    {
        $externalRef = $payload['payment']['externalReference'] ?? null;

        if (!$externalRef || !str_starts_with($externalRef, 'vcard_')) {
            Log::warning('[BrasilWebhook] Unknown externalReference: ' . $externalRef);
            return response()->json(['status' => 'skipped']);
        }

        $vcardId = (int) str_replace('vcard_', '', $externalRef);
        $vcard   = Vcard::withTrashed()->find($vcardId);

        if (!$vcard) {
            Log::error('[BrasilWebhook] VCard not found: #' . $vcardId);
            return response()->json(['error' => 'vcard_not_found'], 404);
        }

        // Activate the card
        $vcard->update([
            'status'           => 'active',
            'payment_deadline' => null,
            'nfc_status'       => $vcard->nfc_status === 'none' ? 'none' : 'pending',
        ]);

        // Restore if soft-deleted before payment
        if ($vcard->trashed()) {
            $vcard->restore();
        }

        Log::info("[BrasilWebhook] VCard#{$vcardId} ACTIVATED via PIX/Asaas");

        return response()->json(['status' => 'activated', 'vcard_id' => $vcardId]);
    }

    private function handlePaymentOverdue(array $payload): JsonResponse
    {
        $externalRef = $payload['payment']['externalReference'] ?? null;
        Log::warning('[BrasilWebhook] Payment OVERDUE: ' . $externalRef);
        return response()->json(['status' => 'noted']);
    }

    private function handlePaymentRefunded(array $payload): JsonResponse
    {
        $externalRef = $payload['payment']['externalReference'] ?? null;
        Log::info('[BrasilWebhook] Payment REFUNDED: ' . $externalRef);
        return response()->json(['status' => 'noted']);
    }
}