laravel-msegat maintained by aghfatehi
Installation
composer require aghfatehi/laravel-msegat
Laravel auto-discovery registers the service provider and facade automatically.
Publish Configuration
php artisan vendor:publish --provider="Aghfatehi\Msegat\MsegatServiceProvider" --tag=msegat-config
Publish Migrations (Optional)
Track sent messages, OTP requests, delivery reports, and webhooks in your database. If you publish and run the migrations, five tables will be created:
| Table | Purpose |
|---|---|
msegat_sms_logs |
History of all sent SMS messages |
msegat_otp_requests |
OTP request tracking |
msegat_delivery_reports |
Delivery report storage from Msegat |
msegat_webhook_logs |
Webhook event log |
msegat_failed_requests |
Failed request records |
This step is optional. The package works fully without migrations — skip this section if you don't need database logging.
Option A — Run migrations directly from the package (recommended):
Runs only the package's migrations without publishing:
php artisan migrate --path=/vendor/aghfatehi/laravel-msegat/database/migrations
Option B — Publish then migrate (if you need to modify the migrations):
php artisan vendor:publish --provider="Aghfatehi\Msegat\MsegatServiceProvider" --tag=msegat-migrations
php artisan migrate
Configuration
Add to your .env (required variables marked with REQUIRED):
# ─── REQUIRED ───────────────────────────────────────
MSEGAT_USERNAME=your_username
MSEGAT_API_KEY=your_api_key
# ─── OPTIONAL ───────────────────────────────────────
MSEGAT_SENDER=YourSender
MSEGAT_BASE_URL=https://www.msegat.com/gw/
MSEGAT_TIMEOUT=30
MSEGAT_RETRIES=3
MSEGAT_VERIFY_SSL=true
MSEGAT_QUEUE_ENABLED=false
MSEGAT_LOGGING_ENABLED=true
MSEGAT_WEBHOOK_SECRET=your_webhook_secret
MSEGAT_WHATSAPP_EMAIL=your_t2_email
MSEGAT_WHATSAPP_PASSWORD=your_t2_password
Config Options
| Variable | Default | Required | Description |
|---|---|---|---|
MSEGAT_USERNAME |
— | Yes | Msegat account username |
MSEGAT_API_KEY |
— | Yes | Msegat API key |
MSEGAT_SENDER |
'' |
No | Default sender name |
MSEGAT_BASE_URL |
https://www.msegat.com/gw/ |
No | API base URL |
MSEGAT_TIMEOUT |
30 |
No | HTTP request timeout (seconds) |
MSEGAT_RETRIES |
3 |
No | Max retry attempts on failure |
MSEGAT_VERIFY_SSL |
true |
No | Verify SSL certificate |
MSEGAT_QUEUE_ENABLED |
false |
No | Enable async webhook processing |
MSEGAT_LOGGING_ENABLED |
true |
No | Enable request/response logging |
MSEGAT_WEBHOOK_SECRET |
'' |
No | Secret for webhook signature verification |
MSEGAT_WHATSAPP_EMAIL |
— | No | T2 Communicate WhatsApp login email |
MSEGAT_WHATSAPP_PASSWORD |
— | No | T2 Communicate WhatsApp login password |
MSEGAT_WHATSAPP_BASE_URL |
https://communicateapi.t2.sa/api |
No | T2 WhatsApp API base URL |
MSEGAT_WHATSAPP_TOKEN_CACHE_TTL |
3300 |
No | JWT token cache TTL (seconds) |
Usage
SMS
use Aghfatehi\Msegat\Facades\Msegat;
// Single recipient
$response = Msegat::sms()
->to('966512345678')
->message('Hello World')
->send();
// Multiple recipients
$response = Msegat::sms()
->to(['966512345678', '966598765432'])
->message('Bulk message')
->send();
// Custom sender
$response = Msegat::sms()
->sender('CustomAD')
->to('966512345678')
->message('Custom sender test')
->send();
// Scheduled message
$response = Msegat::sms()
->to('966512345678')
->message('Scheduled message')
->at('2026-12-01 10:00:00')
->send();
// Get bulk ID
$response = Msegat::sms()
->to(['966512345678', '966598765432'])
->message('Get bulk ID')
->options(['reqBulkId' => true])
->send();
$bulkId = $response->bulkId;
Personalized Messages
$response = Msegat::sms()
->to(['966512345678', '966598765432'])
->message('Hello {name}, your order {order} is ready')
->sendPersonalized([
['name' => 'Ahmed', 'order' => '1001'],
['name' => 'Mohammed', 'order' => '1002'],
]);
OTP
// Send OTP
$otpResponse = Msegat::otp()
->to('966512345678')
->sendOtp();
$otpId = $otpResponse->otpId;
// Verify OTP
$verification = Msegat::otp()
->to('966512345678')
->verifyOtp('123456');
if ($verification->successful) {
// OTP verified
}
WhatsApp (T2 Communicate API)
WhatsApp messages are sent via the T2 Communicate WhatsApp Business API — a separate gateway from Msegat SMS. Requires its own credentials.
Text Message
$response = Msegat::whatsapp()
->to('966512345678')
->message('Hello from WhatsApp!')
->send();
$messageId = $response->messageId;
Template Message
$response = Msegat::whatsapp()
->to('966512345678')
->template('welcome')
->variables(['John', 'Support'])
->send();
if ($response->successful) {
echo "Sent: {$response->messageId}";
}
Response Object
| Field | Type | Description |
|---|---|---|
successful |
bool |
Whether the API accepted the message |
messageId |
string |
Unique message ID for tracking |
conversationId |
string |
WhatsApp conversation ID |
contactNumber |
string |
Recipient phone number |
status |
string |
Sent, Delivered, Read, Failed, etc. |
contactName |
`string | null` |
Balance
$balance = Msegat::getBalance();
$credits = $balance->balance; // float
Message Cost Calculation
$cost = Msegat::sms()
->to(['966512345678', '966598765432'])
->message('Test message')
->calculateCost();
// Returns float
Sender Management
// List senders
$senders = Msegat::getSenders();
// Add sender
// (available via direct API call - endpoint: addSender.php)
Retrieve Messages
$messages = Msegat::forBulkId('BULK123')
->getMessages();
$messages = Msegat::forBulkId('BULK123')
->page(2)
->limit(10)
->getMessages();
Test Message
Msegat::sms()
->to('966512345678')
->sendTestMessage();
Queue Support
// Dispatch to default queue
Msegat::sms()
->to('966512345678')
->message('Queued message')
->queue();
// Custom queue connection
Msegat::sms()
->to('966512345678')
->message('Queued message')
->queue('redis', 'high');
The SendSmsJob retries up to 3 times with a 5-second backoff.
Events
| Event | Payload | Description |
|---|---|---|
MessageSending |
$data (array) |
Before sending SMS |
MessageSent |
$response (SmsResponse) |
After SMS or WhatsApp sent |
OtpGenerated |
$number, $response (OtpResponse) |
After OTP sent |
OtpVerified |
$number, $code, $response (OtpResponse) |
After OTP verified |
WebhookReceived |
$type, $payload (array) |
When webhook is received |
Example listener registration in EventServiceProvider:
protected $listen = [
\Aghfatehi\Msegat\Events\MessageSent::class => [
\App\Listeners\LogMsegatMessage::class,
],
];
Webhooks
The package registers four webhook routes under the /webhook/msegat/ prefix:
| Route | Purpose |
|---|---|
POST /webhook/msegat/delivery |
Delivery reports |
POST /webhook/msegat/status |
Message status updates |
POST /webhook/msegat/incoming |
Incoming messages |
POST /webhook/msegat/failed |
Failed messages |
Signature Verification
Set MSEGAT_WEBHOOK_SECRET in .env and each webhook request must include:
X-Msegat-Signature: HMAC-SHA256 oftimestamp.payloadX-Msegat-Timestamp: Unix timestamp
Requests outside a 5-minute tolerance window are rejected.
Notification Channel
namespace App\Notifications;
use Illuminate\Notifications\Notification;
class WelcomeSms extends Notification
{
public function via($notifiable): array
{
return ['msegat'];
}
public function toMsegat($notifiable): string
{
return "Welcome {$notifiable->name} to our platform!";
}
}
Add routeNotificationForMsegat() to your notifiable model:
public function routeNotificationForMsegat(): string
{
return $this->phone;
}
Artisan Commands
# Check account balance
php artisan msegat:balance
# List registered senders
php artisan msegat:senders
Testing
composer test
With coverage:
composer test-coverage
The test suite includes:
- Unit Tests: DTOs, enums, exceptions, phone formatter, WhatsApp response
- Feature Tests: SMS sending, OTP, balance, webhooks, config, WhatsApp text/template
- Integration Tests: Events, queues
Code Quality (For Contributors)
# Laravel Pint (PSR-12)
composer lint
# Auto-fix
composer lint-fix
# PHPStan (level 6)
composer analyse
# Rector
composer rector
Database Migrations
| Table | Purpose |
|---|---|
msegat_sms_logs |
SMS send history |
msegat_otp_requests |
OTP request tracking |
msegat_delivery_reports |
Delivery report storage |
msegat_webhook_logs |
Webhook event log |
msegat_failed_requests |
Failed request records |
Status Codes and Messages
Success
| Code | Message |
|---|---|
M0000 |
Success |
Errors
| Code | Message |
|---|---|
M0001 |
Variables missing |
M0002 |
Invalid login info |
M0022 |
Exceed number of senders allowed |
M0023 |
Sender Name is active or under activation or refused |
M0024 |
Sender Name should be in English or number |
M0025 |
Invalid Sender Name Length |
M0026 |
Sender Name is already activated or not found |
M0027 |
Activation Code is not Correct |
1010 |
Variables missing |
1020 |
Invalid login info |
1050 |
MSG body is empty |
1060 |
Balance is not enough |
1061 |
MSG duplicated |
1064 |
Free OTP, Invalid MSG content you should use "Pin Code is: xxxx", "Verification Code: xxxx" or upgrade your account and activate your sender to send any content |
1110 |
Sender name is missing or incorrect |
1120 |
Mobile numbers is not correct |
1140 |
MSG length is too long |
M0029 |
Invalid Sender Name - Sender Name should contain only letters, numbers and the maximum length should be 11 characters |
M0030 |
Sender Name should ended with AD |
M0031 |
Maximum allowed size of uploaded file is 5 MB |
M0032 |
Only pdf, png, jpg and jpeg files are allowed! |
M0033 |
Sender Type should be normal or whitelist only |
M0034 |
Please Use POST Method |
M0036 |
There is no any sender |
Changelog
See CHANGELOG for recent changes.
Security
If you discover any security-related issues, please email instead of using the issue tracker.
Contributing
Contributions are welcome! Please follow these steps to contribute:
- Fork the repository.
- Create a new branch (
git checkout -b feature/new-feature). - Commit your changes (
git commit -am 'Add new feature'). - Push to the branch (
git push origin feature/new-feature). - Create a new Pull Request.
Support
If you have any questions or issues, feel free to open an issue on the GitHub repository or contact the author AL-AGHBARI Fatehi.
License
The MIT License (MIT). See LICENSE for details.