amaizing-company/laravel-zava-video-call-client

Zava videocall api client package for laravel.

v1.0.0 2025-08-09 01:09 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

A Laravel package that provides a convenient and robust client for integrating with the Zava Videocall API. This package allows you to easily manage users, appointments, and attendees for video consultations in your Laravel application.

Features

  • User management (create, update, delete, list)
  • Appointment management (create, update, delete, get, list)
  • Attendee management for appointments
  • Meeting URL generation for both users and attendees
  • Event system for appointment lifecycle
  • Optimized token caching with automatic refresh
  • Configurable retry mechanism for failed API requests
  • Rate limiting support

Installation

You can install the package via composer:

composer require amaizing-company/zava-video-call-client

Configuration

You can publish the config file with:

php artisan vendor:publish --tag="zava-video-call-client-config"

This is the contents of the published config file:

return [
    'client_id' => env('ZAVA_CLIENT_ID'),
    'client_secret' => env('ZAVA_CLIENT_SECRET'),
    'owner_id' => env('ZAVA_OWNER_ID'),
    'organisation_id' => env('ZAVA_ORGANISATION_ID'),
    
    'urls' => [
        'auth' => env('ZAVA_AUTH_URL', 'https://identity.sandbox.sprechstunde.online'),
        'base' => env('ZAVA_BASE_URL', 'https://app.sandbox.sprechstunde.online/api/v2'),
        'user_video_service' => env('ZAVA_USER_VIDEO_SERVICE_URL', 'https://app.sprechstunde.online/video-service'),
        'attendee_video_service' => env('ZAVA_ATTENDEE_VIDEO_SERVICE_URL', 'https://app.sprechstunde.online/attendee/session'),
    ],
    
    // Token management configuration
    'token' => [
        'refresh_threshold' => env('ZAVA_TOKEN_REFRESH_THRESHOLD', 0.8),
    ],
    
    // Retry configuration for failed API requests
    'retry' => [
        'max_attempts' => env('ZAVA_RETRY_MAX_ATTEMPTS', 3),
        'base_delay' => env('ZAVA_RETRY_BASE_DELAY', 100), // in milliseconds
        'max_delay' => env('ZAVA_RETRY_MAX_DELAY', 1000), // in milliseconds
        'retryable_status_codes' => [408, 429, 500, 502, 503, 504],
        'retryable_exceptions' => [
            \Illuminate\Http\Client\ConnectionException::class,
            \AmaizingCompany\ZavaVideoCallClient\Exceptions\NetworkException::class,
            \AmaizingCompany\ZavaVideoCallClient\Exceptions\ServerException::class,
            \AmaizingCompany\ZavaVideoCallClient\Exceptions\RateLimitException::class,
        ],
    ],
    
    // Rate limiting configuration
    'rate_limiting' => [
        'enabled' => env('ZAVA_RATE_LIMITING_ENABLED', true),
        'max_requests' => env('ZAVA_RATE_LIMITING_MAX_REQUESTS', 60),
        'window' => env('ZAVA_RATE_LIMITING_WINDOW', 60), // in seconds
    ],
];

Environment Variables

Add the following environment variables to your .env file:

ZAVA_CLIENT_ID=your-client-id
ZAVA_CLIENT_SECRET=your-client-secret
ZAVA_OWNER_ID=your-owner-id
ZAVA_ORGANISATION_ID=your-organisation-id

# Optional: Override default URLs if needed
ZAVA_AUTH_URL=https://identity.sandbox.sprechstunde.online
ZAVA_BASE_URL=https://app.sandbox.sprechstunde.online/api/v2
ZAVA_USER_VIDEO_SERVICE_URL=https://app.sprechstunde.online/video-service
ZAVA_ATTENDEE_VIDEO_SERVICE_URL=https://app.sprechstunde.online/attendee/session

# Optional: Configure token refresh behavior
ZAVA_TOKEN_REFRESH_THRESHOLD=0.8

# Optional: Configure retry behavior
ZAVA_RETRY_MAX_ATTEMPTS=3
ZAVA_RETRY_BASE_DELAY=100
ZAVA_RETRY_MAX_DELAY=1000

# Optional: Configure rate limiting
ZAVA_RATE_LIMITING_ENABLED=true
ZAVA_RATE_LIMITING_MAX_REQUESTS=60
ZAVA_RATE_LIMITING_WINDOW=60

Usage

Basic Usage

use AmaizingCompany\ZavaVideoCallClient\ZavaVideoCallClient;

// The client is automatically registered in the service container
$client = app(ZavaVideoCallClient::class);

// Or you can use the facade
use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

$appointments = ZavaVideoCallClient::listAppointments();

User Management

Creating a User

use AmaizingCompany\ZavaVideoCallClient\DataObjects\User;
use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Create a user object
$user = new User(
    email: 'doctor@example.com',
    title: 'Dr.',
    firstName: 'John',
    lastName: 'Doe',
    occupation: 'General Practitioner'
);

// Optionally add a profile image
$profileImageContents = file_get_contents('path/to/profile-image.jpg');
$user->profileImage($profileImageContents);

// Create the user in Zava
$response = ZavaVideoCallClient::createUser($user);

// Get the user ID from the response
$userId = $response->getUserId();

Updating a User

use AmaizingCompany\ZavaVideoCallClient\DataObjects\User;
use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Create a user object with updated information
$user = new User(
    email: 'doctor@example.com',
    title: 'Dr.',
    firstName: 'John',
    lastName: 'Smith', // Updated last name
    occupation: 'Cardiologist' // Updated occupation
);

// Update the user in Zava
$response = ZavaVideoCallClient::updateUser('user-id', $user);

Deleting a User

use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Delete the user from Zava
$response = ZavaVideoCallClient::deleteUser('user-id');

Listing All Users

use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Get all users
$response = ZavaVideoCallClient::listUsers();
$users = $response->getUsers();

foreach ($users as $user) {
    echo $user->getId() . ': ' . $user->getFirstName() . ' ' . $user->getLastName();
}

Appointment Management

Creating an Appointment

use AmaizingCompany\ZavaVideoCallClient\DataObjects\Appointment;
use AmaizingCompany\ZavaVideoCallClient\DataObjects\Attendee;
use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;
use Illuminate\Support\Carbon;

// Create an appointment
$appointment = new Appointment(
    startDate: Carbon::now()->addHour(),
    endDate: Carbon::now()->addHour()->addMinutes(30),
    subject: 'Medical Consultation'
);

// Add a description
$appointment->description('Regular check-up appointment');

// Add metadata if needed
$appointment->metadata([
    'reference_id' => '12345',
    'department' => 'Cardiology',
]);

// Add an attendee (patient)
$attendee = new Attendee(name: 'Jane Smith');
$attendee->email('patient@example.com');
$attendee->mobile('+1234567890');
$attendee->metadata(['patient_id' => '98765']);

$appointment->addAttendee($attendee);

// Create the appointment for a specific user
$response = ZavaVideoCallClient::createAppointment('user-id', $appointment);

// Get the appointment ID from the response
$appointmentId = $response->getAppointment()->getId();

Getting an Appointment

use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Get a specific appointment
$response = ZavaVideoCallClient::getAppointment('user-id', 'appointment-id');
$appointment = $response->getAppointment();

echo "Appointment: " . $appointment->getSubject();
echo "Start: " . $appointment->getStartDate()->format('Y-m-d H:i:s');
echo "End: " . $appointment->getEndDate()->format('Y-m-d H:i:s');

// Get attendees
$attendees = $appointment->getAttendees();
foreach ($attendees as $attendee) {
    echo "Attendee: " . $attendee->getName() . " (" . $attendee->getEmail() . ")";
}

Updating an Appointment

use AmaizingCompany\ZavaVideoCallClient\DataObjects\Appointment;
use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;
use Illuminate\Support\Carbon;

// Create an appointment object with updated information
$appointment = new Appointment(
    startDate: Carbon::now()->addHours(2), // Updated start time
    endDate: Carbon::now()->addHours(2)->addMinutes(45), // Updated end time
    subject: 'Follow-up Consultation' // Updated subject
);

// Update the appointment
$response = ZavaVideoCallClient::updateAppointment('user-id', 'appointment-id', $appointment);

Deleting an Appointment

use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Delete an appointment
$response = ZavaVideoCallClient::deleteAppointment('user-id', 'appointment-id');

Listing All Appointments

use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Get all appointments
$response = ZavaVideoCallClient::listAppointments();
$appointments = $response->getAppointments();

foreach ($appointments as $appointment) {
    echo $appointment->getId() . ': ' . $appointment->getSubject();
    echo " (" . $appointment->getStartDate()->format('Y-m-d H:i:s') . ")";
}

Meeting URLs

Getting User Meeting URL

use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Get the meeting URL for the healthcare provider
$userMeetingUrl = ZavaVideoCallClient::getUserMeetingUrl('meeting-token');

// Redirect the user to the meeting
return redirect()->away($userMeetingUrl);

Getting Attendee Meeting URL

use AmaizingCompany\ZavaVideoCallClient\Facades\ZavaVideoCallClient;

// Get the meeting URL for the patient
$attendeeMeetingUrl = ZavaVideoCallClient::getAttendeeMeetingUrl('meeting-token');

// Send the URL to the patient
Mail::to('patient@example.com')->send(new MeetingInvitation($attendeeMeetingUrl));

Token Management

This package implements an optimized token caching strategy that automatically refreshes access tokens before they expire. This helps prevent API request failures due to expired tokens and ensures a smoother user experience.

How It Works

  1. When an access token is first obtained, it is stored in the cache along with its expiration time.
  2. The package uses a configurable refresh threshold to determine when to proactively refresh the token.
  3. When a request is made and the token is close to expiration (based on the refresh threshold), the package automatically refreshes the token before proceeding with the request.
  4. Thread safety is ensured through the use of a lock mechanism, preventing multiple processes from refreshing the token simultaneously.

Configuration

You can configure the token refresh behavior using the token.refresh_threshold option in the config file:

'token' => [
    // Percentage of token lifetime after which to refresh (0.8 = 80%)
    // For example, if a token is valid for 3600 seconds (1 hour) and the threshold is 0.8,
    // the token will be refreshed after 2880 seconds (48 minutes).
    'refresh_threshold' => env('ZAVA_TOKEN_REFRESH_THRESHOLD', 0.8),
],

You can adjust the refresh threshold by setting the ZAVA_TOKEN_REFRESH_THRESHOLD environment variable. A higher value (closer to 1.0) will refresh the token later, while a lower value will refresh it earlier.

Retry Mechanism

The package includes a configurable retry mechanism for handling transient API failures. This helps improve the reliability of your application by automatically retrying failed requests.

Configuration

You can configure the retry behavior using the retry section in the config file:

'retry' => [
    'max_attempts' => env('ZAVA_RETRY_MAX_ATTEMPTS', 3),
    'base_delay' => env('ZAVA_RETRY_BASE_DELAY', 100), // in milliseconds
    'max_delay' => env('ZAVA_RETRY_MAX_DELAY', 1000), // in milliseconds
    'retryable_status_codes' => [408, 429, 500, 502, 503, 504],
    'retryable_exceptions' => [
        \Illuminate\Http\Client\ConnectionException::class,
        \AmaizingCompany\ZavaVideoCallClient\Exceptions\NetworkException::class,
        \AmaizingCompany\ZavaVideoCallClient\Exceptions\ServerException::class,
        \AmaizingCompany\ZavaVideoCallClient\Exceptions\RateLimitException::class,
    ],
],

Rate Limiting

The package includes support for client-side rate limiting to help you stay within the API's rate limits.

Configuration

You can configure the rate limiting behavior using the rate_limiting section in the config file:

'rate_limiting' => [
    'enabled' => env('ZAVA_RATE_LIMITING_ENABLED', true),
    'max_requests' => env('ZAVA_RATE_LIMITING_MAX_REQUESTS', 60),
    'window' => env('ZAVA_RATE_LIMITING_WINDOW', 60), // in seconds
],

Events

This package dispatches events for various appointment actions, allowing you to hook into the lifecycle of appointments and perform additional actions when these events occur.

Available Events

  • AppointmentCreated: Dispatched when a new appointment is created
  • AppointmentUpdated: Dispatched when an existing appointment is updated
  • AppointmentDeleted: Dispatched when an appointment is deleted
  • AppointmentRetrieved: Dispatched when an appointment is retrieved
  • AppointmentsListed: Dispatched when all appointments are listed
  • UserCreated: Dispatched when a new user is created

Listening for Events

You can listen for these events in your Laravel application by registering event listeners in your EventServiceProvider:

use AmaizingCompany\ZavaVideoCallClient\Events\AppointmentCreated;
use AmaizingCompany\ZavaVideoCallClient\Events\AppointmentUpdated;
use AmaizingCompany\ZavaVideoCallClient\Events\AppointmentDeleted;
use App\Listeners\HandleAppointmentCreated;
use App\Listeners\HandleAppointmentUpdated;
use App\Listeners\HandleAppointmentDeleted;

protected $listen = [
    AppointmentCreated::class => [
        HandleAppointmentCreated::class,
    ],
    AppointmentUpdated::class => [
        HandleAppointmentUpdated::class,
    ],
    AppointmentDeleted::class => [
        HandleAppointmentDeleted::class,
    ],
];

Example Listener

Here's an example of a listener that sends a notification when an appointment is created:

namespace App\Listeners;

use AmaizingCompany\ZavaVideoCallClient\Events\AppointmentCreated;
use App\Notifications\AppointmentCreatedNotification;
use Illuminate\Support\Facades\Notification;

class HandleAppointmentCreated
{
    public function handle(AppointmentCreated $event)
    {
        // Access appointment data
        $userId = $event->userId;
        $appointmentId = $event->appointmentId;
        $appointment = $event->appointment;
        
        // Get the appointment from the response
        $responseAppointment = $event->response->getAppointment();
        
        // Perform additional actions, such as sending notifications
        Notification::route('mail', 'admin@example.com')
            ->notify(new AppointmentCreatedNotification($appointment));
    }
}

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.