Files
app_umbrix/app/api/referral/track/route.ts
Umbrix Dev b43eb3c724 Реферальная система: БД, API, UI
**База данных:**
- Создана таблица referrals в MariaDB (193.168.175.128)
- Поля: username, referrer_username, referral_count, bonus_days_earned
- Foreign keys к users таблице с CASCADE/SET NULL

**API Endpoints:**
- POST /api/referral/track - отслеживание новых рефералов
  - Автоматический расчёт бонусов: +7 дней за каждого
  - Milestone bonus: +30 дней за каждые 5 рефералов
  - Обновление expire даты реферера в users таблице

- GET /api/referral/stats?username=xxx - статистика
  - Возвращает количество рефералов, бонусные дни
  - Список приглашённых пользователей со статусами

**Интеграция:**
- POST /api/create-user принимает referrerId параметр
- Автоматический вызов /api/referral/track после создания юзера
- Параметр ref из URL при активации trial

**UI:**
- /app/referral/page.tsx - страница статистики
  - 3 KPI карточки: рефералов, бонусных дней, milestone
  - Реферальная ссылка с кнопкой копирования
  - Список приглашённых юзеров с иконками статуса
  - Инфоблок о механике начисления бонусов

**ReferralModal обновлён:**
- Добавлена кнопка «Моя статистика» → /referral
- Перенос Share/Copy кнопок на второй/третий план

**Зависимости:**
- mysql2@3.16.3 - для подключения к MariaDB

**Логика бонусов:**
- +7 дней за каждого успешного реферала
- +30 дней бонус за каждые 5 рефералов (milestone)
- Автоматическое обновление expire поля в users таблице
- Сохранение всех бонусов в bonus_days_earned
2026-02-06 20:51:40 +03:00

136 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// API endpoint для отслеживания реферальной регистрации
// POST /api/referral/track - записывает нового пользователя с реферером
import { NextRequest, NextResponse } from 'next/server';
import mysql from 'mysql2/promise';
// Database connection config
const dbConfig = {
host: '193.168.175.128',
user: 'marzban_user',
password: '2CuopqFd0Y5V5n/qBM+eygOQb6aC8B8pACcdHjeVJsE=',
database: 'marzban_prod',
};
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { username, referrer_username } = body;
if (!username) {
return NextResponse.json(
{ success: false, error: 'Username is required' },
{ status: 400 }
);
}
// Connect to database
const connection = await mysql.createConnection(dbConfig);
try {
// Check if user already exists in referrals table
const [existingRows] = await connection.query(
'SELECT id FROM referrals WHERE username = ?',
[username]
);
if ((existingRows as any[]).length > 0) {
return NextResponse.json({
success: false,
error: 'User already tracked',
});
}
// Insert new referral record
await connection.query(
'INSERT INTO referrals (username, referrer_username) VALUES (?, ?)',
[username, referrer_username || null]
);
// If referrer exists, increment their referral_count
if (referrer_username) {
// Check if referrer exists in users table
const [referrerRows] = await connection.query(
'SELECT username FROM users WHERE username = ?',
[referrer_username]
);
if ((referrerRows as any[]).length > 0) {
// Update or insert referrer's stats
await connection.query(
`INSERT INTO referrals (username, referral_count)
VALUES (?, 1)
ON DUPLICATE KEY UPDATE
referral_count = referral_count + 1,
updated_at = CURRENT_TIMESTAMP`,
[referrer_username]
);
// Calculate bonus days
const [statsRows] = await connection.query(
'SELECT referral_count FROM referrals WHERE username = ?',
[referrer_username]
);
const referralCount = (statsRows as any[])[0]?.referral_count || 0;
let bonusDays = 0;
// +7 days for each referral
bonusDays = referralCount * 7;
// +30 days milestone bonus for every 5 referrals
if (referralCount >= 5) {
const milestones = Math.floor(referralCount / 5);
bonusDays += milestones * 30;
}
// Update bonus_days_earned
await connection.query(
'UPDATE referrals SET bonus_days_earned = ? WHERE username = ?',
[bonusDays, referrer_username]
);
// Add bonus days to referrer's expire date in users table
await connection.query(
`UPDATE users
SET expire = CASE
WHEN expire IS NULL OR expire < UNIX_TIMESTAMP()
THEN UNIX_TIMESTAMP() + (? * 86400)
ELSE expire + (7 * 86400)
END
WHERE username = ?`,
[bonusDays, referrer_username]
);
return NextResponse.json({
success: true,
message: 'Referral tracked successfully',
referrer_bonus: {
username: referrer_username,
new_referral_count: referralCount,
bonus_days_added: 7,
total_bonus_days: bonusDays,
},
});
}
}
return NextResponse.json({
success: true,
message: 'User tracked without referrer',
});
} finally {
await connection.end();
}
} catch (error) {
console.error('Referral track error:', error);
return NextResponse.json(
{
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
},
{ status: 500 }
);
}
}