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

Sdk Laravel Package

target365/sdk

PHP SDK for Target365’s messaging platform, making it easy to send SMS and RCS messages, manage contacts and subscriptions, and handle delivery reports from Laravel or any PHP app via a clean, PSR-compatible API.

View on GitHub
Deep Wiki
Context7

Getting Started

Target365 is a Norwegian SMS gateway (with premium-SMS/Strex payment support). This SDK is a thin PHP client over their REST API — not a Laravel package. There is no service provider, no facade, no config to publish. Plan to wire it up yourself.

1. Install

composer require target365/sdk

The last release was 2025-03-11, so pin a version ("target365/sdk": "^2.0" or whatever the README shows) and commit composer.lock.

2. Add credentials to config/services.php

'target365' => [
    'base_url' => env('TARGET365_BASE_URL', 'https://test.target365.io'),
    'key'      => env('TARGET365_KEY'),
    'secret'   => env('TARGET365_SECRET'),
],

Target365 uses an API key/secret pair that the SDK signs per-request; both test and api (production) hosts exist with different credentials.

3. Look at first in the README

Read the constructor signature for Target365Client and the Models\OutboundMessage class — those two define how you actually send anything. Most of the rest of the SDK is DTOs (StrexTransaction, Keyword, Content, etc.) that mirror the REST payloads.

4. First use case: send an SMS

use Target365\Sdk\Target365Client;
use Target365\Sdk\Models\OutboundMessage;

$client = new Target365Client(
    config('services.target365.base_url'),
    config('services.target365.key'),
    config('services.target365.secret'),
);

$message = new OutboundMessage();
$message->recipient = '+4799999999';          // E.164
$message->content   = 'Thanks for your order #1234';
$message->transactionId = (string) Str::uuid(); // your idempotency key
$message->sender    = 'MyShop';

$client->send($message); // adjust to README — often ->outbound->send(...) or ->sendSms(...)

Once a single SMS lands on a real handset in test mode, you have enough to build everything else.

Implementation Patterns

Bind as a singleton in a service provider

// AppServiceProvider::register()
$this->app->singleton(Target365Client::class, fn () => new Target365Client(
    config('services.target365.base_url'),
    config('services.target365.key'),
    config('services.target365.secret'),
));

Wrap it behind your own interface (SmsGateway) so tests and non-Target365 paths can fake it without depending on SDK internals.

Send from a queued job, never the request cycle

Sending takes hundreds of milliseconds and can fail. Put it in a job:

final class SendSms implements ShouldQueue
{
    use Queueable;

    public function __construct(public string $to, public string $body) {}

    public function handle(Target365Client $client): void
    {
        $msg = new OutboundMessage();
        $msg->recipient = $this->to;
        $msg->content = $this->body;
        $msg->transactionId = $this->job->uuid(); // stable per job, safe on retry
        $client->send($msg);
    }

    public function backoff(): array { return [10, 60, 300]; }
    public function retryUntil() { return now()->addHours(6); }
}

The transactionId is your friend: use a deterministic value (Str::uuid() stored before dispatch, or the job UUID) so a queued retry after a timeout doesn't double-send.

Use it for the whole messaging workflow

Typical flows: OTPs, order/shipping notifications, appointment reminders, and premium-SMS/Strex payments. Strex has its own transaction model and a callback flow — treat that as a separate, more careful integration than plain outbound SMS.

Receive callbacks on a public endpoint

Delivery reports and inbound replies are pushed to a URL you configure in the Target365 portal. Build a Route::post('/webhooks/target365', ...) that is api.php-style, no CSRF, no auth middleware — and verify the signature yourself. Look up the message by your own transactionId, not by Target365's internal ID, so your system can find the original record.

Test by mocking the transport

If the SDK accepts an injected GuzzleHttp\Client or PSR-18 client, use MockHandler:

$mock = new MockHandler([new Response(200, [], '{"id":"abc"}')]);
$client = new Target365Client(new GuzzleClient(['handler' => HandlerStack::create($mock)]), ...);

If it doesn't, don't fight it — resolve your SmsGateway interface to a fake in tests and only exercise the SDK in one integration test.

Gotchas and Tips

  • It's not Laravel-aware. No ServiceProvider, no publish, no facade. If you find a tutorial referencing Target365::send(...), it doesn't exist here.
  • Test vs. production base URL. Defaulting to https://test.target365.io is right for local and CI; make sure TARGET365_BASE_URL is set per environment, and make sure prod credentials never leak into test config.
  • Signature auth and clock skew. The SDK signs requests with a timestamp/nonce. On container hosts with drifting clocks you'll get 401s that look like bad credentials — keep NTP running. Also check the README for how the key/secret is passed; some setups call for a pre-signed API key.
  • Class and method names have drifted between versions. Target365Client, OutboundMessage, send() vs. outbound->send() differ across tags. Pin the version and confirm method names against the README for that tag, not the latest docs on the web.
  • Phone numbers must be E.164. +47… for Norway. Validate on the way in; Target365 will reject 99999999 and the error surfaces late.
  • Message encoding and length. Plain GSM-7 is ~160 chars; anything with æøå or emoji flips to UCS-2 and cuts the limit to ~70. Segments cost money — validate lengths and warn users in the UI, otherwise a "short" SMS quietly becomes 3 parts.
  • Don't retry a 4xx. Validate, parse, and log the error body — 401 is auth, 400 is malformed payload, 429 is rate limit (retry with backoff), 5xx is transient. Blind ->retry(3) in the job will triple-bill you on a 400.
  • Delivery is asynchronous. A 200 from send means "accepted", not "delivered". Track delivery reports via webhook and persist state (sent → delivered / failed) against your transactionId.
  • sendTime is UTC ISO-8601. If you schedule messages in local time you'll be off by one or two hours (CET/CEST). Use now()->utc()->toIso8601String().
  • Webhook signature. Verify the HMAC header before acting on it, and respond 200 quickly — enqueue the actual processing. Target365 will retry failed callbacks.
  • Small community. 3 stars, 0 dependents. That's fine — the SDK is small and the API is documented — but treat the SDK source as the real documentation, and expect to read it once. Keep it behind your own SmsGateway abstraction so you can swap or fork later.
  • Log the request id. Persist Target365's returned message ID alongside your transactionId so support tickets can be traced end-to-end.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
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