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

Kudi Sms Php Laravel Package

toneflix-code/kudi-sms-php

A Laravel/PHP package for sending SMS through the Kudi SMS API. It offers a simple, framework-friendly interface for adding transactional or bulk messaging to your applications, with straightforward configuration and a clean API for quick integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm the package is actually installed and what it exposes before designing around it:

composer require toneflix-code/kudi-sms-php:1.0.6

Then read, in this order:

  1. composer.json — PHP version constraint, whether Guzzle/cURL is used, and whether there is a extra.laravel block (i.e. auto-discovery). With zero dependents and a single maintainer, the source is the documentation.
  2. src/ — the main client class, its constructor signature (API token? sender ID? base URI?), and the exact method names and return types.
  3. README.md — usually the only usage example.

Provision credentials from your KudiSMS dashboard: an API token and an approved sender ID. The sender ID is not something you invent at call time — it must be registered/approved on the KudiSMS side, so request it before you write code.

Minimal first use case: a transactional message to a Nigerian MSK number.

// Namespace/class are illustrative — confirm from composer.json and src/.
use ToneflixCode\KudiSmsPhp\KudiSms;

$sms = new KudiSms(apiToken: config('services.kudisms.token'));

$response = $sms->send(
    to: '2348030000000',
    message: 'Your verification code is 123456',
    senderID: config('services.kudisms.sender'), // note: `senderID` on >=1.0.6; `senderId` on <=1.0.5
);

// Inspect the raw response; don't assume a bool.
logger()->info('kudisms.send', ['response' => $response]);

If the constructor takes positional arguments, wrap the instantiation in your own factory so you are not coupled to the signature. Get one real message delivered end-to-end (including a non-Nigerian number rejected cleanly) before building abstractions on top.

On 1.0.6 specifically: the release only renames the parameter senderId → senderID. That is a no-op for positional callers and a hard Error/TypeError for anyone using named arguments. Before adopting, grep your codebase (and any published stubs/tests) for senderId and update. The rename does tell you the sender ID is accepted by the client (constructor and/or send()), so it's a required credential, not a dashboard-only setting.

Implementation Patterns

Bind it in the container, don't new it in controllers. Because this is a framework-agnostic PHP wrapper, it almost certainly has no service provider. Register it yourself:

// app/Providers/AppServiceProvider.php
$this->app->singleton(KudiSms::class, fn () => new KudiSms(
    token: config('services.kudisms.token'),
    // sender/base URI if the constructor accepts them
));

Add config/services.php entries (token, sender, timeout) and matching .env keys (KUDISMS_TOKEN, KUDISMS_SENDER). Never hardcode the token.

Never pass the sender ID by named argument at the call site. The 1.0.6 rename is proof that this package's parameter names are not a stable contract — it is a typo fix in a 1.0.x patch, which under SemVer is technically a breaking change for named callers. Resolve the sender from config inside your adapter instead, so a future senderID → sender_id rename is a one-line diff in one class.

Hide it behind your own interface. The package has 0 stars and 0 dependents; treat it as replaceable. Define App\Contracts\SmsGateway with send(string $to, string $message): SmsResult and implement it with a KudiSmsGateway adapter. When you outgrow the wrapper (or it is abandoned), you swap one class, not every call site.

Integrate via a Laravel Notification channel. This is the highest-leverage day-to-day pattern: OTP, order updates, and payment confirmations all become notifications rather than direct calls.

class KudiSmsChannel
{
    public function __construct(private SmsGateway $gateway) {}

    public function send(object $notifiable, Notification $notification): void
    {
        $this->gateway->send($notifiable->routeNotificationFor('sms'), $notification->toSms($notifiable));
    }
}

Then return [(new KudiSmsChannel(app(SmsGateway::class)))]; from via().

Queue bulk sends and chunk recipients. Whether the wrapper exposes a bulk endpoint or only a single-send method, do not loop synchronously inside a request. Push a job, chunk recipients (e.g. 50–100 per API call if bulk is supported, or sequential calls with a small delay otherwise), and record per-recipient results.

Persist an audit row per send. Store recipient, sender ID, message hash (not necessarily the full body, for privacy), provider response/message ID, and status. This is what makes debugging "did the customer get the OTP?" tractable and lets you reconcile against the KudiSMS dashboard.

Retry deliberately. Wrap sends in a job with $tries = 3 and exponential backoff, but only for transport errors and 5xx responses. A 4xx (bad number, unapproved sender, insufficient balance) must fail fast — retrying it burns money and time.

Fake it in tests. Bind a FakeSmsGateway implementing your contract in the test container and assert on recorded messages. Do not hit the live API from CI.

Upgrade with eyes open. 1.0.6 is a two-word diff; check out 1.0.5..1.0.6 anyway, since a single-maintainer project can slip behaviour changes into a "typo fix" commit. If you cannot upgrade immediately, pin 1.0.5 exactly rather than using ^1.0, which would silently pull the rename on your next composer update.

Gotchas and Tips

  • 1.0.6 renamed senderId → senderID. If you call with named arguments (senderId: $sender), this patch release breaks you at runtime. It will not show up in static analysis of the vendor class if you are passing it through dynamically, and it will not show up in tests that never exercise the real client. Grep for senderId, update, and pin the version in composer.json.
  • Number formats differ from what you expect. Nigerian numbers arrive as 0803…, +234803…, 234803…, and with stray spaces/dashes. Normalize to one canonical form in an adapter layer and confirm from the source which format KudiSMS expects. A wrong prefix often returns a 200 with an error body rather than an exception.
  • HTTP 200 does not mean success. Many SMS gateways return {status: "error"} with a 200. Always parse the response payload and check the wrapper's success signal — or the absence of one. If the wrapper returns raw arrays, wrap that in your own SmsResult DTO with an ok flag.
  • Sender ID is pre-approved and per-account. An unregistered sender may be silently substituted or rejected. If messages arrive with the wrong sender, check this first — and note the client may only surface a generic error for it.
  • Timeouts inside the request cycle. Default Guzzle timeouts (often 30s) are fatal for OTP on a login request. Set a short connect/read timeout (3–5s) if the client exposes one; otherwise configure the underlying client or send OTP from a queued job and verify via polling/websocket.
  • No auto-discovery. Don't assume a publishable config or facade exists. Read composer.json for extra.laravel; if it is absent, none of that is wired up, and any "config" file is something you create.
  • Unicode and segment billing. GSM-7 vs UCS-2 changes the per-message segment count (and your cost). Emoji or non-Latin characters can double or triple the billed segments. Trim messages or validate length before sending.
  • Balance and rate limits. Check the account balance endpoint (if exposed) before large campaigns; a batch that fails halfway is worse than a pre-flight check. Add a small delay between sequential sends to avoid per-second rate limits.
  • Pin the version. With a single maintainer and no dependents, composer.json should use an exact or tilde constraint rather than *. 1.0.6 is a concrete example of why: a cosmetic-looking patch was source-breaking for named-argument consumers. Vendor the repo if you need a fix upstream has not merged.
  • Logging hygiene. Never log the API token; mask recipient numbers in logs (NDPR/GDPR). Log the provider message ID, not the OTP body.
  • Extension points are limited. If the client does not accept an injected HTTP client, you cannot intercept requests for testing or tracing — another reason to keep everything behind your own SmsGateway interface from day one.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin