接口地址与反向代理
微信要求获取 access_token 的服务器出口 IP 必须在公众号「IP 白名单」中。若你的 Halo 服务器没有固定公网 IP(动态 IP、家用宽带、部署在 NAT 之后等),白名单会频繁失效,导致同步失败。
解决办法:准备一台有固定公网 IP 的低配服务器(VPS)作为反向代理 / 白名单代理,只把这台代理服务器的固定 IP 加入微信 IP 白名单。Halo 将微信接口请求发往「接口地址」,由代理转发到 api.weixin.qq.com——微信看到的出口 IP 始终是代理的固定 IP,从而绕开 Halo 无固定公网 IP 的限制。
Halo 服务器(无固定公网 IP)
│ 请求发往插件设置的「接口地址」
▼
反向代理服务器(固定公网 IP,已加入微信 IP 白名单)
│ 原样转发到
▼
https://api.weixin.qq.com
配置:在插件设置的 接口地址 中填入代理服务器地址(如 https://wechat-proxy.example.com);留空则直连微信官方接口。地址支持带路径前缀(如 https://example.com/wechat-proxy),插件会保留前缀并去除尾部 /。
⚠️ 重要提醒:代理服务器会获取请求中的敏感信息(包括但不限于
access_token、AppID 等敏感信息),务必使用自行部署或可信的服务器进行代理,切勿使用来源不明的公共代理,以免造成信息泄露。
⚠️ 你必须在该地址上反向代理插件用到的全部微信接口,并保持原始请求路径不变,否则相应步骤会失败。其中
material/get_material(封面复用前的校验)与draft/get(重复同步前校验已有草稿)是校验用接口:漏掉它们不会让同步失败,只会退化为「每次同步都重传一份封面 / 每次同步都新建一份草稿」,建议一并放行(见下方说明)。
插件用到的微信接口(相对于「接口地址」基址,均为微信官方路径):
| 方法 | 路径 | 用途 | 请求体 |
|---|---|---|---|
GET | /cgi-bin/token | 获取 access_token | 查询参数 |
POST | /cgi-bin/media/uploadimg | 上传正文图片 | multipart/form-data |
POST | /cgi-bin/material/add_material?type=image | 上传封面为永久图片素材 | multipart/form-data |
POST | /cgi-bin/material/get_material | 复用封面前校验该永久素材是否仍在(请求体 {"media_id":"..."}) | application/json |
POST | /cgi-bin/draft/add | 创建图文草稿 | application/json |
POST | /cgi-bin/draft/get | 重复同步前校验上次写入的草稿是否仍在(请求体 {"media_id":"..."};仅开启「重复同步更新草稿」时调用) | application/json |
POST | /cgi-bin/draft/update | 更新既有草稿(请求体 {"media_id":"...","index":0,"articles":{...}};仅开启「重复同步更新草稿」时调用) | application/json |
ℹ️ 关于
material/get_material:它是只读校验接口,用来判断缓存里的封面media_id还能不能复用——素材仍在时微信直接返回图片二进制流(不是 JSON),素材已被删除时返回{"errcode":40007,"errmsg":"invalid media_id"}。代理没有转发它不会导致同步失败(插件按「给不出结论」处理,保守地重新上传封面),但代价是每次同步都新增一份封面永久素材:永久图片素材有 10 万份上限,长期如此会白占配额,日志里也会反复出现「校验给不出结论…重新上传」。因此建议一并转发该路径;转发时同样要保持路径原样(该接口是POST,请求体为 JSON)。
ℹ️ 关于
draft/get与draft/update:开启「重复同步更新草稿」(默认开启,见配置)时,重复同步同一篇文章会先用draft/get校验上次写入的草稿是否还在——在则用draft/update更新那份草稿,不在(或校验给不出结论)则用draft/add新建;该开关关闭时这两个路径都不会被调用。只转发旧的那几个路径也不会让同步失败:draft/get拿不到结论时按「草稿不存在」处理、走新建,只是会退化为「每次同步都新建一份草稿」(草稿箱里会越积越多,需自行清理)。因此建议连同这两个路径一并转发;它们同样是POST+ JSON 请求体,路径也须原样透传。
Nginx 反向代理示例(部署在代理服务器上,将上述路径整体转发到微信):
server {
listen 443 ssl;
server_name wechat-proxy.example.com;
# ssl_certificate /path/to/fullchain.pem;
# ssl_certificate_key /path/to/privkey.pem;
# 仅放行插件用到的 7 个接口路径,其余一律拒绝,避免沦为开放代理
location ~ ^/cgi-bin/(token|media/uploadimg|material/add_material|material/get_material|draft/add|draft/get|draft/update)$ {
proxy_pass https://api.weixin.qq.com; # 不含 URI,nginx 会原样透传路径与查询参数
proxy_set_header Host api.weixin.qq.com;
proxy_ssl_server_name on; # 关键:向微信发起 TLS 时携带 SNI
proxy_ssl_name api.weixin.qq.com;
client_max_body_size 20m; # 素材上传可能较大,按需调整
proxy_request_buffering off;
proxy_read_timeout 60s;
}
location / {
return 403;
}
}
1Panel 反向代理示例(适用于通过 1Panel 建站面板管理的服务器):
location ~ ^/cgi-bin/(token|media/uploadimg|material/add_material|material/get_material|draft/add|draft/get|draft/update)$ {
proxy_pass https://api.weixin.qq.com;
proxy_set_header Host api.weixin.qq.com;
proxy_ssl_server_name on;
proxy_ssl_name api.weixin.qq.com;
client_max_body_size 30m; # 素材上传可能较大,按需调整
proxy_request_buffering off;
proxy_read_timeout 120s;
}
在 1Panel 中创建「反向代理」网站后,进入该网站的 反向代理,将上方整段
location配置粘贴到源文文件中保存即可生效。
要点:
proxy_pass到https://上游时务必开启proxy_ssl_server_name on;(SNI),否则与微信的 TLS 握手可能失败。- 保持路径原样转发:
proxy_pass后不要带会改写路径的 URI 部分,让 nginx 原样透传/cgi-bin/...路径与查询参数。 - 代理服务器的出口 IP 必须与加入微信白名单的 IP 一致。
- 建议用
location精确匹配上面 7 个路径、拒绝其它请求,防止代理被滥用;material/get_material与draft/get漏掉不会报错,但会让「封面复用 / 草稿更新」分别退化为每次都重传封面、每次都新建草稿(draft/get、draft/update仅在开启「重复同步更新草稿」时才会用到,见上文说明)。 - 生产环境请为代理配置
https://与合法证书;仅内网测试时可用http://。