leonis/easysms-notification-channel
A Laravel notification channel for EasySMS that lets you send SMS messages through Laravel’s notification system. Integrate EasySMS gateways with a simple, consistent API for delivering text messages from your app.
The package is a thin bridge between Laravel's notification system and overtrue/easysms, so you spend almost no time on the channel itself and most of your time on the EasySms gateway config. Start there first.
composer require leonis/easysms-notification-channel
Laravel auto-discovery registers the service provider. Next, publish the EasySms config (this is the file you'll actually live in):
php artisan vendor:publish --provider="Overtrue\EasySms\EasySmsServiceProvider"
config/easysms.php holds default, gateways (aliyun, tencent, yunpian, etc.), and timeout. Put credentials in .env and reference them from the config.
Then create a notification:
use Leonis\Notifications\EasySms\Channels\EasySmsChannel;
use Leonis\Notifications\EasySms\Messages\EasySmsMessage;
class VerificationCode extends Notification
{
public function via($notifiable)
{
return [EasySmsChannel::class];
}
public function toEasySms($notifiable)
{
return (new EasySmsMessage())
->setTemplate('SMS_123456')
->setData(['code' => 1234]);
}
}
Add a routing method to the notifiable (usually User):
public function routeNotificationForEasySms($notification)
{
return $this->phone;
}
First use case to prove the wiring: a one-off php artisan tinker call, $user->notify(new VerificationCode()), using EasySms's log gateway locally so you see the payload without sending real SMS.
Template-driven sending (default for CN gateways). Aliyun/Tencent require pre-approved templates, so the pattern is almost always setTemplate() + setData() and rarely setContent(). Treat setContent() as a local/dev or international-gateway affordance.
public function toEasySms($notifiable)
{
return (new EasySmsMessage())
->setTemplate('SMS_987654')
->setData(['name' => $notifiable->name, 'amount' => $this->amount]);
}
Per-message gateway override. Useful for failover or when one message type needs a different provider:
return (new EasySmsMessage())
->setGateway('tencent')
->setTemplate('...')->setData([...]);
Multiple recipients. routeNotificationForEasySms can return an array, and the message is dispatched to each number. Combine with Notification::route('easysms', $numbers)->notify(...) for ad-hoc sends where the recipient isn't a user model.
Queueing. SMS is slow and provider rate-limited — always implement ShouldQueue on OTP and marketing notifications. The channel is synchronous; without a queue your request thread pays the HTTP latency.
class OrderShipped extends Notification implements ShouldQueue
{
public $tries = 3;
public $backoff = [10, 60];
}
Reusable message builder. When 10 notifications share the same template shape, extract a trait or base notification that returns a configured EasySmsMessage. It keeps notification classes one-liners and the template IDs in one place.
Testing. In tests, either use Notification::fake() and assert on the notification class (fastest, doesn't touch the channel), or set easysms.default = 'log' in the testing config so the channel writes to the log and you can assert on output.
Monitoring. Because gateway errors surface as EasySms exceptions, wrap the dispatch in your own listener on Illuminate\Notifications\Events\NotificationFailed to log the provider response — that's where content, template, and data are in the event payload.
config('easysms.*'); after changing gateways, run php artisan config:cache (or config:clear) or your old credentials linger. Also verify config/easysms.php actually got published — the service provider registers it, but if you renamed the file, the package silently reads nulls.+86 or national-format depending on the gateway; EasySms validates but doesn't normalize. Normalize in routeNotificationForEasySms (strip spaces/dashes, add country code) rather than in each notification.setContent() won't work on Chinese gateways. Aliyun rejects raw content without a registered template; you get an EasySms\Exceptions\InvalidArgumentException that looks cryptic. If your notification works locally with the log gateway but fails in production, this is usually why.routeNotificationForEasySms returns null/empty, the channel no-ops. Add a fallback (?? $this->phone) or a test asserting the number is non-empty.composer.json lock before copying examples from the README — a config that worked two years ago will silently misbehave. Pin a known-good minor in composer.json.GatewayInterface and register it in config/easysms.php. The channel just forwards to EasySms::send().$tries/$backoff instead of retrying bad templates forever.usleep or dispatch through a queue with ->delay() to avoid hitting the provider's limit when a marketing blast shares the same account.How can I help you explore Laravel packages today?