Weave Code
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

Spot Hit Notifier Laravel Package

symfony/spot-hit-notifier

Symfony Notifier transport for Spot-Hit SMS. Configure via SPOTHIT_DSN with your API token and sender (from), with optional settings for long SMS and concatenation count validation. Links to Spot-Hit API docs and Symfony issue/PR channels.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the Package (via Composer):

    composer require symfony/spot-hit-notifier
    

    Note: Since this is a Symfony package, direct Laravel integration requires a wrapper or Symfony components. Use symfony/http-client and symfony/messenger as alternatives if needed.

  2. Configure DSN in .env:

    SPOTHIT_DSN=spothit://YOUR_SPOTHIT_TOKEN@default?from=YOURSENDER&smslong=1
    
    • Replace YOUR_SPOTHIT_TOKEN with your Spot-Hit API key.
    • from is optional (default: 5-digit phone number).
    • smslong enables long SMS (set to 1 for messages >160 chars).
  3. First Use Case: Send an SMS Use Laravel’s Notification facade or Symfony’s Notifier component (if integrated via a bridge). Example with Laravel’s Notification:

    use Illuminate\Support\Facades\Notification;
    use App\Notifications\SpotHitSMS;
    
    Notification::route('spot-hit', '+33612345678')
                ->notify(new SpotHitSMS('Your verification code is: 123456'));
    

    Create a custom SpotHitSMS notification class extending Illuminate\Notifications\Notification.


Implementation Patterns

1. Symfony Notifier Integration (Recommended for Laravel)

Since Laravel lacks native Symfony Notifier support, create a wrapper class to bridge the gap:

// app/Services/SpotHitNotifier.php
namespace App\Services;

use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Transport\SpotHitTransport;
use Symfony\Component\Notifier\Message\SmsMessage;

class SpotHitNotifier
{
    public function __construct(private Notifier $notifier)
    {
        $this->notifier = $notifier;
    }

    public function sendSMS(string $phone, string $message): void
    {
        $transport = new SpotHitTransport('spothit://' . env('SPOTHIT_DSN'));
        $this->notifier->send(new SmsMessage($message), $phone, $transport);
    }
}

Register the service in AppServiceProvider:

public function register()
{
    $this->app->singleton(SpotHitNotifier::class, function ($app) {
        return new SpotHitNotifier(new Notifier());
    });
}

2. Laravel Notification Channel (Alternative)

Extend Laravel’s NotificationChannel to use Spot-Hit:

// app/Channels/SpotHitChannel.php
namespace App\Channels;

use Illuminate\Notifications\Notification;
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Transport\SpotHitTransport;
use Symfony\Component\Notifier\Message\SmsMessage;

class SpotHitChannel
{
    public function __construct(private Notifier $notifier)
    {}

    public function send($notifiable, Notification $notification)
    {
        $message = $notification->toSpotHit($notifiable);
        $transport = new SpotHitTransport('spothit://' . env('SPOTHIT_DSN'));
        $this->notifier->send($message, $notifiable->route['spot-hit'], $transport);
    }
}

Register the channel in config/services.php:

'channels' => [
    'spot-hit' => [
        'driver' => 'spot-hit',
    ],
],

3. Workflow: Sending Notifications

  • Step 1: Define a notification class:
    // app/Notifications/SpotHitSMS.php
    namespace App\Notifications;
    
    use Illuminate\Notifications\Notification;
    use Symfony\Component\Notifier\Message\SmsMessage;
    
    class SpotHitSMS extends Notification
    {
        public function __construct(private string $message)
        {}
    
        public function toSpotHit($notifiable)
        {
            return new SmsMessage($this->message);
        }
    }
    
  • Step 2: Trigger the notification:
    use App\Notifications\SpotHitSMS;
    use Illuminate\Support\Facades\Notification;
    
    Notification::route('spot-hit', '+33612345678')
                ->notify(new SpotHitSMS('Hello from Laravel!'));
    

4. Handling Long SMS

Configure smslong in .env and validate message length in your notification class:

public function toSpotHit($notifiable)
{
    $message = $this->message;
    if (strlen($message) > 160 && env('SPOTHIT_SMSLONG', 0) !== '1') {
        throw new \RuntimeException('Long SMS not enabled in config.');
    }
    return new SmsMessage($message);
}

Gotchas and Tips

Pitfalls

  1. Symfony Dependency Conflicts:

    • The package assumes Symfony’s HttpClient and Notifier. If conflicts arise (e.g., version mismatches), use Laravel’s HttpClient or Guzzle as a drop-in replacement:
      // Replace Symfony's HttpClient with Laravel's
      $client = new \Illuminate\Http\Client\PendingRequest();
      
    • Fix: Create a custom transport class extending Symfony\Component\Notifier\Transport\AbstractTransport and override __send() to use Laravel’s HTTP client.
  2. DSN Configuration Errors:

    • Invalid SPOTHIT_DSN formats (e.g., missing from or smslong) will throw cryptic exceptions.
    • Debug Tip: Log the parsed DSN components:
      $dsn = 'spothit://TOKEN@default?from=FROM&smslong=1';
      $parts = parse_url($dsn);
      // Log $parts['query'] to verify parameters.
      
  3. Message Length Rejection:

    • Spot-Hit rejects messages exceeding the expected concatenated SMS count (specified by smslongnbr).
    • Solution: Calculate the expected SMS count in your notification class:
      $expectedSmsCount = ceil(strlen($message) / 160);
      if ($expectedSmsCount !== (int) env('SPOTHIT_SMSLONGNBR', 0)) {
          throw new \RuntimeException("Message length mismatch. Expected {$expectedSmsCount} SMS.");
      }
      
  4. Rate Limiting:

    • Spot-Hit may throttle requests. Implement exponential backoff in your transport layer:
      use Symfony\Component\Notifier\Exception\TransportException;
      use Symfony\Component\Notifier\Transport\RetryStrategy;
      
      $transport = new SpotHitTransport($dsn, new RetryStrategy(3, 1000));
      

Debugging Tips

  1. Enable Symfony Notifier Debugging: Add this to config/services.php to log transport interactions:

    'notifier' => [
        'debug' => env('APP_DEBUG', false),
    ],
    

    Check Laravel logs for Symfony\Component\Notifier\ entries.

  2. Mock Spot-Hit in Tests: Use Laravel’s HttpClient mocking to test without hitting Spot-Hit’s API:

    use Illuminate\Support\Facades\Http;
    
    Http::fake([
        'api.spot-hit.com' => Http::response('{"status":"success"}'),
    ]);
    
    // Test your notification logic here.
    
  3. Validate API Responses: Spot-Hit may return non-200 status codes (e.g., 400 for invalid numbers). Handle these in your transport class:

    public function __send(SmsMessage $message, $to): void
    {
        $response = Http::post('https://api.spot-hit.com/sms', [
            'to' => $to,
            'message' => $message->getContent(),
        ]);
    
        if ($response->status() !== 200) {
            throw new TransportException('Spot-Hit API error: ' . $response->body());
        }
    }
    

Extension Points

  1. Custom Transport Logic: Extend Symfony\Component\Notifier\Transport\AbstractTransport to add features like:

    • Message Templates: Replace plain text with Twig templates.
    • Webhook Callbacks: Trigger events on delivery status.
    • Fallback Transports: Retry failed messages via email or another channel.
  2. Event Listeners: Use Laravel’s events to react to notification failures:

    // app/Providers/EventServiceProvider.php
    protected $listen = [
        \Symfony\Component\Notifier\Exception\TransportException::class => [
            \App\Listeners\HandleSpotHitFailure::class,
        ],
    ];
    
  3. Dynamic DSN Configuration: Load the DSN dynamically (e.g., from a database) for multi-tenant apps:

    $
    
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.
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views