Compare commits
2 Commits
30d3104e76
...
0e97812c03
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e97812c03 | |||
| a4ac682ad0 |
@ -26,6 +26,11 @@ class BindOpenIdRequest(BaseModel):
|
|||||||
open_id: str
|
open_id: str
|
||||||
|
|
||||||
|
|
||||||
|
class BindOpenIdByCodeRequest(BaseModel):
|
||||||
|
"""通过 wx.login code 绑定微信 OpenID"""
|
||||||
|
code: str
|
||||||
|
|
||||||
|
|
||||||
@router.post("/login")
|
@router.post("/login")
|
||||||
def login(
|
def login(
|
||||||
payload: LoginRequest, # 登录请求体,包含用户名、密码、角色类型
|
payload: LoginRequest, # 登录请求体,包含用户名、密码、角色类型
|
||||||
@ -51,7 +56,7 @@ def wechat_login(
|
|||||||
"""微信手机号一键登录接口
|
"""微信手机号一键登录接口
|
||||||
|
|
||||||
用途:通过微信手机号授权登录,自动匹配系统用户并绑定 open_id。
|
用途:通过微信手机号授权登录,自动匹配系统用户并绑定 open_id。
|
||||||
请求参数:WechatLoginRequest(code、encrypted_data、iv)。
|
请求参数:WechatLoginRequest(code、phone_code)。
|
||||||
返回值:登录结果,包含 token 等认证信息。
|
返回值:登录结果,包含 token 等认证信息。
|
||||||
权限要求:无需认证(公开接口)。
|
权限要求:无需认证(公开接口)。
|
||||||
"""
|
"""
|
||||||
@ -103,3 +108,20 @@ def bind_openid(
|
|||||||
"""
|
"""
|
||||||
wechat_notification_service.bind_open_id(session, current_user["user_id"], payload.open_id)
|
wechat_notification_service.bind_open_id(session, current_user["user_id"], payload.open_id)
|
||||||
return success_payload({"success": True})
|
return success_payload({"success": True})
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/bind-openid-by-code")
|
||||||
|
def bind_openid_by_code(
|
||||||
|
payload: BindOpenIdByCodeRequest, # 通过 code 绑定
|
||||||
|
auth_service: AuthService = Depends(get_auth_service), # 注入认证服务
|
||||||
|
session: Session = Depends(get_db_session), # 注入数据库会话
|
||||||
|
current_user: dict = Depends(get_current_user), # 当前登录用户
|
||||||
|
) -> dict:
|
||||||
|
"""通过 wx.login code 绑定微信 OpenID
|
||||||
|
|
||||||
|
用途:密码登录后调用,用 code 换取 open_id 并绑定到当前用户。
|
||||||
|
请求参数:BindOpenIdByCodeRequest(code - wx.login 获取的临时凭证)。
|
||||||
|
返回值:绑定结果 {"success": true}。
|
||||||
|
权限要求:必须已登录。
|
||||||
|
"""
|
||||||
|
return success_payload(auth_service.bind_openid_by_code(current_user["user_id"], payload.code, session))
|
||||||
|
|||||||
@ -273,6 +273,40 @@ class AuthService:
|
|||||||
pass
|
pass
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def bind_openid_by_code(self, user_id: int, code: str, session: Session | None = None) -> dict:
|
||||||
|
"""通过 wx.login code 绑定 open_id 到指定用户。
|
||||||
|
|
||||||
|
用于密码登录后自动绑定 open_id,为微信订阅消息通知做准备。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: 用户 ID
|
||||||
|
code: wx.login() 获取的临时凭证
|
||||||
|
session: 数据库会话
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
{"success": True}
|
||||||
|
|
||||||
|
被调用路由: auth.py - POST /auth/bind-openid-by-code
|
||||||
|
"""
|
||||||
|
if session is None:
|
||||||
|
raise AppException(code=ErrorCode.INTERNAL_ERROR, message="数据库连接不可用", status_code=500)
|
||||||
|
|
||||||
|
settings = self.settings
|
||||||
|
if not settings.wechat_app_id or not settings.wechat_app_secret:
|
||||||
|
return {"success": True, "skipped": True}
|
||||||
|
|
||||||
|
_, open_id = self._code2session(code, settings)
|
||||||
|
if not open_id:
|
||||||
|
return {"success": True, "skipped": True}
|
||||||
|
|
||||||
|
user = self.repository.get_user(session, user_id)
|
||||||
|
if user is not None:
|
||||||
|
user.open_id = open_id
|
||||||
|
session.add(user)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return {"success": True}
|
||||||
|
|
||||||
def get_me(self, token: str, session: Session | None = None) -> dict | None:
|
def get_me(self, token: str, session: Session | None = None) -> dict | None:
|
||||||
"""根据 Token 获取当前用户信息(无需重新登录)。
|
"""根据 Token 获取当前用户信息(无需重新登录)。
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,21 @@ Page({
|
|||||||
auth.setToken(data.token);
|
auth.setToken(data.token);
|
||||||
auth.setUser(data);
|
auth.setUser(data);
|
||||||
|
|
||||||
|
// 密码登录成功后自动绑定 open_id(为微信消息通知做准备)
|
||||||
|
try {
|
||||||
|
var loginCode = await new Promise(function (resolve, reject) {
|
||||||
|
wx.login({ success: resolve, fail: reject });
|
||||||
|
});
|
||||||
|
await app.request({
|
||||||
|
url: "/api/auth/bind-openid-by-code",
|
||||||
|
method: "POST",
|
||||||
|
data: { code: loginCode.code },
|
||||||
|
});
|
||||||
|
} catch (bindErr) {
|
||||||
|
// 绑定失败不影响登录
|
||||||
|
console.log("open_id 绑定跳过:", bindErr.message);
|
||||||
|
}
|
||||||
|
|
||||||
wx.showToast({
|
wx.showToast({
|
||||||
title: "欢迎," + (data.real_name || data.username),
|
title: "欢迎," + (data.real_name || data.username),
|
||||||
icon: "success",
|
icon: "success",
|
||||||
|
|||||||
@ -11,8 +11,9 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleGetPhoneNumber: async function (e) {
|
handleGetPhoneNumber: async function (e) {
|
||||||
|
console.log("[DEBUG] getPhoneNumber event:", JSON.stringify(e.detail));
|
||||||
if (e.detail.errMsg !== "getPhoneNumber:ok") {
|
if (e.detail.errMsg !== "getPhoneNumber:ok") {
|
||||||
this.setData({ message: "您拒绝了手机号授权" });
|
this.setData({ message: "授权失败:" + (e.detail.errMsg || JSON.stringify(e.detail)) });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setData({ loading: true, message: "" });
|
this.setData({ loading: true, message: "" });
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user