Integrate with Symfony
Add billing and payments to your Symfony application.
Install
composer require commet/commet-phpConfigure
COMMET_API_KEY=ck_sandbox_xxx
COMMET_WEBHOOK_SECRET=whsec_xxxservices:
Commet\Commet:
factory: ['@App\Factory\CommetFactory', 'create']
App\Factory\CommetFactory:
arguments:
$apiKey: '%env(COMMET_API_KEY)%'
$environment: '%kernel.environment%'<?php
namespace App\Factory;
use Commet\Commet;
class CommetFactory
{
public function __construct(
private string $apiKey,
private string $environment,
) {}
public function create(): Commet
{
return new Commet(
apiKey: $this->apiKey,
environment: $this->environment === 'prod' ? 'live' : 'sandbox',
);
}
}Subscribe
<?php
namespace App\Controller;
use Commet\Commet;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
class BillingController extends AbstractController
{
public function __construct(
private Commet $commet,
) {}
#[Route('/billing/subscribe', methods: ['POST'])]
public function subscribe(Request $request): JsonResponse
{
$data = $request->toArray();
$this->commet->customers->create(
email: $data['email'],
externalId: $data['external_id'],
);
$subscription = $this->commet->subscriptions->create(
externalId: $data['external_id'],
planCode: 'pro',
);
return $this->json([
'checkout_url' => $subscription->data['checkout_url'],
]);
}
}Check Access
#[Route('/billing/subscription/{externalId}', methods: ['GET'])]
public function getSubscription(string $externalId): JsonResponse
{
$subscription = $this->commet->subscriptions->get(externalId: $externalId);
return $this->json([
'status' => $subscription->data['status'],
]);
}
#[Route('/billing/features/{feature}/{externalId}', methods: ['GET'])]
public function checkFeature(string $feature, string $externalId): JsonResponse
{
$result = $this->commet->features->check(code: $feature, externalId: $externalId);
return $this->json([
'allowed' => $result->data['allowed'],
]);
}Track Usage
#[Route('/billing/usage', methods: ['POST'])]
public function trackUsage(Request $request): JsonResponse
{
$data = $request->toArray();
$this->commet->usage->track(
externalId: $data['external_id'],
feature: 'api_calls',
value: 1,
);
return $this->json(['tracked' => true]);
}Usage is aggregated and billed at end of period.
Customer Portal
use Symfony\Component\HttpFoundation\RedirectResponse;
#[Route('/billing/portal', methods: ['GET'])]
public function portal(): RedirectResponse
{
$result = $this->commet->portal->getUrl(externalId: 'user_123');
return $this->redirect($result->data['portal_url']);
}Webhooks
<?php
namespace App\Controller;
use Commet\Webhooks;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class WebhookController extends AbstractController
{
public function __construct(
#[Autowire(env: 'COMMET_WEBHOOK_SECRET')]
private string $webhookSecret,
) {}
#[Route('/webhooks/commet', methods: ['POST'])]
public function handle(Request $request): JsonResponse|Response
{
$webhooks = new Webhooks();
$payload = $webhooks->verifyAndParse(
rawBody: $request->getContent(),
signature: $request->headers->get('x-commet-signature'),
secret: $this->webhookSecret,
);
if ($payload === null) {
return new Response('Invalid signature', 401);
}
match ($payload['event']) {
'subscription.activated' => $this->handleActivated($payload),
'subscription.canceled' => $this->handleCanceled($payload),
default => null,
};
return $this->json(['ok' => true]);
}
private function handleActivated(array $payload): void
{
// handle activation
}
private function handleCanceled(array $payload): void
{
// handle cancellation
}
}Related
How is this guide?