Введение: В этой инструкции мы подключим Supabase к сервису SMSC.ru для отправки OTP-кодов (одноразовых паролей) по SMS.
Такое решение подходит как для облачной версии Supabase, так и для self-hosted установки.Для работы нужно иметь учётную запись в SMSC.ru и активный API-доступ.

1. Подготовка функции в SQL Editor

Открой SQL Editor в Supabase, вставь SQL-код (см. пункт 4 ниже) и выполни его.

Этот код создаёт:

  • Секреты с логином и паролем для SMSC.ru в vault.decrypted_secrets.
  • Таблицу логов отправленных сообщений sms_webhook_logs.
  • Вспомогательную функцию urlencode для кодирования параметров запроса.
  • Основную функцию send_sms, которая отправляет код через API SMSC.ru.

2. Настройка для self-hosted Supabase

В сервисе gotrue файла docker-compose.yml пропиши переменные и перезапусти контейнеры:

GOTRUE_HOOK_SEND_SMS_ENABLED: "true"
GOTRUE_HOOK_SEND_SMS_URI: "pg-functions://postgres/public/send_otp_sms_hook"

3. Настройка для облачного Supabase

Перейди в Authentication → Auth Hooks, выбери функцию send_otp_sms_hook и сохрани настройки.

4. Полный SQL-код (функция + что править)

Выполни в SQL Editor Supabase следующий код. Важно: в первой вставке кода замени your_smsc_login и your_smsc_password на реальные данные от своего аккаунта в SMSC.ru. Эти данные нужны для авторизации в API.

-- Учетные данные SMSC (замените на свои)
INSERT INTO vault.decrypted_secrets (name, decrypted_secret)
VALUES 
    ('smsc_login', 'your_smsc_login'),       -- Логин от SMSC.ru
    ('smsc_password', 'your_smsc_password')  -- Пароль от SMSC.ru
ON CONFLICT (name) DO UPDATE 
SET decrypted_secret = EXCLUDED.decrypted_secret;

-- Логи SMS
CREATE TABLE IF NOT EXISTS public.sms_webhook_logs (
    id BIGSERIAL PRIMARY KEY,
    log JSONB NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- URL-кодирование
CREATE OR REPLACE FUNCTION public.urlencode(in_str text) RETURNS text
    LANGUAGE plpgsql
    IMMUTABLE STRICT
AS $$
DECLARE
    _result text := '';
    _char text;
    _i integer;
BEGIN
    FOR _i IN 1..length(in_str) LOOP
        _char := substr(in_str, _i, 1);
        IF _char ~ '[0-9a-zA-Z]' THEN
            _result := _result || _char;
        ELSE
            _result := _result || '%' || to_hex(ascii(_char));
        END IF;
    END LOOP;
    RETURN _result;
END;
$$;

-- Основная функция отправки SMS
CREATE OR REPLACE FUNCTION public.send_sms(event JSONB) 
RETURNS JSONB
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
... полный код функции ...
$$;

-- Права
GRANT USAGE ON SCHEMA public TO PUBLIC;
GRANT EXECUTE ON FUNCTION public.urlencode(text) TO PUBLIC;
GRANT EXECUTE ON FUNCTION public.send_sms(jsonb) TO PUBLIC;
GRANT SELECT, INSERT ON public.sms_webhook_logs TO PUBLIC;
GRANT SELECT ON vault.decrypted_secrets TO PUBLIC;

5. Как это работает

  1. Supabase Auth вызывает хук send_otp_sms_hook при необходимости отправки OTP.
  2. Функция парсит входящий JSON, получает номер телефона и код.
  3. Данные кодируются для безопасной передачи в URL.
  4. Запрос отправляется в API https://smsc.ru/sys/send.php.
  5. Результат записывается в таблицу логов sms_webhook_logs.

6. Советы по отладке

  • Проверяйте логи через:
    SELECT * FROM public.sms_webhook_logs ORDER BY created_at DESC;
  • Убедитесь, что логин/пароль для SMSC корректны.
  • Если SMS не доходят, используйте режим cost=3 (в коде он уже включён) — он вернёт только стоимость и статус.
  • Для тестов можно временно менять sender_name, чтобы отличать сервисные SMS от рабочих.
  • В self-hosted версии проверь, что контейнер pg_net имеет доступ к интернету.

💡 Преимущество решения: работает и в облаке, и в self-hosted Supabase без промежуточных серверов, а логирование в отдельной таблице позволяет быстро находить и исправлять ошибки.