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

Messaging Laravel Package

inovanti-bank/messaging

A Laravel/PHP package from Inovanti Bank for adding messaging capabilities to your application. It offers a structured way to send, receive, and manage messages, making it easier to integrate bank-related communication workflows with minimal setup and clean, maintainable code.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up. The package is a Laravel service provider, so the usual flow applies:

composer require inovanti-bank/messaging
php artisan vendor:publish --provider="InovantiBank\Messaging\MessagingServiceProvider"
php artisan migrate

Package discovery should register the provider and any facade alias automatically. If it doesn't, check composer.json for extra.laravel.providers before manually adding it to config/app.php — a missing discovery block is a common early tripwire in small packages.

Set credentials before you touch code. Expect a config/messaging.php with a default channel/driver plus per-channel blocks (SMS, email, push, instant message). Copy the env keys it references into .env — typically per-driver credentials (SMS gateway SID/token, mail transport, push service key). Do this first, because most failures in week one are "no driver configured" rather than logic bugs.

Where to look, in order:

  1. config/messaging.php — the source of truth for channels, drivers, and the queue connection.
  2. The manager/facade class (src/MessagingManager.php or similar) — this is the public API surface; read its methods before writing any call sites.
  3. src/Channels/ and src/Drivers/ — tells you exactly which transports are actually supported versus aspirational in the README.
  4. database/migrations/ — whether message/status records are persisted for you, and what columns you can query for delivery reporting.
  5. The service provider's register()/boot() — extension points, bindings, and any registered routes (especially webhook endpoints).

First use case: transactional, low-volume notification — an OTP by SMS or an order-confirmation email — sent through the package's single manager entry point rather than by calling a vendor SDK directly. The whole value proposition is that you write one call site and swap the driver later, so validate that promise on day one with a trivial send:

use InovantiBank\Messaging\Facades\Messaging;

Messaging::channel('sms')->send($recipient, $message);

Confirm what the actual method signature is from the manager class — see Gotchas below on why you shouldn't trust README examples here.

Implementation Patterns

Route everything through one internal service. Don't call the facade from controllers. Wrap it in a thin application-level service (App\Support\MessageDispatcher or a domain-specific notifier) so that driver quirks, retries, logging, and recipient normalization live in one place. When the package's API shifts — likely, given the maturity level — you change one file instead of forty.

Wrap sends in queued jobs, not in the request cycle. Outbound messaging is I/O against a third party; a 3-second gateway timeout should not become a 3-second page load. Give each job a dedicated queue with a low retry count and an explicit $tries/backoff, and pass a stable idempotency key (order ID, notification UUID) so a retry doesn't double-send.

final class SendOrderShippedSms implements ShouldQueue
{
    public int $tries = 3;
    public array $backoff = [10, 60, 300];

    public function handle(MessageDispatcher $dispatcher): void
    {
        $dispatcher->sms($this->order->phone, 'order_shipped', ['order' => $this->order->id]);
    }
}

Use templates at the package layer, not string concatenation in PHP. If the package supports named templates, put copy there so marketing can change wording without a deploy. If it doesn't, keep the template key in your call and render text in your own presenter — but keep the key in the payload regardless, so your stored message records are meaningful in reports.

Normalize recipients once, at the boundary. Convert phone numbers to E.164 and validate email before they reach the dispatcher. Driver-side rejection messages for malformed numbers are usually opaque, and this is the single biggest source of "the package is broken" reports.

Channel fallback as an explicit policy. Model it in your dispatcher: try push, fall back to SMS if the push token is missing or the send fails with a transient error. Don't bury fallback logic in the package's config unless its semantics are documented — behavior on failure is exactly the kind of thing that is under-specified in a young package.

Pair with Laravel Notifications for user-facing messaging. Notification::send() gives you per-user channel preferences and via() routing for free; let the package be the transport underneath rather than re-implementing preference logic. Write a custom notification channel class that delegates to the package.

Handle delivery receipts deliberately. Most multi-channel packages register a webhook route. Exclude it from CSRF (bootstrap/app.php or VerifyCsrfToken), verify the provider signature per driver, and persist status transitions (queued → sent → delivered → failed) idempotently — webhooks retry and arrive out of order. Update by provider message ID, never append blindly.

Test with a fake. If the package ships a fake/Messaging::fake() helper, use it in feature tests and assert on dispatched messages. If it doesn't, bind a recording double to the manager's interface in the container and assert against that. Either way, no test should hit a real gateway.

Observe sends as events. Listen to whatever the package dispatches on send/failure and pipe it into your logs or metrics with the message ID, channel, and latency. Without this you cannot answer "did the customer get the OTP?" during an incident.

Gotchas and Tips

Calibrate expectations to the maturity level. One star, zero dependents, and a future-dated last release mean the README is the least reliable artifact in the repo. Treat the source and the service provider as authoritative; treat any documented method name, config key, or event as a hypothesis to verify in tinker. Pin the version in composer.json and read the changelog before every bump — there is no ecosystem of blog posts or Stack Overflow answers to fall back on.

Duplicate sends are the classic failure. Queued jobs with retries plus a non-idempotent downstream gateway equals customers receiving the same SMS three times. Always pass an idempotency key if the package supports one; if it doesn't, guard in your dispatcher with a cache lock keyed on the logical event ("sms:order-shipped:{$orderId}").

config:cache breaks dynamic config. Reading per-tenant credentials from the database and stuffing them into config() at runtime will silently fail in production once config is cached. Use per-send credentials passed through the call, or a driver instance resolved per tenant, not config() mutation.

"Sent" is not "delivered." A successful API call from the package usually means "accepted by the gateway." Delivery status arrives later via webhook or poll. Never show users a "Delivered" badge based on the send return value, and don't delete your own record of the message after a successful send.

Rate limits and throughput. Gateways throttle per-second and per-day. If the package doesn't expose a rate limiter, wrap sends in RateLimiter::attempt() or a Redis-backed limiter. Bulk campaigns should be chunked with Bus::batch() rather than looped, and given a separate queue so a marketing blast can't starve OTPs.

Driver payloads are not interchangeable. The unified channel abstraction will have a lowest common denominator, and driver-specific options (sender ID, DLT template IDs, push TTL/collapse keys, rich media) will need to be passed through a raw/extras array — or won't be supported at all. Check the driver source before promising a feature to product.

Timeouts and silent failures. Confirm the HTTP client timeout in the driver; Laravel's default can be far longer than your queue's retry_after, which causes jobs to run twice. Log every non-2xx response with the provider body, and distinguish transient (5xx, 429) from permanent (4xx, invalid recipient) failures so you don't retry the unretryable.

Webhook endpoint exposure. Package-registered routes may be unauthenticated by default. Verify signatures, restrict by IP if the provider publishes ranges, and make the handler idempotent and fast — queue the processing, acknowledge with a 200 immediately.

Extension points worth knowing: a driver contract/interface you can implement for an in-house gateway, container bindings in the service provider you can override, and published config. If no driver interface exists, that's your signal to keep the package at arm's length behind your own dispatcher interface rather than leaking it into domain code — and it's a strong argument for evaluating a more established alternative before this becomes load-bearing.

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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel