"""企业微信JS-SDK路由""" from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel from sqlalchemy.orm import Session from ..database import get_db from ..models.tenant_app import TenantApp from ..models.tenant_wechat_app import TenantWechatApp from ..services.wechat import WechatService, get_wechat_service_by_id router = APIRouter(prefix="/wechat", tags=["企业微信"]) class JssdkSignatureRequest(BaseModel): """JS-SDK签名请求""" url: str # 当前页面URL(不含#及其后面部分) class JssdkSignatureResponse(BaseModel): """JS-SDK签名响应""" appId: str agentId: str timestamp: int nonceStr: str signature: str class OAuth2UrlRequest(BaseModel): """OAuth2授权URL请求""" redirect_uri: str scope: str = "snsapi_base" state: str = "" class UserInfoRequest(BaseModel): """用户信息请求""" code: str @router.post("/jssdk/signature") async def get_jssdk_signature( request: JssdkSignatureRequest, tenant_id: str = Query(..., alias="tid"), app_code: str = Query(..., alias="aid"), db: Session = Depends(get_db) ): """获取JS-SDK签名 用于前端初始化企业微信JS-SDK Args: request: 包含当前页面URL tenant_id: 租户ID app_code: 应用代码 Returns: JS-SDK签名信息 """ # 查找租户应用配置 tenant_app = db.query(TenantApp).filter( TenantApp.tenant_id == tenant_id, TenantApp.app_code == app_code, TenantApp.status == 1 ).first() if not tenant_app: raise HTTPException(status_code=404, detail="租户应用配置不存在") if not tenant_app.wechat_app_id: raise HTTPException(status_code=400, detail="该应用未配置企业微信") # 获取企微服务 wechat_service = await get_wechat_service_by_id(tenant_app.wechat_app_id, db) if not wechat_service: raise HTTPException(status_code=404, detail="企业微信应用不存在或已禁用") # 生成签名 signature_data = await wechat_service.get_jssdk_signature(request.url) if not signature_data: raise HTTPException(status_code=500, detail="获取JS-SDK签名失败") return signature_data @router.get("/jssdk/signature") async def get_jssdk_signature_get( url: str = Query(..., description="当前页面URL"), tenant_id: str = Query(..., alias="tid"), app_code: str = Query(..., alias="aid"), db: Session = Depends(get_db) ): """获取JS-SDK签名(GET方式) 方便前端JSONP调用 """ # 查找租户应用配置 tenant_app = db.query(TenantApp).filter( TenantApp.tenant_id == tenant_id, TenantApp.app_code == app_code, TenantApp.status == 1 ).first() if not tenant_app: raise HTTPException(status_code=404, detail="租户应用配置不存在") if not tenant_app.wechat_app_id: raise HTTPException(status_code=400, detail="该应用未配置企业微信") # 获取企微服务 wechat_service = await get_wechat_service_by_id(tenant_app.wechat_app_id, db) if not wechat_service: raise HTTPException(status_code=404, detail="企业微信应用不存在或已禁用") # 生成签名 signature_data = await wechat_service.get_jssdk_signature(url) if not signature_data: raise HTTPException(status_code=500, detail="获取JS-SDK签名失败") return signature_data @router.post("/oauth2/url") async def get_oauth2_url( request: OAuth2UrlRequest, tenant_id: str = Query(..., alias="tid"), app_code: str = Query(..., alias="aid"), db: Session = Depends(get_db) ): """获取OAuth2授权URL 用于企业微信内网页获取用户身份 """ # 查找租户应用配置 tenant_app = db.query(TenantApp).filter( TenantApp.tenant_id == tenant_id, TenantApp.app_code == app_code, TenantApp.status == 1 ).first() if not tenant_app: raise HTTPException(status_code=404, detail="租户应用配置不存在") if not tenant_app.wechat_app_id: raise HTTPException(status_code=400, detail="该应用未配置企业微信") # 获取企微服务 wechat_service = await get_wechat_service_by_id(tenant_app.wechat_app_id, db) if not wechat_service: raise HTTPException(status_code=404, detail="企业微信应用不存在或已禁用") # 生成OAuth2 URL oauth_url = wechat_service.get_oauth2_url( redirect_uri=request.redirect_uri, scope=request.scope, state=request.state ) return {"url": oauth_url} @router.post("/oauth2/userinfo") async def get_user_info( request: UserInfoRequest, tenant_id: str = Query(..., alias="tid"), app_code: str = Query(..., alias="aid"), db: Session = Depends(get_db) ): """通过OAuth2 code获取用户信息 在OAuth2回调后,用code换取用户信息 """ # 查找租户应用配置 tenant_app = db.query(TenantApp).filter( TenantApp.tenant_id == tenant_id, TenantApp.app_code == app_code, TenantApp.status == 1 ).first() if not tenant_app: raise HTTPException(status_code=404, detail="租户应用配置不存在") if not tenant_app.wechat_app_id: raise HTTPException(status_code=400, detail="该应用未配置企业微信") # 获取企微服务 wechat_service = await get_wechat_service_by_id(tenant_app.wechat_app_id, db) if not wechat_service: raise HTTPException(status_code=404, detail="企业微信应用不存在或已禁用") # 获取用户信息 user_info = await wechat_service.get_user_info_by_code(request.code) if not user_info: raise HTTPException(status_code=400, detail="获取用户信息失败,code可能已过期") return user_info @router.get("/oauth2/userinfo") async def get_user_info_get( code: str = Query(..., description="OAuth2回调的code"), tenant_id: str = Query(..., alias="tid"), app_code: str = Query(..., alias="aid"), db: Session = Depends(get_db) ): """通过OAuth2 code获取用户信息(GET方式)""" # 查找租户应用配置 tenant_app = db.query(TenantApp).filter( TenantApp.tenant_id == tenant_id, TenantApp.app_code == app_code, TenantApp.status == 1 ).first() if not tenant_app: raise HTTPException(status_code=404, detail="租户应用配置不存在") if not tenant_app.wechat_app_id: raise HTTPException(status_code=400, detail="该应用未配置企业微信") # 获取企微服务 wechat_service = await get_wechat_service_by_id(tenant_app.wechat_app_id, db) if not wechat_service: raise HTTPException(status_code=404, detail="企业微信应用不存在或已禁用") # 获取用户信息 user_info = await wechat_service.get_user_info_by_code(code) if not user_info: raise HTTPException(status_code=400, detail="获取用户信息失败,code可能已过期") return user_info @router.get("/user/{user_id}") async def get_user_detail( user_id: str, tenant_id: str = Query(..., alias="tid"), app_code: str = Query(..., alias="aid"), db: Session = Depends(get_db) ): """获取企业微信成员详细信息""" # 查找租户应用配置 tenant_app = db.query(TenantApp).filter( TenantApp.tenant_id == tenant_id, TenantApp.app_code == app_code, TenantApp.status == 1 ).first() if not tenant_app: raise HTTPException(status_code=404, detail="租户应用配置不存在") if not tenant_app.wechat_app_id: raise HTTPException(status_code=400, detail="该应用未配置企业微信") # 获取企微服务 wechat_service = await get_wechat_service_by_id(tenant_app.wechat_app_id, db) if not wechat_service: raise HTTPException(status_code=404, detail="企业微信应用不存在或已禁用") # 获取用户详情 user_detail = await wechat_service.get_user_detail(user_id) if not user_detail: raise HTTPException(status_code=404, detail="用户不存在") return user_detail