from fastapi import APIRouter, Request, Query, Depends from fastapi.responses import PlainTextResponse from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.services.crypto import verify_url, decrypt_message from app.services.wechat_client import sync_msg from app.services.message_service import save_messages from app.config import settings import logging logger = logging.getLogger(__name__) router = APIRouter() @router.get("/webhook") async def verify_callback( msg_signature: str = Query(..., alias="msg_signature"), timestamp: str = Query(...), nonce: str = Query(...), echostr: str = Query(...), ): """URL 验证:解密 echostr 并返回明文""" try: plain = verify_url(msg_signature, timestamp, nonce, echostr) return PlainTextResponse(plain) except Exception as e: logger.error(f"URL 验证失败: {e}") return PlainTextResponse("verification failed", status_code=400) @router.post("/webhook") async def receive_callback(request: Request, db: AsyncSession = Depends(get_db)): """接收消息回调:解密 XML → 拉取消息 → 入库""" try: xml_body = await request.body() xml_str = xml_body.decode("utf-8") logger.info(f"收到回调: {xml_str[:200]}") token, open_kfid = decrypt_message(xml_str) if not token or not open_kfid: logger.warning("解密后 Token 或 OpenKfId 为空") return PlainTextResponse("fail") # 拉取消息 result = await sync_msg(open_kfid, token=token, limit=100) msg_list = result.get("msg_list", []) if msg_list: saved = await save_messages(db, msg_list) logger.info(f"回调拉取消息 {len(msg_list)} 条,新增入库 {saved} 条") return PlainTextResponse("success") except Exception as e: logger.error(f"回调处理失败: {e}") return PlainTextResponse("fail")