Gestion d'Envoi de SMS à Grande Échelle : Retour d'Expérience

· 12,719 vues
Gestion d'Envoi de SMS à Grande Échelle : Retour d'Expérience

Le Contexte

J'ai récemment développé une plateforme SaaS pour BAAF GROUP en Guinée, un acteur du secteur FinTech. La plateforme permet la gestion de points de vente, d'agents et le traitement de milliers de transactions quotidiennes.

Le Défi

Avec plusieurs milliers de transactions par jour, le système doit envoyer automatiquement des SMS pour :

  • Confirmer les paiements de factures
  • Notifier les agents des transactions
  • Envoyer les reçus aux clients
  • etc ....

Le volume d'envoi peut atteindre plusieurs milliers de SMS par jour, nécessitant une solution robuste et flexible.

La Solution Technique

Architecture Multi-Provider

Pour éviter la dépendance à un seul fournisseur et assurer la continuité de service, j'ai implémenté une abstraction simple :

<?php

namespace App\Enums;

enum SmsProvider: string
{
    case ORANGE = 'orange';
    case NIMBA = 'nimba';

    public static function getCurrent(): self
    {
        return self::from(env('SMS_PROVIDER', 'orange'));
    }
}
<?php

namespace App\Helpers;

use App\Enums\SmsProvider;
use Tmoh\NimbaSms\Facades\NimbaSms;
use Tmoh\OrangeSmsPackage\Facades\OrangeSms;

class SmsProviderHelper
{
    public static function sendSms(string $phoneNumber, string $message): mixed
    {
        return match (SmsProvider::getCurrent()) {
            SmsProvider::ORANGE => OrangeSms::sendSms(
                recipientAddress: $phoneNumber,
                message: $message
            ),
            SmsProvider::NIMBA => NimbaSms::sendSms($phoneNumber, $message),
        };
    }
}

Traitement Asynchrone avec Jobs

Pour gérer le volume d'envois sans impacter les performances, j'utilise les queues Laravel :

<?php

namespace App\Jobs;

use App\Helpers\SmsProviderHelper;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SendTransactionSmsJob implements ShouldQueue
{
    use Dispatchable, Queueable;

    public $tries = 3;

    public function __construct(
        public string $phoneNumber,
        public string $message
    ) {}

    public function handle(): void
    {
        SmsProviderHelper::sendSms(
            phoneNumber: $this->phoneNumber,
            message: $this->message
        );
    }
}

Utilisation

// Lors d'un paiement de facture
SendTransactionSmsJob::dispatch(
    phoneNumber: $customer->phone,
    message: "Paiement de {$amount} GNF effectué. Référence: {$ref}"
);

// Pour les agents
SendTransactionSmsJob::dispatch(
    phoneNumber: $agent->phone,
    message: "Transaction validée. Commission: {$commission} GNF"
);

// En cas d'activité suspecte
SendTransactionSmsJob::dispatch(
    phoneNumber: $user->phone,
    message: "Alerte sécurité: Tentative de connexion depuis un nouvel appareil. Si ce n'est pas vous, contactez-nous immédiatement."
);

Les Avantages

Flexibilité : Changement de provider SMS via une simple variable d'environnement
Performance : Traitement asynchrone sans ralentir l'application
Fiabilité : Système de retry automatique en cas d'échec
Scalabilité : Capable de gérer plusieurs milliers d'envois par jour

Stack Technique

Installation

# Installer les packages SMS
composer require tmoh/orange-sms-package
composer require tmoh/nimba-sms

# Installer Horizon pour le monitoring
composer require laravel/horizon

Configuration

# Provider SMS actif
SMS_PROVIDER=orange

# Configuration Orange SMS
ORANGE_SMS_CLIENT_ID=your_client_id
ORANGE_SMS_CLIENT_SECRET=your_client_secret

# Configuration Nimba SMS
NIMBA_SMS_API_KEY=your_api_key

# Configuration Redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

Résultat

Le système traite actuellement plusieurs milliers de SMS par jour de manière stable et fiable pour BAAF GROUP, avec :

Un taux de succès supérieur à 99% Un temps de traitement moyen inférieur à 2 secondes Zéro interruption de service depuis le déploiement Capacité à gérer des pics de **20,000+ SMS/Jour **


Projet développé pour BAAF GROUP - Guinée