import uuid import httpx from fastapi import APIRouter, Depends, HTTPException, Request from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from database import get_db from models import User, ChatSession, ChatMessage router = APIRouter(prefix="/api/wecom", tags=["wecom"]) @router.post("/callback") async def wecom_callback(request: Request, db: AsyncSession = Depends(get_db)): """ 接收企业微信回调消息,路由到AI助手处理并回复。 企微配置的回调URL指向此端点。 """ try: body = await request.json() except Exception: body = await request.body() msg_type = "text" wecom_user_id = "" content = "" if isinstance(body, dict): msg_type = body.get("msg_type", body.get("MsgType", "text")) wecom_user_id = body.get("user_id", body.get("FromUserName", "")) content = body.get("content", body.get("Content", "")) if not wecom_user_id or not content: return {"code": 200, "message": "received"} user_result = await db.execute( select(User).where(User.wecom_user_id == wecom_user_id) ) user = user_result.scalar_one_or_none() if not user: return {"code": 200, "message": "received", "data": {"note": "user not found"}} from agentscope.message import Msg session_result = await db.execute( select(ChatSession) .where(ChatSession.user_id == user.id, ChatSession.agent_type == "employee") .order_by(ChatSession.updated_at.desc()) .limit(1) ) session = session_result.scalar_one_or_none() session_id = f"wecom_{wecom_user_id}_{uuid.uuid4().hex[:8]}" if not session: session = ChatSession( user_id=user.id, agent_type="employee", session_id=session_id, ) db.add(session) await db.flush() user_msg = ChatMessage( session_id=session.id, user_id=user.id, role="user", content=content, ) db.add(user_msg) await db.flush() from agentscope_integration.factory import AgentFactory agent = await AgentFactory.create_agent( agent_type="employee", user_id=str(user.id), user_name=user.display_name, department_id=str(user.department_id) if user.department_id else None, ) input_msg = Msg(name="user", content=content, role="user") response = await agent.reply(input_msg) reply_text = response.get_text_content() if hasattr(response, 'get_text_content') else str(response) ai_msg = ChatMessage( session_id=session.id, user_id=user.id, role="assistant", content=reply_text, ) db.add(ai_msg) return { "code": 200, "message": "ok", "data": { "msg_type": msg_type, "user_id": wecom_user_id, "reply": reply_text, }, } @router.post("/send") async def send_wecom_message( request: Request, payload: dict, db: AsyncSession = Depends(get_db), ): """ 向企业微信用户推送消息。 生产环境中需配置真实的企微API凭据。 """ to_user = payload.get("to_user", "") msg_content = payload.get("content", "") msg_type = payload.get("msg_type", "text") if not to_user: raise HTTPException(400, "缺少目标用户") corp_id = "" corp_secret = "" wecom_message_id = f"msg_{uuid.uuid4().hex[:12]}" if corp_id and corp_secret: try: async with httpx.AsyncClient() as client: token_resp = await client.get( "https://qyapi.weixin.qq.com/cgi-bin/gettoken", params={"corpid": corp_id, "corpsecret": corp_secret}, ) token_data = token_resp.json() access_token = token_data.get("access_token") if access_token: msg_body = { "touser": to_user, "msgtype": msg_type, "agentid": 0, } if msg_type == "text": msg_body["text"] = {"content": msg_content} elif msg_type == "textcard": msg_body["textcard"] = payload.get("card", {}) msg_resp = await client.post( f"https://qyapi.weixin.qq.com/cgi-bin/message/send", params={"access_token": access_token}, json=msg_body, ) resp_data = msg_resp.json() if resp_data.get("errcode") == 0: wecom_message_id = resp_data.get("msgid", wecom_message_id) except Exception: pass return { "code": 200, "message": "消息已发送", "data": {"wecom_message_id": wecom_message_id}, } @router.get("/config") async def get_wecom_config(request: Request): return { "code": 200, "data": { "bot_name": "企业AI助手", "status": "configured", "features": ["消息对话", "文件处理", "任务通知", "工作流触发"], }, }