sepiosky/kavenegar-notifications-channel
Installation:
composer require sepiosky/kavenegar-notifications-channel
Publish the config (optional but recommended for customization):
php artisan vendor:publish --provider="NotificationChannels\Kavenegar\KavenegarServiceProvider"
Configure API Key:
Add your Kavenegar credentials to .env:
KAVENEGAR_API_KEY=your_api_key_here
KAVENEGAR_SENDER=your_sender_name # Optional (for SMS webservice)
Verify the config in config/services.php:
'kavenegar' => [
'key' => env('KAVENEGAR_API_KEY'),
'sender' => env('KAVENEGAR_SENDER'),
],
First Use Case:
Create a notification class (e.g., App\Notifications\SendSmsNotification) and use the KavenegarChannel in the via() method:
use NotificationChannels\Kavenegar\KavenegarMessage;
use NotificationChannels\Kavenegar\KavenegarChannel;
public function via($notifiable)
{
return [KavenegarChannel::class];
}
public function toKavenegar($notifiable)
{
return (new KavenegarMessage)
->method('sm...') // SMS method (e.g., 'sm...' for plain SMS)
->content('Your message here');
}
Send the Notification: Dispatch the notification in your controller or service:
$user->notify(new SendSmsNotification());
Plain SMS Notifications:
Use the sm... method for standard SMS delivery:
public function toKavenegar($notifiable)
{
return (new KavenegarMessage)
->method('sm...')
->content('Hello, this is a test message!')
->to($notifiable->phone_number);
}
OTP Notifications:
Use the otp method for one-time passwords:
public function toKavenegar($notifiable)
{
return (new KavenegarMessage)
->method('otp')
->content('123456') // OTP code
->to($notifiable->phone_number);
}
Dynamic Message Content: Use closures or dynamic data for personalized messages:
public function toKavenegar($notifiable)
{
return (new KavenegarMessage)
->method('sm...')
->content(function ($notifiable) {
return "Hello {$notifiable->name}, your order #{$notifiable->order_id} is confirmed!";
})
->to($notifiable->phone_number);
}
Routing Messages:
Use the route method to specify a custom route for SMS delivery (e.g., for specific carriers or regions):
public function toKavenegar($notifiable)
{
return (new KavenegarMessage)
->method('sm...')
->content('Hello!')
->route('route1') // Custom route ID
->to($notifiable->phone_number);
}
Handling Responses:
Override the toKavenegar method to handle the response from Kavenegar:
public function toKavenegar($notifiable)
{
$message = (new KavenegarMessage)
->method('sm...')
->content('Hello!');
return $message->to($notifiable->phone_number)
->onResponse(function ($response) {
// Log or process the response
Log::info('Kavenegar response:', $response);
});
}
User Registration: Send an OTP during registration:
$user->notify(new VerifyPhoneNotification($otpCode));
Order Confirmation: Send a plain SMS with order details:
$user->notify(new OrderConfirmationNotification($order));
Password Reset: Send a time-sensitive OTP for password reset:
$user->notify(new ResetPasswordNotification($otp));
Two-Factor Authentication: Integrate with Laravel's auth system to send OTPs for 2FA:
// In a custom 2FA trait or service
$user->notify(new TwoFactorNotification($code));
Queue Notifications: Use Laravel's queue system to avoid timeouts for high-volume SMS:
$user->notify(new SendSmsNotification())->onQueue('sms');
Rate Limiting: Implement rate limiting in your notification logic to avoid hitting Kavenegar's API limits:
// In a service or middleware
if (cache()->has("sms_limit_{$user->id}")) {
return;
}
cache()->put("sms_limit_{$user->id}", true, now()->addMinutes(1));
$user->notify(new Notification());
Fallback Channels: Combine with email notifications for critical messages:
public function via($notifiable)
{
return [MailChannel::class, KavenegarChannel::class];
}
Testing: Use mocks or a testing mode to avoid real API calls during development:
// In a test
$this->actingAs($user)
->fakeNotificationsFor(KavenegarChannel::class)
->assertSent(function ($notification) {
return $notification instanceof SendSmsNotification;
});
API Key Exposure:
Ensure KAVENEGAR_API_KEY is never committed to version control. Use .env and add it to your .gitignore.
Sender Configuration:
The sender field in config/services.php is only used for SMS webservice (not OTP). Omitting it for OTP may cause unexpected behavior.
Phone Number Formatting:
Kavenegar expects phone numbers in a specific format (e.g., +989123456789). Validate and format numbers before sending:
$phone = preg_replace('/[^0-9]/', '', $notifiable->phone);
$phone = '+' . substr($phone, 0, 1) . substr($phone, 1); // Example for Iran
Response Handling: Kavenegar's API responses may include errors (e.g., invalid numbers, throttling). Always handle responses gracefully:
$message->onResponse(function ($response) {
if (isset($response['error'])) {
Log::error('Kavenegar error:', $response['error']);
// Optionally retry or notify admin
}
});
Method Selection:
Incorrect method selection (e.g., using sm... for OTP) will fail silently. Double-check the method:
sm... for plain SMS.otp for one-time passwords.Queue Failures: If using queues, ensure your queue worker processes are running to avoid missed notifications. Monitor failed jobs:
php artisan queue:failed-table
php artisan queue:work
Log API Requests:
Enable Laravel's logging for the KavenegarChannel to inspect outgoing requests:
// In a service provider or boot method
\NotificationChannels\Kavenegar\KavenegarManager::extend('kavenegar', function ($app) {
$manager = new \NotificationChannels\Kavenegar\KavenegarManager($app);
$manager->setLogger(function () {
return new \Monolog\Logger('kavenegar', [new \Monolog\Handler\StreamHandler(storage_path('logs/kavenegar.log'))]);
});
return $manager;
});
Test with Sandbox: Use Kavenegar's sandbox environment for testing:
// Temporarily override the API key in tests
$this->app->instance('config', [
'services.kavenegar.key' => 'sandbox_api_key',
]);
Check API Status: Verify Kavenegar's API status at status.kavenegar.com if messages fail unexpectedly.
sender is configured, Kavenegar will use a default sender. Specify it explicitly for branding:
'kavenegar' => [
'key' => env('KAVENEGAR_API_KEY'),
'sender' => env('APP_NAME', 'DefaultSender'),
How can I help you explore Laravel packages today?