import logging import httpx logger = logging.getLogger(__name__) QRCODE_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create" QRCODE_SHOW_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode" class WeChatQRCode: def __init__(self, gateway): self._gateway = gateway async def create_temp(self, scene_str: str, expire_seconds: int = 2592000) -> dict | None: token = self._gateway.access_token if self._gateway else None if not token: return None payload = { "expire_seconds": min(expire_seconds, 2592000), "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": scene_str}}, } try: async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.post(f"{QRCODE_CREATE_URL}?access_token={token}", json=payload) data = resp.json() if "ticket" in data: return { "ticket": data["ticket"], "expire_seconds": data.get("expire_seconds", 0), "url": data.get("url", ""), "qrcode_url": f"{QRCODE_SHOW_URL}?ticket={data['ticket']}", } logger.warning( "Create temp qrcode failed: errcode=%s errmsg=%s", data.get("errcode"), data.get("errmsg"), ) except Exception: logger.exception("Create temp qrcode exception") return None async def create_permanent(self, scene_str: str) -> dict | None: token = self._gateway.access_token if self._gateway else None if not token: return None payload = { "action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": scene_str}}, } try: async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.post(f"{QRCODE_CREATE_URL}?access_token={token}", json=payload) data = resp.json() if "ticket" in data: return { "ticket": data["ticket"], "url": data.get("url", ""), "qrcode_url": f"{QRCODE_SHOW_URL}?ticket={data['ticket']}", } logger.warning( "Create permanent qrcode failed: errcode=%s errmsg=%s", data.get("errcode"), data.get("errmsg"), ) except Exception: logger.exception("Create permanent qrcode exception") return None