masihjay-z/kavenegar
Laravel integration for the Kavenegar SMS API, providing a simple way to send SMS messages, OTP codes, and lookup-based notifications from your PHP applications through a clean, framework-friendly wrapper.
Treat masihjay-z/kavenegar as a thin, unmaintained convenience wrapper around Kavenegar's REST API, not a first-party integration. Adoption signals are essentially zero (0 stars, 0 dependents, score 0) and it targets Laravel 4/5, so your first hour should be spent reading source, not writing feature code.
1. Install and inspect before you trust the API surface.
composer require masihjay-z/kavenegar
Then immediately open composer.json in the package and check:
Masihjay\Kavenegar\... — verify, don't assume),illuminate/support constraint and required PHP version,extra.laravel.providers for auto-discovery (it likely predates Laravel 5.5 discovery).2. Register the provider and facade manually in config/app.php (Laravel 4/5 convention):
'providers' => [
Masihjay\Kavenegar\KavenegarServiceProvider::class, // verify from src/
],
'aliases' => [
'Kavenegar' => Masihjay\Kavenegar\Facades\Kavenegar::class, // verify
],
3. Publish config and supply credentials.
php artisan vendor:publish --provider="Masihjay\Kavenegar\KavenegarServiceProvider"
KAVENEGAR_API_KEY=your-api-key
KAVENEGAR_SENDER=10004346
4. Where to look first: composer.json, then src/ for the service provider, the facade, and the config keys. The package's README is the only documentation — do not assume config key names or method names match the official kavenegar/laravel package; this wrapper is old enough that send vs Send vs sendSms is genuinely uncertain until you read the code.
5. First use case: an OTP / verification code, the dominant Kavenegar workload in Iranian Laravel apps.
Kavenegar::send($mobile, 'کد ورود شما: 12345');
Confirm the real signature from source before shipping. If you are on Laravel 6+, PHP 8+, or need queued notifications, delivery callbacks, or lookup templates, stop here and write a small Http:: client or use the official Kavenegar SDK instead.
Wrap it behind your own interface from day one. This is the single highest-leverage habit with a package this thin and this unmaintained — it converts an adoption risk into a removable detail.
interface SmsSender {
public function send(string $mobile, string $message, ?string $sender = null): bool;
}
class KavenegarSender implements SmsSender
{
public function send(string $mobile, string $message, ?string $sender = null): bool
{
// delegate to the package facade; normalize response + errors here
}
}
Bind it in a service provider ($this->app->bind(SmsSender::class, KavenegarSender::class)) so call sites depend on your contract, not the facade.
Queue everything; never send inline in a request. SMS is a paid outbound network call with latency. Dispatch a job onto a dedicated queue:
dispatch(new SendOtp($user, $code))->onQueue('sms');
This gives you retries, backoff, and a place to add rate limiting without touching controllers.
Integrate via a Notification channel, not ad-hoc controller calls. One channel means one logging policy, one retry policy, one place to swap providers.
class SmsChannel
{
public function __construct(private SmsSender $sender) {}
public function send($notifiable, Notification $notification)
{
$this->sender->send(
$notifiable->routeNotificationFor('sms'),
$notification->toSms($notifiable)
);
}
}
Expose routeNotificationForSms() on your User model so Laravel can resolve the number.
Read config through config(), never env() at runtime. Publish the package config, then in your own config layer:
// config/services.php or config/sms.php
'sms' => [
'otp' => env('KAVENEGAR_SENDER_OTP'),
'marketing' => env('KAVENEGAR_SENDER_MARKETING'),
],
env() returns null once php artisan config:cache runs — a classic "OTPs stopped working in production" bug.
Route senders explicitly for multiple lines. Don't rely on the package's single default sender when you have transactional and marketing lines; pass the sender per message type.
Fake it in tests. Bind a FakeSmsSender / LogSmsSender in the container so CI never burns credit or touches the network, and assert on recorded messages rather than the package's boolean return.
Add observability at the wrapper, not the package. Log mobile (masked), template/message type, provider status code, and Kavenegar's return.message. This is the only telemetry you'll get.
illuminate/support constraint. On Laravel 9+ you may be tempted by --with-all-dependencies or --ignore-platform-reqs; resist — you're inheriting a fork-and-own obligation. The official kavenegar/laravel package or a ~40-line Http client is lower risk.200 OK with a JSON payload whose return.status is 400+ for invalid keys, insufficient credit, blacklisted numbers, or bad sender lines. Never treat a non-exception return as success — parse the status/code inside your SmsSender::send() and log return.message (usually Persian).true/false, you'll have no diagnostic. Log the raw response at your wrapper layer; you'll need it the first time OTPs "silently stop working."Redis::throttle or a RateLimited job middleware; it's cheaper than a support ticket./sms/receive), you implement the controller and verify secrets yourself — assume the package doesn't.Kavenegar alias can clash with other packages or a local class. Prefer constructor-injecting your SmsSender interface over resolving the facade anywhere in application code..env and out of logs; older config files sometimes dump request params on error, which can leak the key into storage/logs.SmsSender implementation. Write it so that removing the package means deleting one class — that's the whole migration path.How can I help you explore Laravel packages today?