接口跑通,基础功能全部实现
This commit is contained in:
@@ -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),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user