sunra/turbosms-bundle
Symfony bundle that integrates the TurboSMS SMS gateway, helping you configure API credentials and send SMS messages from your application through a simple service-based interface.
The first thing to internalize: this is a Symfony2 bundle, not a Laravel package. There is no service provider, no facade, no config/turbosms.php. If you install it into a Laravel app you will be pulling in symfony/dependency-injection, symfony/http-kernel, and friends from the 2016 era, and you will spend more time wiring the container than sending an SMS. Treat the repository as a reference implementation of the TurboSMS HTTP API rather than a dependency you composer require.
That said, if you inherit a project (or a legacy Symfony2 service) that already uses it, here is where to look first:
DependencyInjection/*Extension.php) — this defines the config keys (login, password, sender, debug, etc.). Your credentials and default sender live here.Services/*.php or Service/Turbosms.php) — this is the thin wrapper around https://api.turbosms.ua. Every method you care about (send, getMessageStatus, getBalance) is a file_get_contents/cURL call to a JSON endpoint.Minimal first use case, in a Laravel app, by calling the API directly (which is what the bundle does under the hood):
// config/services.php
'turbosms' => [
'token' => env('TURBOSMS_TOKEN'),
'sender' => env('TURBOSMS_SENDER', 'Msg'),
],
$response = Http::withToken(config('services.turbosms.token'))
->post('https://api.turbosms.ua/message/send.json', [
'recipients' => ['380501234567'],
'sms' => [
'sender' => config('services.turbosms.sender'),
'text' => 'Your code is 1234',
],
]);
// $response['response_code'] === 0 means accepted
// $response['response_result'][0]['message_id'] is what you persist
If you genuinely need the bundle in a Symfony app, the steps are: add the repo to composer.json, register Sunra\TurbosmsBundle\TurbosmsBundle in AppKernel, add turbosms: { login: ..., password: ... } to config.yml, then inject turbosms (the service id) into your controller.
Wrap it, don't touch it. Whether you keep the bundle or reimplement, put a single interface in front of SMS sending so the choice is reversible:
interface SmsSender {
public function send(string $phone, string $text): string; // returns message_id
}
Prefer a Laravel Notification channel for anything user-facing. This keeps controllers clean and gives you via(), queueing, and per-channel throttling for free:
class SmsChannel
{
public function send($notifiable, SmsNotification $notification): void
{
app(SmsSender::class)->send(
$notifiable->routeNotificationFor('sms'),
$notification->toSms($notifiable)
);
}
}
Always queue. TurboSMS is a network call with real latency and occasional 5xx responses. Dispatch a SendSmsJob with $tries = 3 and backoff = [10, 60, 300]. Never send synchronously from a request that a user is waiting on.
Persist the message_id immediately in your own table (sms_messages: id, user_id, phone, text, provider_id, status, sent_at). The bundle does not give you delivery receipts; the only way to reconcile is polling getMessageStatus with the ID, or accepting the "accepted" response as good enough.
Batch carefully. The API accepts an array of recipients. A common pattern is to chunk recipients (10–50 per call) and let the job handle each chunk, so a single failure doesn't lose the whole campaign.
Config over constants. If you inherit the bundle, check whether sender name is hardcoded in the service. Move it to .env. The sender must be pre-approved in your TurboSMS account; if it isn't, the API silently substitutes Msg.
380XXXXXXXXX — no +, no spaces, no leading 0. Normalize on the way in; otherwise numbers are accepted into the batch and then rejected per-recipient with a non-zero response_code, which is easy to miss if you only check the top-level response_code.response_code tells you whether the request succeeded; response_result[*].response_code tells you whether each recipient was accepted. Log both. A 0 at the top with failures inside the array is the classic silent failure.login/password query parameters. The modern API uses a bearer token. Do not assume the bundle's auth flow is current — verify against the provider docs before deploying.file_get_contents calls have no timeout. Wrap direct calls with Http::timeout(10)->retry(3, 200). An SMS to a marketing list should not be able to hang a queue worker.How can I help you explore Laravel packages today?