diff --git a/bank.py b/bank.py
deleted file mode 100644
index b000ea9..0000000
--- a/bank.py
+++ /dev/null
@@ -1,3754 +0,0 @@
-from flask import Flask, request, redirect, session, Response, jsonify
-import json, os, random, time, uuid
-from datetime import datetime
-from functools import wraps
-
-app = Flask(__name__)
-app.secret_key = "bank_secret_key_2025"
-app.config['SESSION_PERMANENT'] = True
-app.config['PERMANENT_SESSION_LIFETIME'] = 3600
-
-USERS_FILE = "users.json"
-HISTORY_FILE = "history.json"
-CARDS_FILE = "cards.json"
-SHOP_FILE = "shop.json"
-PAYMENTS_FILE = "payments.json" # Новый файл для платежей
-
-# ---------- ИНИЦИАЛИЗАЦИЯ ФАЙЛОВ ----------
-def init_files():
- """Инициализация файлов (без удаления существующих)"""
- # Создаем файлы если они не существуют
- files_to_init = [
- (USERS_FILE, {
- "admin": {
- "password": "admin123",
- "balance": 100000,
- "deposit": 0,
- "credit": 0,
- "role": "admin",
- "full_name": "Администратор Системы",
- "email": "admin@bank.com",
- "api_key": None
- }
- }),
- (HISTORY_FILE, []),
- (CARDS_FILE, {}),
- (SHOP_FILE, {"items": [], "ads": []}),
- (PAYMENTS_FILE, []) # Инициализация файла платежей
- ]
-
- for filename, default_data in files_to_init:
- if not os.path.exists(filename):
- with open(filename, "w", encoding='utf-8') as f:
- json.dump(default_data, f, indent=4, ensure_ascii=False)
-
-# Инициализируем файлы при запуске
-init_files()
-
-# ---------- ФУНКЦИИ ДЛЯ РАБОТЫ С ДАННЫМИ ----------
-def load_users():
- try:
- with open(USERS_FILE, 'r', encoding='utf-8') as f:
- data = json.load(f)
- # Убеждаемся, что данные в правильном формате
- if not isinstance(data, dict):
- print("Warning: users.json is not a dictionary, resetting to default")
- data = {
- "admin": {
- "password": "admin123",
- "balance": 100000,
- "deposit": 0,
- "credit": 0,
- "role": "admin",
- "full_name": "Администратор Системы",
- "email": "admin@bank.com",
- "api_key": None
- }
- }
- save_users(data)
- return data
- # Проверяем, что все значения являются словарями
- cleaned_data = {}
- for username, user_data in data.items():
- if isinstance(user_data, dict):
- cleaned_data[username] = user_data
- else:
- print(f"Warning: User {username} data is not a dict, resetting")
- cleaned_data[username] = {
- "password": "reset123",
- "balance": 1000,
- "deposit": 0,
- "credit": 0,
- "role": "client",
- "full_name": "Пользователь",
- "email": "user@example.com",
- "api_key": None
- }
- if cleaned_data != data:
- save_users(cleaned_data)
- return cleaned_data
- except Exception as e:
- print(f"Error loading users: {e}")
- data = {
- "admin": {
- "password": "admin123",
- "balance": 100000,
- "deposit": 0,
- "credit": 0,
- "role": "admin",
- "full_name": "Администратор Системы",
- "email": "admin@bank.com",
- "api_key": None
- }
- }
- save_users(data)
- return data
-
-def save_users(data):
- with open(USERS_FILE, "w", encoding='utf-8') as f:
- json.dump(data, f, indent=4, ensure_ascii=False)
-
-def load_history():
- try:
- with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
- return json.load(f)
- except:
- return []
-
-def save_history(data):
- with open(HISTORY_FILE, "w", encoding='utf-8') as f:
- json.dump(data, f, indent=4, ensure_ascii=False)
-
-def load_cards():
- try:
- with open(CARDS_FILE, 'r', encoding='utf-8') as f:
- return json.load(f)
- except:
- return {}
-
-def save_cards(data):
- with open(CARDS_FILE, "w", encoding='utf-8') as f:
- json.dump(data, f, indent=4, ensure_ascii=False)
-
-# ---------- ФУНКЦИИ ДЛЯ ПЛАТЕЖЕЙ ----------
-def load_payments():
- """Загрузка платежей"""
- try:
- with open(PAYMENTS_FILE, 'r', encoding='utf-8') as f:
- return json.load(f)
- except:
- return []
-
-def save_payments(data):
- """Сохранение платежей"""
- with open(PAYMENTS_FILE, "w", encoding='utf-8') as f:
- json.dump(data, f, indent=4, ensure_ascii=False)
-
-def create_payment(payer, receiver, amount, description="", external_id=""):
- """Создание платежа"""
- payments = load_payments()
-
- payment_id = str(uuid.uuid4())[:12]
- payment_data = {
- "id": payment_id,
- "payer": payer,
- "receiver": receiver,
- "amount": int(amount),
- "description": description,
- "external_id": external_id,
- "created": int(time.time()),
- "status": "pending", # pending, completed, failed, cancelled
- "completed_at": None
- }
-
- payments.append(payment_data)
- save_payments(payments)
-
- return payment_id, payment_data
-
-def process_payment(payment_id, payer_username=None):
- """Обработка платежа"""
- payments = load_payments()
- users = load_users()
-
- payment = None
- for p in payments:
- if p["id"] == payment_id:
- payment = p
- break
-
- if not payment:
- return False, "Платеж не найден"
-
- if payment["status"] != "pending":
- return False, f"Платеж уже обработан (статус: {payment['status']})"
-
- # Если передан payer_username, проверяем что это тот же плательщик
- if payer_username and payment["payer"] != payer_username:
- return False, "Неверный плательщик"
-
- payer = payment["payer"]
- receiver = payment["receiver"]
- amount = payment["amount"]
-
- # Проверяем существование пользователей
- if payer not in users:
- return False, "Плательщик не найден"
-
- if receiver not in users:
- return False, "Получатель не найден"
-
- # Проверяем баланс плательщика
- if users[payer]["balance"] < amount:
- return False, "Недостаточно средств"
-
- # Выполняем перевод
- users[payer]["balance"] -= amount
- users[receiver]["balance"] += amount
- save_users(users)
-
- # Обновляем статус платежа
- for p in payments:
- if p["id"] == payment_id:
- p["status"] = "completed"
- p["completed_at"] = int(time.time())
- break
-
- save_payments(payments)
-
- # Добавляем в историю
- add_history(payer, "payment_sent", amount, f"Платеж #{payment_id} для {receiver}")
- add_history(receiver, "payment_received", amount, f"Платеж #{payment_id} от {payer}")
-
- return True, "Платеж успешно выполнен"
-
-def cancel_payment(payment_id):
- """Отмена платежа"""
- payments = load_payments()
-
- for payment in payments:
- if payment["id"] == payment_id and payment["status"] == "pending":
- payment["status"] = "cancelled"
- save_payments(payments)
- return True, "Платеж отменен"
-
- return False, "Платеж не найден или уже обработан"
-
-# ---------- ФУНКЦИИ ДЛЯ МАГАЗИНА ----------
-def load_shop():
- """Загрузка данных магазина"""
- try:
- with open(SHOP_FILE, 'r', encoding='utf-8') as f:
- data = json.load(f)
- # Обеспечиваем наличие всех ключей
- if "items" not in data:
- data["items"] = []
- if "ads" not in data:
- data["ads"] = []
- return data
- except:
- return {"items": [], "ads": []}
-
-def save_shop(data):
- """Сохранение данных магазина"""
- with open(SHOP_FILE, "w", encoding='utf-8') as f:
- json.dump(data, f, indent=4, ensure_ascii=False)
-
-def create_shop_item(seller_username, title, description, price, category="other"):
- """Создание товара в магазине"""
- shop_data = load_shop()
-
- item_id = str(uuid.uuid4())[:8]
- new_item = {
- "id": item_id,
- "seller": seller_username,
- "title": title,
- "description": description,
- "price": int(price),
- "category": category,
- "created": int(time.time()),
- "status": "available",
- "buyer": None
- }
-
- shop_data["items"].append(new_item)
- save_shop(shop_data)
-
- # Добавляем в историю
- add_history(seller_username, "create_shop_item", 0, f"Товар: {title}")
-
- return item_id
-
-def create_advertisement(author, title, content, contact_info):
- """Создание объявления"""
- shop_data = load_shop()
-
- ad_id = str(uuid.uuid4())[:8]
- new_ad = {
- "id": ad_id,
- "author": author,
- "title": title,
- "content": content,
- "contact_info": contact_info,
- "created": int(time.time()),
- "status": "active"
- }
-
- shop_data["ads"].append(new_ad)
- save_shop(shop_data)
-
- # Добавляем в историю
- add_history(author, "create_advertisement", 0, f"Объявление: {title}")
-
- return ad_id
-
-def buy_item(item_id, buyer_username):
- """Покупка товара"""
- shop_data = load_shop()
- users = load_users()
-
- # Находим товар
- item_to_buy = None
- for item in shop_data["items"]:
- if item["id"] == item_id and item["status"] == "available":
- item_to_buy = item
- break
-
- if not item_to_buy:
- return False, "Товар не найден или уже продан"
-
- seller = item_to_buy["seller"]
- price = item_to_buy["price"]
-
- # Проверяем, есть ли у покупателя достаточно средств
- if buyer_username not in users:
- return False, "Покупатель не найден"
-
- if users[buyer_username]["balance"] < price:
- return False, "Недостаточно средств"
-
- # Проверяем, что покупатель не покупает у себя
- if buyer_username == seller:
- return False, "Нельзя купить собственный товар"
-
- # Проверяем, существует ли продавец
- if seller not in users:
- return False, "Продавец не найден"
-
- # Выполняем транзакцию
- users[buyer_username]["balance"] -= price
- users[seller]["balance"] += price
- save_users(users)
-
- # Обновляем статус товара
- for item in shop_data["items"]:
- if item["id"] == item_id:
- item["status"] = "sold"
- item["buyer"] = buyer_username
- item["sold_date"] = int(time.time())
- break
-
- save_shop(shop_data)
-
- # Добавляем в историю
- add_history(buyer_username, "buy_item", price, f"Товар: {item_to_buy['title']} от {seller}")
- add_history(seller, "sell_item", price, f"Товар: {item_to_buy['title']} покупателю {buyer_username}")
-
- return True, "Покупка успешно завершена"
-
-# ---------- API КЛЮЧИ ----------
-def generate_api_key():
- """Генерация API ключа"""
- return f"bank_api_{uuid.uuid4().hex[:16]}"
-
-def get_user_by_api_key(api_key):
- """Получение пользователя по API ключу - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- if not api_key:
- return None, None
-
- users = load_users()
- for username, user_data in users.items():
- # Проверяем, что user_data является словарем
- if isinstance(user_data, dict) and user_data.get('api_key') == api_key:
- return username, user_data
- return None, None
-
-# ---------- БАНКОВСКИЕ КАРТЫ ----------
-def generate_card_number(user_id, card_type="standard"):
- """Генерация номера банковской карты"""
- prefixes = {
- "standard": ["5469", "4276", "5375", "4856"],
- "gold": ["5469", "5278", "5375"],
- "platinum": ["4475", "4876", "4999"]
- }
-
- prefix = random.choice(prefixes.get(card_type, prefixes["standard"]))
- middle = ''.join([str(random.randint(0, 9)) for _ in range(8)])
- last_digits = ''.join([str(random.randint(0, 9)) for _ in range(4)])
-
- card_number = f"{prefix}{middle}{last_digits}"
- formatted = ' '.join([card_number[i:i+4] for i in range(0, len(card_number), 4)])
-
- return formatted
-
-def generate_cvv():
- """Генерация CVV кода"""
- return str(random.randint(100, 999))
-
-def generate_expiry_date():
- """Генерация срока действия карты"""
- from datetime import datetime, timedelta
- expiry = datetime.now() + timedelta(days=365*3)
- return expiry.strftime("%m/%y")
-
-def get_user_cards(user_id):
- """Получение всех карт пользователя"""
- cards = load_cards()
- return cards.get(user_id, [])
-
-def create_user_card(user_id, user_data, card_type="standard"):
- """Создание новой карты для пользователя"""
- cards = load_cards()
-
- if user_id not in cards:
- cards[user_id] = []
-
- # Проверяем, не слишком ли много карт у пользователя
- if len(cards[user_id]) >= 5:
- return None
-
- card_id = str(uuid.uuid4())[:8]
-
- new_card = {
- "id": card_id,
- "number": generate_card_number(user_id, card_type),
- "holder": user_data.get('full_name', user_id.upper()),
- "type": card_type,
- "cvv": generate_cvv(),
- "expiry": generate_expiry_date(),
- "balance": user_data.get('balance', 0),
- "currency": "USD",
- "created": int(time.time()),
- "active": True,
- "limit": 10000 if card_type == "standard" else 50000 if card_type == "gold" else 100000,
- "color": {
- "standard": "#4361ee",
- "gold": "#ffd166",
- "platinum": "#e5e5e5"
- }.get(card_type, "#4361ee")
- }
-
- cards[user_id].append(new_card)
- save_cards(cards)
-
- # Добавляем в историю
- add_history(user_id, f"create_{card_type}_card", 0, f"Card {new_card['number'][-4:]}")
-
- return new_card
-
-# ---------- БАНКОВСКИЕ ОПЕРАЦИИ ----------
-def daily_update():
- """Ежедневное обновление депозитов и кредитов"""
- users = load_users()
- updated = False
- for user_id, u in users.items():
- if isinstance(u, dict): # Проверяем, что это словарь
- if u.get('deposit', 0) > 0:
- u['deposit'] = int(u['deposit'] * 1.01)
- updated = True
- if u.get('credit', 0) > 0:
- u['credit'] = int(u['credit'] * 1.05)
- updated = True
- if updated:
- save_users(users)
-
-def add_history(user, action, amount, target=None):
- """Добавление записи в историю"""
- hist = load_history()
- hist.append({
- "time": int(time.time()),
- "user": user,
- "action": action,
- "amount": amount,
- "target": target,
- "id": str(uuid.uuid4())[:8]
- })
- save_history(hist)
-
-# ---------- ДЕКОРАТОРЫ ----------
-def login_required(f):
- """Декоратор для проверки авторизации"""
- @wraps(f)
- def decorated_function(*args, **kwargs):
- if 'user' not in session:
- return redirect('/')
- return f(*args, **kwargs)
- return decorated_function
-
-def admin_required(f):
- """Декоратор для проверки прав администратора"""
- @wraps(f)
- def decorated_function(*args, **kwargs):
- if 'user' not in session:
- return redirect('/')
-
- users = load_users()
- user_data = users.get(session['user'])
-
- if not user_data or not isinstance(user_data, dict) or user_data.get('role') != 'admin':
- return redirect('/dashboard')
-
- return f(*args, **kwargs)
- return decorated_function
-
-# ИСПРАВЛЕННЫЙ ДЕКОРАТОР API
-def api_key_required(f):
- """Декоратор для проверки API ключа - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- @wraps(f)
- def decorated_function(*args, **kwargs):
- api_key = None
-
- # 1. Проверяем заголовок X-API-Key
- if 'X-API-Key' in request.headers:
- api_key = request.headers.get('X-API-Key')
-
- # 2. Проверяем параметр запроса api_key
- if not api_key and request.args.get('api_key'):
- api_key = request.args.get('api_key')
-
- # 3. Проверяем JSON тело
- if not api_key and request.is_json:
- try:
- data = request.get_json()
- if data and 'api_key' in data:
- api_key = data.get('api_key')
- except:
- pass
-
- # 4. Проверяем форму
- if not api_key and request.form.get('api_key'):
- api_key = request.form.get('api_key')
-
- if not api_key:
- return jsonify({'success': False, 'error': 'API key required'}), 401
-
- # Получаем пользователя по API ключу
- username, user_data = get_user_by_api_key(api_key)
- if not username:
- return jsonify({'success': False, 'error': 'Invalid API key'}), 401
-
- # Сохраняем данные пользователя в объекте request
- request.username = username
- request.user_data = user_data
-
- return f(*args, **kwargs)
- return decorated_function
-
-# ---------- HTML ШАБЛОНЫ ----------
-def render_login():
- return '''
-
-
-
-
-
- Банк | Вход в систему
-
-
-
-
-
-
-
-
-
-'''
-
-def render_register():
- return '''
-
-
-
-
-
- Банк | Регистрация
-
-
-
-
-
-
-
-
-
-'''
-
-def render_card_html(card, width="400px"):
- """Генерация HTML для банковской карты"""
- colors = {
- "standard": "#4361ee",
- "gold": "#ffd166",
- "platinum": "#e5e5e5"
- }
-
- bg_color = card.get('color', colors.get(card['type'], "#4361ee"))
- text_color = "#ffffff" if card['type'] == 'standard' else "#000000"
-
- return f'''
-
-
-
- {card['number']}
-
-
- {card['holder']}
-
-
-'''
-
-def render_dashboard(user_data, history_data, user_cards, shop_data=None):
- """Генерация HTML личного кабинета"""
- # Форматирование времени истории
- for h in history_data:
- h['formatted_time'] = datetime.fromtimestamp(h['time']).strftime('%d.%m.%Y %H:%M')
-
- # HTML для истории
- history_html = ""
- for h in history_data[-10:][::-1]:
- icon = "fa-history"
- color = "text-primary"
- if "deposit" in h['action']:
- icon = "fa-piggy-bank"
- color = "text-info"
- elif "credit" in h['action']:
- icon = "fa-credit-card"
- color = "text-warning"
- elif "transfer" in h['action']:
- icon = "fa-exchange-alt"
- color = "text-primary"
- elif "card" in h['action']:
- icon = "fa-credit-card"
- color = "text-success"
- elif "api" in h['action']:
- icon = "fa-key"
- color = "text-secondary"
- elif "shop" in h['action'] or "item" in h['action'] or "advertisement" in h['action']:
- icon = "fa-shopping-cart"
- color = "text-success"
- elif "payment" in h['action']:
- icon = "fa-credit-card"
- color = "text-success"
-
- history_html += f'''
-
- {h['formatted_time']}
- {h['user']}
- {h['action']}
- {h['amount']:,} $
- {h.get('target', '-')}
-
- '''
-
- # HTML для банковских карт
- cards_html = ""
- if user_cards:
- for card in user_cards:
- width = "350px" if len(card['number']) < 24 else "400px" if len(card['number']) < 28 else "450px"
- cards_html += f'''
-
-
-
-
-
- Карта {card['type'].upper()}
-
- {render_card_html(card, width)}
-
-
CVV: {card['cvv']}
-
Срок: {card['expiry']}
-
Баланс: ${card['balance']:,}
-
Лимит: ${card['limit']:,}
-
-
-
-
-
- '''
- else:
- cards_html = '''
-
-
-
- У вас еще нет банковских карт. Создайте свою первую карту!
-
-
- '''
-
- # HTML для API ключа
- api_key_html = ""
- if user_data.get('api_key'):
- api_key_html = f'''
-
-
Ваш API ключ
-
-
-
-
-
-
-
Используйте этот ключ для доступа к API
-
- '''
- else:
- api_key_html = '''
-
-
API ключ не создан
-
-
- '''
-
- # HTML для магазина
- shop_tab_content = ""
- if shop_data:
- # Товары
- shop_items_html = ""
- available_items = [item for item in shop_data["items"] if item["status"] == "available"]
-
- if available_items:
- for item in available_items[-10:][::-1]: # Последние 10 товаров
- created_date = datetime.fromtimestamp(item["created"]).strftime('%d.%m.%Y')
- shop_items_html += f'''
-
-
-
-
{item["title"]}
-
{item["description"]}
-
- Продавец: {item["seller"]}
- Категория: {item["category"]}
- Дата: {created_date}
-
-
- ${item["price"]:,}
-
-
-
-
-
- '''
- else:
- shop_items_html = '''
-
-
-
- В магазине пока нет товаров. Будьте первым, кто добавит товар!
-
-
- '''
-
- # Объявления
- ads_html = ""
- active_ads = [ad for ad in shop_data["ads"] if ad["status"] == "active"]
-
- if active_ads:
- for ad in active_ads[-10:][::-1]: # Последние 10 объявлений
- created_date = datetime.fromtimestamp(ad["created"]).strftime('%d.%m.%Y')
- ads_html += f'''
-
-
-
-
{ad["title"]}
-
{ad["content"]}
-
- Автор: {ad["author"]}
- Контакты: {ad["contact_info"]}
- Дата: {created_date}
-
-
-
-
- '''
-
- shop_tab_content = f'''
-
-
-
-
-
Магазин
-
-
- Добавить товар
-
-
- Добавить объявление
-
-
-
-
-
-
-
Товары в магазине
-
- {shop_items_html}
-
-
-
Объявления
-
- {ads_html}
-
-
- '''
-
- # HTML для админ-панели
- admin_tab = ""
- if user_data.get('role') == 'admin':
- admin_tab = '''
-
-
- Админ-панель
-
-
- '''
-
- return f'''
-
-
-
-
-
- Банк | Личный кабинет
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Вклады
-
Откройте вклад под 1% ежедневно и получайте пассивный доход.
-
-
-
Кредиты
-
Получите кредит на любые цели. Ставка 5% ежедневно.
-
-
-
Переводы
-
Быстрые переводы между клиентами банка без комиссий.
-
-
-
Банковские карты
-
Выпустите банковскую карту для удобных платежей.
-
-
-
Магазин
-
Покупайте и продавайте товары, размещайте объявления.
-
-
-
Платежи
-
Принимайте платежи от клиентов через API или ссылки.
-
-
-
API Доступ
-
Интегрируйте банковские услуги в ваши приложения через API.
-
-
-
-
-
-
- {shop_tab_content}
-
-
-
-
-
-
- Время
- Пользователь
- Операция
- Сумма
- Получатель
-
-
-
- {history_html}
-
-
-
-
-
-
-
-
Документация API
-
Используйте ваш API ключ для доступа к банковским операциям через REST API.
-
-
Базовый URL
-
- http://ваш-домен/api/v1/
-
-
-
Аутентификация
-
Добавьте заголовок с вашим API ключом:
-
- X-API-Key: ваш_api_ключ
-
-
Или передайте как параметр:
-
- ?api_key=ваш_api_ключ
-
-
-
Доступные методы
-
-
-
-
- Метод
- Эндпоинт
- Описание
- Параметры
-
-
-
-
- GET
- /api/v1/balance
- Получить информацию о балансе
- -
-
-
- GET
- /api/v1/history
- Получить историю операций
- limit (опционально)
-
-
- GET
- /api/v1/cards
- Получить список карт
- -
-
-
- POST
- /api/v1/deposit
- Открыть вклад
- amount (int)
-
-
- POST
- /api/v1/credit
- Взять кредит
- amount (int)
-
-
- POST
- /api/v1/transfer
- Сделать перевод
- target (str), amount (int)
-
-
- POST
- /api/v1/cards/create
- Создать карту
- card_type (standard|gold|platinum)
-
-
- POST
- /api/v1/cards/delete
- Удалить карту
- card_id (str)
-
-
- GET
- /api/v1/shop/items
- Получить список товаров
- -
-
-
- GET
- /api/v1/shop/ads
- Получить список объявлений
- -
-
-
- POST
- /api/v1/payment/create
- Создать платеж
- receiver, amount, description
-
-
- POST
- /api/v1/payment/process
- Выполнить платеж
- payment_id
-
-
-
-
-
-
Примеры использования
-
Python с requests:
-
-import requests
-
-api_key = "ваш_api_ключ"
-base_url = "http://ваш-домен/api/v1"
-
-# Получить баланс
-headers = {{"X-API-Key": api_key}}
-response = requests.get(f"{{base_url}}/balance", headers=headers)
-print(response.json())
-
-# Сделать перевод
-data = {{"target": "получатель", "amount": 100}}
-response = requests.post(f"{{base_url}}/transfer", headers=headers, json=data)
-print(response.json())
-
-
-
cURL:
-
-# Получить баланс
-curl -H "X-API-Key: ваш_api_ключ" http://ваш-домен/api/v1/balance
-
-# Сделать перевод
-curl -X POST -H "X-API-Key: ваш_api_ключ" \\
- -H "Content-Type: application/json" \\
- -d '{{"target": "получатель", "amount": 100}}' \\
- http://ваш-домен/api/v1/transfer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Заголовок
-
-
-
- Содержание
-
-
-
- Контактная информация
-
-
-
-
-
-
-
-
-
-
-
-
-
-'''
-
-def render_admin_panel(users):
- """Генерация HTML админ-панели - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- users_html = ""
- current_user = session.get('user')
-
- valid_users_count = 0
- total_balance = 0
- total_deposit = 0
- total_credit = 0
-
- for username, user in users.items():
- # Пропускаем текущего пользователя
- if username == current_user:
- continue
-
- # Проверяем, что пользователь - словарь (корректные данные)
- if not isinstance(user, dict):
- continue
-
- # Безопасно получаем данные пользователя
- role = user.get('role', 'client')
- balance = user.get('balance', 0)
- deposit = user.get('deposit', 0)
- credit = user.get('credit', 0)
- email = user.get('email', 'нет')
-
- # Обновляем статистику
- valid_users_count += 1
- total_balance += balance
- total_deposit += deposit
- total_credit += credit
-
- # Определяем цвет бейджа роли
- badge_color = "success" if role == 'admin' else "primary" if role == 'manager' else "secondary"
-
- users_html += f'''
-
-
-
-
{username}
-
- Роль: {role}
- Баланс: ${balance:,}
- Вклад: ${deposit:,}
- Кредит: ${credit:,}
- Email: {email}
-
-
-
-
- Клиент
- Админ
- Менеджер
-
- Изменить роль
-
-
-
-
-
- +
-
-
-
-
-
- '''
-
- return f'''
-
-
-
-
-
- Админ-панель
-
-
-
-
-
-
-
-
-
- {users_html if users_html else '''
-
-
-
- Нет других пользователей для управления.
-
-
- '''}
-
-
-
-
-
-
-
Статистика системы
-
-
-
-
Всего пользователей
- {valid_users_count + 1}
-
-
-
-
-
Общий баланс
- ${total_balance:,}
-
-
-
-
-
Общие вклады
- ${total_deposit:,}
-
-
-
-
-
Общие кредиты
- ${total_credit:,}
-
-
-
-
-
-
-
-
-
-
-
-
-'''
-
-# ---------- СТРАНИЦА ОПЛАТЫ ----------
-def render_payment_page():
- """Страница оплаты"""
- return '''
-
-
-
-
-
- Оплата | Банковская система
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Создать ссылку для оплаты
-
-
- Получатель (логин)
-
-
-
- Сумма ($)
-
-
-
- Описание платежа
-
-
-
- Создать ссылку
-
-
-
-
-
QR-код для оплаты
-
- QR-код появится после создания ссылки
-
-
-
-
-
-
API для оплаты
-
Используйте API для интеграции платежей в ваши приложения:
-
-
1. Создать платеж:
-
- POST /api/v1/payment/create
- Headers: X-API-Key: ваш_ключ
- Body: {
- "receiver": "username",
- "amount": 100,
- "description": "Оплата за услугу"
- }
-
-
-
2. Получить статус платежа:
-
- GET /api/v1/payment/status/{payment_id}
- Headers: X-API-Key: ваш_ключ
-
-
-
3. Пример ссылки для оплаты:
-
- http://ваш-домен/pay/{payment_id}
-
-
-
-
Как это работает:
-
- Создаете платеж через форму или API
- Получаете уникальную ссылку или payment_id
- Отправляете ссылку клиенту
- Клиент переходит по ссылке и оплачивает
- Вы получаете деньги на счет
-
-
-
-
-
-
-
Последние платежи
-
-
-
-
- ID
- Сумма
- Получатель
- Статус
- Дата
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-'''
-
-def render_pay_page(payment_id):
- """Страница оплаты для клиента"""
- payments = load_payments()
-
- payment = None
- for p in payments:
- if p["id"] == payment_id:
- payment = p
- break
-
- if not payment:
- return '''
-
-
-
- Платеж не найден
-
-
-
-
-
-
Платеж не найден
-
Проверьте правильность ссылки или обратитесь к отправителю.
-
На главную
-
-
-
-
- '''
-
- if payment["status"] != "pending":
- status_message = {
- "completed": "Оплачен",
- "failed": "Не удался",
- "cancelled": "Отменен"
- }.get(payment["status"], "Неизвестен")
-
- return f'''
-
-
-
- Статус платежа
-
-
-
-
-
-
-
-
-
-
Платеж {status_message}
-
-
-
-
ID платежа: {payment_id}
-
Сумма: ${payment['amount']}
-
Получатель: {payment['receiver']}
-
Описание: {payment['description']}
-
На главную
-
-
-
-
-
-
-
- '''
-
- return f'''
-
-
-
-
-
- Оплата #{payment_id}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${payment['amount']}
-
-
-
-
- Получатель:
- {payment['receiver']}
-
-
- Описание:
- {payment['description'] or 'Нет описания'}
-
-
- Статус:
- Ожидает оплаты
-
-
-
-
-
- Ваш логин
-
-
-
- Пароль
-
-
-
-
- Оплатить ${payment['amount']}
-
-
-
- После оплаты средства будут переведены получателю
-
-
-
-
-
Безопасная оплата
-
Все платежи защищены банковской системой. Для оплаты требуется авторизация.
-
-
-
-
-
-
-
-
-
-'''
-
-# ---------- ИСПРАВЛЕННЫЕ API МАРШРУТЫ ----------
-
-@app.route('/api/v1/balance', methods=['GET'])
-@api_key_required
-def api_balance():
- """API: Получить информацию о балансе - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- user_data = request.user_data
- return jsonify({
- 'success': True,
- 'username': request.username,
- 'balance': user_data.get('balance', 0),
- 'deposit': user_data.get('deposit', 0),
- 'credit': user_data.get('credit', 0),
- 'total': user_data.get('balance', 0) + user_data.get('deposit', 0) - user_data.get('credit', 0)
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/history', methods=['GET'])
-@api_key_required
-def api_history():
- """API: Получить историю операций - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- history = load_history()
- user_history = [h for h in history if h['user'] == request.username]
-
- limit = request.args.get('limit', type=int, default=50)
- if limit > 0 and limit < len(user_history):
- user_history = user_history[-limit:]
-
- for h in user_history:
- h['time_formatted'] = datetime.fromtimestamp(h['time']).strftime('%Y-%m-%d %H:%M:%S')
-
- return jsonify({
- 'success': True,
- 'count': len(user_history),
- 'history': user_history[::-1]
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/cards', methods=['GET'])
-@api_key_required
-def api_cards():
- """API: Получить список карт - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- cards = get_user_cards(request.username)
-
- safe_cards = []
- for card in cards:
- safe_card = card.copy()
- if 'number' in safe_card and len(safe_card['number']) > 4:
- safe_card['number_masked'] = '**** **** **** ' + safe_card['number'][-4:]
- safe_card['cvv'] = '***'
- safe_cards.append(safe_card)
-
- return jsonify({
- 'success': True,
- 'count': len(safe_cards),
- 'cards': safe_cards
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/deposit', methods=['POST'])
-@api_key_required
-def api_deposit():
- """API: Открыть вклад - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- amount = data.get('amount')
-
- if not amount:
- return jsonify({'success': False, 'error': 'Amount required'}), 400
-
- amount = int(amount)
- if amount <= 0:
- return jsonify({'success': False, 'error': 'Amount must be positive'}), 400
-
- users = load_users()
- user = users.get(request.username)
-
- if not user or user['balance'] < amount:
- return jsonify({'success': False, 'error': 'Insufficient funds'}), 400
-
- user['balance'] -= amount
- user['deposit'] += amount
- save_users(users)
-
- add_history(request.username, 'api_deposit', amount)
-
- return jsonify({
- 'success': True,
- 'message': f'Deposit of ${amount} created successfully',
- 'new_balance': user['balance'],
- 'new_deposit': user['deposit']
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/credit', methods=['POST'])
-@api_key_required
-def api_credit():
- """API: Взять кредит - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- amount = data.get('amount')
-
- if not amount:
- return jsonify({'success': False, 'error': 'Amount required'}), 400
-
- amount = int(amount)
- if amount <= 0:
- return jsonify({'success': False, 'error': 'Amount must be positive'}), 400
-
- users = load_users()
- user = users.get(request.username)
-
- if not user:
- return jsonify({'success': False, 'error': 'User not found'}), 404
-
- user['balance'] += amount
- user['credit'] += amount
- save_users(users)
-
- add_history(request.username, 'api_credit', amount)
-
- return jsonify({
- 'success': True,
- 'message': f'Credit of ${amount} taken successfully',
- 'new_balance': user['balance'],
- 'new_credit': user['credit']
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/transfer', methods=['POST'])
-@api_key_required
-def api_transfer():
- """API: Сделать перевод - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- target = data.get('target', '').strip()
- amount = data.get('amount')
-
- if not target:
- return jsonify({'success': False, 'error': 'Target username required'}), 400
-
- if not amount:
- return jsonify({'success': False, 'error': 'Amount required'}), 400
-
- amount = int(amount)
- if amount <= 0:
- return jsonify({'success': False, 'error': 'Amount must be positive'}), 400
-
- users = load_users()
-
- if target not in users:
- return jsonify({'success': False, 'error': 'Target user not found'}), 404
-
- if target == request.username:
- return jsonify({'success': False, 'error': 'Cannot transfer to yourself'}), 400
-
- sender = users.get(request.username)
- if not sender:
- return jsonify({'success': False, 'error': 'Sender not found'}), 404
-
- if sender['balance'] < amount:
- return jsonify({'success': False, 'error': 'Insufficient funds'}), 400
-
- sender['balance'] -= amount
- users[target]['balance'] += amount
- save_users(users)
-
- add_history(request.username, 'api_transfer', amount, target)
-
- return jsonify({
- 'success': True,
- 'message': f'Transfer of ${amount} to {target} successful',
- 'new_balance': sender['balance']
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/cards/create', methods=['POST'])
-@api_key_required
-def api_create_card():
- """API: Создать карту - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- card_type = data.get('card_type', 'standard')
-
- if card_type not in ['standard', 'gold', 'platinum']:
- return jsonify({'success': False, 'error': 'Invalid card type'}), 400
-
- users = load_users()
- user = users.get(request.username)
-
- if not user:
- return jsonify({'success': False, 'error': 'User not found'}), 404
-
- costs = {'standard': 0, 'gold': 50, 'platinum': 100}
- cost = costs.get(card_type, 0)
-
- if user['balance'] < cost:
- return jsonify({'success': False, 'error': 'Insufficient funds'}), 400
-
- if cost > 0:
- user['balance'] -= cost
- save_users(users)
-
- card = create_user_card(request.username, user, card_type)
-
- if not card:
- if cost > 0:
- user['balance'] += cost
- save_users(users)
- return jsonify({'success': False, 'error': 'Card creation failed. Maximum cards limit reached?'}), 400
-
- safe_card = card.copy()
- if 'number' in safe_card and len(safe_card['number']) > 4:
- safe_card['number_masked'] = '**** **** **** ' + safe_card['number'][-4:]
- safe_card['cvv'] = '***'
-
- return jsonify({
- 'success': True,
- 'message': f'{card_type.capitalize()} card created successfully',
- 'card': safe_card,
- 'cost': cost,
- 'new_balance': user['balance']
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/cards/delete', methods=['POST'])
-@api_key_required
-def api_delete_card():
- """API: Удалить карту - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- card_id = data.get('card_id')
-
- if not card_id:
- return jsonify({'success': False, 'error': 'Card ID required'}), 400
-
- cards = load_cards()
- user_cards = cards.get(request.username, [])
-
- card_to_delete = None
- for card in user_cards:
- if card['id'] == card_id:
- card_to_delete = card
- break
-
- if not card_to_delete:
- return jsonify({'success': False, 'error': 'Card not found'}), 404
-
- cards[request.username] = [c for c in user_cards if c['id'] != card_id]
- save_cards(cards)
-
- add_history(request.username, 'api_delete_card', 0, f"Card {card_to_delete['number'][-4:]}")
-
- return jsonify({
- 'success': True,
- 'message': f"Card ending with {card_to_delete['number'][-4:]} deleted successfully"
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-# ---------- API ДЛЯ ПЛАТЕЖЕЙ ----------
-
-@app.route('/api/v1/payment/create', methods=['POST'])
-@api_key_required
-def api_payment_create():
- """API: Создать платеж"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- receiver = data.get('receiver')
- amount = data.get('amount')
- description = data.get('description', '')
- external_id = data.get('external_id', '')
-
- if not receiver:
- return jsonify({'success': False, 'error': 'Receiver required'}), 400
-
- if not amount:
- return jsonify({'success': False, 'error': 'Amount required'}), 400
-
- try:
- amount_int = int(amount)
- if amount_int <= 0:
- return jsonify({'success': False, 'error': 'Amount must be positive'}), 400
- except:
- return jsonify({'success': False, 'error': 'Invalid amount'}), 400
-
- # Проверяем существование получателя
- users = load_users()
- if receiver not in users:
- return jsonify({'success': False, 'error': 'Receiver not found'}), 404
-
- # Создаем платеж
- payment_id, payment_data = create_payment(
- payer=request.username,
- receiver=receiver,
- amount=amount_int,
- description=description,
- external_id=external_id
- )
-
- return jsonify({
- 'success': True,
- 'message': 'Payment created successfully',
- 'payment_id': payment_id,
- 'payment': payment_data,
- 'payment_url': f'/pay/{payment_id}'
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/payment/process', methods=['POST'])
-@api_key_required
-def api_payment_process():
- """API: Выполнить платеж"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- payment_id = data.get('payment_id')
-
- if not payment_id:
- return jsonify({'success': False, 'error': 'Payment ID required'}), 400
-
- success, message = process_payment(payment_id, request.username)
-
- return jsonify({
- 'success': success,
- 'message': message
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/payment/status/', methods=['GET'])
-@api_key_required
-def api_payment_status(payment_id):
- """API: Получить статус платежа"""
- try:
- payments = load_payments()
-
- payment = None
- for p in payments:
- if p["id"] == payment_id:
- payment = p
- break
-
- if not payment:
- return jsonify({'success': False, 'error': 'Payment not found'}), 404
-
- # Проверяем, имеет ли пользователь доступ к этому платежу
- if payment["payer"] != request.username and payment["receiver"] != request.username:
- users = load_users()
- if users.get(request.username, {}).get('role') != 'admin':
- return jsonify({'success': False, 'error': 'Access denied'}), 403
-
- return jsonify({
- 'success': True,
- 'payment': payment
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/payment/list', methods=['GET'])
-@api_key_required
-def api_payment_list():
- """API: Получить список платежей пользователя"""
- try:
- payments = load_payments()
-
- # Фильтруем платежи по пользователю
- user_payments = []
- for payment in payments:
- if payment["payer"] == request.username or payment["receiver"] == request.username:
- user_payments.append(payment)
-
- # Сортируем по дате (новые сверху)
- user_payments.sort(key=lambda x: x['created'], reverse=True)
-
- # Ограничиваем количество
- limit = min(20, len(user_payments))
- user_payments = user_payments[:limit]
-
- return jsonify({
- 'success': True,
- 'count': len(user_payments),
- 'payments': user_payments
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/shop/items', methods=['GET'])
-@api_key_required
-def api_shop_items():
- """API: Получить список товаров - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- shop_data = load_shop()
- available_items = [item for item in shop_data["items"] if item["status"] == "available"]
-
- for item in available_items:
- item['created_formatted'] = datetime.fromtimestamp(item['created']).strftime('%Y-%m-%d %H:%M:%S')
-
- return jsonify({
- 'success': True,
- 'count': len(available_items),
- 'items': available_items[::-1]
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/shop/ads', methods=['GET'])
-@api_key_required
-def api_shop_ads():
- """API: Получить список объявлений - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- shop_data = load_shop()
- active_ads = [ad for ad in shop_data["ads"] if ad["status"] == "active"]
-
- for ad in active_ads:
- ad['created_formatted'] = datetime.fromtimestamp(ad['created']).strftime('%Y-%m-%d %H:%M:%S')
-
- return jsonify({
- 'success': True,
- 'count': len(active_ads),
- 'ads': active_ads[::-1]
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/system/status', methods=['GET'])
-@api_key_required
-def api_system_status():
- """API: Получить статус системы - ИСПРАВЛЕННАЯ ВЕРСИЯ"""
- try:
- users = load_users()
- valid_users = [u for u in users.values() if isinstance(u, dict)]
- total_users = len(valid_users)
- total_balance = sum(u.get('balance', 0) for u in valid_users)
- total_deposit = sum(u.get('deposit', 0) for u in valid_users)
- total_credit = sum(u.get('credit', 0) for u in valid_users)
-
- return jsonify({
- 'success': True,
- 'system_status': 'operational',
- 'statistics': {
- 'total_users': total_users,
- 'total_balance': total_balance,
- 'total_deposit': total_deposit,
- 'total_credit': total_credit,
- 'net_worth': total_balance + total_deposit - total_credit
- },
- 'timestamp': int(time.time())
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-# ДОБАВЛЕННЫЕ API ЭНДПОИНТЫ
-
-@app.route('/api/v1/users', methods=['GET'])
-@api_key_required
-def api_users():
- """API: Получить список пользователей (только для админов)"""
- try:
- users = load_users()
-
- if not isinstance(request.user_data, dict) or request.user_data.get('role') != 'admin':
- return jsonify({'success': False, 'error': 'Admin access required'}), 403
-
- safe_users = {}
- for username, user in users.items():
- if isinstance(user, dict):
- safe_user = user.copy()
- safe_user.pop('password', None)
- safe_users[username] = safe_user
-
- return jsonify({
- 'success': True,
- 'count': len(safe_users),
- 'users': safe_users
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/health', methods=['GET'])
-def api_health():
- """API: Проверка здоровья системы (не требует API ключа)"""
- try:
- files = [USERS_FILE, HISTORY_FILE, CARDS_FILE, SHOP_FILE, PAYMENTS_FILE]
- file_status = {}
-
- for file in files:
- file_status[file] = os.path.exists(file)
-
- return jsonify({
- 'status': 'healthy',
- 'timestamp': int(time.time()),
- 'files': file_status,
- 'message': 'System is operational'
- })
- except Exception as e:
- return jsonify({'status': 'unhealthy', 'error': str(e)}), 500
-
-@app.route('/api/v1/shop/create_item', methods=['POST'])
-@api_key_required
-def api_create_shop_item():
- """API: Создать товар в магазине"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- title = data.get('title')
- description = data.get('description')
- price = data.get('price')
- category = data.get('category', 'other')
-
- if not title or not description or not price:
- return jsonify({'success': False, 'error': 'Title, description and price required'}), 400
-
- try:
- price_int = int(price)
- if price_int <= 0:
- return jsonify({'success': False, 'error': 'Price must be positive'}), 400
- except:
- return jsonify({'success': False, 'error': 'Invalid price'}), 400
-
- item_id = create_shop_item(request.username, title, description, price_int, category)
-
- return jsonify({
- 'success': True,
- 'message': f'Item "{title}" created successfully',
- 'item_id': item_id
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-@app.route('/api/v1/shop/buy_item', methods=['POST'])
-@api_key_required
-def api_buy_item():
- """API: Купить товар"""
- try:
- if not request.is_json:
- return jsonify({'success': False, 'error': 'JSON data required'}), 400
-
- data = request.get_json()
- item_id = data.get('item_id')
-
- if not item_id:
- return jsonify({'success': False, 'error': 'Item ID required'}), 400
-
- success, message = buy_item(item_id, request.username)
-
- return jsonify({
- 'success': success,
- 'message': message
- })
- except Exception as e:
- return jsonify({'success': False, 'error': str(e)}), 500
-
-# ---------- МАГАЗИН МАРШРУТЫ ----------
-@app.route('/create_shop_item', methods=['POST'])
-@login_required
-def create_shop_item_route():
- """Создание товара в магазине"""
- title = request.form.get('title')
- description = request.form.get('description')
- price = request.form.get('price')
- category = request.form.get('category', 'other')
-
- if not title or not description or not price:
- return redirect('/dashboard')
-
- try:
- price_int = int(price)
- if price_int <= 0:
- return redirect('/dashboard')
- except:
- return redirect('/dashboard')
-
- item_id = create_shop_item(session['user'], title, description, price_int, category)
-
- return redirect('/dashboard')
-
-@app.route('/create_advertisement', methods=['POST'])
-@login_required
-def create_advertisement_route():
- """Создание объявления"""
- title = request.form.get('title')
- content = request.form.get('content')
- contact_info = request.form.get('contact_info')
-
- if not title or not content or not contact_info:
- return redirect('/dashboard')
-
- ad_id = create_advertisement(session['user'], title, content, contact_info)
-
- return redirect('/dashboard')
-
-@app.route('/buy_item/', methods=['POST'])
-@login_required
-def buy_item_route(item_id):
- """Покупка товара"""
- success, message = buy_item(item_id, session['user'])
-
- return redirect('/dashboard')
-
-# ---------- ПЛАТЕЖНЫЕ МАРШРУТЫ ----------
-@app.route('/payment_page')
-@login_required
-def payment_page():
- """Страница управления платежами"""
- return render_payment_page()
-
-@app.route('/create_payment_link', methods=['POST'])
-@login_required
-def create_payment_link():
- """Создание ссылки для оплаты"""
- receiver = request.form.get('receiver')
- amount = request.form.get('amount')
- description = request.form.get('description', '')
-
- if not receiver or not amount:
- return redirect('/payment_page')
-
- try:
- amount_int = int(amount)
- if amount_int <= 0:
- return redirect('/payment_page')
- except:
- return redirect('/payment_page')
-
- payment_id, payment_data = create_payment(
- payer=session['user'],
- receiver=receiver,
- amount=amount_int,
- description=description
- )
-
- return redirect(f'/payment_page')
-
-@app.route('/pay/', methods=['GET'])
-def pay_page(payment_id):
- """Страница оплаты для клиента"""
- return render_pay_page(payment_id)
-
-@app.route('/process_payment/', methods=['POST'])
-def process_payment_route(payment_id):
- """Обработка платежа (для неавторизованных пользователей)"""
- username = request.form.get('username')
- password = request.form.get('password')
-
- if not username or not password:
- return "Неверные данные", 400
-
- # Проверяем логин и пароль
- users = load_users()
- user_data = users.get(username)
-
- if not user_data or user_data['password'] != password:
- return "Неверный логин или пароль", 401
-
- # Проверяем, что пользователь является плательщиком
- payments = load_payments()
- payment = None
- for p in payments:
- if p["id"] == payment_id:
- payment = p
- break
-
- if not payment:
- return "Платеж не найден", 404
-
- if payment["payer"] != username:
- return "Вы не являетесь плательщиком по этому платежу", 403
-
- # Выполняем платеж
- success, message = process_payment(payment_id, username)
-
- if success:
- return redirect(f'/pay/{payment_id}')
- else:
- return f"Ошибка: {message}", 400
-
-# ---------- ОСНОВНЫЕ МАРШРУТЫ ----------
-@app.route('/', methods=['GET', 'POST'])
-def login():
- if request.method == 'POST':
- users = load_users()
- username = request.form.get('username')
- password = request.form.get('password')
-
- user_data = users.get(username)
- if user_data and isinstance(user_data, dict) and user_data['password'] == password:
- session['user'] = username
- return redirect('/dashboard')
- else:
- return render_login().replace('',
- 'Неверный логин или пароль
')
-
- return render_login()
-
-@app.route('/register', methods=['GET', 'POST'])
-def register():
- if request.method == 'POST':
- users = load_users()
- username = request.form.get('username')
-
- if username in users:
- return render_register().replace('',
- 'Пользователь уже существует
')
-
- user_data = {
- 'password': request.form.get('password'),
- 'balance': 1000,
- 'deposit': 0,
- 'credit': 0,
- 'role': 'client',
- 'full_name': f"{request.form.get('first_name')} {request.form.get('last_name')}",
- 'email': request.form.get('email'),
- 'api_key': None
- }
-
- users[username] = user_data
- save_users(users)
-
- session['user'] = username
- return redirect('/dashboard')
-
- return render_register()
-
-@app.route('/dashboard')
-@login_required
-def dashboard():
- users = load_users()
- history = load_history()
-
- if session['user'] not in users:
- session.clear()
- return redirect('/')
-
- user_data = users[session['user']]
- user_history = [h for h in history if h['user'] == session['user']]
- user_cards = get_user_cards(session['user'])
- shop_data = load_shop()
-
- return render_dashboard(user_data, user_history[-20:], user_cards, shop_data)
-
-@app.route('/generate_api_key', methods=['POST'])
-@login_required
-def generate_api_key_route():
- users = load_users()
- user = users.get(session['user'])
- if user and isinstance(user, dict):
- user['api_key'] = generate_api_key()
- save_users(users)
- add_history(session['user'], 'generate_api_key', 0)
- return redirect('/dashboard')
-
-@app.route('/deposit', methods=['POST'])
-@login_required
-def deposit():
- users = load_users()
- user = users.get(session['user'])
-
- try:
- amount = int(request.form.get('amount', 0))
- if amount > 0 and user and user['balance'] >= amount:
- user['balance'] -= amount
- user['deposit'] += amount
- save_users(users)
- add_history(session['user'], 'deposit', amount)
- except:
- pass
-
- return redirect('/dashboard')
-
-@app.route('/credit', methods=['POST'])
-@login_required
-def credit():
- users = load_users()
- user = users.get(session['user'])
-
- try:
- amount = int(request.form.get('amount', 0))
- if amount > 0 and user:
- user['balance'] += amount
- user['credit'] += amount
- save_users(users)
- add_history(session['user'], 'credit', amount)
- except:
- pass
-
- return redirect('/dashboard')
-
-@app.route('/transfer', methods=['POST'])
-@login_required
-def transfer():
- users = load_users()
- sender = session['user']
-
- try:
- target = request.form.get('target')
- amount = int(request.form.get('amount', 0))
-
- sender_data = users.get(sender)
- target_data = users.get(target)
-
- if (amount > 0 and target_data and target != sender and
- sender_data and sender_data['balance'] >= amount):
- sender_data['balance'] -= amount
- target_data['balance'] += amount
- save_users(users)
- add_history(sender, 'transfer', amount, target)
- except Exception as e:
- print(f"Transfer error: {e}")
- pass
-
- return redirect('/dashboard')
-
-@app.route('/create_card', methods=['POST'])
-@login_required
-def create_card():
- users = load_users()
- user = users.get(session['user'])
- card_type = request.form.get('card_type', 'standard')
-
- costs = {
- 'standard': 0,
- 'gold': 50,
- 'platinum': 100
- }
-
- cost = costs.get(card_type, 0)
-
- if user and user['balance'] >= cost:
- user['balance'] -= cost
- save_users(users)
-
- card = create_user_card(session['user'], user, card_type)
- if card:
- add_history(session['user'], 'create_card', cost, f"{card_type}_{card['number'][-4:]}")
-
- return redirect('/dashboard')
-
-@app.route('/delete_card/', methods=['POST'])
-@login_required
-def delete_card(card_id):
- cards = load_cards()
- user_cards = cards.get(session['user'], [])
- cards[session['user']] = [c for c in user_cards if c['id'] != card_id]
- save_cards(cards)
- return redirect('/dashboard')
-
-# ---------- АДМИН МАРШРУТЫ (ИСПРАВЛЕННЫЕ) ----------
-@app.route('/admin')
-@admin_required
-def admin():
- users = load_users()
- return render_admin_panel(users)
-
-@app.route('/admin/change_role', methods=['POST'])
-@admin_required
-def admin_change_role():
- users = load_users()
- username = request.form.get('username')
- new_role = request.form.get('role')
-
- if username in users and username != session['user'] and isinstance(users[username], dict):
- users[username]['role'] = new_role
- save_users(users)
- add_history(session['user'], 'change_role', 0, f"{username}->{new_role}")
-
- return redirect('/admin')
-
-@app.route('/admin/add_money', methods=['POST'])
-@admin_required
-def admin_add_money():
- users = load_users()
- username = request.form.get('username')
- amount = int(request.form.get('amount', 0))
-
- if username in users and amount > 0 and isinstance(users[username], dict):
- users[username]['balance'] += amount
- save_users(users)
- add_history('admin', 'add_money', amount, username)
-
- return redirect('/admin')
-
-@app.route('/logout')
-def logout():
- session.clear()
- return redirect('/')
-
-# ---------- API ДОКУМЕНТАЦИЯ ----------
-@app.route('/api/docs')
-def api_docs():
- """Страница с документацией API"""
- return '''
-
-
-
-
-
- API Документация
-
-
-
-
-
-
-
-
-
-
-
Документация API
-
Используйте API для интеграции банковских услуг в ваши приложения.
-
-
Базовый URL
-
- http://localhost:5000/api/v1/
-
-
-
Аутентификация
-
Для использования API необходим API ключ. Получите его в личном кабинете.
-
Передавайте ключ одним из способов:
-
-
Заголовок HTTP:
-
- X-API-Key: ваш_api_ключ
-
-
-
Параметр запроса:
-
- ?api_key=ваш_api_ключ
-
-
-
JSON тело запроса:
-
- {
- "api_key": "ваш_api_ключ",
- ...
- }
-
-
-
Доступные эндпоинты
-
-
-
GET /api/v1/health
-
Проверка здоровья системы (не требует API ключа)
-
-curl http://localhost:5000/api/v1/health
-
-
-
-
-
GET /api/v1/balance
-
Получить информацию о балансе пользователя
-
-curl -H "X-API-Key: ваш_ключ" http://localhost:5000/api/v1/balance
-
-
-
-
-
GET /api/v1/history?limit=50
-
Получить историю операций (опциональный параметр limit)
-
-
-
-
POST /api/v1/deposit
-
Открыть вклад. Требуется JSON: {"amount": 100}
-
-curl -X POST -H "X-API-Key: ваш_ключ" -H "Content-Type: application/json"
- -d "{\\"amount\\": 100}" http://localhost:5000/api/v1/deposit
-
-
-
-
-
POST /api/v1/credit
-
Взять кредит. Требуется JSON: {"amount": 100}
-
-
-
-
POST /api/v1/transfer
-
Сделать перевод. Требуется JSON: {"target": "username", "amount": 100}
-
-
-
-
GET /api/v1/cards
-
Получить список карт пользователя
-
-
-
-
POST /api/v1/cards/create
-
Создать карту. Требуется JSON: {"card_type": "standard"}
-
-
-
-
GET /api/v1/shop/items
-
Получить список товаров в магазине
-
-
-
-
POST /api/v1/payment/create
-
Создать платеж. Требуется JSON: {"receiver": "...", "amount": 100, "description": "..."}
-
-
-
-
POST /api/v1/payment/process
-
Выполнить платеж. Требуется JSON: {"payment_id": "..."}
-
-
-
-
GET /api/v1/payment/status/{payment_id}
-
Получить статус платежа
-
-
-
-
GET /api/v1/system/status
-
Получить статус системы
-
-
-
-
-
-
-
-
-'''
-# ================= ДЕКОРАТОР УЧИТЕЛЯ =================
-
-from functools import wraps
-
-def teacher_required(f):
- @wraps(f)
- def decorated(*args, **kwargs):
- if 'user' not in session:
- return redirect("/")
-
- users = load_users()
- user = users.get(session['user'])
-
- if not user:
- return redirect("/")
-
- if user.get("role") not in ["teacher", "admin"]:
- return redirect("/dashboard")
-
- return f(*args, **kwargs)
- return decorated
-
-# ============================================================
-# ========= ГРАФИК ДИНАМИКИ СРЕДНЕГО БАЛЛА ==================
-# ============================================================
-
-@app.route("/student_avg_graph/")
-@login_required
-@teacher_required
-def student_avg_graph(student):
- journal = load_journal()
-
- if student not in journal:
- return "Нет данных"
-
- subjects = journal[student]
-
- # собираем оценки по порядку добавления
- all_grades = []
- for subject, grades in subjects.items():
- all_grades += grades
-
- averages = []
- current = []
-
- for g in all_grades:
- current.append(g)
- averages.append(sum(current) / len(current))
-
- plt.figure()
- plt.plot(range(1, len(averages)+1), averages)
-
- plt.xlabel("Количество оценок")
- plt.ylabel("Средний балл")
- plt.title(f"Динамика среднего балла {student}")
-
- img = BytesIO()
- plt.savefig(img, format="png")
- plt.close()
- img.seek(0)
-
- graph_url = base64.b64encode(img.getvalue()).decode()
-
- return f"""
- 📈 Динамика среднего балла: {student}
- Назад
-
-
- """
-
-
-# ============================================================
-# ========= ФИНАНСОВЫЙ ГРАФИК УЧЕНИКА ========================
-# ============================================================
-
-@app.route("/student_finance_graph/")
-@login_required
-@teacher_required
-def student_finance_graph(student):
- journal = load_journal()
- users = load_users()
-
- if student not in journal:
- return "Нет данных"
-
- subjects = journal[student]
-
- # считаем баланс на основе оценок
- balance_history = []
- balance = 0
-
- for subject, grades in subjects.items():
- for g in grades:
- balance += calculate_money_for_grade(g)
- balance_history.append(balance)
-
- if not balance_history:
- return "Нет оценок"
-
- plt.figure()
- plt.plot(range(1, len(balance_history)+1), balance_history)
-
- plt.xlabel("Количество оценок")
- plt.ylabel("Баланс ($)")
- plt.title(f"Финансовая динамика {student}")
-
- img = BytesIO()
- plt.savefig(img, format="png")
- plt.close()
- img.seek(0)
-
- graph_url = base64.b64encode(img.getvalue()).decode()
-
- return f"""
- 💰 Финансовый график: {student}
- Назад
-
-
- """
-
-
-# ============================================================
-# ОБНОВЛЕНИЕ ТАБЛИЦЫ В ЖУРНАЛЕ (добавление ссылок)
-# ============================================================
-
-@app.route("/journal")
-@login_required
-@teacher_required
-def journal_page():
- journal = load_journal()
-
- table = ""
-
- for student, subjects in journal.items():
- total = []
- for grades in subjects.values():
- total += grades
-
- avg = round(sum(total)/len(total),2) if total else 0
-
- table += f"""
-
- {student}
- {avg}
-
- 📊 Успеваемость
- 📈 Средний
- 💰 Финансы
-
-
- """
-
- return f"""
- Электронный журнал PRO MAX
- Назад
-
-
- Создать класс
-
-
- Создать
-
-
- Добавить ученика в класс
-
-
-
- Добавить
-
-
- Поставить оценку
-
-
-
-
- Поставить
-
-
-
- Ученики
-
-
- Ученик
- Средний балл
- Графики
-
- {table}
-
-
-
- 🏆 Смотреть рейтинг
- """
-
-
-if __name__ == '__main__':
- import threading
-
- def daily_update_thread():
- while True:
- time.sleep(86400)
- daily_update()
-
- thread = threading.Thread(target=daily_update_thread, daemon=True)
- thread.start()
- app.run(host='0.0.0.0', port=5000, debug=True)
\ No newline at end of file