Commet
  • Pricing
Log InTry out
Introduction

Quickstart

Integrate with PHPIntegrate with LaravelIntegrate with Symfony

Learn

Resources

SDK ReferenceError HandlingTestingCLI

Plugins

Better Auth
DocumentationKnowledge BaseBuild with AIAPI ReferenceWebhooks

Integrate with Laravel

Add billing and payments to your Laravel application.

Install

composer require commet/commet-php

Configure

.env
COMMET_API_KEY=ck_sandbox_xxx
COMMET_WEBHOOK_SECRET=whsec_xxx
app/Providers/AppServiceProvider.php
<?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'),
                environment: app()->environment('production') ? 'live' : 'sandbox',
            );
        });
    }
}
config/services.php
'commet' => [
    'api_key' => env('COMMET_API_KEY'),
    'webhook_secret' => env('COMMET_WEBHOOK_SECRET'),
],

Subscribe

app/Http/Controllers/BillingController.php
<?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',
            'external_id' => 'required|string',
        ]);

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

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

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

Check Access

app/Http/Controllers/BillingController.php
public function getSubscription(string $externalId): JsonResponse
{
    $subscription = $this->commet->subscriptions->get(externalId: $externalId);

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

public function checkFeature(string $feature, string $externalId): JsonResponse
{
    $result = $this->commet->features->check(code: $feature, externalId: $externalId);

    return response()->json([
        'allowed' => $result->data['allowed'],
    ]);
}

Track Usage

app/Http/Controllers/BillingController.php
public function trackUsage(Request $request): JsonResponse
{
    $request->validate([
        'external_id' => 'required|string',
    ]);

    $this->commet->usage->track(
        externalId: $request->input('external_id'),
        feature: 'api_calls',
        value: 1,
    );

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

Usage is aggregated and billed at end of period.

Customer Portal

app/Http/Controllers/BillingController.php
use Illuminate\Http\RedirectResponse;

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

    return redirect($result->data['portal_url']);
}

Webhooks

app/Http/Controllers/WebhookController.php
<?php

namespace App\Http\Controllers;

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

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

        $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
    {
        // handle activation
    }

    private function handleCanceled(array $payload): void
    {
        // handle cancellation
    }
}

Exclude the webhook route from CSRF verification:

bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'webhooks/commet',
    ]);
})

Routes

routes/api.php
<?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/{externalId}', [BillingController::class, 'getSubscription']);
Route::get('/billing/features/{feature}/{externalId}', [BillingController::class, 'checkFeature']);
Route::post('/billing/usage', [BillingController::class, 'trackUsage']);
Route::get('/billing/portal', [BillingController::class, 'portal']);
Route::post('/webhooks/commet', [WebhookController::class, 'handle']);

Related

  • Subscriptions
  • Track Usage
  • Customer Portal
  • SDK Reference

How is this guide?

Integrate with PHP

Install and configure the Commet PHP SDK.

Integrate with Symfony

Add billing and payments to your Symfony application.

On this page

Install
Configure
Subscribe
Check Access
Track Usage
Customer Portal
Webhooks
Routes
Related