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

Laravel Bulksmsbd Laravel Package

iqbalhasandev/laravel-bulksmsbd

A Laravel package for sending SMS through the BulkSMSBD gateway. It wraps the BulkSMSBD API in a simple, configurable integration so you can dispatch single or bulk messages from your Laravel app with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a thin convenience wrapper around the BulkSMSBD HTTP API, not an ecosystem-level SMS abstraction. With 21 stars, zero dependents, and an archived repo, treat it as a starting point you will likely own and fork, not a dependency you can rely on for the long term. The day-to-day value is small: it saves you from hand-rolling one Http::get() call. Budget ten minutes to read src/ before wiring it in, because the README is sparse and the public surface is tiny.

Minimal setup

  1. Pin the version explicitly — the package was last released in January 2023 and is archived, so an unpinned require is a future broken build:
    composer require iqbalhasandev/laravel-bulksmsbd:^1.0
    
  2. Publish the config file. Check the service provider's boot() for the exact tag; it is typically:
    php artisan vendor:publish --provider="Iqbalhasandev\BulkSmsBd\BulkSmsBdServiceProvider"
    
  3. Add credentials to .env. Read config/bulksmsbd.php first — the key names are whatever that file reads, commonly BULKSMSBD_API_KEY and BULKSMSBD_SENDER_ID:
    BULKSMSBD_API_KEY=your_api_key
    BULKSMSBD_SENDER_ID=your_approved_sender
    
  4. Confirm the facade alias or service binding registered by the provider. It is usually something like BulkSmsBd::send($number, $message) or a resolvable BulkSmsBdService class.

Where to look first

  • config/bulksmsbd.php — endpoint, credentials, sender ID, any type (text vs unicode) default.
  • src/ — the actual send method and its return shape. This determines everything downstream.
  • The service provider — bindings, facade alias, publish tags. If there is no facade, you will app() the service class.

First use case

The realistic first use is a single transactional message: an OTP on login or an order-confirmation SMS. Verify the whole path once with php artisan tinker against a real number before building anything on top:

BulkSmsBd::send('8801XXXXXXXXX', 'Test message from staging');

If that returns something you can interpret (bool, array, response object), you know enough to proceed.

Implementation Patterns

Pattern 1 — Direct call, immediately wrapped

Do not scatter facade calls through controllers. Put one seam between your app and the package on day one:

interface SmsSender
{
    public function send(string $number, string $message): bool;
}

class BulkSmsBdSender implements SmsSender
{
    public function send(string $number, string $message): bool
    {
        $response = BulkSmsBd::send($number, $message);
        // Normalize the package's return shape to a bool here.
        return (bool) ($response['response_code'] ?? $response);
    }
}

Bind it in a service provider. When the package dies (it is archived, so plan for it), you swap one class instead of grepping the codebase.

Pattern 2 — Queued job with retry

The package makes a synchronous HTTP call. Never do that inline in a request that a user is waiting on:

class SendSms implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public array $backoff = [10, 60, 300];

    public function __construct(
        public string $number,
        public string $message,
    ) {}

    public function handle(SmsSender $sms): void
    {
        if (! $sms->send($this->number, $this->message)) {
            $this->release(60);
        }
    }
}

Note that release() retries forever unless you also fail explicitly — check $this->attempts() if the package cannot distinguish "temporary failure" from "bad number".

Pattern 3 — Notification channel

If the package ships a notification channel (check src/Channels or the README), prefer it for user-facing messages so SMS sits alongside mail and database notifications:

public function via($notifiable): array
{
    return [BulkSmsBdChannel::class];
}

public function toBulkSmsBd($notifiable): string
{
    return "Your order #{$this->order->id} has shipped.";
}

The notifiable needs a phone attribute the channel can find — usually phone or phone_number. Verify which one the channel reads before renaming columns.

Pattern 4 — Bulk sends

BulkSMSBD accepts comma-separated numbers in a single request. Use that for announcements instead of looping, but chunk to a sane size (50–100 per request) so one bad number does not poison the whole batch, and so a timeout does not lose an hour of sends.

Pattern 5 — Bangla / Unicode content

The API distinguishes text and unicode type. If you send Bangla, you must set the unicode type, otherwise the message arrives as garbage. Check whether the package exposes that parameter; if not, this is your first fork patch.

Pattern 6 — Testing

Never hit the live API in tests. Fake the underlying HTTP call if the package uses the Laravel HTTP client:

Http::fake([
    'bulksmsbd.net/*' => Http::response(['response_code' => 202], 200),
]);

If it uses raw cURL or Guzzle directly, bind a fake SmsSender in the container instead and assert against that. This is another argument for the wrapper in Pattern 1.

Gotchas and Tips

The archive status is the headline risk. There is no Laravel 11/12 compatibility guarantee and no security patches. Check composer.json constraints against your framework version before installing. If you are on a modern Laravel, budget for a fork or a 30-line replacement using Http::withHeaders()->post().

The endpoint is often plain HTTP. BulkSMSBD's API has historically been served over http://bulksmsbd.net/api/smsapi, which sends your API key and message contents in cleartext. If the config allows an HTTPS base URL, use it; if not, patch the config and verify the gateway accepts TLS.

Number formatting will bite you. The API expects a specific Bangladeshi format — usually 8801XXXXXXXXX rather than 01XXXXXXXXX. Normalize at the boundary: strip spaces and dashes, convert local 01 prefixes to 8801, and reject anything that is not 13 digits after normalization. A silently malformed number returns a generic failure that is easy to misread as a credential problem.

Response parsing is inconsistent. The gateway returns JSON with response_code, success_message, and error_message, but the package may return the raw array, a bool, or a decoded object depending on version. Log the raw response once during integration, then normalize to a single return type in your wrapper. Do not trust a truthy string as success.

Config caching. After changing .env credentials, run php artisan config:clear (or config:cache in deploy). The classic "it works in tinker but not in the app" symptom is a stale cached config reading old credentials.

Sender ID must be approved. A masked sender ID that is not registered against your BulkSMSBD account will fail at the gateway, not in your code. Confirm approval in the BulkSMSBD dashboard before debugging further.

Set timeouts. The package likely uses a default HTTP timeout (or none). Wrap the call or override the client so a hung gateway does not stall your queue worker. 10–15 seconds is reasonable.

Cost and rate limits. Every retry costs money. Cap $tries, and add per-number throttling for OTPs (e.g. one per 60 seconds via RateLimiter) so a stuck job cannot spam a user or burn credit.

Do not log phone numbers or message bodies at info level. They are PII and often contain OTPs. Log the normalized response code and a hash of the number instead.

Extension points are your exit ramp. The useful knobs are the published config (endpoint, credentials, sender ID) and the container binding. If the package's facade is bound as a singleton, you can app()->instance() a decorated version in a service provider to add logging, retries, or normalization without touching vendor code. That decorator is also the cleanest migration path when you eventually replace the package.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource