常见问题(FAQ)
Q:同步失败,提示「微信公众号草稿必须包含封面图」? 微信草稿强制要求封面。请为文章设置封面后重试;若封面是相对路径,请确认已在 Halo 配置「外部访问地址」。当前版本在点击「同步到微信公众号」时也会先行预检封面,这类问题通常在打开预览前就会直接提示。
Q:点击「同步到微信公众号」后直接弹出错误提示、没有打开预览窗? 这是提交前的自动预检在提前报告「提交前即可发现」的已知问题(微信配置、封面图、文章是否正在同步中),有问题会直接提示并中止、不会产生同步任务。常见提示与处理:
- 「插件尚未配置微信公众号信息」/「未找到保存 AppSecret 的 Secret」等:前往插件「设置 - 微信公众号」填写或重新保存 AppID / AppSecret;
- 「当前文章未设置封面图」:为文章设置封面后再试(微信草稿强制要求封面,无法省略);
- 「无法解析封面图地址」:封面为相对路径,请先在 Halo「基本设置 - 外部访问地址」配置站点公网地址;
- 「该文章正在同步中」:等待当前任务完成后再试。
预检只读——不调用微信接口、不写任何记录;通过后才会进入预览与确认同步流程。
Q:提示获取 access_token 失败?
检查 AppID / AppSecret 是否正确,以及是否已在公众平台配置 IP 白名单(Halo 服务器公网出口 IP)。
Q:Halo 服务器没有固定公网 IP,白名单总是失效怎么办? 用一台有固定公网 IP 的服务器做反向代理,把代理服务器的 IP 加入微信白名单,并在插件「接口地址」中填入代理地址。详见接口地址与反向代理。
Q:提示接口无权限 / 48001 等错误? 草稿箱、素材管理等接口需要已认证的公众号并开通对应权限,未认证或个人订阅号可能无法调用。
Q:同步失败,红色 Logo 悬停显示一串 errcode,怎么查?
先记录下 errcode 与 errmsg,再到 微信接口错误码速查 对照:该节按插件用到的 7 个接口整理了微信官方的限制与接口级错误码、通用错误码的常见诱因,以及官方文档未列出但实践中会遇到的错误码(如 40243 AppSecret 被冻结、89503 需管理员确认、1003 multipart 被代理改写等)。若提示里没有 errcode,多半是网络、反向代理或图片下载环节的问题,可对照「非 errcode 类失败」一节排查。注意其中 material/get_material 只用于封面复用前的校验、draft/get 只用于重复同步前的草稿校验,它们的错误不会让同步失败,详见「素材校验接口 material/get_material 的判定规则」与「草稿校验接口 draft/get 的判定规则」。
Q:日志反复出现「校验给不出结论…重新上传」,封面每次都重新上传一份素材?
封面复用前插件会调用 material/get_material 确认缓存里的 media_id 是否还在微信侧;拿不到结论时保守重传(同步不受影响,但每次会多占一份永久素材配额)。若每次同步都出现,多半是「接口地址」代理没有放行 /cgi-bin/material/get_material(也可能被限流、凭证失效或网络异常):按接口地址与反向代理补上该路径即可。反之,若日志提示「微信侧已不存在」,说明该素材确实已被删除(在公众号后台清理过素材),此时重传是预期行为,会顺带刷新缓存。
Q:封面或图片是 webp,能同步吗?
可以。插件会自动把 webp 解码并重编码为微信支持的 png/jpg 再上传。
Q:报 412 Precondition Failed?
这是历史版本的已知问题(微信校验 Content-Length,而 Spring 6.1+ 默认分块传输)。当前版本已通过手动构造 multipart 报文并显式设置 Content-Length 修复。
Q:正文里的图片同步后不显示?
微信会过滤文章正文中的外部图片链接。插件已通过 media/uploadimg 将正文图片转存到微信域名;若个别图片转存失败会保留原地址,请确认这些图片可被 Halo 服务器正常访问。
Q:文章里的附件(pdf、zip 等下载链接)同步后怎么变成一串地址了?
这是有意为之:微信图文里的外链不可点击,非图片文件也无法转存到微信素材库(uploadimg 只收图片,硬传只会换来 40005 / 40113 报错)。插件在提交草稿前会对正文里的附件链接逐个判定——按真实字节能识别为微信支持的图片(jpg/png/gif/bmp,webp 自动转码)就转存为微信图片显示;其余(pdf / zip 等非图片、字节与图片不符、下载失败)不调用微信接口,把链接改为纯文本。纯文本显示原始地址(默认)还是链接自身的文字,可在插件设置 正文美化 → 附件链接显示 中切换。判断为「附件」的依据是站点附件库路径(/upload/...)、URL 末段带文件扩展名或链接带 download 属性;站内文章路由、无文件扩展名的网页链接不受影响,原样保留。
Q:预览里的效果和草稿最终效果一致吗?
预览展示的正文美化结果,以及标题、作者、原文链接、留言设置,均来自与同步流程完全相同的解析规则(标题按微信 64 字上限截断后展示;作者优先插件设置的「默认作者」、留空回退文章作者,两者都截断到 8 字;摘要截断到 120 字;原文链接由站点「外部访问地址」与文章路由拼接;留言设置取插件配置);标题、作者、摘要中任一字段被截断时,预览都会在该字段旁显示「已截断」标识(悬停可看上限与说明),并在草稿元信息下方给出长度检查结论(无截断时显示「均在上限内」,避免误判),版式按手机端图文观感模拟;预览的正文区域采用样式隔离渲染(Shadow DOM),不受 Console 页面自身样式影响、也不会把正文样式带到页面,正文只按自身的行内样式呈现;分栏卡片/画廊在「表格」版式下重建出的布局表格会以浅灰细边框标注(仅预览标记、不会提交到草稿),相邻卡片/画廊之间留出间距,每个分栏卡片/画廊各对应一个独立表格,便于核对并排结构是否生效;分栏或画廊选择「独占一行」版式时该项不会生成布局表格,会按每栏、每图各占一行展示。正文图片与图片型附件在提交后才会真正转存(预览中仍显示原图地址与原链接,其中相对地址已按站点「外部访问地址」补全为完整链接,便于 MCP 等脱离站点的客户端直接加载图片;草稿侧不受影响);确定提交不到微信的附件链接(pdf、zip 等非图片)在预览中就已按「附件链接显示」配置呈现为纯文本,与草稿一致;字体渲染等细节以公众号后台的「发布预览」为准。
Q:同步一直失败,想先在公众号里手动发布怎么办? 用预览弹窗的 复制正文:在文章列表点「同步到微信公众号」进入预览(预览不调用微信接口,与同步是否成功无关),点底部「复制正文」把美化后的正文按富文本复制到剪贴板,再到公众号编辑器正文区直接粘贴——行内样式会一起带过去,标题、引用、代码块、表格、折叠卡片等排版与预览一致。
注意事项:
- 图片需要自行上传处理:复制的内容里,正文图片仍是原图地址(转存到微信素材库发生在提交同步时),公众号编辑器对粘贴进来的外部图片链接通常不会自动转存、甚至会被过滤,粘贴后请逐张确认——缺失的图片需在微信里手动上传替换;
- 封面图不在复制内容里:封面是草稿的元信息而非正文,需在公众号编辑器里单独上传(微信图文强制要求封面);
- 若图片是内网地址、需登录才能访问或已失效,粘贴后同样无法显示,请先确保图片可公网访问,再重试或手动上传;
- 复制的是美化后的正文,不含标题、作者、摘要、原文链接与留言设置——这些可按预览中列出的值在公众号里手填;
- 预览中给分栏卡片/画廊加上的浅灰细边框、代码块行号样式等只是预览标记,不会随复制内容带入(粘贴后的效果以公众号后台为准);
- 想让图片自动转存到微信素材库,仍需同步成功(图片转存发生在同步流程中),复制粘贴只是兜底方案。
Q:状态列一直显示「同步中」? 同步在服务端后台执行,正文图片较多、带宽较低时上传耗时较久属正常情况:列表会自动轮询刷新,任务出结果(成功/失败)后自动更新。若插件在同步过程中重启,未完成的任务会在插件下次启动时自动恢复执行(状态继续显示「同步中」,悬停可看到「正在自动恢复」);任务多次中断仍未能完成时会被标记为失败,手动重新同步即可;长时间仍显示「同步中」时可查看服务端日志确认任务是否异常。
Q:可以同时同步多篇文章吗?
可以。各篇文章的同步任务相互独立、并发执行(同一篇文章在「同步中」时重复提交会被拒绝,返回 409,请等待完成后再试)。注意:并发任务共享服务器出口带宽,且正文图片逐张串行上传,同时同步过多可能相互拖慢,建议视带宽情况控制并发数量。
Q:同一篇文章同步了两次,公众号草稿箱里为什么还是只有一份草稿?
这是有意的:同一篇文章首次同步会新建草稿,之后每次同步都会先校验上次写入的那份草稿是否还在——在则更新它(草稿 media_id 不变、草稿箱里不会多出一份),不在(比如你在公众号后台把它删了)则新建。该行为由插件设置 微信公众号 → 重复同步更新草稿 控制(默认开启);关闭后不做任何校验,每次同步都新建一份草稿,两次结果就都在草稿箱里。若保持开启、但想让两次同步各留一份,可在公众号后台先把草稿另存/复制一份,或直接以公众号后台的版本为准。另外,若日志里出现「校验草稿是否存在…按『不存在』处理,改为新建草稿」,说明校验没拿到结论(多半是「接口地址」代理未放行 /cgi-bin/draft/get),此时会退化为每次新建草稿,按接口地址与反向代理补上该路径即可。
Q:为什么任务记录里留着草稿 media_id?
它记录的是「这篇文章当前对应哪份草稿」,重复同步时据此决定更新还是新建,因此成功同步后一直保留(同步失败也不会被清掉——上次那份草稿多半还在,下次重试应当更新它)。它只是资源标识,不是凭据。
Q:同步后草稿的排版和网站上不一样?
这是微信的限制而非缺陷:微信图文会剥离外部 CSS、<style> 与 class/id 属性,只保留元素上的行内 style。Halo 正文靠主题 class + 外部 CSS 排版,直接塞进草稿会丢样式。插件已在提交前按标签注入微信友好的内联样式做美化;如需完全自定义排版,可在正文编辑器里对元素设置行内样式(其优先级高于插件默认样式)。引用块边框(可开关)与背景色、标题边框、H1–H6 标题颜色与 H1 对齐方式、行内代码配色、折叠块配色均可在设置的 正文美化 标签中调整。
Q:文章里粘贴的 <style>/<script> 会出现在预览或草稿里吗?
不会。从其他平台粘贴或导入的文章,原始 <style>/<script> 常被编辑器转义为纯文本残留在正文里,微信无法渲染、只会显示为源码文本。预览与提交共用同一套正文美化:这类残留块(连同其中的 CSS/JS 内容)在生成预览与提交草稿前都会被整体移除;代码块中的示例代码不受影响。
Q:文章里使用了其他插件生成的内容,能同步到微信吗? 不能。此类内容依赖插件自身的样式与脚本渲染,而微信图文只保留标准 HTML 与行内样式,无法在微信中渲染与显示(兼容与测试均以 Halo 默认编辑器输出的内容为准)。需要同步的正文请使用默认编辑器的标准排版元素(标题、段落、图片、代码块、表格、分栏卡片、画廊、折叠内容等)编写。
Q:日志里出现 Start to initialize indices for type…、Total indexed count、Indexing from @start,是插件出问题了吗?
不是。这是 Halo 核心的扩展索引初始化日志(由 run.halo.app.extension.indexer.DefaultIndicesInitializer 打印,不是本插件输出的),正常且无需处理。
Halo 会为每种自定义模型建立内存索引(metadata.name、创建/删除时间与标签),用于加速 list、字段选择器与排序查询。插件在启动时注册了 WechatSyncTask 模型,Halo 便在注册 Scheme 的那一刻同步扫描库里已存在的该类型记录、灌入索引,然后打印累计条数与耗时。逐行含义:
Start to initialize indices for type: …WechatSyncTask, prefix: /registry/api.wechat-sync.halo.run/wechatsynctasks:开始为哪个模型建索引、扫描哪段存储(前缀由模型的@GVK推导);Total indexed count: 9:本次扫描并送入索引的任务记录数。任务是一篇文章一条(任务名规则wechat-sync-<文章 name>),所以这个数字约等于曾经提交过同步的文章数(成功与失败记录都会保留);StopWatch 'Initialize indices for …WechatSyncTask'与下方的耗时表:Indexing from @start是第一批(从头扫,每批 100 条),Indexing from /registry/…/wechat-sync-e0248eaf-…是从上一批最后一条记录之后继续——那串就是本插件的任务名,文章name是 Halo 生成的随机串,看起来像 UUID(任务记录里的spec.postTitle保存了提交时的文章标题,可据此对应回文章);由于循环要再取一次空批才能确认结束,100 条以内固定会看到 2 行批次。
每次插件启动或热重载(重新注册模型)都会看到这组日志,耗时与任务记录条数相关,通常只有几毫秒。若它随时间明显变长,可从「任务记录条数」入手排查——文章被永久删除时对应任务会被自动清理、任务落到终态后也会清空正文快照,因此不会无限增长。