import logging import httpx logger = logging.getLogger(__name__) TEMPLATE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send" TEMPLATE_LIST_URL = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template" SUBSCRIBE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send" class WeChatTemplate: def __init__(self, gateway): self._gateway = gateway async def send( self, to_user: str, template_id: str, data: dict, url: str = "", miniprogram: dict | None = None, ) -> bool: token = self._gateway.access_token if self._gateway else None if not token: return False payload = { "touser": to_user, "template_id": template_id, "data": {k: {"value": v} for k, v in data.items()}, } if url: payload["url"] = url if miniprogram: payload["miniprogram"] = miniprogram try: async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.post(f"{TEMPLATE_SEND_URL}?access_token={token}", json=payload) result = resp.json() return result.get("errcode") == 0 except Exception: logger.exception("Send template message exception") return False async def list_templates(self) -> list[dict]: token = self._gateway.access_token if self._gateway else None if not token: return [] try: async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.get(f"{TEMPLATE_LIST_URL}?access_token={token}") data = resp.json() if "template_list" in data: return data["template_list"] logger.warning( "List templates failed: errcode=%s errmsg=%s", data.get("errcode"), data.get("errmsg"), ) except Exception: logger.exception("List templates exception") return [] async def send_subscribe( self, to_user: str, template_id: str, data: dict, page: str = "", miniprogram_state: str = "formal", lang: str = "zh_CN", ) -> bool: token = self._gateway.access_token if self._gateway else None if not token: return False payload = { "touser": to_user, "template_id": template_id, "data": {k: {"value": v} for k, v in data.items()}, "miniprogram_state": miniprogram_state, "lang": lang, } if page: payload["page"] = page try: async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.post(f"{SUBSCRIBE_SEND_URL}?access_token={token}", json=payload) result = resp.json() return result.get("errcode") == 0 except Exception: logger.exception("Send subscribe message exception") return False