> ## Documentation Index
> Fetch the complete documentation index at: https://commet.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrar con Laravel

> Agrega cobros y pagos a tu aplicación de Laravel.

Instala la Commet Skill para que tu agente integre el SDK actual y valide su trabajo contra el contrato vivo de la API.

```bash theme={null}
npx skills add commet-labs/skills --skill commet
```

<Steps>
  <Step title="Instalar">
    ```bash theme={null}
    composer require commet/commet-php
    ```
  </Step>

  <Step title="Configurar">
    ```bash title=".env" theme={null}
    COMMET_API_KEY=ck_sandbox_xxx
    COMMET_WEBHOOK_SECRET=whsec_xxx
    ```

    ```php title="app/Providers/AppServiceProvider.php" theme={null}
    <?php

    namespace App\Providers;

    use Commet\Commet;
    use Illuminate\Support\ServiceProvider;

    class AppServiceProvider extends ServiceProvider
    {
        public function register(): void
        {
            $this->app->singleton(Commet::class, function () {
                return new Commet(
                    apiKey: config('services.commet.api_key'),
                );
            });
        }
    }
    ```

    ```php title="config/services.php" theme={null}
    'commet' => [
        'api_key' => env('COMMET_API_KEY'),
        'webhook_secret' => env('COMMET_WEBHOOK_SECRET'),
    ],
    ```
  </Step>

  <Step title="Suscribir">
    ```php title="app/Http/Controllers/BillingController.php" theme={null}
    <?php

    namespace App\Http\Controllers;

    use Commet\Commet;
    use Illuminate\Http\JsonResponse;
    use Illuminate\Http\Request;

    class BillingController extends Controller
    {
        public function __construct(
            private Commet $commet,
        ) {}

        public function subscribe(Request $request): JsonResponse
        {
            $request->validate([
                'email' => 'required|email',
                'customer_id' => 'required|string',
            ]);

            $this->commet->customers->create(
                email: $request->input('email'),
                id: $request->input('customer_id'),
            );

            $subscription = $this->commet->subscriptions->create(
                customerId: $request->input('customer_id'),
                planCode: 'pro',
            );

            return response()->json([
                'checkout_url' => $subscription->checkoutUrl,
            ]);
        }
    }
    ```
  </Step>

  <Step title="Verificar acceso">
    ```php title="app/Http/Controllers/BillingController.php" theme={null}
    public function getSubscription(string $customerId): JsonResponse
    {
        $subscription = $this->commet->subscriptions->getActive($customerId);

        if ($subscription === null) {
            return response()->json(['error' => 'no_active_subscription'], 404);
        }

        return response()->json([
            'status' => $subscription->status->value,
        ]);
    }

    public function checkFeature(string $feature, string $customerId): JsonResponse
    {
        $result = $this->commet->featureAccess->get(code: $feature, customerId: $customerId);

        return response()->json([
            'allowed' => $result->allowed,
        ]);
    }
    ```
  </Step>

  <Step title="Trackear uso">
    ```php title="app/Http/Controllers/BillingController.php" theme={null}
    public function trackUsage(Request $request): JsonResponse
    {
        $request->validate([
            'customer_id' => 'required|string',
        ]);

        $this->commet->usage->track(
            customerId: $request->input('customer_id'),
            featureCode: 'api_calls',
            value: 1,
        );

        return response()->json(['tracked' => true]);
    }
    ```

    El uso se agrega y se cobra al final del período.
  </Step>

  <Step title="Portal del Cliente">
    ```php title="app/Http/Controllers/BillingController.php" theme={null}
    use Illuminate\Http\RedirectResponse;

    public function portal(): RedirectResponse
    {
        $result = $this->commet->portal->getUrl(customerId: 'user_123');

        return redirect($result->portalUrl);
    }
    ```
  </Step>

  <Step title="Webhooks">
    ```php title="app/Http/Controllers/WebhookController.php" theme={null}
    <?php

    namespace App\Http\Controllers;

    use Commet\Resources\WebhooksResource;
    use Illuminate\Http\JsonResponse;
    use Illuminate\Http\Request;

    class WebhookController extends Controller
    {
        public function handle(Request $request): JsonResponse
        {
            $webhooks = new WebhooksResource();

            $payload = $webhooks->verifyAndParse(
                rawBody: $request->getContent(),
                signature: $request->header('x-commet-signature'),
                secret: config('services.commet.webhook_secret'),
            );

            if ($payload === null) {
                return response()->json(['error' => 'Invalid signature'], 401);
            }

            match ($payload['event']) {
                'subscription.activated' => $this->handleActivated($payload),
                'subscription.canceled' => $this->handleCanceled($payload),
                default => null,
            };

            return response()->json(['ok' => true]);
        }

        private function handleActivated(array $payload): void
        {
            // manejar activación
        }

        private function handleCanceled(array $payload): void
        {
            // manejar cancelación
        }
    }
    ```

    Excluye la ruta del webhook de la verificación CSRF:

    ```php title="bootstrap/app.php" theme={null}
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->validateCsrfTokens(except: [
            'webhooks/commet',
        ]);
    })
    ```
  </Step>

  <Step title="Rutas">
    ```php title="routes/api.php" theme={null}
    <?php

    use App\Http\Controllers\BillingController;
    use App\Http\Controllers\WebhookController;
    use Illuminate\Support\Facades\Route;

    Route::post('/billing/subscribe', [BillingController::class, 'subscribe']);
    Route::get('/billing/subscription/{customerId}', [BillingController::class, 'getSubscription']);
    Route::get('/billing/features/{feature}/{customerId}', [BillingController::class, 'checkFeature']);
    Route::post('/billing/usage', [BillingController::class, 'trackUsage']);
    Route::get('/billing/portal', [BillingController::class, 'portal']);
    Route::post('/webhooks/commet', [WebhookController::class, 'handle']);
    ```
  </Step>
</Steps>

## Relacionado

* [Suscripciones](/docs/es/manage-subscriptions)
* [Trackear Uso](/docs/es/track-usage)
* [Portal del Cliente](/docs/es/customer-portal)
* [Referencia del SDK](/docs/es/sdk-reference)


## Related topics

- [Integrar con PHP](/docs/es/integrate-with-php.md)
- [Integrar con Flask](/docs/es/integrate-with-flask.md)
- [Integrar con Java](/docs/es/integrate-with-java.md)
- [Integrar con Django](/docs/es/integrate-with-django.md)
- [Integrar con Encore](/docs/es/integrate-with-encore.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.