Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Touch Sms Laravel Package

laravel-notification-channels/touch-sms

A Laravel notification channel for sending SMS through Touch SMS. Connect the Touch SMS gateway to Laravel's notification system and deliver messages from any notification class using a dedicated channel and simple configuration. Useful for transactional messages and alerts.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a standard Laravel notification channel, so the setup mirrors Vonage/Twilio-style channels you already know. As of 2.1.0 it supports Laravel 12.x, so you can use it on current projects without a version pin conflict.

1. Install and let package discovery register the provider:

composer require laravel-notification-channels/touch-sms

2. Add credentials. Either publish the package config or add a block to config/services.php (check the README for the exact key name — these channels usually read services.touch_sms.* or a dedicated config/touch-sms.php):

// config/services.php
'touch_sms' => [
    'token' => env('TOUCH_SMS_TOKEN'),
    'from'  => env('TOUCH_SMS_FROM'),   // sender ID / number registered with TouchSMS
],
TOUCH_SMS_TOKEN=your-api-token
TOUCH_SMS_FROM=YourBrand

3. Make your notifiable routable. The channel needs a recipient number, so add a routing method to the model:

public function routeNotificationForTouchSms(): ?string
{
    return $this->phone; // E.164, e.g. +61412345678
}

4. First use case — a shipping or OTP notification:

use Illuminate\Notifications\Notification;
use NotificationChannels\TouchSms\TouchSmsChannel;
use NotificationChannels\TouchSms\TouchSmsMessage;

class OrderShipped extends Notification
{
    public function via($notifiable): array
    {
        return [TouchSmsChannel::class];
    }

    public function toTouchSms($notifiable): TouchSmsMessage
    {
        return TouchSmsMessage::create()
            ->content("Order #{$this->order->id} is on its way.");
    }
}

Trigger with $user->notify(new OrderShipped($order)); and confirm the send landed in the TouchSMS dashboard.

Where to look first: the README (fluent methods on TouchSmsMessage), then src/TouchSmsChannel.php (~100 lines, easy to read end-to-end) and the service provider. Because the package is young and low-star, reading the channel source is the fastest way to understand exactly which HTTP endpoint and payload shape it emits.

Implementation Patterns

Fluent message construction. The message object is the natural unit of reuse — compose it in the notification's toTouchSms() method and keep string interpolation out of the channel:

public function toTouchSms($notifiable): TouchSmsMessage
{
    return TouchSmsMessage::create()
        ->content($this->body)
        ->from(config('services.touch_sms.from')); // override per-message
}

Multi-channel fan-out. Pair SMS with mail/database so users can opt into SMS without losing the durable record:

public function via($notifiable): array
{
    return $notifiable->sms_opt_in
        ? [TouchSmsChannel::class, 'mail', 'database']
        : ['mail', 'database'];
}

Always queue SMS. Notifications should implement ShouldQueue — SMS APIs are the slowest, flakiest dependency in the request path:

class OrderShipped extends Notification implements ShouldQueue
{
    public int $tries = 3;
    public int $backoff = 30;
}

The channel itself typically does no retrying, so queue-level $tries/$backoff is your resilience story.

Testing without hitting TouchSMS. Fakes keep the suite fast:

Notification::fake();
$user->notify(new OrderShipped($order));
Notification::assertSentTo($user, OrderShipped::class);

// If you want to assert the payload, use the message object directly:
$message = (new OrderShipped($order))->toTouchSms($user);
$this->assertStringContainsString('Order #', $message->content);

If you need to assert on HTTP shape, Http::fake() and assert the URL/body rather than mocking the channel class.

Wrapping in a domain service. For OTPs, wrap in a small service so tokens, expiry, and rate-limiting live in your code, not in notifications:

class OtpService
{
    public function send(User $user): void
    {
        $code = Str::random(6);
        Cache::put("otp:{$user->id}", $code, now()->addMinutes(5));
        $user->notify(new SendOtp($code));
    }
}

Integration tips.

  • Register the channel class explicitly in via() rather than a string alias — it's clearer and survives refactors.
  • Use a dedicated sender ID per use case (transactional vs. marketing) if TouchSMS lets you register multiple.
  • Log the notifiable ID, not the phone number, from NotificationSent/NotificationFailed events.
  • On Laravel 12, package discovery and the notification channel contract are unchanged, so existing notifications port over with no code changes.

Gotchas and Tips

Phone number format is on you. The channel does not normalize numbers. Store and pass E.164 (+61412345678); mixing local (0412...) and international formats is the most common "message never arrived" bug.

Sender ID rules bite. Australian numbers have strict alphanumeric sender ID registration. An unregistered from may be rejected or silently rewritten to a shared shortcode. If you change TOUCH_SMS_FROM for a new brand, test in sandbox first.

config:cache freezes credentials. After changing .env, run php artisan config:clear in local dev. A stale cached config with the old token is an easy 90-minute debug session.

Segment math. A single message segment is ~160 GSM characters; anything longer is billed multiple times and may be split by the carrier. Trim notification bodies, or explicitly track length:

if (mb_strlen($content) > 160) { /* split or shorten */ }

Token-in-URL risk. TouchSMS's REST API historically accepts the token as a query parameter. If the package does this, the token can leak into HTTP client logs, Telescope, or exception messages. Turn off Http::globalOptions() debug logging for the TouchSMS host, and never dump request objects in exception handlers.

routeNotificationForTouchSms must exist. Forgetting it produces a NotificationException at dispatch time, not at registration — surprising in queue workers where the failure is silent until you check failed_jobs. Add a fallback:

public function routeNotificationForTouchSms()
{
    return $this->phone ?: null; // channel skips if null in most implementations
}

Verify the channel's null handling in its source; if it throws instead of returning early, guard your via() accordingly.

Version pinning and framework support. The 2.1.0 release is a Laravel 12.x support bump — no API changes to the channel or message classes, so no migration work if you're already on 2.x. Pin to the current line so you get future Laravel compatibility fixes without surprise majors:

"laravel-notification-channels/touch-sms": "^2.1"

The package remains small (five stars, zero dependents), so still vendor-review TouchSmsChannel.php before upgrading. If your needs outgrow it (delivery receipts, batch sends, template IDs), swapping to a thin custom Http:: client is a ~50-line change — the channel interface is the only contract you need to preserve.

Extension points.

  • Subclass TouchSmsChannel and override the send method to add logging, metrics, or fallback providers.
  • Wrap TouchSmsMessage construction in a factory/builder so all SMS copy lives in one place.
  • Listen to Illuminate\Notifications\Events\NotificationFailed to alert on repeated TouchSMS failures — the channel's own error reporting is minimal.

Debugging order of operations: (1) routeNotificationForTouchSms returns the right number, (2) token present via config('services.touch_sms.token') after config:cache, (3) sender ID registered for your destination country, (4) Http::fake a known-good payload against the real API with Http::withOptions(['debug' => true]) once.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo