.
This commit is contained in:
@@ -0,0 +1,752 @@
|
||||
# API для запуска стратегий продвижения
|
||||
|
||||
## Обзор
|
||||
|
||||
Данный документ описывает API для управления credentials социальных сетей и запуска маркетинговых стратегий с автоматической публикацией постов.
|
||||
|
||||
## Базовый URL
|
||||
|
||||
```
|
||||
http://your-server:port/api
|
||||
```
|
||||
|
||||
## Аутентификация
|
||||
|
||||
Все endpoints требуют JWT токен в заголовке `Authorization`:
|
||||
|
||||
```
|
||||
Authorization: Bearer <your-jwt-token>
|
||||
```
|
||||
|
||||
## Управление Credentials социальных сетей
|
||||
|
||||
### 1. Сохранение/обновление credentials
|
||||
|
||||
Сохраняет или обновляет credentials для указанной платформы. Credentials автоматически шифруются перед сохранением.
|
||||
|
||||
**Endpoint:** `POST /api/social-media/credentials`
|
||||
|
||||
**Headers:**
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"platform": "facebook",
|
||||
"credentials": "your-facebook-access-token"
|
||||
}
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
|
||||
- `platform` (string, required) - Название платформы (например: "facebook", "instagram")
|
||||
- `credentials` (string, required) - Access token или другие credentials для платформы
|
||||
|
||||
**Response 200 OK:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Credentials успешно сохранены для платформы facebook",
|
||||
"data": {
|
||||
"platform": "facebook",
|
||||
"hasCredentials": true,
|
||||
"createdAt": "2024-01-15T10:30:00",
|
||||
"updatedAt": "2024-01-15T10:30:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response 400 Bad Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Ошибка валидации",
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "Platform is required",
|
||||
"details": {
|
||||
"platform": "Platform is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response 401 Unauthorized:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Не авторизован",
|
||||
"error": {
|
||||
"code": "UNAUTHORIZED",
|
||||
"message": "Требуется аутентификация. Пожалуйста, предоставьте валидный JWT токен."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Пример запроса (JavaScript):**
|
||||
|
||||
```javascript
|
||||
const saveCredentials = async (platform, accessToken) => {
|
||||
const response = await fetch('/api/social-media/credentials', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
platform: platform,
|
||||
credentials: accessToken,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
// Использование
|
||||
await saveCredentials('facebook', 'EAABwzLix...');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Получение информации о credentials
|
||||
|
||||
Проверяет наличие credentials для указанной платформы.
|
||||
|
||||
**Endpoint:** `GET /api/social-media/credentials/{platform}`
|
||||
|
||||
**Headers:**
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Path Parameters:**
|
||||
|
||||
- `platform` (string) - Название платформы
|
||||
|
||||
**Response 200 OK:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Операция выполнена успешно",
|
||||
"data": {
|
||||
"platform": "facebook",
|
||||
"hasCredentials": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Пример запроса:**
|
||||
|
||||
```javascript
|
||||
const checkCredentials = async (platform) => {
|
||||
const response = await fetch(`/api/social-media/credentials/${platform}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
return data.data.hasCredentials;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Получение списка всех credentials
|
||||
|
||||
Возвращает список всех платформ, для которых у пользователя настроены credentials.
|
||||
|
||||
**Endpoint:** `GET /api/social-media/credentials`
|
||||
|
||||
**Headers:**
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response 200 OK:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Операция выполнена успешно",
|
||||
"data": [
|
||||
{
|
||||
"platform": "facebook",
|
||||
"hasCredentials": true,
|
||||
"createdAt": "2024-01-15T10:30:00",
|
||||
"updatedAt": "2024-01-15T10:30:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Пример запроса:**
|
||||
|
||||
```javascript
|
||||
const getAllCredentials = async () => {
|
||||
const response = await fetch('/api/social-media/credentials', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
return data.data;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Удаление credentials
|
||||
|
||||
Удаляет credentials для указанной платформы.
|
||||
|
||||
**Endpoint:** `DELETE /api/social-media/credentials/{platform}`
|
||||
|
||||
**Headers:**
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Path Parameters:**
|
||||
|
||||
- `platform` (string) - Название платформы
|
||||
|
||||
**Response 200 OK:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Credentials для платформы facebook успешно удалены",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
**Response 404 Not Found:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Credentials не найдены",
|
||||
"error": {
|
||||
"code": "NOT_FOUND",
|
||||
"message": "Credentials для платформы facebook не найдены"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Пример запроса:**
|
||||
|
||||
```javascript
|
||||
const deleteCredentials = async (platform) => {
|
||||
const response = await fetch(`/api/social-media/credentials/${platform}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Запуск стратегии продвижения
|
||||
|
||||
### Запуск стратегии
|
||||
|
||||
Запускает выполнение маркетинговой стратегии. Система автоматически создает задачи публикации из календаря постов стратегии и добавляет их в очередь для выполнения.
|
||||
|
||||
**Endpoint:** `POST /api/marketing/analysis/strategy/{strategyId}/start`
|
||||
|
||||
**Headers:**
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Path Parameters:**
|
||||
|
||||
- `strategyId` (string) - ID стратегии для запуска
|
||||
|
||||
**Request Body (опционально):**
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
**Response 200 OK:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Стратегия успешно запущена",
|
||||
"data": {
|
||||
"strategyId": "67890abcdef",
|
||||
"tasksCreated": 12,
|
||||
"platforms": ["facebook", "instagram"],
|
||||
"message": "Стратегия успешно запущена. Создано задач: 12"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response 400 Bad Request (стратегия не завершена):**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Стратегия не готова к запуску",
|
||||
"error": {
|
||||
"code": "INVALID_STATUS",
|
||||
"message": "Стратегия еще не завершена. Статус: processing"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response 400 Bad Request (нет credentials):**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Не удалось запустить стратегию",
|
||||
"error": {
|
||||
"code": "MISSING_CREDENTIALS",
|
||||
"message": "Credentials not found for platform: facebook. Please configure credentials first."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response 404 Not Found:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Стратегия не найдена",
|
||||
"error": {
|
||||
"code": "NOT_FOUND",
|
||||
"message": "Стратегия с указанным ID не найдена"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response 403 Forbidden:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Доступ запрещен",
|
||||
"error": {
|
||||
"code": "FORBIDDEN",
|
||||
"message": "У вас нет доступа к этой стратегии"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Пример запроса:**
|
||||
|
||||
```javascript
|
||||
const startStrategy = async (strategyId) => {
|
||||
const response = await fetch(
|
||||
`/api/marketing/analysis/strategy/${strategyId}/start`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
}
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
console.log(`Создано задач: ${data.data.tasksCreated}`);
|
||||
console.log(`Платформы: ${data.data.platforms.join(', ')}`);
|
||||
} else {
|
||||
console.error('Ошибка:', data.error.message);
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Полный пример использования
|
||||
|
||||
### Шаг 1: Настройка credentials для Facebook
|
||||
|
||||
```javascript
|
||||
// Сохраняем Facebook Access Token
|
||||
const facebookToken = 'EAABwzLix...'; // Получить из Facebook Developer Console
|
||||
|
||||
const result = await saveCredentials('facebook', facebookToken);
|
||||
if (result.success) {
|
||||
console.log('Facebook credentials сохранены');
|
||||
}
|
||||
```
|
||||
|
||||
### Шаг 2: Получение стратегии
|
||||
|
||||
```javascript
|
||||
// Получаем список стратегий пользователя
|
||||
const response = await fetch('/api/marketing/analysis/strategy/my', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
const strategies = data.data;
|
||||
|
||||
// Выбираем завершенную стратегию
|
||||
const completedStrategy = strategies.find((s) => s.status === 'completed');
|
||||
```
|
||||
|
||||
### Шаг 3: Запуск стратегии
|
||||
|
||||
```javascript
|
||||
if (completedStrategy) {
|
||||
// Проверяем наличие credentials для платформ стратегии
|
||||
const platforms = completedStrategy.priorityPlatforms || [];
|
||||
|
||||
for (const platform of platforms) {
|
||||
const hasCreds = await checkCredentials(platform);
|
||||
if (!hasCreds) {
|
||||
console.warn(`Необходимо настроить credentials для ${platform}`);
|
||||
// Показать пользователю форму для ввода credentials
|
||||
}
|
||||
}
|
||||
|
||||
// Запускаем стратегию
|
||||
const startResult = await startStrategy(completedStrategy.strategyId);
|
||||
|
||||
if (startResult.success) {
|
||||
console.log(
|
||||
`Стратегия запущена! Создано ${startResult.data.tasksCreated} задач`
|
||||
);
|
||||
// Показать уведомление пользователю
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Обработка ошибок
|
||||
|
||||
### Типичные ошибки и их обработка
|
||||
|
||||
1. **UNAUTHORIZED (401)**
|
||||
|
||||
- Причина: Невалидный или отсутствующий JWT токен
|
||||
- Решение: Обновить токен или перенаправить на страницу входа
|
||||
|
||||
2. **VALIDATION_ERROR (400)**
|
||||
|
||||
- Причина: Невалидные данные в запросе
|
||||
- Решение: Проверить обязательные поля и их формат
|
||||
|
||||
3. **MISSING_CREDENTIALS (400)**
|
||||
|
||||
- Причина: Не настроены credentials для платформы
|
||||
- Решение: Предложить пользователю настроить credentials
|
||||
|
||||
4. **INVALID_STATUS (400)**
|
||||
|
||||
- Причина: Стратегия еще не завершена
|
||||
- Решение: Дождаться завершения генерации стратегии
|
||||
|
||||
5. **NOT_FOUND (404)**
|
||||
|
||||
- Причина: Стратегия или credentials не найдены
|
||||
- Решение: Проверить правильность ID
|
||||
|
||||
6. **FORBIDDEN (403)**
|
||||
- Причина: Пользователь не имеет доступа к ресурсу
|
||||
- Решение: Проверить права доступа
|
||||
|
||||
### Пример обработки ошибок
|
||||
|
||||
```javascript
|
||||
const handleApiError = (error) => {
|
||||
switch (error.code) {
|
||||
case 'UNAUTHORIZED':
|
||||
// Перенаправить на страницу входа
|
||||
window.location.href = '/login';
|
||||
break;
|
||||
|
||||
case 'MISSING_CREDENTIALS':
|
||||
// Показать модальное окно для настройки credentials
|
||||
showCredentialsModal(error.message);
|
||||
break;
|
||||
|
||||
case 'INVALID_STATUS':
|
||||
// Показать сообщение о том, что стратегия еще не готова
|
||||
showNotification(
|
||||
'Стратегия еще не завершена. Пожалуйста, подождите.',
|
||||
'warning'
|
||||
);
|
||||
break;
|
||||
|
||||
case 'VALIDATION_ERROR':
|
||||
// Показать ошибки валидации
|
||||
showValidationErrors(error.details);
|
||||
break;
|
||||
|
||||
default:
|
||||
showNotification('Произошла ошибка. Попробуйте позже.', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
// Использование
|
||||
try {
|
||||
const result = await startStrategy(strategyId);
|
||||
if (!result.success) {
|
||||
handleApiError(result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Network error:', error);
|
||||
showNotification('Ошибка сети. Проверьте подключение.', 'error');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Статусы задач публикации
|
||||
|
||||
После запуска стратегии создаются задачи со следующими статусами:
|
||||
|
||||
- `pending` - Задача ожидает выполнения (дата публикации еще не наступила)
|
||||
- `processing` - Задача выполняется в данный момент
|
||||
- `completed` - Задача успешно выполнена
|
||||
- `failed` - Задача не выполнена из-за ошибки
|
||||
|
||||
**Примечание:** Задачи с датой публикации в прошлом выполняются сразу после создания.
|
||||
|
||||
---
|
||||
|
||||
## Планировщик задач
|
||||
|
||||
Система автоматически проверяет очередь задач каждую минуту и выполняет задачи, у которых наступило время публикации.
|
||||
|
||||
- Планировщик включен по умолчанию
|
||||
- Можно отключить через настройку `posting.scheduler.enabled=false`
|
||||
- Задачи выполняются асинхронно
|
||||
|
||||
---
|
||||
|
||||
## Поддерживаемые платформы
|
||||
|
||||
На данный момент поддерживается:
|
||||
|
||||
- **Facebook** - через Facebook Graph API v18.0
|
||||
|
||||
В будущем планируется поддержка:
|
||||
|
||||
- Instagram
|
||||
- LinkedIn
|
||||
- Telegram
|
||||
- TikTok
|
||||
- YouTube
|
||||
|
||||
---
|
||||
|
||||
## Получение Facebook Access Token
|
||||
|
||||
Для получения Facebook Access Token:
|
||||
|
||||
1. Перейдите на [Facebook Developers](https://developers.facebook.com/)
|
||||
2. Создайте приложение
|
||||
3. Добавьте продукт "Facebook Login"
|
||||
4. Настройте OAuth и получите Access Token
|
||||
5. Используйте полученный токен в API
|
||||
|
||||
**Важно:**
|
||||
|
||||
- Access Token имеет срок действия
|
||||
- Для долгосрочного использования рекомендуется использовать Long-Lived Token
|
||||
- Токен должен иметь разрешения `pages_manage_posts` для публикации
|
||||
|
||||
---
|
||||
|
||||
## Примеры React компонентов
|
||||
|
||||
### Компонент для настройки credentials
|
||||
|
||||
```jsx
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const CredentialsForm = ({ platform, onSave }) => {
|
||||
const [token, setToken] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/social-media/credentials', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
platform: platform,
|
||||
credentials: token,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
onSave();
|
||||
setToken('');
|
||||
} else {
|
||||
setError(data.error.message);
|
||||
}
|
||||
} catch (err) {
|
||||
setError('Ошибка сети');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div>
|
||||
<label>Access Token для {platform}:</label>
|
||||
<input
|
||||
type='text'
|
||||
value={token}
|
||||
onChange={(e) => setToken(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
{error && <div className='error'>{error}</div>}
|
||||
<button type='submit' disabled={loading}>
|
||||
{loading ? 'Сохранение...' : 'Сохранить'}
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default CredentialsForm;
|
||||
```
|
||||
|
||||
### Компонент для запуска стратегии
|
||||
|
||||
```jsx
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const StartStrategyButton = ({ strategyId, onStart }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const handleStart = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/marketing/analysis/strategy/${strategyId}/start`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwtToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
}
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
onStart(data.data);
|
||||
} else {
|
||||
setError(data.error.message);
|
||||
}
|
||||
} catch (err) {
|
||||
setError('Ошибка сети');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button onClick={handleStart} disabled={loading}>
|
||||
{loading ? 'Запуск...' : 'Запустить стратегию'}
|
||||
</button>
|
||||
{error && <div className='error'>{error}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StartStrategyButton;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Часто задаваемые вопросы
|
||||
|
||||
### Q: Как часто проверяются задачи на выполнение?
|
||||
|
||||
A: Планировщик проверяет очередь каждую минуту.
|
||||
|
||||
### Q: Что происходит, если credentials истекли?
|
||||
|
||||
A: Задача получит статус `failed` с сообщением об ошибке. Необходимо обновить credentials и перезапустить стратегию.
|
||||
|
||||
### Q: Можно ли отменить выполнение стратегии?
|
||||
|
||||
A: На данный момент нет, но можно удалить credentials для платформы, что предотвратит выполнение будущих задач.
|
||||
|
||||
### Q: Как узнать статус выполнения задач?
|
||||
|
||||
A: Статусы задач можно получить через API (будет добавлено в будущих версиях).
|
||||
|
||||
### Q: Поддерживается ли публикация с изображениями?
|
||||
|
||||
A: На данный момент поддерживается только текстовая публикация. Поддержка изображений планируется в будущем.
|
||||
|
||||
---
|
||||
|
||||
## Версионирование API
|
||||
|
||||
Текущая версия: **v1**
|
||||
|
||||
Все endpoints могут изменяться в будущих версиях. При изменении API будет указана новая версия.
|
||||
|
||||
---
|
||||
|
||||
## Поддержка
|
||||
|
||||
При возникновении проблем:
|
||||
|
||||
1. Проверьте логи в консоли браузера
|
||||
2. Убедитесь, что JWT токен валиден
|
||||
3. Проверьте формат запросов согласно документации
|
||||
4. Обратитесь к разработчикам с описанием проблемы
|
||||
Reference in New Issue
Block a user