import logging import httpx logger = logging.getLogger(__name__) AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize" GET_USER_INFO_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo" GET_USER_DETAIL_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/get" def build_authorize_url( corp_id: str, redirect_uri: str, state: str = "", scope: str = "snsapi_base", agent_id: int = 0, ) -> str: params = { "appid": corp_id, "redirect_uri": redirect_uri, "response_type": "code", "scope": scope, "state": state, } if agent_id > 0: params["agentid"] = str(agent_id) query = "&".join(f"{k}={v}" for k, v in params.items()) return f"{AUTHORIZE_URL}?{query}#wechat_redirect" async def get_user_info(access_token: str, code: str) -> dict | None: url = f"{GET_USER_INFO_URL}?access_token={access_token}&code={code}" async with httpx.AsyncClient(timeout=10.0) as client: try: resp = await client.get(url) data = resp.json() if data.get("errcode") == 0: return { "user_id": data.get("UserId"), "device_id": data.get("DeviceId"), "open_id": data.get("OpenId"), } logger.warning("WeCom OAuth get_user_info failed: %s", data) return None except Exception: logger.exception("WeCom OAuth get_user_info error") return None async def get_user_detail(access_token: str, user_id: str) -> dict | None: url = f"{GET_USER_DETAIL_URL}?access_token={access_token}&userid={user_id}" async with httpx.AsyncClient(timeout=10.0) as client: try: resp = await client.get(url) data = resp.json() if data.get("errcode") == 0: return data logger.warning("WeCom OAuth get_user_detail failed: %s", data) return None except Exception: logger.exception("WeCom OAuth get_user_detail error") return None