Files
chat/docs/MOBILE_API_SPECS.md
Andrew K. Choi 7c22664daf
All checks were successful
continuous-integration/drone/push Build is passing
sdf
2025-09-26 12:22:14 +09:00

14 KiB
Raw Blame History

API Спецификации для мобильного приложения Women's Safety App

Обзор системы

Микросервисная архитектура с 6 сервисами:

  • API Gateway (порт 8000) - точка входа
  • User Service (порт 8001) - управление пользователями
  • Emergency Service (порт 8002) - экстренные ситуации
  • Location Service (порт 8003) - геолокация
  • Calendar Service (порт 8004) - календарь здоровья
  • Notification Service (порт 8005) - уведомления

Базовый URL: http://192.168.0.103:8000 (API Gateway) Прямые сервисы: http://192.168.0.103:800X (где X - номер сервиса)


🔐 Система авторизации

Регистрация пользователя

POST /api/v1/auth/register

{
  "username": "testuser",
  "email": "test@example.com", 
  "password": "password123",
  "full_name": "Test User",
  "phone": "+1234567890"
}

Вход в систему

POST /api/v1/auth/login

{
  "username": "testuser", // или "email": "test@example.com"
  "password": "password123"
}

Ответ:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

👤 User Service API

Профиль пользователя

GET /api/v1/user/profile Ответ: Полная информация о пользователе

PUT /api/v1/user/profile - Обновление профиля

Дашборд пользователя

GET /api/v1/user/dashboard Ответ:

{
  "user_info": {...},
  "recent_alerts": [...],
  "emergency_contacts": [...],
  "safety_stats": {...}
}

Экстренные контакты

GET /api/v1/user/emergency-contacts - Список контактов POST /api/v1/user/emergency-contacts - Добавить контакт PUT /api/v1/user/emergency-contacts/{id} - Обновить контакт DELETE /api/v1/user/emergency-contacts/{id} - Удалить контакт

Схема контакта:

{
  "name": "Мама",
  "phone_number": "+1234567890",
  "relationship": "mother",
  "notes": "Основной контакт",
  "is_active": true
}

🆘 Emergency Service API (Полная спецификация)

Типы данных

enum AlertType {
  GENERAL = "general",
  MEDICAL = "medical", 
  VIOLENCE = "violence",
  HARASSMENT = "harassment",
  UNSAFE_AREA = "unsafe_area",
  ACCIDENT = "accident",
  FIRE = "fire",
  NATURAL_DISASTER = "natural_disaster"
}

enum AlertStatus {
  ACTIVE = "active",
  RESOLVED = "resolved", 
  CANCELLED = "cancelled",
  INVESTIGATING = "investigating"
}

enum ResponseType {
  HELP_ON_WAY = "help_on_way",
  CONTACTED_AUTHORITIES = "contacted_authorities",
  SAFE_NOW = "safe_now",
  FALSE_ALARM = "false_alarm"
}

Основные endpoints

1. Создание экстренного оповещения

POST /api/v1/alert (через Emergency Service напрямую: порт 8002)

{
  "latitude": 55.7558,
  "longitude": 37.6176,
  "alert_type": "general",
  "message": "Нужна помощь",
  "address": "Красная площадь, Москва",
  "contact_emergency_services": true,
  "notify_emergency_contacts": true
}

2. Получение оповещений

  • GET /api/v1/alerts/my - Мои оповещения
  • GET /api/v1/alerts/active - Активные оповещения
  • GET /api/v1/alerts/nearby?latitude=55.7558&longitude=37.6176&radius_km=10 - Ближайшие

3. Отклик на оповещение

POST /api/v1/alert/{alert_id}/respond

{
  "response_type": "help_on_way",
  "message": "Еду к вам!",
  "eta_minutes": 15,
  "location_sharing": true
}

4. Управление оповещением

  • PUT /api/v1/alert/{alert_id} - Обновить оповещение
  • PUT /api/v1/alert/{alert_id}/resolve - Пометить как решенное
  • GET /api/v1/alert/{alert_id}/responses - Получить отклики

5. Отчеты о происшествиях

POST /api/v1/report

{
  "latitude": 55.7558,
  "longitude": 37.6176, 
  "report_type": "harassment",
  "description": "Описание происшествия",
  "severity": 4,
  "is_anonymous": false
}

6. Отметки безопасности

POST /api/v1/safety-check

{
  "message": "Я в безопасности",
  "location_latitude": 55.7558,
  "location_longitude": 37.6176
}

7. Статистика

GET /api/v1/stats

{
  "total_alerts": 150,
  "active_alerts": 12,
  "resolved_alerts": 138,
  "total_responders": 89,
  "avg_response_time_minutes": 8.5
}

📍 Location Service API

Обновление местоположения

POST /api/v1/location/update

{
  "latitude": 55.7558,
  "longitude": 37.6176,
  "accuracy": 10.0,
  "altitude": 150.0
}

Поиск пользователей рядом

GET /api/v1/nearby-users?latitude=55.7558&longitude=37.6176&radius_km=1.0

Геокодирование

GET /api/v1/geocode/reverse?latitude=55.7558&longitude=37.6176 GET /api/v1/geocode/forward?address=Красная площадь, Москва


📅 Calendar Service API

Календарь здоровья

GET /api/v1/calendar/entries - Записи календаря POST /api/v1/calendar/entries - Добавить запись

Схема записи:

{
  "date": "2024-01-15",
  "entry_type": "period_start", // period_start, period_end, mood, symptoms
  "notes": "Заметки",
  "mood_score": 4, // 1-5
  "symptoms": ["headache", "fatigue"]
}

Аналитика

GET /api/v1/calendar/analytics - Аналитика цикла


🔔 Notification Service API

Отправка уведомления

POST /api/v1/send-notification

{
  "user_id": 123,
  "title": "Экстренное оповещение",
  "message": "Новое оповещение рядом с вами",
  "type": "emergency_alert",
  "data": {"alert_id": 456}
}

Push токены

POST /api/v1/push-token

{
  "token": "fcm_or_apns_token",
  "platform": "ios" // или "android"
}

🔗 Интеграция для мобильного приложения

Базовый HTTP клиент

class WomenSafetyAPI {
  constructor(baseUrl = 'http://192.168.0.103:8000') {
    this.baseUrl = baseUrl;
    this.token = null;
  }
  
  setToken(token) {
    this.token = token;
  }
  
  async request(method, endpoint, data = null) {
    const config = {
      method,
      headers: {
        'Content-Type': 'application/json',
      }
    };
    
    if (this.token) {
      config.headers.Authorization = `Bearer ${this.token}`;
    }
    
    if (data && (method === 'POST' || method === 'PUT')) {
      config.body = JSON.stringify(data);
    }
    
    const url = `${this.baseUrl}${endpoint}`;
    const response = await fetch(url, config);
    
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail || 'API Error');
    }
    
    return await response.json();
  }
}

Основные методы API

class EmergencyAPI extends WomenSafetyAPI {
  // Авторизация
  async login(username, password) {
    const response = await this.request('POST', '/api/v1/auth/login', {
      username,
      password
    });
    this.setToken(response.access_token);
    return response;
  }
  
  async register(userData) {
    return await this.request('POST', '/api/v1/auth/register', userData);
  }
  
  // Экстренные ситуации (через порт 8002)
  async createAlert(alertData) {
    const emergencyUrl = this.baseUrl.replace('8000', '8002');
    return await fetch(`${emergencyUrl}/api/v1/alert`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`
      },
      body: JSON.stringify(alertData)
    }).then(r => r.json());
  }
  
  async getNearbyAlerts(latitude, longitude, radiusKm = 10) {
    const emergencyUrl = this.baseUrl.replace('8000', '8002');
    const params = new URLSearchParams({
      latitude: latitude.toString(),
      longitude: longitude.toString(),
      radius_km: radiusKm.toString()
    });
    
    return await fetch(`${emergencyUrl}/api/v1/alerts/nearby?${params}`, {
      headers: { 'Authorization': `Bearer ${this.token}` }
    }).then(r => r.json());
  }
  
  async respondToAlert(alertId, responseData) {
    const emergencyUrl = this.baseUrl.replace('8000', '8002');
    return await fetch(`${emergencyUrl}/api/v1/alert/${alertId}/respond`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`
      },
      body: JSON.stringify(responseData)
    }).then(r => r.json());
  }
  
  // Профиль пользователя
  async getProfile() {
    return await this.request('GET', '/api/v1/user/profile');
  }
  
  async getDashboard() {
    return await this.request('GET', '/api/v1/user/dashboard');
  }
  
  // Экстренные контакты
  async getEmergencyContacts() {
    return await this.request('GET', '/api/v1/user/emergency-contacts');
  }
  
  async addEmergencyContact(contactData) {
    return await this.request('POST', '/api/v1/user/emergency-contacts', contactData);
  }
  
  // Местоположение
  async updateLocation(locationData) {
    return await this.request('POST', '/api/v1/location/update', locationData);
  }
  
  // Отметка безопасности
  async createSafetyCheck(safetyData) {
    const emergencyUrl = this.baseUrl.replace('8000', '8002');
    return await fetch(`${emergencyUrl}/api/v1/safety-check`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.token}`
      },
      body: JSON.stringify(safetyData)
    }).then(r => r.json());
  }
}

Примеры использования

// Инициализация
const api = new EmergencyAPI('http://192.168.0.103:8000');

// Авторизация
await api.login('testuser', 'password123');

// Создание экстренного оповещения
const alert = await api.createAlert({
  latitude: 55.7558,
  longitude: 37.6176,
  alert_type: 'general',
  message: 'Нужна помощь!',
  address: 'Красная площадь, Москва'
});

// Поиск ближайших оповещений
const nearbyAlerts = await api.getNearbyAlerts(55.7558, 37.6176, 5);

// Отклик на оповещение
const response = await api.respondToAlert(alert.id, {
  response_type: 'help_on_way',
  message: 'Еду к вам!',
  eta_minutes: 10
});

// Получение профиля
const profile = await api.getProfile();

// Отметка безопасности
const safetyCheck = await api.createSafetyCheck({
  message: 'Добрался домой безопасно',
  location_latitude: 55.7600,
  location_longitude: 37.6100
});

🛡️ Безопасность и аутентификация

JWT токены

  • Время жизни: настраивается в конфигурации
  • Формат: Bearer {token}
  • Включают: user_id, email, exp (время истечения)

Заголовки запросов

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

Коды ошибок

  • 401 Unauthorized - Неверные учетные данные
  • 403 Forbidden - Недостаточно прав
  • 422 Unprocessable Entity - Ошибки валидации
  • 500 Internal Server Error - Внутренняя ошибка

📱 Рекомендации для мобильной разработки

Push уведомления

  1. Зарегистрируйте push токен через /api/v1/push-token
  2. Обрабатывайте входящие уведомления для экстренных ситуаций
  3. Показывайте локальные уведомления при получении emergency_alert

Геолокация

  1. Запрашивайте разрешения на точное местоположение
  2. Обновляйте координаты через /api/v1/location/update
  3. Кэшируйте последнее известное местоположение

Оффлайн режим

  1. Кэшируйте экстренные контакты локально
  2. Сохраняйте черновики оповещений для отправки при восстановлении связи
  3. Показывайте статус подключения к сервису

UI/UX

  1. Красная кнопка SOS должна быть всегда доступна
  2. Быстрый доступ к созданию оповещения (виджет, ярлык)
  3. Показывайте статус отправленных оповещений
  4. Уведомления о новых откликах на оповещения

🧪 Тестирование

Используйте прилагаемый скрипт test_emergency_api.sh для полного тестирования API:

./test_emergency_api.sh

Скрипт проверит:

  • Регистрацию и авторизацию
  • Создание и управление оповещениями
  • Отклики на оповещения
  • Отчеты и отметки безопасности
  • Статистику и аналитику