본문 바로가기
Documentation menu

PHP / SDK REFERENCE

WordPress / WooCommerce SDK Guide

The official WordPress plugin for sending Kakao Alimtalk, Brand Message and SMS — with automatic WooCommerce order notifications.

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

The official WordPress plugin for sending Kakao Alimtalk, Brand Message and SMS, with automatic WooCommerce order notifications

sendgo/wordpress bundles the sendgo/php core through Composer and wires it into WordPress: a settings screen for your keys, and WooCommerce hooks that notify the buyer when an order changes state.

Requires PHP 8.2+.


Install

The distributed zip bundles the core SDK in vendor/, so it runs without Composer. Upload it under Plugins → Add New, or unpack it into wp-content/plugins/sendgo.

With Composer

composer require sendgo/wordpress

Or from inside the plugin directory:

cd wp-content/plugins/sendgo
composer install

composer install generates the vendor/autoload.php that contains the core SDK. A checkout straight from source has no vendor/ directory, and without it the plugin cannot send — client() returns null and an admin notice explains why.

Activate

Activate Sendgo under Plugins in the WordPress admin.


Configure

Open Settings → Sendgo:

Field Description
Access Key Sendgo access key
Secret Key Sendgo secret key
Kakao Sender Key Kakao sender profile key (Alimtalk / Brand Message)
SMS Sender Key SMS caller ID key (SMS / LMS / MMS)
API Version v1 or v2

Sending stays disabled until both the access key and secret key are filled in. Keys are stored server-side in the sendgo_options option and never exposed to the front end.

The API version defaults to v1. Brand Message and Short URL need v2, so switch it if you plan to use those channels.

The API base URL is read from the url option but has no settings field. To point the plugin at a different host, set it programmatically:

$options = get_option('sendgo_options', []);
$options['url'] = 'https://staging.sendgo.io';
update_option('sendgo_options', $options);

Before 1.2.4 this value was dropped the first time the settings form was saved. It now survives a save.


WooCommerce order notifications

With WooCommerce active, the plugin notifies the billing phone number on these transitions:

  • Completed (woocommerce_order_status_completed)
  • Processing (woocommerce_order_status_processing)

Configure each state separately under Settings → Sendgo → WooCommerce Order Notifications:

Field Description
[Order completed] Alimtalk template code Template sent on completion. The order number is passed as the first variable (#{var1}).
[Order completed] SMS text used if Alimtalk fails Sent when the Alimtalk fails or no template code is set. Supports the {order_number} placeholder.
[Processing] Alimtalk template code Template sent when the order enters processing.
[Processing] SMS text used if Alimtalk fails SMS fallback for the processing state.

A state you leave blank sends nothing. Filling in both means every order triggers two messages — one on processing, one on completion — so only configure the states you actually want to announce.

Each order notifies once per state. On a successful send the plugin records order meta (_sendgo_notified_completed / _sendgo_notified_processing), so re-saving the order in the admin or another plugin re-applying the status will not send again. A failed send is not recorded, so the next transition retries it.

A send failure never interrupts the checkout or order flow — it is caught and written to the WooCommerce log under source sendgo.

Upgrading from 1.0.x — earlier versions shared a single order_template_code between both states, so an order moving processing → completed delivered the same message twice and billed the customer twice. Completed keeps the original option key; processing now needs its own field before it sends anything. Existing configurations keep working; only the duplicate goes away.

Phone numbers

The billing phone is reduced to digits (preg_replace('/[^0-9]/', ...)) before sending, so 010-1234-5678 and +82 10 1234 5678 both need to already be a Korean number the API accepts — the plugin strips punctuation but does not convert country codes. Orders with an empty billing phone are skipped silently.


Sending from your own code

Once the plugin is loaded, the core client is available directly:

$client = Sendgo_Plugin::instance()->client();

if ($client) {
    // Alimtalk
    $client->alimtalk->send([
        'templateCode' => 'ORDER_CONFIRM_001',
        'contacts'     => [['contact' => '01012345678', 'var1' => 'ORD-001']],
    ]);

    // SMS
    $client->sms->sendSms([
        'content'  => 'Verification code: 123456',
        'contacts' => [['contact' => '01012345678']],
    ]);
}

Always guard on $client — it is null when the keys are unset or vendor/autoload.php is missing, and calling a method on null would white-screen the page you are hooked into.

Every channel is a property on the client:

Property Channel
$client->alimtalk Kakao Alimtalk
$client->friendtalk Kakao Friendtalk
$client->brandMessage Kakao Brand Message (v2 only)
$client->sms SMS / LMS / MMS

The client is memoised for the request, so calling Sendgo_Plugin::instance()->client() repeatedly is cheap.

Hook it to your own event

add_action('user_register', function (int $user_id): void {
    $client = Sendgo_Plugin::instance()->client();
    if (!$client) {
        return;
    }

    $user  = get_userdata($user_id);
    $phone = preg_replace('/[^0-9]/', '', (string) get_user_meta($user_id, 'billing_phone', true));

    if ('' === $phone) {
        return;
    }

    try {
        $client->alimtalk->send([
            'templateCode' => 'WELCOME_001',
            'contacts'     => [['contact' => $phone, 'var1' => $user->display_name]],
        ]);
    } catch (\Throwable $e) {
        // Never let a messaging failure break registration.
        error_log('Sendgo welcome message failed: ' . $e->getMessage());
    }
}, 10, 1);

Wrapping the call in try/catch is the important part: an unhandled SendgoException inside a WordPress hook surfaces as a fatal error on whatever page fired it.


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: it reaches recipients who are not channel friends ('targeting' => 'N') and can broadcast to every consenting channel friend ('targeting' => 'F'). Message types map one-to-one with Friendtalk (FT→BT, FI→BI, FW→BW, FL→BL, FC→BC, FM→BM, FP→BP, FA→BA).

v2 only. Set Settings → Sendgo → API Version to v2; the plugin defaults to v1.

$client = Sendgo_Plugin::instance()->client();

// Single send — targeting M/N/I requires `contacts`
$client->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 recipient list
$result = $client->brandMessage->broadcast([
    'messageType'        => 'FW',
    'friendTemplateUuid' => '9cd5460b-6458-4edc-9b11-c26d3013c340',
]);

// A broadcast is asynchronous upstream, so poll for progress
$client->brandMessage->campaign($result['data']['campaignId']);
$client->brandMessage->campaigns(['count' => 10]);

A broadcast can reach your entire friend list, so trigger it from a deliberate admin action — a WP-CLI command or an admin-post handler behind a capability check — never from a public hook.


Error handling

use Sendgo\Php\Exception\SendgoException;

try {
    $client->alimtalk->send([...]);
} catch (SendgoException $e) {
    // Send failures should be logged, not surfaced to the shopper.
    if (function_exists('wc_get_logger')) {
        wc_get_logger()->error(
            sprintf('Sendgo %d [%s]: %s', $e->getStatusCode(), $e->getErrorCode(), $e->getMessage()),
            ['source' => 'sendgo']
        );
    }
}

Branch on getErrorCode(), not on the message text — messages can change, codes are the contract. TOKEN_EXPIRED and TOKEN_MISMATCH are handled inside the core SDK: the token is reissued and the request retried once.


FAQ

Can I use it without WooCommerce? Yes. Sendgo_Plugin::instance()->client() works on any WordPress install; only the automatic order notifications depend on WooCommerce.

client() returns null. Either the access key / secret key is unset, or the plugin came from source and composer install was never run, so vendor/autoload.php does not exist. The second case raises an admin notice. The distributed zip includes vendor/, so it cannot happen there.

Nothing sends and there is no error. Check that you registered the outbound IP of your WordPress site under Integrations → Integration Info in the console — a request from an unlisted address is rejected. On shared hosting or behind a CDN that address differs from the one your browser reports.

Where are the credentials stored? Server-side in the sendgo_options option. They are never printed to the front end, and the secret key renders as a password field in the admin.

Does uninstalling clean everything up? uninstall.php deletes the sendgo_options option. The _sendgo_notified_* order meta is left in place — it is harmless, and deleting it would mean a bulk write across every order.


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.

$client = Sendgo_Plugin::instance()->client();

if ($client) {
    $short = $client->shortUrl->create([
        'targetUrl' => get_permalink($post_id),
        'title'     => get_the_title($post_id),
    ]);

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

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.


External services

This plugin sends Kakao Alimtalk, Kakao Brand Message and SMS/LMS/MMS through the Sendgo API (https://sendgo.io). A Sendgo account is required and message delivery is a paid service.

  • Before any send, the access key and secret key are exchanged for a short-lived token.
  • When a WooCommerce order changes to processing or completed and that state has a template code or SMS fallback configured, the buyer's billing phone number and the order number are sent along with your sender key and the template code.
  • When you call the client from your own code, the recipient numbers and body you pass are sent as is.

Nothing is sent when the plugin is merely installed or activated, or when both the template code and the SMS fallback are empty.


Package information

Getting your API keys

Sign in to Sendgo and open Integrations → Integration Info to issue an access key and secret key, and to register the IP addresses allowed to use them — a request from an unlisted address is rejected. Register a Kakao sender profile under Kakao Sender Profile to get your Kakao Sender Key, and a caller ID under Sender Management for SMS.

이 패키지로 할 수 있는 것

관련 패키지

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