본문 바로가기
Documentation menu

PHP / SDK REFERENCE

Laravel SDK Guide

The official Laravel package for sending Kakao Alimtalk, Brand Message and SMS — auto-discovered service provider, facade and publishable config.

이 문서의 목차
패키지
sendgo/laravel
언어
PHP
레지스트리
Packagist
설치
composer require sendgo/laravel

The official Laravel package for sending Kakao Alimtalk, Brand Message and SMS

sendgo/laravel wraps the sendgo/php core as a Laravel-native package: the service provider and facade are auto-discovered, and the config file is publishable.

Requires Laravel 10 or newer and PHP 8.2+.


Install

composer require sendgo/laravel

Laravel's package auto-discovery registers the service provider and the Sendgo facade for you.


Configure

1. Environment variables

SENDGO_ACCESS_KEY=your_access_key
SENDGO_SECRET_KEY=your_secret_key
SENDGO_KAKAO_SENDER_KEY=your_kakao_sender_key
SENDGO_SMS_SENDER_KEY=your_sms_sender_key
SENDGO_API_VERSION=v2

2. Publish the config (optional)

php artisan vendor:publish --tag=sendgo-config

This writes config/sendgo.php, which reads the variables above.


Quick start

<?php

use Sendgo\Laravel\Facades\Sendgo;

// Send an Alimtalk
Sendgo::alimtalk()->send([
    'templateCode' => 'ORDER_CONFIRM_001',
    'contacts'     => [
        ['contact' => '01012345678', 'name' => 'Gildong Hong', 'var1' => 'ORD-001'],
    ],
]);

// Send an SMS
Sendgo::sms()->sendSms([
    'content'  => '[Sendgo] Your code is 123456 (valid for 5 minutes)',
    'contacts' => [['contact' => '01012345678']],
]);

The facade exposes each channel as a method: Sendgo::alimtalk(), Sendgo::friendtalk(), Sendgo::brandMessage(), Sendgo::sms().


Dependency injection

If you prefer injecting the client — easier to fake in tests — resolve the core class:

<?php

namespace App\Services;

use Sendgo\Php\Sendgo;

class OrderNotifier
{
    public function __construct(private readonly Sendgo $sendgo) {}

    public function confirmed(string $phone, string $orderNo): void
    {
        $this->sendgo->alimtalk->send([
            'templateCode' => 'ORDER_CONFIRM_001',
            'contacts'     => [['contact' => $phone, 'var1' => $orderNo]],
        ]);
    }
}

Both styles reach the same singleton, so the facade and the injected instance share one token cache.


Brand Message

Friendtalk was discontinued on 2025-12-31. Since 2026-01-01 Kakao delivers Friendtalk requests as Brand Message (free-form) automatically. friendtalk still works and is still the only path for free-form FT/FI/FW to individual recipients — use Brand Message for template-based rich types (FL/FC/FM/FP/FA), non-friend targeting (N/I) and broadcasts (F). Brand Message is the successor channel to Friendtalk. Message types map one-to-one (FT→BT, FI→BI, FW→BW, FL→BL, FC→BC, FM→BM, FP→BP, FA→BA); pass the Friendtalk code and the server converts it.

Unlike Friendtalk it can also reach recipients who are not channel friends (targeting: 'N') and broadcast to every consenting channel friend (targeting: 'F').

v2 only. Set SENDGO_API_VERSION=v2.

<?php

use Sendgo\Laravel\Facades\Sendgo;

// Single send — channel friends
Sendgo::brandMessage()->send([
    'targeting'          => 'M',
    'messageType'        => 'FL',
    'friendTemplateUuid' => '9cd5460b-6458-4edc-9b11-c26d3013c340',
    'contacts'           => [['contact' => '01012345678', 'var1' => '29,000 KRW']],
]);

// Broadcast — every consenting channel friend (no contacts)
Sendgo::brandMessage()->broadcast([
    'messageType'        => 'FW',
    'friendTemplateUuid' => '9cd5460b-6458-4edc-9b11-c26d3013c340',
]);

// Campaign lookups
$list = Sendgo::brandMessage()->campaigns(['count' => 10]);
$one  = Sendgo::brandMessage()->campaign('1f0a6d0e-6b3b-4f0f-9b2f-2f6f6a1b7c11');

Queued sending

Sending is an outbound HTTP call, so it belongs in a job rather than a request cycle.

<?php

namespace App\Jobs;

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Sendgo\Php\Exception\SendgoException;
use Sendgo\Php\Sendgo;

class SendOrderConfirm implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue;

    public int $tries = 3;

    public function __construct(
        private readonly string $phone,
        private readonly string $orderNo,
    ) {}

    public function handle(Sendgo $sendgo): void
    {
        try {
            $sendgo->alimtalk->send([
                'templateCode' => 'ORDER_CONFIRM_001',
                'contacts'     => [['contact' => $this->phone, 'var1' => $this->orderNo]],
            ]);
        } catch (SendgoException $e) {
            // 5xx is transient; a 4xx will not succeed on retry, so fail fast.
            if ($e->getStatusCode() >= 500) {
                $this->release(now()->addSeconds(30));

                return;
            }

            $this->fail($e);
        }
    }
}
SendOrderConfirm::dispatch($order->phone, $order->number);

Notification channel

To send through Laravel's notification system, forward from a notification to the client:

<?php

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Sendgo\Php\Sendgo;

class OrderConfirmed extends Notification
{
    public function __construct(private readonly string $orderNo) {}

    public function via(object $notifiable): array
    {
        return ['sendgo'];
    }

    public function toSendgo(object $notifiable): void
    {
        app(Sendgo::class)->alimtalk->send([
            'templateCode' => 'ORDER_CONFIRM_001',
            'contacts'     => [['contact' => $notifiable->phone, 'var1' => $this->orderNo]],
        ]);
    }
}

Register the driver in a service provider:

Notification::extend('sendgo', fn () => new class {
    public function send($notifiable, Notification $notification): void
    {
        $notification->toSendgo($notifiable);
    }
});

Testing

Bind a fake over the container binding so no request leaves your test suite:

use Sendgo\Php\Sendgo;

$this->instance(Sendgo::class, new class extends Sendgo {
    public array $sent = [];

    public function __construct() {} // skip the parent's token setup

    public function __call(string $name, array $arguments): object
    {
        return new class($this, $name) {
            public function __construct(private $parent, private string $channel) {}

            public function send(array $payload): array
            {
                $this->parent->sent[] = [$this->channel, $payload];

                return ['message' => 'Success'];
            }
        };
    }
});

Error handling

<?php

use Sendgo\Php\Exception\SendgoException;
use Sendgo\Laravel\Facades\Sendgo;

try {
    Sendgo::alimtalk()->send([
        'templateCode' => 'ORDER_CONFIRM_001',
        'contacts'     => [['contact' => '01012345678']],
    ]);
} catch (SendgoException $e) {
    match ($e->getErrorCode()) {
        'INVALID_ACCESS_KEY',
        'INVALID_SECRET_KEY'    => Log::critical('Check the Sendgo API keys.'),
        'PAYMENT_REQUIRED'      => Log::critical('Out of Sendgo credit.'),
        'IP_NOT_ALLOWED'        => Log::critical('IP is not allow-listed.'),
        'INVALID_TEMPLATE_CODE' => Log::warning('Unknown template'),
        default                 => Log::error("Sendgo {$e->getStatusCode()}: {$e->getMessage()}"),
    };
}

Branch on getErrorCode(), not on the message text — messages can change, codes are the contract.


Configuration reference

config/sendgo.php maps one-to-one onto the core client options.

Key Env Default Description
access_key SENDGO_ACCESS_KEY — Sendgo access key (required)
secret_key SENDGO_SECRET_KEY — Sendgo secret key (required)
kakao_sender_key SENDGO_KAKAO_SENDER_KEY null Kakao sender profile key
sms_sender_key SENDGO_SMS_SENDER_KEY null SMS caller ID key
api_version SENDGO_API_VERSION v1 API version (v1 | v2)
url SENDGO_URL https://sendgo.io API base URL

Short URL

Short URLs shrink the links in your message body and count whether they were actually clicked. SMS is billed by byte, so a shorter link leaves more room for copy.

v2 only.

Shortening the same target URL again returns the existing link. Pass forceNew to mint a new code when you want per-campaign reaction figures kept separate.

deactivate does not delete the link — it only stops the redirect. Use it when a link in an already-sent message has to be killed; the accumulated stats stay, and visitors to a stopped link get 410 Gone.

use Sendgo\Laravel\Facades\Sendgo;

$short = Sendgo::shortUrl()->create([
    'targetUrl' => 'https://example.com/promotions/summer-sale',
    'title'     => 'Summer sale landing',
]);

$link = $short['data']['shortUrl'];
$code = $short['data']['code'];

$stats = Sendgo::shortUrl()->stats($code, ['from' => '2026-08-01']);
Sendgo::shortUrl()->deactivate($code);

stats returns a daily series (daily) plus breakdowns by device (byDevice), referrer (byReferer) and country (byCountry). The daily series is read from a pre-aggregated table, so response time stays flat no matter how many clicks accumulate.


Package information

Getting your API keys

Sign in to Sendgo and open API/SDK → API integration to issue an access key and secret key. Register a Kakao sender profile under Kakao channel to get your kakao_sender_key, and a caller ID under Sender numbers for SMS.

이 패키지로 할 수 있는 것

관련 패키지

Focus on building. Leave messaging to Sendgo.Back to top ↑