Looking to hire Laravel developers? Try LaraJobs

laravel-twilio maintained by groupesti

Description
Intégration Twilio pour Laravel : messagerie SMS/MMS, appels vocaux, médias, TOTP, webhooks signés et audit.
Author
Last update
2026/08/01 15:56 (dev-main)
License
Links
Downloads
0
Tags

Comments
comments powered by Disqus

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\HasUuidTwilio\Concerns\HasUuid (réimplémenté).
  • App\Support\Models\ReferenceModelTwilio\Models\ReferenceModel (réimplémenté ; la couche de cache de la version applicative n'a pas été reprise).
  • App\Support\Providers\ModuleServiceProviderIlluminate\Support\ServiceProvider standard.
  • App\Http\Controllers\ControllerIlluminate\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.