Files
erv-ticket-dev/docs/n8n_migration_plan.md
Fedor ed4270312e feat: SMS verification через n8n webhook
- Перенесена проверка SMS кода в n8n webhook (N8N_SMS_VERIFY_WEBHOOK)
- Упрощен формат ответа: убран токен, только success/message
- sms-verify.php теперь проксирует запросы на n8n
- Обновлен JS код: убрано использование токена
- Обновлена документация с упрощенным форматом ответа
- Протестировано: верный и неверный коды работают корректно
2026-01-15 18:11:18 +03:00

9.1 KiB
Raw Permalink Blame History

План миграции SMS верификации в n8n

Текущая логика (PHP)

1. Отправка SMS (sms-verify.php?action=send)

┌─────────────┐
│  Frontend   │
│  (JS)       │
└──────┬──────┘
       │ POST: phonenumber
       ▼
┌─────────────────────┐
│  sms-verify.php     │
│  action=send        │
└──────┬──────────────┘
       │
       ├─► Нормализация номера (clear_phone)
       ├─► Проверка rate limit (Redis)
       ├─► Генерация кода (generateCode)
       ├─► Сохранение в Redis (setex, 10 мин)
       ├─► Отправка SMS → n8n webhook
       └─► Ответ: success

2. Проверка кода (sms-verify.php?action=verify)

┌─────────────┐
│  Frontend   │
│  (JS)       │
└──────┬──────┘
       │ POST: phonenumber, code
       ▼
┌─────────────────────┐
│  sms-verify.php     │
│  action=verify      │
└──────┬──────────────┘
       │
       ├─► Нормализация номера
       ├─► Проверка rate limit попыток
       ├─► Чтение кода из Redis
       ├─► Сравнение кодов
       ├─► Удаление кода из Redis
       ├─► Создание токена верификации
       └─► Ответ: success, token

Новая логика (n8n)

Workflow 1: Отправка SMS

┌─────────────────┐
│  Webhook        │  POST /webhook/sms-send
│  Trigger        │  Body: { phonenumber: "+79262306381" }
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Function       │  Нормализация номера
│  (JS Code)      │  phone.replace(/[() -+]/g, '').replace(/^(\+?7|8)/, '')
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Redis          │  GET sms:ratelimit:send:9262306381
│  (Get)          │  Если >= 5 → ошибка
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Function       │  Генерация кода
│  (JS Code)      │  Math.floor(100000 + Math.random() * 900000)
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Redis          │  SETEX sms:code:9262306381 600 "106574"
│  (Set)          │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Redis          │  INCR sms:ratelimit:send:9262306381
│  (Increment)    │  EXPIRE 3600
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  HTTP Request   │  POST к SMS API
│  (SMS Send)     │  Body: { phone, text: "Код: 106574" }
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  IF (error)     │  Если ошибка → удалить код из Redis
│  (Error Handle) │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Respond to     │  { success: true, message: "..." }
│  Webhook        │
└─────────────────┘

Workflow 2: Проверка кода

┌─────────────────┐
│  Webhook        │  POST /webhook/sms-verify
│  Trigger        │  Body: { phonenumber: "+79262306381", code: "106574" }
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Function       │  Нормализация номера
│  (JS Code)      │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Redis          │  GET sms:ratelimit:attempts:9262306381
│  (Get)          │  Если >= 10 → ошибка
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Redis          │  INCR sms:ratelimit:attempts:9262306381
│  (Increment)    │  EXPIRE 900
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Redis          │  GET sms:code:9262306381
│  (Get)          │  Если null → ошибка "Код не найден"
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  IF             │  Если code !== stored_code → ошибка "Неверный код"
│  (Compare)      │
└────────┬────────┘
         │ (success)
         ▼
┌─────────────────┐
│  Redis          │  DEL sms:code:9262306381
│  (Delete)       │  DEL sms:ratelimit:attempts:9262306381
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Function       │  Генерация токена
│  (JS Code)      │  crypto.randomBytes(32).toString('hex')
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Redis          │  SETEX sms:verified:9262306381 3600 "token"
│  (Set)          │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Respond to     │  { success: true, token: "..." }
│  Webhook        │
└─────────────────┘

Пошаговая миграция

Шаг 1: Создать workflows в n8n

  1. Зайти в n8n: https://n8n.clientright.pro
  2. Создать новый workflow "SMS Send"
  3. Создать новый workflow "SMS Verify"
  4. Создать новый workflow "SMS Check Verified" (опционально)

Шаг 2: Настроить Redis в n8n

  • Добавить Redis credentials в n8n
  • Host: crm.clientright.ru
  • Port: 6379
  • Password: (из .env)

Шаг 3: Протестировать workflows

  • Запустить тестовые запросы через Postman/curl
  • Проверить, что коды сохраняются в Redis
  • Проверить, что SMS отправляются

Шаг 4: Изменить PHP код

Вариант A: Прокси через PHP (проще)

// sms-verify.php просто перенаправляет на n8n
$n8n_url = 'https://n8n.clientright.pro/webhook/sms-send';
// ... curl запрос к n8n

Вариант B: Прямой вызов n8n из JS (лучше)

// js/common.js
$.ajax({
    url: 'https://n8n.clientright.pro/webhook/sms-send',
    // ...
});

Шаг 5: Удалить старую логику из PHP

  • Удалить генерацию кода
  • Удалить работу с Redis (оставить только fallback на файлы, если нужно)
  • Оставить только проксирование запросов

Преимущества

Визуализация - видно весь процесс в n8n Логирование - автоматические логи каждого шага Мониторинг - видно ошибки и задержки Гибкость - легко добавить новые шаги Тестирование - можно тестировать каждый шаг отдельно Масштабируемость - легко добавить несколько SMS провайдеров


Примеры кода для n8n

Нормализация номера (Function Node)

const phone = $input.item.json.phonenumber || '';
const cleaned = phone
  .replace(/[() -]/g, '')
  .replace(/^(\+?7|8)/, '');

return { json: { phone_cleaned: cleaned } };

Генерация кода (Function Node)

const code = Math.floor(100000 + Math.random() * 900000).toString();
return { json: { code } };

Генерация токена (Function Node)

const crypto = require('crypto');
const token = crypto.randomBytes(32).toString('hex');
return { json: { token } };