# 微信 access_token 中控（腾讯云静态 IP 换 token）

## 为什么

gateway 换 access_token 时微信看到的是**本地宽带出网 IP（动态会变）**，一变白名单
就失效、二维码建不出来（40164）。微信官方推荐「中控服务器」：一台**固定 IP** 的机器
统一换 token，业务机拉取使用。腾讯云那台（`162.14.122.200`，静态）当中控。

微信 IP 白名单**只限制换 token 这一步**（用 appsecret），拿 token 建二维码不查 IP。
所以：腾讯云换 token → gateway 拉 token → gateway 本地建二维码。白名单只填腾讯云 IP。

## 实际采用方案（B：宝塔 nginx + IP + 密钥）

腾讯云未配域名，用 IP 直接 serve token.json，加密钥头保护。token 走公网明文传，
但强随机密钥保护 + 90 分钟轮换，风险可控（单产品早期可接受；要更严可后续换 frp 隧道）。

### 腾讯云（宝塔）

1. **计划任务**（宝塔「计划任务」→ 添加，Shell 脚本，每 90 分钟）：
   ```bash
   #!/bin/bash
   APPID="wxc236cddde8e7f863"
   SECRET="你的公众号AppSecret"
   mkdir -p /home/workspace/wxtoken
   OUT="/home/workspace/wxtoken/token.json"
   resp=$(curl -s "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${SECRET}")
   echo "$resp" | grep -q '"access_token"' && echo "$resp" > "$OUT.tmp" && mv "$OUT.tmp" "$OUT"
   ```
   加完点一次「执行」，确认 `/home/workspace/wxtoken/token.json` 生成、内容含 access_token。

2. **建站点 + nginx**（宝塔「网站」→ 添加，域名填 IP `162.14.122.200`，纯静态）。
   站点「配置文件」的 `server { }` 里加（密钥换成 `openssl rand -hex 24` 生成的强随机串）：
   ```nginx
   location = /wxtoken/token.json {
       if ($http_authorization != "Bearer <强随机密钥>") { return 403; }
       default_type application/json;
       alias /home/workspace/wxtoken/token.json;
       add_header Cache-Control "no-store";
   }
   ```
   自测：带密钥能取、不带 403。

3. **微信 IP 白名单**：只填腾讯云 `162.14.122.200`（换 token 只发生在这台）。

### gateway（132 的 .env）
```
WECHAT_TOKEN_URL=http://162.14.122.200/wxtoken/token.json
WECHAT_TOKEN_SECRET=<与 nginx 那串一字不差>
```
配了 gateway 就**只从中控拉、不自己换 token**；不配则维持直连。

## 切换 + 验证（关键，坐实 qrcode 不受 IP 限制）

1. 先让**本地 IP 和腾讯云 IP 都在白名单**，配好上面一切、部署，扫码确认能登录。
2. 去公众平台把**本地 IP 删掉、只留腾讯云 `162.14.122.200`**，再扫码：
   - **能登录** → 换 token 走了中控、建二维码本地也没被拦，方案坐实、IP 隐患彻底消除。
   - **建二维码报 40164** → qrcode 也受 IP 限制，改用备选：腾讯云装 tinyproxy 正向代理，
     gateway 加 `WECHAT_HTTP_PROXY`（需再改一处 http 客户端）。

## 安全提醒

- `WECHAT_TOKEN_SECRET` 用强随机串（`openssl rand -hex 24`），别用品牌名等易猜词——
  泄露就能拉到 token 冒用公众号 2 小时。
- token 走公网明文传是本方案的固有代价；要消除，后续可改 frp stcp 隧道（token 不出公网）。

## 排查

- gateway 日志 `[wxlogin] 建二维码失败: ... 40164` → 中控没生效或没配 env，仍在本地换 token
- gateway 拉取 403 → `WECHAT_TOKEN_SECRET` 与 nginx 里的密钥不一致
- token.json 过期/为空 → 宝塔计划任务没跑，或脚本手动执行失败
