Files
sundynix-agentix/deploy/wechat-token-zhongkong.md
T
Blizzard a1c68ec6b2 feat(auth): 微信 access_token 走中控服务器(腾讯云静态 IP 换 token)
隐患:gateway 换 access_token 时微信看到的是本地宽带出网 IP(106.58.232.43,
动态会变),一变白名单就失效、二维码建不出来(40164)。

按微信官方推荐的「中控服务器」架构解决:腾讯云静态 IP 统一换 token,gateway 拉取
使用。微信 IP 白名单只限制换 token 这一步,拿 token 建二维码不查 IP —— 所以
换 token 挪到中控、建二维码仍在 gateway 本地,白名单只填腾讯云 IP,永不失效。

- wechat.PullToken:从中控 HTTPS 端点拉 token(Bearer 密钥鉴权),坏响应/403/空
  token 一律报错不当成功;中控没给 expires_in 时按 7200 兜底。
- handler.accessToken:配了 WECHAT_TOKEN_URL 就只从中控拉、绝不自己 FetchAccessToken
  (微信要求单点刷新,多点各自换会互相顶掉 token);不配维持直连,零副作用可回退。
- compose:gateway 加 WECHAT_TOKEN_URL / WECHAT_TOKEN_SECRET(从宿主机 .env 注入)。
- deploy/wechat-token-zhongkong.md:腾讯云侧 cron 脚本 + nginx 配置 + 切换验证步骤。

本地验证(假中控 httptest + 真 gateway):建票时 Redis 缓存的是中控给的 token
(FAKE_TOKEN_FROM_ZHONGKONG),gateway 未直连微信换 token;随后拿该 token 调
qrcode/create(假 token 报 40001 属预期)——证明「中控换 token → 本地建二维码」链路成立。
4 组 PullToken 单测覆盖正常/403/坏JSON/兜底。

真机验证(部署后):把本地 IP 从白名单删掉、只留腾讯云 IP,扫码仍能登录即坐实
qrcode 不受 IP 限制;若建二维码报 40164 则退回 tinyproxy 正向代理备选。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 09:53:27 +08:00

85 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 微信 access_token 中控(腾讯云静态 IP
## 为什么
gateway 换 access_token 时微信看到的是**本地宽带出网 IP(动态,会变)**,一变白名单
就失效、二维码建不出来(40164)。微信官方推荐「中控服务器」:一台**固定 IP** 的机器
统一换 token,业务机拉取使用。腾讯云那台(`162.14.122.200`,静态)正好当中控。
微信 IP 白名单**只限制换 token 这一步**(用 appsecret),拿 token 建二维码不查 IP。
所以:腾讯云换 token → gateway 拉 token → gateway 本地建二维码。白名单只填腾讯云 IP。
## 腾讯云上做(三步)
### 1. 换 token 脚本 `/home/workspace/wxtoken/refresh.sh`
```bash
#!/bin/bash
# 用 appid/secret 换 access_token,写成 token.json。从腾讯云静态 IP 发出。
APPID="wxc236cddde8e7f863"
SECRET="你的公众号 AppSecret" # 建议重置后填新的
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}")
# 只在拿到 access_token 时才覆盖,避免偶发失败把好文件冲掉
echo "$resp" | grep -q '"access_token"' && echo "$resp" > "$OUT.tmp" && mv "$OUT.tmp" "$OUT"
```
```bash
chmod +x /home/workspace/wxtoken/refresh.sh
/home/workspace/wxtoken/refresh.sh # 先手动跑一次,确认 token.json 生成
```
### 2. cron 每 ~1.5 小时刷新(token 有效 2h,留足余量)
```bash
crontab -e
# 加一行:
*/90 * * * * /home/workspace/wxtoken/refresh.sh
```
### 3. nginx 把 token.json 以 HTTPS + 密钥吐出
在腾讯云那台的站点配置里加(token 是 2h 高权限凭证,必须 HTTPS + 密钥,不能裸奔):
```nginx
location = /wxtoken/token.json {
# 共享密钥校验:gateway 拉取时带 Authorization: Bearer <同一串>
if ($http_authorization != "Bearer 换成你自定的强随机串") { return 403; }
default_type application/json;
alias /home/workspace/wxtoken/token.json;
add_header Cache-Control "no-store";
}
```
reload nginx 后自测(换成真域名):
```bash
curl -s -H "Authorization: Bearer 换成你自定的强随机串" https://<腾讯云域名>/wxtoken/token.json
# 应返回 {"access_token":"...","expires_in":7200}
curl -s https://<腾讯云域名>/wxtoken/token.json # 不带密钥应 403
```
## gateway 侧(在 132 的 .env 里配,随部署生效)
```
WECHAT_TOKEN_URL=https://<腾讯云域名>/wxtoken/token.json
WECHAT_TOKEN_SECRET=换成你自定的强随机串 # 与 nginx 那串一字不差
```
配了 gateway 就**只从中控拉、不自己换 token**;不配则维持直连(受本地 IP 白名单约束)。
## 切换 + 验证(关键,坐实 qrcode 不受 IP 限制)
1. 先让**本地 IP 和腾讯云 IP 都在白名单**,配好上面 env、部署,扫码确认能登录(此时不确定
token 是中控给的还是本地换的都能过)。
2. 去公众平台把**本地 IP 从白名单删掉,只留腾讯云 `162.14.122.200`**,再扫码:
- **能登录** → 换 token 走了中控、建二维码本地也没被拦,方案坐实,IP 隐患彻底消除。
- **建二维码报 40164** → qrcode 也受 IP 限制,改用备选:腾讯云装 tinyproxy 正向代理,
gateway 加 `WECHAT_HTTP_PROXY` env(代码侧已预留思路,需再改一处 http 客户端)。
## 排查
- gateway 日志 `[wxlogin] 建二维码失败: ... 40164` → 中控没生效或没配 env,仍在本地换 token
- 中控 token.json 过期/为空 → 看 cron 有没有在跑、`refresh.sh` 手动能否生成
- gateway 拉取 403 → `WECHAT_TOKEN_SECRET` 与 nginx 里的密钥不一致