Installation
composer require aziz403/ux-zoom
Add the bundle to config/bundles.php:
return [
// ...
Aziz403\UxZoom\UxZoomBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console config:dump-reference Aziz403\UxZoomBundle
Update config/packages/ux_zoom.yaml with your Zoom API credentials:
ux_zoom:
api_key: '%env(ZOOM_API_KEY)%'
api_secret: '%env(ZOOM_API_SECRET)%'
First Use Case: Embedding a Meeting
Use the UxZoomMeetingEmbed component in Twig:
{{ render(controller('Aziz403\\UxZoom\\Controller\\MeetingController::embedMeetingAction', {
'meetingId': '1234567890',
'meetingSecret': 'your_meeting_secret'
})) }}
Meeting Creation
Use the ZoomService to create meetings programmatically:
$zoomService = $this->container->get('ux_zoom.zoom_service');
$meeting = $zoomService->createMeeting([
'topic' => 'Team Sync',
'type' => 2, // Scheduled
'start_time' => '2023-12-25T10:00:00',
'duration' => 60,
]);
Webhook Handling
Register a route for Zoom webhooks (e.g., meeting.started):
# config/routes.yaml
ux_zoom_webhook:
path: /zoom/webhook
controller: Aziz403\UxZoom\Controller\WebhookController::handle
Validate payloads in your controller:
public function handle(Request $request, ZoomService $zoomService)
{
$payload = json_decode($request->getContent(), true);
if (!$zoomService->validateWebhook($payload)) {
throw new \RuntimeException('Invalid webhook signature');
}
// Process event...
}
Twig Integration Pass meeting data to templates:
return $this->render('meeting/show.html.twig', [
'meeting' => $meeting,
'joinUrl' => $zoomService->getJoinUrl($meeting),
]);
Use Twig helpers for embeds:
{{ ux_zoom_embed(meeting) }}
Environment Variables
Store sensitive keys in .env:
ZOOM_API_KEY=your_api_key
ZOOM_API_SECRET=your_api_secret
ZOOM_WEBHOOK_SECRET=your_webhook_secret
Dependency Injection
Bind the ZoomService to your controllers/services:
use Aziz403\UxZoom\Service\ZoomService;
public function __construct(private ZoomService $zoomService) {}
Event Listeners
Subscribe to Zoom events (e.g., MeetingCreatedEvent):
// src/EventListener/MeetingListener.php
public function onMeetingCreated(MeetingCreatedEvent $event)
{
// Send notification, log, etc.
}
Register in services.yaml:
services:
App\EventListener\MeetingListener:
tags:
- { name: kernel.event_listener, event: ux_zoom.meeting.created }
Webhook Validation
ZOOM_WEBHOOK_SECRET is misconfigured or the request timestamp is out of sync.Meeting Secrets
meetingSecret in templates exposes security risks.ZoomService:
$meetingSecret = $zoomService->getMeetingSecret($meetingId);
Rate Limiting
429 errors.try {
$zoomService->createMeeting($data);
} catch (\GuzzleHttp\Exception\RequestException $e) {
if ($e->getCode() === 429) {
sleep(2); // Retry after delay
retry();
}
}
Deprecated Methods
^4.4.17).config/services.yaml to enforce stricter types:
Aziz403\UxZoom\Service\ZoomService:
arguments:
$client: '@http_client' # Use Symfony's HTTP client
Enable API Logging Configure Guzzle middleware to log requests:
// config/packages/ux_zoom.yaml
ux_zoom:
debug: true
Check logs in var/log/dev.log for API responses/errors.
Test Webhooks Locally
Use ngrok to expose a local endpoint for testing:
ngrok http 8000
Configure the Zoom app to send webhooks to https://your-ngrok-url.ngrok.io/zoom/webhook.
Validate API Responses Inspect raw responses for errors:
$response = $zoomService->createMeeting($data);
if ($response->getStatusCode() !== 201) {
$error = json_decode($response->getBody(), true);
throw new \RuntimeException($error['message'] ?? 'Unknown error');
}
Custom Meeting Fields
Extend the Meeting entity by overriding the service:
// src/Service/CustomZoomService.php
class CustomZoomService extends \Aziz403\UxZoom\Service\ZoomService
{
public function createMeeting(array $data): Meeting
{
$data['custom_field'] = 'value'; // Add custom data
return parent::createMeeting($data);
}
}
Bind it in services.yaml:
services:
ux_zoom.zoom_service:
class: App\Service\CustomZoomService
Add Event Subscribers Extend the bundle’s event system:
// src/EventSubscriber/ZoomSubscriber.php
class ZoomSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'ux_zoom.meeting.created' => 'onMeetingCreated',
];
}
public function onMeetingCreated(MeetingCreatedEvent $event)
{
// Custom logic
}
}
Override Twig Functions
Replace the default ux_zoom_embed function:
{% macro customEmbed(meeting) %}
<div class="custom-zoom-embed">
{{- include('Aziz403UxZoom::meeting/embed.html.twig', {
meeting: meeting,
joinUrl: app.service('ux_zoom.zoom_service').getJoinUrl(meeting)
}) -}}
</div>
{% endmacro %}
How can I help you explore Laravel packages today?