laravel-twilio maintained by groupesti
groupesti/laravel-twilio
Intégration Twilio pour Laravel : messagerie SMS/MMS, appels vocaux, téléchargement de médias, codes à usage unique (TOTP), webhooks à signature validée et journal d'audit.
Extrait du module applicatif App\Modules\Twilio et transformé en package Composer autonome.
Prérequis
- PHP 8.2+
- Laravel 12
twilio/sdk^8.3 (installé automatiquement)
Installation
composer require groupesti/laravel-twilio
Le fournisseur Twilio\Providers\TwilioServiceProvider est enregistré par auto-discovery.
php artisan vendor:publish --tag=twilio-config
php artisan vendor:publish --tag=twilio-lang
php artisan migrate
Les migrations sont chargées directement depuis le package ; --tag=twilio-migrations ne sert que si vous souhaitez les modifier.
Namespace et cohabitation avec le SDK Twilio
Le package utilise Twilio\ comme namespace racine, le même préfixe que le SDK officiel twilio/sdk. C'est volontaire et fonctionnel : Composer accepte plusieurs répertoires pour un même préfixe PSR-4 et les résout dans l'ordre.
Deux sous-espaces se croisent sans collision de nom de classe :
| Sous-espace | SDK officiel | Ce package |
|---|---|---|
Twilio\Exceptions\ |
TwilioException, RestException, ConfigurationException… |
TwilioModuleException, TwilioConfigurationException, TwilioDeliveryException, TwilioWebhookException |
Twilio\Http\ |
Client, CurlClient, Request, Response |
Controllers\, Middleware\, Requests\ |
Contrainte à respecter en évolution : n'ajoutez jamais dans ce package une classe dont le nom pleinement qualifié existe déjà dans le SDK (par exemple Twilio\Http\Client ou Twilio\Exceptions\TwilioException). Le chargeur en retiendrait une seule et le comportement dépendrait de l'ordre d'autoload.
Configuration
Les valeurs de config/twilio.php servent de repli. Twilio\Services\TwilioConfigResolver privilégie toujours l'enregistrement TwilioConfig actif en base de données.
Variables d'environnement principales :
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_FROM_NUMBER=
TWILIO_MESSAGING_SERVICE_SID=
TWILIO_VALIDATE_SIGNATURE=true
TWILIO_VOICE_LOCALE="fr-CA"
TWILIO_RECORDING_ENABLED=false
TWILIO_DEFAULT_AGENT_PHONE=
TWILIO_TOTP_LENGTH=6
TWILIO_TOTP_TTL=300
TWILIO_MEDIA_DISK=public
TWILIO_MEDIA_PATH=twilio/media
Routes
Trois groupes, pilotés par config('twilio.routes') :
| Groupe | Défaut | Préfixe | Middleware |
|---|---|---|---|
webhooks |
activé | twilio |
twilio.audit, twilio.signature |
api |
activé | api |
api + auth:sanctum (déclaré dans le fichier de routes) |
web |
désactivé | admin/twilio |
web, auth |
Les routes web sont désactivées par défaut parce que leurs contrôleurs rendent les vues apps.twilio.* (dashboard, messages, calls, media, statuses, config, audit), qui ne font pas partie du package et doivent être fournies par l'application hôte. Activez-les une fois ces vues en place :
TWILIO_ROUTES_WEB=true
Webhooks à déclarer dans la console Twilio :
POST https://exemple.com/twilio/messaging/inbound
POST https://exemple.com/twilio/messaging/status
POST https://exemple.com/twilio/voice/inbound
POST https://exemple.com/twilio/voice/status
POST https://exemple.com/twilio/voice/recording
Utilisation
use Twilio\Actions\SendTwilioMessageAction;
use Twilio\DTOs\SendMessageData;
$message = app(SendTwilioMessageAction::class)->handle(
new SendMessageData(to: '+15145550100', body: 'Bonjour.'),
);
use Twilio\Actions\StartTwilioVoiceCallAction;
use Twilio\DTOs\VoiceCallData;
$call = app(StartTwilioVoiceCallAction::class)->handle(
new VoiceCallData(to: '+15145550100', message: 'Votre rendez-vous est confirmé.'),
);
Le client REST est résolu via l'interface, ce qui permet de le substituer en test :
use Twilio\Interfaces\TwilioClientInterface;
$this->app->instance(TwilioClientInterface::class, $fake);
Structure
config/twilio.php Configuration de repli
database/factories/ Factories Eloquent (Twilio\Database\Factories)
database/migrations/ 8 tables : configs, conversations, statuses,
messages, audits, calls, media, totps
lang/{fr,en}/ twilio.php (erreurs, TOTP), twilio_admin.php (libellés)
routes/ web.php, api.php, webhooks.php
src/Actions/ 15 actions métier
src/Concerns/HasUuid.php Clé primaire UUID v7
src/DTOs/ Objets d'entrée
src/Exceptions/ Exceptions typées avec clé de traduction et statut HTTP
src/Http/ Contrôleurs admin/API/webhooks, middlewares, form requests
src/Interfaces/ TwilioClientInterface
src/Models/ 8 modèles + ReferenceModel
src/Providers/ TwilioServiceProvider
src/Services/ Client, resolver de configuration, présentateur de statuts,
fabrique de réponses TwiML
src/Support/ Extraction de payload, construction d'URL de webhook
Traductions
Les clés utilisées (twilio.errors.*, twilio_admin.*) ne sont pas namespacées : elles doivent être publiées dans le dossier lang/ de l'application.
php artisan vendor:publish --tag=twilio-lang
Écarts avec le module d'origine
App\Traits\HasUuid→Twilio\Concerns\HasUuid(réimplémenté).App\Support\Models\ReferenceModel→Twilio\Models\ReferenceModel(réimplémenté ; la couche de cache de la version applicative n'a pas été reprise).App\Support\Providers\ModuleServiceProvider→Illuminate\Support\ServiceProviderstandard.App\Http\Controllers\Controller→Illuminate\Routing\Controller.- Clés de configuration ajoutées, référencées par le code mais absentes du module :
voice.default_agent_phone,totp.message_key,media.disk,media.path. - Fichiers de langue fournis, reconstitués à partir des clés effectivement appelées.