764 lines
20 KiB
Markdown
764 lines
20 KiB
Markdown
# 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` для публикации
|
|
|
|
**Для запуска рекламных кампаний в Facebook требуется дополнительная настройка:**
|
|
|
|
📖 **Подробная инструкция:** См. [FACEBOOK_ADS_CREDENTIALS.md](./FACEBOOK_ADS_CREDENTIALS.md)
|
|
|
|
Для рекламы нужны:
|
|
|
|
- Access Token с разрешениями `ads_management`, `ads_read`, `business_management`
|
|
- Ad Account ID (формат: `act_XXXXXXXXX`)
|
|
- App ID и App Secret
|
|
- Page ID (опционально)
|
|
|
|
---
|
|
|
|
## Примеры 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. Обратитесь к разработчикам с описанием проблемы
|