expertsystemsau/transmitsms-laravel-client
Composer 安装命令:
composer require expertsystemsau/transmitsms-laravel-client
包简介
Laravel notification channel and integration for the TransmitSMS API
README 文档
README
Laravel notification channel and integration for the TransmitSMS API.
Installation
composer require expertsystemsau/transmitsms-laravel
Publish the configuration file:
php artisan vendor:publish --tag="transmitsms-config"
Configuration
Add your credentials to your .env file:
TRANSMITSMS_API_KEY=your-api-key TRANSMITSMS_API_SECRET=your-api-secret # Optional default sender ID — see "Sender IDs" below before setting this TRANSMITSMS_FROM=
Sender IDs
TRANSMITSMS_FROM (or the per-message from() / from option) is the sender ID
recipients see. It can be:
- A dedicated virtual number (VMN) in international format, e.g.
61412345678— supports two-way messaging (recipients can reply). - An alphanumeric sender ID ("alpha tag") such as
MyBrand— max 11 characters, letters and digits only, no spaces. One-way only; recipients cannot reply. - Omitted (leave empty) — TransmitSMS falls back to a shared number for the destination country.
⚠️ Alpha tags must be registered and approved before you can send with them. For messages to Australian numbers, alphanumeric sender IDs must be listed on the ACMA SMS Sender ID Register (enforced from 1 July 2026) — an unregistered sender ID is replaced with "Unverified" on the recipient's device. Registration requires your registered entity name, ABN, and an authorised contact. Register your sender IDs through the TransmitSMS dashboard before setting
TRANSMITSMS_FROM; until then, leave it empty to send from a shared number.
Usage
Facade
The facade proxies to the resource-based client: SMS operations live on sms(),
account operations on account(), reporting on reporting(), and so on.
use ExpertSystems\TransmitSms\Laravel\Facades\TransmitSms; // Send an SMS — send(string $message, string $to, ?string $from = null, ?callable $configure = null) TransmitSms::sms()->send('Hello from Laravel!', '+61400000000'); // Get account balance $balance = TransmitSms::account()->getBalance();
Notifications
Create a notification that uses the TransmitSMS channel:
use Illuminate\Notifications\Notification; use ExpertSystems\TransmitSms\Laravel\Notifications\TransmitSmsMessage; class OrderShipped extends Notification { public function via($notifiable): array { return ['transmitsms']; } public function toTransmitSms($notifiable): TransmitSmsMessage { return TransmitSmsMessage::create('Your order has been shipped!') ->from('MyStore'); } }
Add the routeNotificationForTransmitsms method to your notifiable model:
class User extends Authenticatable { use Notifiable; public function routeNotificationForTransmitsms($notification): ?string { return $this->phone_number; } }
Then send notifications:
$user->notify(new OrderShipped());
Message options
TransmitSmsMessage is a fluent builder covering every send option:
TransmitSmsMessage::create('Your order has shipped!') ->from('MyStore') // sender ID (else config/default) ->countryCode('AU') // normalise local numbers ->formatNumbers() // format numbers to E.164 client-side ->validity(60) // minutes to attempt delivery ->sendAt('2026-12-25 09:00:00') // schedule ->repliesToEmail('inbox@example.com') // route replies to an email ->trackedLinkUrl('https://example.com'); // [tracked-link] target
To send to a TransmitSMS contact list instead of the notifiable's number, use
toList() — the resolved recipient is then ignored:
public function toTransmitSms($notifiable): TransmitSmsMessage { return TransmitSmsMessage::create('Flash sale for members!') ->toList(12345); }
DLR & Reply Callbacks
The package provides automatic handling for DLR (Delivery Receipt), Reply, and Link Hit callbacks. When you send an SMS, you can specify a job to be dispatched when a callback is received.
Quick Start
use App\Jobs\UpdateOrderSmsStatusJob; use App\Jobs\ProcessCustomerReplyJob; use ExpertSystems\TransmitSms\Laravel\Notifications\TransmitSmsMessage; class OrderShipped extends Notification { public function __construct(public Order $order) {} public function via($notifiable): array { return ['transmitsms']; } public function toTransmitSms($notifiable): TransmitSmsMessage { return TransmitSmsMessage::create("Your order #{$this->order->id} has shipped!") ->from('MYSTORE') ->onDlr(UpdateOrderSmsStatusJob::class, [ 'order_id' => $this->order->id, ]) ->onReply(ProcessCustomerReplyJob::class, [ 'order_id' => $this->order->id, 'customer_id' => $notifiable->id, ]); } }
Creating Handler Jobs
DLR Handler Job:
namespace App\Jobs; use App\Models\Order; use ExpertSystems\TransmitSms\Data\DlrCallbackData; use ExpertSystems\TransmitSms\Laravel\Contracts\HandlesDlrCallback; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; class UpdateOrderSmsStatusJob implements HandlesDlrCallback, ShouldQueue { use InteractsWithQueue, Queueable; public function __construct( public DlrCallbackData $dlr, public array $context, ) {} public function handle(): void { $order = Order::find($this->context['order_id']); $order->update([ 'sms_status' => $this->dlr->status, 'sms_delivered_at' => $this->dlr->isDelivered() ? now()->parse($this->dlr->datetime) : null, ]); if ($this->dlr->isFailed()) { // Handle failure - maybe send email instead Log::warning('SMS delivery failed', [ 'order_id' => $order->id, 'error' => $this->dlr->errorDescription, ]); } } }
Reply Handler Job:
namespace App\Jobs; use App\Models\SmsConversation; use ExpertSystems\TransmitSms\Data\ReplyCallbackData; use ExpertSystems\TransmitSms\Laravel\Contracts\HandlesReplyCallback; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; class ProcessCustomerReplyJob implements HandlesReplyCallback, ShouldQueue { use Queueable; public function __construct( public ReplyCallbackData $reply, public array $context, ) {} public function handle(): void { SmsConversation::create([ 'order_id' => $this->context['order_id'], 'customer_id' => $this->context['customer_id'], 'direction' => 'inbound', 'message' => $this->reply->message, 'mobile' => $this->reply->mobile, 'received_at' => $this->reply->receivedAt, ]); } }
Link Hit Handler Job:
namespace App\Jobs; use ExpertSystems\TransmitSms\Data\LinkHitCallbackData; use ExpertSystems\TransmitSms\Laravel\Contracts\HandlesLinkHitCallback; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; class TrackLinkClickJob implements HandlesLinkHitCallback, ShouldQueue { use Queueable; public function __construct( public LinkHitCallbackData $linkHit, public array $context, ) {} public function handle(): void { LinkClick::create([ 'campaign_id' => $this->context['campaign_id'], 'mobile' => $this->linkHit->mobile, 'url' => $this->linkHit->url, 'clicked_at' => $this->linkHit->clickedAt, ]); } }
Global Event Listeners
In addition to per-message handlers, you can listen to events for all callbacks:
// App\Providers\EventServiceProvider.php use ExpertSystems\TransmitSms\Laravel\Events\DlrReceived; use ExpertSystems\TransmitSms\Laravel\Events\ReplyReceived; use ExpertSystems\TransmitSms\Laravel\Events\LinkHitReceived; protected $listen = [ DlrReceived::class => [ \App\Listeners\LogDlrCallback::class, ], ReplyReceived::class => [ \App\Listeners\LogReplyCallback::class, ], LinkHitReceived::class => [ \App\Listeners\LogLinkHitCallback::class, ], ];
Example listener:
namespace App\Listeners; use ExpertSystems\TransmitSms\Laravel\Events\DlrReceived; use Illuminate\Support\Facades\Log; class LogDlrCallback { public function handle(DlrReceived $event): void { Log::info('DLR callback received', [ 'message_id' => $event->dlr->messageId, 'mobile' => $event->dlr->mobile, 'status' => $event->dlr->status, 'context' => $event->context, ]); } }
Webhook Configuration
The webhook routes are automatically registered. You can customize them in config/transmitsms.php:
'webhooks' => [ // Enable/disable webhook routes 'enabled' => env('TRANSMITSMS_WEBHOOKS_ENABLED', true), // Route prefix (e.g., /webhooks/transmitsms/dlr) 'prefix' => env('TRANSMITSMS_WEBHOOKS_PREFIX', 'webhooks/transmitsms'), // Middleware for webhook routes 'middleware' => ['api'], // Custom signing key (defaults to APP_KEY) 'signing_key' => env('TRANSMITSMS_SIGNING_KEY'), // DLR callback settings 'dlr' => [ 'enabled' => true, 'path' => 'dlr', 'queue' => env('TRANSMITSMS_DLR_QUEUE', 'default'), ], // Reply callback settings 'reply' => [ 'enabled' => true, 'path' => 'reply', 'queue' => env('TRANSMITSMS_REPLY_QUEUE', 'default'), ], // Link hits callback settings 'link_hits' => [ 'enabled' => true, 'path' => 'link-hits', 'queue' => env('TRANSMITSMS_LINK_HITS_QUEUE', 'default'), ], ],
Callback Data Objects
DlrCallbackData properties:
| Property | Type | Description |
|---|---|---|
messageId |
int |
The message ID |
mobile |
string |
Recipient phone number |
status |
string |
Status: delivered, failed, pending |
datetime |
?string |
Delivery timestamp |
senderId |
?string |
Sender ID used |
errorCode |
?string |
Error code if failed |
errorDescription |
?string |
Error description |
Helper methods: isDelivered(), isFailed(), isPending()
ReplyCallbackData properties:
| Property | Type | Description |
|---|---|---|
messageId |
int |
Original message ID |
mobile |
string |
Sender phone number |
message |
string |
Reply message text |
receivedAt |
string |
Timestamp when received |
responseId |
?int |
Reply ID |
longcode |
?string |
Number replied to |
firstName |
?string |
Sender first name |
lastName |
?string |
Sender last name |
LinkHitCallbackData properties:
| Property | Type | Description |
|---|---|---|
messageId |
int |
Message ID |
mobile |
string |
Recipient phone number |
url |
string |
URL that was clicked |
clickedAt |
string |
Click timestamp |
userAgent |
?string |
Browser user agent |
ipAddress |
?string |
IP address |
How It Works
-
Sending: When you use
onDlr(),onReply(), oronLinkHit(), the package builds a signed callback URL containing your handler class and context data. -
Receiving: When TransmitSMS calls the webhook, the package:
- Verifies the HMAC signature
- Parses the callback data into a DTO
- Dispatches a global event (for logging/monitoring)
- Dispatches your handler job with the data and context
-
Security: The callback URL includes an HMAC signature to prevent tampering. Only callbacks with valid signatures are processed.
┌─────────────────────────────────────────────────────────────────────┐
│ Your App │
│ ──────── │
│ TransmitSmsMessage::create('Hello') │
│ ->onDlr(MyJob::class, ['id' => 1]) │
│ │ │
│ ▼ │
│ Package builds signed callback URL │
│ https://app.com/webhooks/transmitsms/dlr?h=...&c=...&s=... │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ TransmitSMS │
│ ─────────── │
│ Sends SMS → Receives DLR → Calls your webhook URL │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Your App (Webhook) │
│ ───────────────── │
│ WebhookController: │
│ 1. Verify signature ✓ │
│ 2. Parse DlrCallbackData │
│ 3. Dispatch DlrReceived event │
│ 4. Dispatch MyJob with data + context │
└─────────────────────────────────────────────────────────────────────┘
License
The MIT License (MIT). Please see License File for more information.
统计信息
- 总下载量: 27
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-12-09