Search by

djouamaah / laravel-algeria-sms

djouamaah

SMS for Laravel through Algerian providers: OTP codes, transactional and marketing messages, Algerian phone numbers (Mobilis, Djezzy, Ooredoo), notification channel, opt-outs and quiet hours.

Package info

github.com/djouamaah/laravel-algeria-sms

pkg:composer/djouamaah/laravel-algeria-sms

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-10-23 12:49 UTC

This package is auto-updated.

Last update: 2026-10-23 12:50:59 UTC


README

Tests

English documentation ↓

حزمة لارافل لإرسال الرسائل النصية إلى أرقام موبيليس وجيزي وأوريدو:

  • رموز التحقق (OTP): توليد الرمز وإرساله والتحقق منه. لا يُحفظ الرمز إلا مشفّرًا (HMAC). له مدة صلاحية، وحد للمحاولات الخاطئة، وحد لإعادة الإرسال.
  • الرسائل الإعلامية والترويجية: تُرسل عبر الطابور، ولا تصل إلى من رفض استقبالها، ولا تُرسل ليلًا.
  • الرسائل الخدمية: تأكيد طلب، تذكير، تنبيه.
  • الأرقام الجزائرية: تقبل كل الصيغ (0555 12 34 56 و+213555123456…)، وتحدد المتعامل من البادئة (05 أوريدو، 06 موبيليس، 07 جيزي).
  • أدوات لارافل: قناة إشعارات، وقاعدة تحقق AlgerianMobile، وAlgeriaSms::fake() للاختبارات.
  • التكلفة: حساب عدد أجزاء الرسالة. العربية 70 حرفًا للجزء، واللاتينية 160. والدالة gsm() تحوّل الحروف الفرنسية المنبَّرة (ê، ç…) لتبقى الرسالة في 160 حرفًا.

يدعم Laravel 10 و11 و12 و13، وPHP 8.1 فما فوق.

لماذا لا توجد مشغّلات جاهزة لمزوّد بعينه؟

المتعاملون الجزائريون والمزوّدون المحليون لا ينشرون وثائق واجهاتهم البرمجية للعموم، بل تُسلَّم مع العقد التجاري. لذلك تأتي الحزمة بمشغّلين:

  • مشغّل HTTP عام: تضبطه من وثائق مزوّدك في ملف الإعدادات، دون كتابة أي كود.
  • مشغّلك الخاص: يمكنك إضافته لأي مزوّد (SMPP أو غيره) عبر AlgeriaSms::extend().

التثبيت

composer require djouamaah/laravel-algeria-sms
php artisan migrate        # جدول sms_opt_outs (من رفض الرسائل الترويجية)
php artisan vendor:publish --tag=algeria-sms-config
ALGERIA_SMS_DRIVER=log         # log للتطوير، http للإرسال الفعلي
ALGERIA_SMS_SENDER=MaBoutique  # اسم المرسل المسجَّل لدى مزوّدك
ALGERIA_SMS_URL=https://api.mon-fournisseur.dz/sms/send

ضبط مشغّل HTTP

مثال: مزوّد ينتظر JSON بالشكل {"to": "...", "text": "...", "from": "...", "key": "..."} ويرد بـ {"status": "ok", "data": {"id": "..."}}:

// config/algeria-sms.php
'http' => [
    'driver' => 'http',
    'url' => env('ALGERIA_SMS_URL'),
    'method' => 'post',
    'format' => 'json',                       // json أو form أو query
    'headers' => [],
    'params' => [
        'to' => ':to',
        'text' => ':message',
        'from' => ':sender',
        'key' => env('ALGERIA_SMS_KEY'),      // القيم الأخرى تُرسل كما هي
    ],
    'phone_format' => 'international',        // +213555123456 أو digits: 213555123456 أو local: 0555123456
    'success' => ['status' => [200], 'json' => ['status' => 'ok']],
    'message_id' => 'data.id',
],

عدة مزوّدين: أضف مداخل أخرى مثل 'backup' => ['driver' => 'http', ...]، ثم أرسل بـ AlgeriaSms::send($to, $text, 'backup').

الاستعمال

رسالة واحدة

use Djouamaah\AlgeriaSms\Facades\AlgeriaSms;
use Djouamaah\AlgeriaSms\SmsMessage;

AlgeriaSms::send('0555 12 34 56', 'Votre commande est arrivée.');

$sent = AlgeriaSms::send('0661234567', SmsMessage::make('Merci pour votre achat')->from('MaBoutique'));
$sent->id;      // رقم الرسالة لدى المزوّد إن أرجعه
  • عند الرفض: إذا رفض المزوّد الرسالة يُرمى SmsException، ويُطلق الحدث MessageFailed.
  • عند النجاح: يُطلق الحدث MessageSent. استعمل هذين الحدثين لتسجيل الرسائل أو متابعة رصيدك.

رمز التحقق (OTP)

// إرسال: «رمز التحقق الخاص بك: 482913. صالح لمدة 5 دقائق. لا تشاركه مع أي أحد.»
try {
    AlgeriaSms::otp()->send($request->phone, 'register');
} catch (\Djouamaah\AlgeriaSms\Exceptions\OtpThrottled $e) {
    return back()->withErrors(['phone' => "أعد المحاولة بعد {$e->retryAfter} ثانية."]);
}

// التحقق
if (AlgeriaSms::otp()->verify($request->phone, $request->code, 'register')) {
    // الرقم مؤكَّد
}
  • الغرض: ('login' و'register' و'reset-password'…) يفصل بين الرموز، فرمز التسجيل لا يصلح لتسجيل الدخول.
  • الصلاحية: الرمز صالح مرة واحدة. يُلغى بعد 5 محاولات خاطئة، أو بعد 5 دقائق.
  • حدود الإرسال: رمز واحد كل دقيقة، و5 رموز في الساعة لكل رقم.
  • الرسالة: نصها بلغة التطبيق (عربية أو فرنسية أو إنجليزية)، ويمكنك نشر ملفات الترجمة وتعديلها.
  • قناة أخرى: otp()->generate($phone) تولّد الرمز دون إرساله، إن أردت إيصاله عبر قناة أخرى.

الرسائل الترويجية والإعلامية

$count = AlgeriaSms::marketing(
    User::where('newsletter', true)->pluck('phone'),
    SmsMessage::make('Soldes -20% ce week-end !')->gsm(),
);
  • الأرقام المستبعدة: الأرقام غير الصحيحة والمكرَّرة، ومن رفض الاستقبال (AlgeriaSms::optOut($phone)).
  • الطابور: تُرسل على دفعات من 100 رقم، فتحتاج إلى عامل طابور شغّال (php artisan queue:work).
  • ساعات الهدوء: بين 21:00 و08:00 بتوقيت الجزائر. ما يُطلب ليلًا ينتظر حتى الثامنة صباحًا.
  • الرسائل غير المعنية: رسائل التحقق والرسائل الخدمية تصل حتى إلى من رفض الرسائل الترويجية.
AlgeriaSms::optOut('0555123456', 'STOP');   // عندما يطلب الزبون التوقف
AlgeriaSms::optIn('0555123456');
AlgeriaSms::isOptedOut('0555123456');

القانون 18-07 لحماية المعطيات الشخصية يشترط موافقة الشخص على استعمال رقمه في الترويج. الحزمة تحترم الرفض، لكن جمع الموافقة يبقى على عاتق تطبيقك.

الإشعارات

class OrderShipped extends Notification
{
    public function via($notifiable): array
    {
        return ['algeria-sms'];
    }

    public function toSms($notifiable): string
    {
        return "Votre commande {$this->order->number} a été expédiée.";
    }
}

الرقم يؤخذ بالترتيب من:

  1. الدالة routeNotificationForSms() في النموذج.
  2. Notification::route('sms', '0555...').
  3. الحقل phone.

الأرقام والتحقق منها

use Djouamaah\AlgeriaSms\Phone;
use Djouamaah\AlgeriaSms\Rules\AlgerianMobile;
use Djouamaah\AlgeriaSms\Enums\Operator;

$phone = Phone::parse('0555 12 34 56');
$phone->international();   // +213555123456
$phone->local();           // 0555123456
$phone->formatted();       // 0555 12 34 56
$phone->operator();        // Operator::Ooredoo

$request->validate(['phone' => ['required', new AlgerianMobile]]);
$request->validate(['phone' => ['required', new AlgerianMobile(Operator::Mobilis)]]);

طول الرسالة وتكلفتها

$message = SmsMessage::make('Votre commande est prête');
$message->encoding();   // ucs2: الحرف ê ليس من أبجدية GSM-7
$message->gsm();        // "Votre commande est prete"
$message->encoding();   // gsm7
$message->segments();   // 1
الأبجدية رسالة واحدة لكل جزء عند التقسيم
GSM-7 (لاتينية) 160 153
UCS-2 (عربية، إيموجي، ê ç â…) 70 67

مشغّل خاص

use Djouamaah\AlgeriaSms\Contracts\Driver;

AlgeriaSms::extend('monfournisseur', fn ($app, array $config) => new MonFournisseurDriver($config));
// في config/algeria-sms.php:  'drivers' => ['monfournisseur' => ['driver' => 'monfournisseur', 'token' => ...]]

يكفي أن ينفّذ الكلاس الواجهة Driver، أي دالة send(Phone $to, SmsMessage $message): ?string، وأن يرمي SmsException عند الفشل.

الاختبارات في تطبيقك

$sms = AlgeriaSms::fake();

$this->post('/register', ['phone' => '0555123456']);

$sms->assertSentTo('0555123456', fn ($message) => str_contains($message->content, 'رمز التحقق'));
$sms->assertSentCount(1);

الاختبارات

composer install
composer test

الترخيص

MIT

English

SMS for Laravel through Algerian providers (Mobilis, Djezzy, Ooredoo numbers):

  • OTP codes: stored hashed, with expiry, attempt limit and resend limits.
  • Transactional messages.
  • Marketing messages: queued, never sent to opted-out numbers or during quiet hours (21:00–08:00 Algiers time).
  • Algerian phone numbers: parsing in any format and operator detection.
  • Laravel tools: a notification channel, an AlgerianMobile validation rule and AlgeriaSms::fake().
  • Cost: a segment counter (GSM-7 160 / UCS-2 70) and gsm() to keep French text in GSM-7.

Algerian operators and local SMS providers do not publish their APIs; documentation comes with the contract. The package therefore ships a configurable HTTP driver (URL, method, JSON/form/query body, parameter mapping, success check, message id path) and lets you register your own driver with AlgeriaSms::extend().

composer require djouamaah/laravel-algeria-sms
php artisan migrate
use Djouamaah\AlgeriaSms\Facades\AlgeriaSms;
use Djouamaah\AlgeriaSms\SmsMessage;

AlgeriaSms::send('0555 12 34 56', 'Votre commande est arrivée.');

AlgeriaSms::otp()->send($phone, 'register');            // throws OtpThrottled when asked too often
AlgeriaSms::otp()->verify($phone, $code, 'register');   // true once, then false

AlgeriaSms::marketing($phones, SmsMessage::make('Soldes -20% !')->gsm());   // queued, opt-outs and quiet hours respected
AlgeriaSms::optOut('0555123456');

$sms = AlgeriaSms::fake();                               // in tests
$sms->assertSentTo('0555123456');

Notifications: return ['algeria-sms'] from via() and define toSms($notifiable).

Validation: new AlgerianMobile or new AlgerianMobile(Operator::Mobilis).

Law 18-07 on personal data requires consent for marketing messages. The package honours opt-outs, but collecting consent is up to your application.

License

MIT