feat(link_codes): linking method between telegram and website

This commit is contained in:
2026-08-18 21:10:57 +07:00
parent 7ae3c98585
commit 771d44d34c
12 changed files with 247 additions and 9 deletions

View File

@@ -2,6 +2,7 @@ from fastapi import APIRouter
from .auth import router as auth_router
from .health import router as health_router
from .link_codes import router as link_code_router
from .orders import router as orders_router
from .payments import payment_routers
from .plans import router as plans_router
@@ -13,5 +14,6 @@ routers: list[APIRouter] = [
orders_router,
users_routers,
health_router,
link_code_router,
*payment_routers,
]

57
routes/link_codes.py Normal file
View File

@@ -0,0 +1,57 @@
import secrets
from datetime import UTC, datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from config import cfg
from core.deps import get_auth_context, get_service_identity
from db.session import get_db
from repositories.link_codes import create_link_code, get_link_code_by_code
from repositories.users import UserRepository
from schemas.dto import AuthContext
from schemas.enums import LinkCodeStatus
from schemas.link_codes import LinkCodeConsume, LinkCodeResponse
from schemas.user import UserInfo
router = APIRouter(prefix="/link-codes")
@router.post("", response_model=LinkCodeResponse, status_code=201)
async def gen_link_code(
ctx: AuthContext = Depends(get_auth_context), session: AsyncSession = Depends(get_db)
):
code = secrets.token_urlsafe(cfg.link_code_length)
exp = datetime.now(UTC) + timedelta(minutes=cfg.link_code_ttl)
link_code = await create_link_code(
session, code=code, user_id=ctx.user.id, status=LinkCodeStatus.ACTIVE, expires_at=exp
)
return LinkCodeResponse(code=link_code.code, expires_at=link_code.expires_at)
@router.post("/consume", response_model=UserInfo)
async def consume_link_code(
payload: LinkCodeConsume,
ctx: AuthContext = Depends(get_service_identity),
session: AsyncSession = Depends(get_db),
):
link_code = await get_link_code_by_code(session, payload.code)
if not link_code:
raise HTTPException(404, detail="Code not found")
users_repo = UserRepository(session)
user = await users_repo.get_user_by_id(link_code.user_id)
if not user:
raise HTTPException(404, detail="User not found")
user = await users_repo.update_telegram_id(user, payload.telegram_id)
return UserInfo(
username=user.username,
telegram_id=user.telegram_id,
referal_code=user.referal_code,
bonus_balance=user.balance,
)