This commit is contained in:
eric
2026-03-31 07:04:37 -05:00
parent 5a5b4d1beb
commit 1f7894c768
9 changed files with 705 additions and 0 deletions

53
token_client.py Normal file
View File

@@ -0,0 +1,53 @@
import hashlib
import json
import time
import uuid
from typing import Optional
import httpx
from config import APP_ID, TOKEN
TOKEN_URL = "https://openaiapi.weixin.qq.com/v2/token"
def _md5_hex(data: str) -> str:
return hashlib.md5(data.encode("utf-8")).hexdigest()
async def fetch_access_token(account: Optional[str] = None) -> str:
"""
调用微信智能对话 /v2/token 接口,换取 AccessToken。
文档参考https://developers.weixin.qq.com/doc/aispeech/confapi/dialog/token.html
"""
timestamp = int(time.time())
nonce = uuid.uuid4().hex[:16]
body_obj = {}
if account:
body_obj["account"] = account
body_str = json.dumps(body_obj, separators=(",", ":"), ensure_ascii=False)
# sign = md5(Token + str(unix_timestamp) + nonce + md5(body))
body_md5 = _md5_hex(body_str) if body_str else _md5_hex("")
sign_src = f"{TOKEN}{timestamp}{nonce}{body_md5}"
sign = _md5_hex(sign_src)
headers = {
"X-APPID": APP_ID,
"request_id": str(uuid.uuid4()),
"timestamp": str(timestamp),
"nonce": nonce,
"sign": sign,
"content-type": "application/json",
}
async with httpx.AsyncClient(timeout=5) as client:
resp = await client.post(TOKEN_URL, headers=headers, content=body_str.encode("utf-8"))
resp.raise_for_status()
data = resp.json()
if data.get("code") != 0:
raise RuntimeError(f"fetch_access_token error: {data}")
return data["data"]["access_token"]