Search by

cyberxgh / ghana-sms

opokusaint1

Unified SMS interface for Ghanaian providers (Arkesel, mNotify) for PHP and Laravel.

Package info

github.com/opokusaint1/ghana-sms

pkg:composer/cyberxgh/ghana-sms

Statistics

Installs: 7

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.4.0 2026-10-05 12:42 UTC

This package is auto-updated.

Last update: 2026-11-02 13:54:00 UTC


README

One consistent API for Ghanaian SMS providers. Swap providers by changing one config value.

Provider Status
Arkesel Verified live (send)
mNotify Unit-tested, not yet verified against the live API
Hubtel Unit-tested, not yet verified against the live API

Install

composer require cyberxgh/ghana-sms

Laravel

php artisan vendor:publish --tag=sms-config

.env:

SMS_DRIVER=arkesel
ARKESEL_API_KEY=your-key
ARKESEL_SENDER=MyApp

# or
SMS_DRIVER=mnotify
MNOTIFY_API_KEY=your-key
MNOTIFY_SENDER=MyApp

# or
SMS_DRIVER=hubtel
HUBTEL_CLIENT_ID=your-client-id
HUBTEL_CLIENT_SECRET=your-client-secret
HUBTEL_SENDER=MyApp
use GhanaSms\Laravel\Facades\Sms;

Sms::send('0241234567', 'Your code is 4821');

Plain PHP

$sms = new GhanaSms\SmsManager([
    'default' => 'arkesel',
    'drivers' => ['arkesel' => ['api_key' => '...', 'sender' => 'MyApp']],
]);

$response = $sms->send('0241234567', 'Hello');
$response->success;   // bool
$response->messageId; // string|null

Numbers can be written as 024..., +23324... or 23324...; they are normalized for you.

Bulk sending

use GhanaSms\DTO\Message;

$results = $sms->sendBulk([
    new Message('0241234567', 'Reminder: meeting at 3pm'),
    new Message('0201234567', 'Reminder: meeting at 3pm'),
    new Message('0551234567', 'Your order has shipped'),
]);

Messages with the same body and sender are sent in a single request. Results come back in the same order as the input; an invalid number fails only that message.

Error handling

Every failure has a stable type, whichever provider you use:

$response = $sms->send('0241234567', 'Hello');

if (!$response->success) {
    $response->errorType; // ErrorType::Authentication, InsufficientBalance, InvalidSender, InvalidRecipient, Unknown
    $response->error;     // the provider's message
}

Or let it throw:

use GhanaSms\Exceptions\InsufficientBalanceException;

try {
    $sms->send('0241234567', 'Hello')->throwIfFailed();
} catch (InsufficientBalanceException $e) {
    // top up credits
}

Laravel notifications

Use SMS as a notification channel:

use GhanaSms\Laravel\Messages\SmsMessage;
use Illuminate\Notifications\Notification;

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

    public function toSms($notifiable): SmsMessage|string
    {
        return SmsMessage::create("Your order #{$this->order->id} has shipped")
            ->from('MyShop');          // optional
            // ->driver('mnotify');    // optional: pick a provider per message
    }
}

Tell Laravel which number to use on your notifiable model (usually User):

public function routeNotificationForSms($notification = null): ?string
{
    return $this->phone;
}
$user->notify(new OrderShipped($order));

Failures throw typed exceptions (for example InsufficientBalanceException), so queued notifications are retried or marked failed rather than silently lost. If the model has no phone number, the notification is skipped.

Roadmap

  • Arkesel
  • mNotify
  • Bulk sending, typed errors
  • Hubtel
  • Delivery reports
  • Laravel notification channel
  • WordPress adapter

Testing

composer install && composer test