80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
"""WeCom webhook endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from ...core.database import get_db
|
|
from ...services.integrations.wecom import get_wecom_service
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/webhook")
|
|
@router.get("/webhook/", include_in_schema=False)
|
|
async def verify_webhook_url(
|
|
msg_signature: str,
|
|
timestamp: str,
|
|
nonce: str,
|
|
echostr: str,
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
"""验证企业微信事件订阅 URL。"""
|
|
try:
|
|
service = get_wecom_service(db)
|
|
await service.load_config(tenant_id=1)
|
|
|
|
if not service.is_configured():
|
|
raise HTTPException(status_code=400, detail="请先配置企业微信")
|
|
|
|
decrypted_echostr = service.verify_url(msg_signature, timestamp, nonce, echostr)
|
|
|
|
return {
|
|
"errcode": 0,
|
|
"errmsg": "ok",
|
|
"echostr": decrypted_echostr,
|
|
}
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc))
|
|
except Exception as exc:
|
|
raise HTTPException(status_code=500, detail=str(exc))
|
|
|
|
|
|
@router.post("/webhook")
|
|
@router.post("/webhook/", include_in_schema=False)
|
|
async def handle_wecom_event(
|
|
request: Request,
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
"""处理企业微信事件推送。"""
|
|
try:
|
|
msg_signature = request.headers.get("msg_signature", "")
|
|
timestamp = request.headers.get("timestamp", "")
|
|
nonce = request.headers.get("nonce", "")
|
|
|
|
body_bytes = await request.body()
|
|
body = body_bytes.decode("utf-8")
|
|
|
|
service = get_wecom_service(db)
|
|
await service.load_config(tenant_id=1)
|
|
|
|
if not service.verify_callback(msg_signature, timestamp, nonce, body):
|
|
raise HTTPException(status_code=401, detail="签名验证失败")
|
|
|
|
decrypted = service._decrypt(body)
|
|
event_data = json.loads(decrypted) if decrypted else {}
|
|
await service.handle_message_event(event_data)
|
|
|
|
return {
|
|
"errcode": 0,
|
|
"errmsg": "ok",
|
|
}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as exc:
|
|
print(f"[WeCom] Webhook error: {exc}")
|
|
return {"errcode": 0, "errmsg": "ok"}
|