接口跑通,基础功能全部实现

This commit is contained in:
2026-03-16 16:14:08 +08:00
parent f81aec48ca
commit 2f2d5c3795
38 changed files with 3352 additions and 1754 deletions

View File

@@ -13,9 +13,11 @@ import os
import logging
from shared.models import get_db, User
from shared.config import shared_settings
from auth_service.app.models.database import create_tables
from auth_service.app.schemas.user import (
UserCreate, UserLogin, UserResponse, Token, TokenData, RefreshTokenRequest, AuthResponse,
UserCreate, UserLogin, UserResponse, Token, TokenData,
RefreshTokenRequest, AuthResponse, WxLoginRequest,
)
from auth_service.app.services.auth_service import AuthService
from auth_service.app.utils.security import (
@@ -235,3 +237,99 @@ async def get_current_user_info(current_user: UserResponse = Depends(get_current
Get current user information
"""
return current_user
@app.post("/auth/wx-login", response_model=AuthResponse)
async def wx_login(body: WxLoginRequest, db: AsyncSession = Depends(get_db)):
"""
微信小程序登录。
流程:
1. 用 code 调微信 code2Session 接口换取 openid
2. 查找是否已有该 openid 的用户
3. 没有则自动注册,有则直接登录
4. 返回 JWT token
"""
import httpx
appid = shared_settings.WX_APPID
secret = shared_settings.WX_SECRET
if not appid or not secret:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="微信小程序未配置 APPID 和 SECRET",
)
# Step 1: code 换 openid
async with httpx.AsyncClient(timeout=10) as client:
resp = await client.get(
"https://api.weixin.qq.com/sns/jscode2session",
params={
"appid": appid,
"secret": secret,
"js_code": body.code,
"grant_type": "authorization_code",
},
)
wx_data = resp.json()
openid = wx_data.get("openid")
if not openid:
errcode = wx_data.get("errcode", "unknown")
errmsg = wx_data.get("errmsg", "未知错误")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"微信登录失败: {errmsg} (errcode={errcode})",
)
# Step 2: 查找已有用户
result = await db.execute(select(User).where(User.wx_openid == openid))
user = result.scalar_one_or_none()
if user:
# 已有用户 — 更新昵称头像(如果传了)
if body.nickname and body.nickname != user.wx_nickname:
user.wx_nickname = body.nickname
if body.avatar_url and body.avatar_url != user.wx_avatar:
user.wx_avatar = body.avatar_url
await db.commit()
await db.refresh(user)
else:
# Step 3: 自动注册
import uuid
nickname = body.nickname or f"wx_{openid[:8]}"
# 生成唯一 username避免冲突
username = f"wx_{openid[:12]}"
user = User(
id=str(uuid.uuid4()),
username=username,
wx_openid=openid,
wx_nickname=nickname,
wx_avatar=body.avatar_url,
is_active=True,
)
db.add(user)
await db.commit()
await db.refresh(user)
logger.info(f"微信用户自动注册: openid={openid[:16]}..., username={username}")
if not user.is_active:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="账号已被禁用",
)
# Step 4: 签发 token
access_token = create_access_token(
data={"sub": str(user.id), "username": user.username}
)
refresh_token = await create_refresh_token(str(user.id))
return AuthResponse(
access_token=access_token,
refresh_token=refresh_token,
token_type="bearer",
expires_in=3600,
user=UserResponse.from_orm(user),
)