You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

165 lines
5.1 KiB

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": ["消息对话", "文件处理", "任务通知", "工作流触发"],
},
}