feat: SMS verification через n8n webhook
- Перенесена проверка SMS кода в n8n webhook (N8N_SMS_VERIFY_WEBHOOK) - Упрощен формат ответа: убран токен, только success/message - sms-verify.php теперь проксирует запросы на n8n - Обновлен JS код: убрано использование токена - Обновлена документация с упрощенным форматом ответа - Протестировано: верный и неверный коды работают корректно
This commit is contained in:
261
docs/n8n_migration_plan.md
Normal file
261
docs/n8n_migration_plan.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# План миграции 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 (проще)**
|
||||
```php
|
||||
// sms-verify.php просто перенаправляет на n8n
|
||||
$n8n_url = 'https://n8n.clientright.pro/webhook/sms-send';
|
||||
// ... curl запрос к n8n
|
||||
```
|
||||
|
||||
**Вариант B: Прямой вызов n8n из JS (лучше)**
|
||||
```javascript
|
||||
// js/common.js
|
||||
$.ajax({
|
||||
url: 'https://n8n.clientright.pro/webhook/sms-send',
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### Шаг 5: Удалить старую логику из PHP
|
||||
|
||||
- Удалить генерацию кода
|
||||
- Удалить работу с Redis (оставить только fallback на файлы, если нужно)
|
||||
- Оставить только проксирование запросов
|
||||
|
||||
---
|
||||
|
||||
## Преимущества
|
||||
|
||||
✅ **Визуализация** - видно весь процесс в n8n
|
||||
✅ **Логирование** - автоматические логи каждого шага
|
||||
✅ **Мониторинг** - видно ошибки и задержки
|
||||
✅ **Гибкость** - легко добавить новые шаги
|
||||
✅ **Тестирование** - можно тестировать каждый шаг отдельно
|
||||
✅ **Масштабируемость** - легко добавить несколько SMS провайдеров
|
||||
|
||||
---
|
||||
|
||||
## Примеры кода для n8n
|
||||
|
||||
### Нормализация номера (Function Node)
|
||||
|
||||
```javascript
|
||||
const phone = $input.item.json.phonenumber || '';
|
||||
const cleaned = phone
|
||||
.replace(/[() -]/g, '')
|
||||
.replace(/^(\+?7|8)/, '');
|
||||
|
||||
return { json: { phone_cleaned: cleaned } };
|
||||
```
|
||||
|
||||
### Генерация кода (Function Node)
|
||||
|
||||
```javascript
|
||||
const code = Math.floor(100000 + Math.random() * 900000).toString();
|
||||
return { json: { code } };
|
||||
```
|
||||
|
||||
### Генерация токена (Function Node)
|
||||
|
||||
```javascript
|
||||
const crypto = require('crypto');
|
||||
const token = crypto.randomBytes(32).toString('hex');
|
||||
return { json: { token } };
|
||||
```
|
||||
201
docs/n8n_redis_example.md
Normal file
201
docs/n8n_redis_example.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# Пример использования Redis в n8n через Webhook
|
||||
|
||||
## Как это работает
|
||||
|
||||
```
|
||||
Webhook (точка входа) → Redis Node (чтение/запись) → Ответ
|
||||
```
|
||||
|
||||
## Workflow: Проверка SMS кода
|
||||
|
||||
### Структура:
|
||||
|
||||
```
|
||||
1. Webhook Trigger
|
||||
↓
|
||||
2. Function Node (нормализация номера)
|
||||
↓
|
||||
3. Redis Node (GET) - читаем код из Redis
|
||||
↓
|
||||
4. Function Node (сравнение кодов)
|
||||
↓
|
||||
5. Redis Node (DEL) - удаляем код после проверки
|
||||
↓
|
||||
6. Respond to Webhook
|
||||
```
|
||||
|
||||
### Детализация:
|
||||
|
||||
#### Шаг 1: Webhook Trigger
|
||||
- **URL:** `/webhook/sms-verify`
|
||||
- **Method:** POST
|
||||
- **Body:**
|
||||
```json
|
||||
{
|
||||
"phonenumber": "+79262306381",
|
||||
"code": "106574"
|
||||
}
|
||||
```
|
||||
|
||||
#### Шаг 2: Function Node - Нормализация
|
||||
```javascript
|
||||
// Код для Function Node
|
||||
const phone = $input.item.json.phonenumber || '';
|
||||
const cleaned = phone
|
||||
.replace(/[() -]/g, '')
|
||||
.replace(/^(\+?7|8)/, '');
|
||||
|
||||
return {
|
||||
json: {
|
||||
phone_cleaned: cleaned,
|
||||
code: $input.item.json.code
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### Шаг 3: Redis Node - Чтение кода
|
||||
- **Operation:** Get
|
||||
- **Key:** `sms:code:{{ $json.phone_cleaned }}`
|
||||
- **Результат:**
|
||||
```json
|
||||
{
|
||||
"phone_cleaned": "9262306381",
|
||||
"code": "106574",
|
||||
"stored_code": "106574" // из Redis
|
||||
}
|
||||
```
|
||||
|
||||
#### Шаг 4: Function Node - Сравнение
|
||||
```javascript
|
||||
// Код для Function Node
|
||||
const inputCode = $input.item.json.code;
|
||||
const storedCode = $input.item.json.stored_code;
|
||||
|
||||
if (!storedCode) {
|
||||
return {
|
||||
json: {
|
||||
success: false,
|
||||
message: "Код не найден или истек"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (inputCode !== storedCode) {
|
||||
return {
|
||||
json: {
|
||||
success: false,
|
||||
message: "Неверный код"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Код верный - продолжаем
|
||||
return {
|
||||
json: {
|
||||
success: true,
|
||||
phone_cleaned: $input.item.json.phone_cleaned
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### Шаг 5: Redis Node - Удаление кода
|
||||
- **Operation:** Delete
|
||||
- **Key:** `sms:code:{{ $json.phone_cleaned }}`
|
||||
|
||||
#### Шаг 6: Redis Node - Создание токена
|
||||
- **Operation:** Set
|
||||
- **Key:** `sms:verified:{{ $json.phone_cleaned }}`
|
||||
- **Value:** `{{ $json.token }}` (генерируется в Function Node)
|
||||
- **TTL:** 3600 секунд
|
||||
|
||||
#### Шаг 7: Respond to Webhook
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Код подтвержден",
|
||||
"token": "abc123..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow: Отправка SMS кода
|
||||
|
||||
### Структура:
|
||||
|
||||
```
|
||||
1. Webhook Trigger
|
||||
↓
|
||||
2. Function Node (нормализация)
|
||||
↓
|
||||
3. Redis Node (GET) - проверка rate limit
|
||||
↓
|
||||
4. Function Node (генерация кода)
|
||||
↓
|
||||
5. Redis Node (SETEX) - сохранение кода
|
||||
↓
|
||||
6. HTTP Request - отправка SMS
|
||||
↓
|
||||
7. Respond to Webhook
|
||||
```
|
||||
|
||||
### Детализация:
|
||||
|
||||
#### Шаг 3: Redis Node - Проверка rate limit
|
||||
- **Operation:** Get
|
||||
- **Key:** `sms:ratelimit:send:{{ $json.phone_cleaned }}`
|
||||
- **Если значение >= 5** → ошибка через IF Node
|
||||
|
||||
#### Шаг 5: Redis Node - Сохранение кода
|
||||
- **Operation:** Set with Expiration
|
||||
- **Key:** `sms:code:{{ $json.phone_cleaned }}`
|
||||
- **Value:** `{{ $json.code }}`
|
||||
- **TTL:** 600 секунд (10 минут)
|
||||
|
||||
#### Шаг 6: HTTP Request - Отправка SMS
|
||||
- **Method:** POST
|
||||
- **URL:** (SMS API провайдера)
|
||||
- **Body:**
|
||||
```json
|
||||
{
|
||||
"phone": "{{ $json.phone_cleaned }}",
|
||||
"text": "Код подтверждения: {{ $json.code }}"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Настройка Redis в n8n
|
||||
|
||||
### Credentials:
|
||||
|
||||
1. Зайти в n8n → Credentials → New
|
||||
2. Выбрать "Redis"
|
||||
3. Заполнить:
|
||||
- **Host:** `crm.clientright.ru`
|
||||
- **Port:** `6379`
|
||||
- **Password:** (из .env или пусто)
|
||||
- **Database:** `0` (по умолчанию)
|
||||
|
||||
### Использование в Node:
|
||||
|
||||
1. Добавить **Redis Node** в workflow
|
||||
2. Выбрать созданные credentials
|
||||
3. Выбрать операцию (Get, Set, Set with Expiration, Delete, etc.)
|
||||
4. Указать ключ (можно использовать переменные: `sms:code:{{ $json.phone_cleaned }}`)
|
||||
|
||||
---
|
||||
|
||||
## Преимущества
|
||||
|
||||
✅ **Всё в одном месте** - webhook принимает запрос, Redis Node читает/пишет
|
||||
✅ **Визуализация** - видно весь процесс на графике
|
||||
✅ **Логирование** - n8n автоматически логирует все операции
|
||||
✅ **Обработка ошибок** - можно добавить IF Nodes для проверок
|
||||
✅ **Тестирование** - можно тестировать каждый шаг отдельно
|
||||
|
||||
---
|
||||
|
||||
## Пример полного workflow (JSON для импорта в n8n)
|
||||
|
||||
Можно создать workflow вручную или импортировать готовый JSON (если нужно, могу создать).
|
||||
150
docs/n8n_sms_workflow.md
Normal file
150
docs/n8n_sms_workflow.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# N8N Workflow для SMS верификации
|
||||
|
||||
## Текущая архитектура
|
||||
|
||||
```
|
||||
Frontend (JS) → PHP (sms-verify.php) → Redis + n8n (только отправка SMS)
|
||||
```
|
||||
|
||||
## Предлагаемая архитектура
|
||||
|
||||
```
|
||||
Frontend (JS) → n8n Webhook → Redis + SMS отправка (всё в n8n)
|
||||
```
|
||||
|
||||
## Workflow 1: Отправка SMS кода
|
||||
|
||||
**Webhook URL:** `https://n8n.clientright.pro/webhook/sms-send`
|
||||
|
||||
### Шаги:
|
||||
|
||||
1. **Webhook Trigger** (POST)
|
||||
- Принимает: `{ "phonenumber": "+79262306381" }`
|
||||
|
||||
2. **Нормализация номера телефона**
|
||||
- Убрать пробелы, скобки, дефисы
|
||||
- Убрать +7 или 8 в начале
|
||||
- Результат: `9262306381`
|
||||
|
||||
3. **Проверка Rate Limit (Redis)**
|
||||
- Ключ: `sms:ratelimit:send:9262306381`
|
||||
- Если значение >= 5 → ошибка "Превышен лимит"
|
||||
- Иначе → увеличить счетчик (TTL: 1 час)
|
||||
|
||||
4. **Генерация кода**
|
||||
- 6-значный случайный код: `106574`
|
||||
|
||||
5. **Сохранение кода в Redis**
|
||||
- Ключ: `sms:code:9262306381`
|
||||
- Значение: `106574`
|
||||
- TTL: 600 секунд (10 минут)
|
||||
|
||||
6. **Отправка SMS (HTTP Request)**
|
||||
- URL: API SMS провайдера (SigmaSMS или другой)
|
||||
- Метод: POST
|
||||
- Body: `{ "phone": "9262306381", "text": "Код подтверждения: 106574" }`
|
||||
|
||||
7. **Обработка ошибок**
|
||||
- Если SMS не отправилось → удалить код из Redis
|
||||
- Вернуть ошибку
|
||||
|
||||
8. **Ответ**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Код отправлен на ваш номер телефона"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow 2: Проверка SMS кода
|
||||
|
||||
**Webhook URL:** `https://n8n.clientright.pro/webhook/sms-verify`
|
||||
|
||||
### Шаги:
|
||||
|
||||
1. **Webhook Trigger** (POST)
|
||||
- Принимает: `{ "phonenumber": "+79262306381", "code": "106574" }`
|
||||
|
||||
2. **Нормализация номера телефона**
|
||||
- Аналогично workflow 1
|
||||
|
||||
3. **Проверка Rate Limit для попыток (Redis)**
|
||||
- Ключ: `sms:ratelimit:attempts:9262306381`
|
||||
- Если значение >= 10 → ошибка "Превышено количество попыток"
|
||||
- Иначе → увеличить счетчик (TTL: 15 минут)
|
||||
|
||||
4. **Чтение кода из Redis**
|
||||
- Ключ: `sms:code:9262306381`
|
||||
- Если не найден → ошибка "Код не найден или истек"
|
||||
|
||||
5. **Сравнение кодов**
|
||||
- Если `введенный код !== сохраненный код` → ошибка "Неверный код"
|
||||
|
||||
6. **Успешная верификация**
|
||||
- Удалить код из Redis: `sms:code:9262306381`
|
||||
- Удалить счетчик попыток: `sms:ratelimit:attempts:9262306381`
|
||||
- Создать токен верификации: `sms:verified:9262306381` = `random_token` (TTL: 1 час)
|
||||
|
||||
7. **Ответ**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Код подтвержден",
|
||||
"token": "abc123def456..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow 3: Проверка статуса верификации
|
||||
|
||||
**Webhook URL:** `https://n8n.clientright.pro/webhook/sms-check-verified`
|
||||
|
||||
### Шаги:
|
||||
|
||||
1. **Webhook Trigger** (POST)
|
||||
- Принимает: `{ "phonenumber": "+79262306381", "token": "abc123..." }`
|
||||
|
||||
2. **Нормализация номера**
|
||||
|
||||
3. **Проверка токена в Redis**
|
||||
- Ключ: `sms:verified:9262306381`
|
||||
- Если токен совпадает → `verified: true`
|
||||
- Иначе → `verified: false`
|
||||
|
||||
4. **Ответ**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"verified": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Преимущества переноса в n8n
|
||||
|
||||
1. ✅ **Визуализация** - видно весь процесс на графике
|
||||
2. ✅ **Логирование** - все шаги логируются автоматически
|
||||
3. ✅ **Мониторинг** - видно ошибки и задержки
|
||||
4. ✅ **Гибкость** - легко добавить новые шаги (например, уведомления в Telegram)
|
||||
5. ✅ **Тестирование** - можно тестировать каждый шаг отдельно
|
||||
6. ✅ **Масштабируемость** - легко добавить несколько SMS провайдеров с fallback
|
||||
|
||||
---
|
||||
|
||||
## Изменения в PHP коде
|
||||
|
||||
После переноса в n8n, `sms-verify.php` станет простым прокси:
|
||||
|
||||
```php
|
||||
// sms-verify.php?action=send
|
||||
// Просто перенаправляет на n8n webhook
|
||||
|
||||
// sms-verify.php?action=verify
|
||||
// Просто перенаправляет на n8n webhook
|
||||
```
|
||||
|
||||
Или можно вообще убрать PHP и вызывать n8n напрямую из JS.
|
||||
230
docs/n8n_webhook_response.md
Normal file
230
docs/n8n_webhook_response.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# Формат ответа N8N Webhook для проверки SMS кода
|
||||
|
||||
## URL Webhook
|
||||
`https://n8n.clientright.pro/webhook/erv_sms_verify`
|
||||
|
||||
## Входящие данные (POST)
|
||||
|
||||
```json
|
||||
{
|
||||
"phonenumber": "+79262306381",
|
||||
"code": "106574"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Формат ответа
|
||||
|
||||
### ✅ Успешная проверка (HTTP 200)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Код подтвержден"
|
||||
}
|
||||
```
|
||||
|
||||
**Поля:**
|
||||
- `success` (boolean, обязательное) - `true` при успехе
|
||||
- `message` (string, обязательное) - сообщение для пользователя
|
||||
|
||||
---
|
||||
|
||||
### ❌ Ошибки (HTTP 400)
|
||||
|
||||
#### 1. Неверный код
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "invalid_code",
|
||||
"message": "Неверный код"
|
||||
}
|
||||
```
|
||||
|
||||
**Поля:**
|
||||
- `success` (boolean) - `false`
|
||||
- `error` (string) - код ошибки: `"invalid_code"`
|
||||
- `message` (string) - сообщение для пользователя
|
||||
|
||||
---
|
||||
|
||||
#### 2. Код не найден или истек
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "code_not_found",
|
||||
"message": "Код не найден или истек. Запросите новый код."
|
||||
}
|
||||
```
|
||||
|
||||
**Поля:**
|
||||
- `success` (boolean) - `false`
|
||||
- `error` (string) - код ошибки: `"code_not_found"`
|
||||
- `message` (string) - сообщение для пользователя
|
||||
|
||||
---
|
||||
|
||||
#### 3. Превышен лимит попыток
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "rate_limit_exceeded",
|
||||
"message": "Превышено количество попыток. Попробуйте позже."
|
||||
}
|
||||
```
|
||||
|
||||
**Поля:**
|
||||
- `success` (boolean) - `false`
|
||||
- `error` (string) - код ошибки: `"rate_limit_exceeded"`
|
||||
- `message` (string) - сообщение для пользователя
|
||||
|
||||
---
|
||||
|
||||
#### 4. Номер телефона или код не указаны
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "missing_data",
|
||||
"message": "Номер телефона или код не указаны"
|
||||
}
|
||||
```
|
||||
|
||||
**Поля:**
|
||||
- `success` (boolean) - `false`
|
||||
- `error` (string) - код ошибки: `"missing_data"`
|
||||
- `message` (string) - сообщение для пользователя
|
||||
|
||||
---
|
||||
|
||||
#### 5. Внутренняя ошибка сервера (HTTP 500)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "internal_error",
|
||||
"message": "Сервис временно недоступен. Попробуйте позже."
|
||||
}
|
||||
```
|
||||
|
||||
**Поля:**
|
||||
- `success` (boolean) - `false`
|
||||
- `error` (string) - код ошибки: `"internal_error"`
|
||||
- `message` (string) - сообщение для пользователя
|
||||
|
||||
---
|
||||
|
||||
## Коды ошибок
|
||||
|
||||
| Код ошибки | HTTP Status | Описание |
|
||||
|------------|-------------|----------|
|
||||
| `invalid_code` | 400 | Введенный код не совпадает с сохраненным |
|
||||
| `code_not_found` | 400 | Код не найден в Redis или истек (TTL) |
|
||||
| `rate_limit_exceeded` | 400 | Превышен лимит попыток проверки (10 за 15 минут) |
|
||||
| `missing_data` | 400 | Не указан номер телефона или код |
|
||||
| `internal_error` | 500 | Внутренняя ошибка (Redis недоступен и т.д.) |
|
||||
|
||||
---
|
||||
|
||||
## Примеры использования в n8n
|
||||
|
||||
### Успешная проверка
|
||||
|
||||
**Workflow шаги:**
|
||||
1. Webhook Trigger → получает `phonenumber` и `code`
|
||||
2. Function Node → нормализация номера
|
||||
3. Redis Node (GET) → чтение кода: `sms:code:9262306381`
|
||||
4. Function Node → сравнение кодов
|
||||
5. Redis Node (DEL) → удаление кода и счетчика попыток
|
||||
6. **Respond to Webhook** → возвращает успешный ответ
|
||||
|
||||
**Код для Respond to Webhook:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Код подтвержден"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Ошибка: Неверный код
|
||||
|
||||
**Workflow шаги:**
|
||||
1. ... (аналогично успешной проверке)
|
||||
2. Function Node → сравнение кодов
|
||||
3. IF Node → если коды не совпадают
|
||||
4. **Respond to Webhook** → возвращает ошибку
|
||||
|
||||
**Код для Respond to Webhook:**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "invalid_code",
|
||||
"message": "Неверный код"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Ошибка: Код не найден
|
||||
|
||||
**Workflow шаги:**
|
||||
1. ... (аналогично)
|
||||
2. Redis Node (GET) → чтение кода
|
||||
3. IF Node → если код = null
|
||||
4. **Respond to Webhook** → возвращает ошибку
|
||||
|
||||
**Код для Respond to Webhook:**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "code_not_found",
|
||||
"message": "Код не найден или истек. Запросите новый код."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Совместимость с текущим кодом
|
||||
|
||||
Текущий JS код (`common.js`) ожидает:
|
||||
|
||||
```javascript
|
||||
success: function(data) {
|
||||
if (data.success) {
|
||||
// Успех - сохраняем токен
|
||||
sms_verify_token = data.token;
|
||||
// ... показываем форму
|
||||
} else {
|
||||
// Ошибка - показываем сообщение
|
||||
$('.modal .form-item__warning').text(data.message || "Неверный код");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Предложенный формат полностью совместим!** ✅
|
||||
|
||||
---
|
||||
|
||||
## Дополнительные рекомендации
|
||||
|
||||
1. **HTTP Status Codes:**
|
||||
- Успех: `200 OK`
|
||||
- Ошибки клиента: `400 Bad Request`
|
||||
- Ошибки сервера: `500 Internal Server Error`
|
||||
|
||||
2. **Content-Type:**
|
||||
- Всегда: `application/json; charset=utf-8`
|
||||
|
||||
3. **Логирование:**
|
||||
- Логировать все попытки проверки (успешные и неуспешные)
|
||||
- Логировать ошибки с деталями
|
||||
|
||||
4. **Безопасность:**
|
||||
- Не возвращать детали внутренних ошибок в production
|
||||
- Не возвращать реальные коды в ответах
|
||||
Reference in New Issue
Block a user