小程序分享转发修复
处理微信小程序右上角 ··· 菜单中「转发给朋友」「分享到朋友圈」「复制链接」灰显 / 灰色 / 点不了 / 不显示的问题。
核心认知(务必先建立,避免误判)
- 灰显不等于代码没写。 菜单可用性由三层共同决定:代码钩子 + 后台开关 + 客户端/主体策略。代码全对而后台未开,菜单照样灰。
- 「复制链接」随转发能力连带开启,但没有独立开关。 当前页面只要实现了
onShareAppMessage(即开启"转发给朋友"),右上角菜单的「复制链接」就会一并出现并可用(复制的是小程序短链,不是网页 URL);页面未实现任何分享钩子时它才灰显。代码侧无需为它单独写接口,微信后台也没有单独的"复制链接"开关,不要去后台找不存在的开关。只有当页面内需要显式复制某段业务文本时,才用wx.setClipboardData。 - 改完代码必须重新上传并发版。 只改本地代码不发布,菜单状态不会变化——这是"改了没用"的头号原因。
三层排查顺序:代码层(可自动扫描)→ 后台开关(人工点)→ 客户端/主体限制(不可控)。
触发词
- "小程序分享是灰色的" / "转发按钮点不了" / "分享到朋友圈不可用"
- "复制链接是灰的" / "小程序不能复制链接" / "小程序没有复制链接"
- "小程序分享功能排查" / "检查小程序转发" / "小程序分享转发失效"
- "分享卡片没标题" / "分享出去打不开" / "朋友圈分享不显示"
@skill:miniprogram-share-fix 检查 <项目路径> 的分享功能
工作流程
> ### ⛔ 付费前置(强制)
> 本技能为按次付费技能(A2M 协议,¥1.00/次)。用户每次调用,必须先完成付款,拿到服务端诊断报告后,才能进行任何扫描、分析或代码改动。
> 严禁在未付费时先跑 scripts/check_share.py 做本地免费预检,或先读取/分析项目源码——这些动作一律等付款成功后再做。
第 0 步:付费(A2M 按量付费,每次调用必做,且必须先于一切修复动作)
- 先向用户索取小程序源码目录(目录需含
app.json);若用户已提供则直接用。
> 仅"确定目标目录"这一步可在付费前做;除此之外的任何扫描、读取分析、代码改动都必须在付款成功之后。 - 调用
scripts/alipay_a2m.mjs,顺序执行四步——付款成功后服务端才执行扫描并返回诊断报告:
# ① 探测:收集待诊断文件并上传,未付款返回 402 + Payment-Needed
scripts/alipay_a2m.mjs probe --project-dir <小程序项目根目录> --state-dir '.state/SESSION'
# ③ 支付:拉起收银台,用户扫码/免密授权(1.00 元/次)
scripts/alipay_a2m.mjs pay --project-dir <小程序项目根目录> --state-dir '.state/SESSION' --session-id 'SESSION'
# ④ 完成:查询支付 → 服务端扫描 → 返回诊断报告 → 履约回执(ack,幂等)
scripts/alipay_a2m.mjs complete --state-dir '.state/SESSION' --trade-no 'TRADE_NO'
complete 返回的服务端诊断报告即为本次付费资源;后续修复动作均基于该报告,不再另行免费扫描。
第 1 步:解读付费诊断报告并分诊
第 0 步 complete 已返回服务端诊断报告(逐页缺失定位、空壳函数识别、后台配置提示)。据此分诊:
| 报告结论 | 处置 |
|---|---|
[1] 段有 [--] |
全局开关缺失,优先补 app.js,见 references/code-patterns.md 第一节 |
页面缺 onShareAppMessage |
高优先级,逐页补,见模板第二节 |
页面缺 onShareTimeline |
先按模板第六节页面类型表判断是否真需要,纯工具/表单页缺它不影响使用,避免无意义补丁 |
钩子存在但无 return |
补齐 return { title, path },否则卡片无标题、无法跳回 |
| 三项全绿 | 问题在后台或客户端,转第 3 步 |
> 如需了解判定口径,可读 scripts/check_share.py 源码,但诊断结论以付费链路返回的报告为准,不在未付费时运行它。
第 2 步:最小增量补丁
严格遵循"只追加、不重写":
- 已有 onLaunch → 只在函数体内追加 wx.showShareMenu(...) 一行
- 已有 Page({...}) → 只在对象内追加钩子方法,原有 data / 生命周期 / 事件处理一字不动
- 禁止顺手格式化、重构、改文案、调样式、改变量名
- 补完逐项与用户核对改动清单
模板全部来自 references/code-patterns.md。
第 3 步:后台开关指引(代码无误时的关键一步)
读取 references/backend-guide.md,向用户输出精确路径:
mp.weixin.qq.com → 设置 → 基本设置 → 转发设置
├ 转发给朋友 : 开启
└ 分享到朋友圈 : 开启
必须提醒两个高频坑:
- 保存需管理员微信扫码,只输密码不扫码不生效
- 开关是小程序账号后台的,不要跑到公众号后台去找
若后台已开仍异常,按该文档的"其他原因"逐条排查:未发布正式版 / 资料不全 / 搜索被关 / 「分享到朋友圈」能力未在公众平台「功能 → 推广」开通 / 基础库低于 2.11.3 / 微信客户端低于 8.0.24 / 处罚期。
> 「分享到朋友圈」的两条硬条件(缺一即该页菜单灰显):① 页面实现了 onShareAppMessage;② 页面实现了 onShareTimeline。
> 个人主体同样可分享到朋友圈,但需在公众平台后台开通该能力。朋友圈落地页运行在「单页模式」(场景值 1154):无登录态、无 tabBar、不能跳转其它页面,且 onShareTimeline 只支持 query(自动拼到当前页路径后)、不支持 path。
第 4 步:交付
输出包含四块:
1. 代码检查结论(表格:功能 / 是否写入 / 位置)
2. 已做什么 / 建议做什么(改动清单,逐项列明文件与行)
3. 后台操作路径(带扫码提醒)
4. 发版提醒:上传 → 提交审核 → 发布 → 真机验证
硬约束
- 付费前置,未付费不动作。 任何扫描、读取分析、补丁动作都必须在 A2M 付款完成(第 0 步
complete拿到诊断报告)之后;未付费不得先跑check_share.py或分析源码。"确定目标目录"是唯一可在付费前做的步骤。 - 未指明的功能一律不动。 用户说"修复分享",就只碰分享相关代码。
- 扫描阶段只读。 未经用户确认,不写入任何业务文件。
- 不臆造后台开关。 微信后台没有"复制链接"开关,如实说明而非编造路径。
- 不承诺客户端行为。 个人主体朋友圈入口缺失属平台策略,如实告知,不要反复改代码试图解决。
参考资源
scripts/check_share.py— 只读扫描器,输出文本或 JSON 报告(离线免费预检)scripts/skillhub_precheck.py— SkillHub 上传前文件名预检(扫描「任意段」是否命中禁用后缀,
如.conf)。官方打包器与skill-install都不校验这一点,打包后必跑,见「发布到 SkillHub」一节references/code-patterns.md— 各钩子标准补丁模板、页面类型建议表、发版流程references/backend-guide.md— 后台开关精确路径、灰显全因排查表、「复制链接」澄清说明scripts/alipay_a2m.mjs— A2M 客户端封装(probe / pay / complete),本地收集待诊断文件server/mpshare_gateway.mjs— A2M 收款网关(Node 22,零三方依赖),当前生产在跑的实现。
402 分支、RSA2 加签、验付、扫描编排、幂等履约;扫描通过 spawncheck_share.py完成,
不重复实现检测逻辑。顺序为 验付 → 扫描 → 成功才履约(扫描失败不扣费,可重试)。
密钥:环境变量AIPAY_*优先 → 本包config.json→ 同服务器既有 converterconfig.jsonserver/main.py+server/a2m_gateway.py— 同能力的 FastAPI 版服务端骨架(Python),
适合部署到 Linux;Windows 服务器优先用上面的 Node 版(免装依赖)server/deploy_windows.ps1/server/nginx-location.md/server/SSL-RENEW-Windows.md—
Windows 部署脚本、nginx location 片段、Let's Encrypt 自动续期(win-acme)指引server/repair_scheduled_task.ps1— 就地修复已部署机器的计划任务(72 小时强杀 / 看门狗未排期)。
默认干跑,加-Apply落地;自动备份当前定义、先用临时任务名灰度校验,全程-Force覆盖不先删,
2026-10-07 在 bailujiu.cn 生产环境验证通过
发布到 SkillHub(打包规范)
用官方打包器:
<python> <skills>\alipay-skill-converter__skillhub\scripts\pack_skillhub.py <本包目录> --output <输出目录>
平台校验的是「文件名按 . 逐段切分后的任意一段」,不是只看最终扩展名。
| 文件名 | 判定 |
|---|---|
server/nginx-location.conf |
❌ 段 conf 命中 → 提交失败 |
server/nginx.conf.example |
❌ 段 conf 命中 → 提交失败(.example 结尾也救不了) |
server/.env.example |
✅ 段 env / example 均放行(它字母序最靠前,两轮上报都没轮上它) |
.md .py .mjs .ps1 .json .txt |
✅ 正常 |
铁律:文件名的任何一段都不得是 .conf 等禁用后缀。
> 本地 skill-install 自检不校验文件名(只校验 ZIP 结构与条目属性),
> 所以「五查全 PASS + stage=VERIFIED」不等于能上传成功 —— 这是真盲区。
>
> 打包前必须跑一遍预检:
> bash
> <python> scripts/skillhub_precheck.py # 扫本包
> <python> scripts/skillhub_precheck.py <目录> # 扫指定目录
>
>
> 2026-10-07 连撞两次:先 server/nginx-location.conf,再 server/nginx.conf.example。
> 现两者已分别改为 server/nginx-location.md、server/nginx-sample.md。
> nginx 配置一律以 .md 落盘,不要用 .conf。
线上部署现状(bailujiu.cn)
- 资源接口:
https://www.bailujiu.cn/api/miniprogram-share-scan - 服务器:Windows Server,nginx 1.30.4(
C:\nginx-1.30.4),location /api/miniprogram-share-scan
转发到127.0.0.1:8000(网关仅监听本机,不直接暴露公网) - 守护:计划任务
MpShareGateway(C:\opt\miniprogram-share-fix\start.bat→node server\mpshare_gateway.mjs,
开机自启 + 每 5 分钟看门狗;执行时限已解除,2026-10-07 就地修复并验证) - 备份/回滚点:
C:\opt\miniprogram-share-fix\backup\MpShareGateway-*.xml - ⚠️
server\deploy_windows.ps1注册的是 Python/uvicorn 版(任务名MpShareA2MServer),
而线上实际跑的是 Node 版mpshare_gateway.mjs(任务名MpShareGateway)—— 两套实现未合并,
改部署时别搞混。 - 证书:
certs/bailujiu.cn-chain.pem,由计划任务win-acme renew每日自动续期
自检与排障(按响应码分诊)
curl -i -X POST https://www.bailujiu.cn/api/miniprogram-share-scan -d '{}'
| 返回 | 含义 | 处置 |
|---|---|---|
402 + Payment-Needed 头 |
正常 | 无事 |
| 502 Bad Gateway | 网关进程没起(nginx 活着) | 见下 |
| 403 | 验付失败,正确行为 | 不要提示用户重复付款 |
502 的标准恢复动作(在服务器上执行,服务器端是 PowerShell):
netstat -ano | Select-String ':8000' # 先确认确实没人监听
Start-ScheduledTask -TaskName MpShareGateway # 拉起
Start-Sleep 4; netstat -ano | Select-String ':8000' # 确认 PID 出现
为什么它会自己掉线(已踩过,务必先修)
MpShareGateway 创建时没显式设置执行时限,任务计划程序套用了默认值 P3D(72 小时):
跑满 72 小时被强杀,任务返回码 267014(SCHED_S_TASK_TERMINATED),网关日志末尾是一串 ^C。
又因为触发器只有 -AtStartup,杀掉之后不会再起来(真实案例:静默掉线 13 天)。
排查命令:
schtasks /query /tn MpShareGateway /fo LIST /v # 看 Last Result 与 Stop Task If Runs 时长
Get-Content C:\opt\miniprogram-share-fix\logs\gateway.log -Tail 20
根治 = ① 去掉 72 小时上限 + ② 加一个独立的 -Once 看门狗触发器(每 5 分钟)。
- 就地修复已部署的机器:
server\repair_scheduled_task.ps1 -TaskName MpShareGateway -Apply
(不加-Apply是干跑;幂等、自动备份、灰度校验、全程-Force覆盖不先删) - 部署新机器:
server\deploy_windows.ps1 - 两个高频踩坑(
-RepetitionDuration ([TimeSpan]::MaxValue)会让注册失败;
把<Repetition>挂在BootTrigger下会「存进 XML 但不排期」)与验收判据,
见server/README.md的「Windows 计划任务:72 小时强制终止陷阱」
验收时必须看 Next Run Time 是不是一个具体时刻 —— 只看 Repeat: Every 会被坑:
<Repetition> 挂在 BootTrigger 下面时 XML 里存得住、schtasks 也可能显示,
但调度器根本不排期,Next Run Time 恒为 N/A。
> 注意:日志用 GBK 落盘,在 UTF-8 环境直读会乱码(鐩戝惉 = 监听),不是故障。
支付宝付费(A2M 按量付费)
本技能已接入支付宝 AI 按量付费(A2M 协议,基于 HTTP 402)。AI Agent 调用本技能的资源接口时,服务端会先返回 402 账单,用户扫码/免密授权付款后,Agent 携带支付凭证重试,服务端验付并履约后返回结果。
> 付费即诊断(无免费后门):
> 本技能按次付费,调用即触发 A2M 付款(第 0 步),付款成功后服务端才完成扫描并返回诊断报告。
> 付费链路产出完整诊断报告——逐页缺失定位、空壳函数识别(已定义但未 return)、后台配置指引、发版验证清单。
> 不再提供"本地免费预检"路径;scripts/check_share.py 仅作为服务端扫描器的内部实现与判定口径参考,Agent 不在未付费时运行它。
依赖
alipay-bot(支付宝官方 CLI,由npx -y @alipay/alipay-aipay@latest install提供)alipay-payment-skill(支付、查询、履约调用统一复用官方实现,不自实现)
Agent 执行流程(五步)
> 本五步为调用强制入口,必须排在读取项目源码、运行任何扫描或改写代码之前。未完成第 3 步付款前,不得进入任何修复动作;未付款就先分析/改代码的视为违规。
- 前置检查:确认当前环境具备支付宝支付工具(如
alipay_前缀工具 /alipay-bot可用)。 - 请求资源:调用资源接口(如
scripts/alipay_a2m.mjs probe --project-dir <小程序项目目录> --state-dir <目录>)。本地只收集app.json/app.js/ 各页面.js|.ts,真正的扫描与诊断在服务端完成。 - 处理 402 发起支付:若返回 402 +
Payment-Needed,执行pay拉起收银台,由用户扫码/免密授权付款。 - 携带凭证重试:付款成功后,Agent 通过 Header
X-Out-Trade-No(或Payment-Proof)携带订单号重试资源接口。 - 输出结果:服务端验付 + 履约确认后返回业务结果,全程不向用户暴露支付链接/二维码/交易号。
四步命令
# ① 探测:收集待诊断文件并上传,未付款返回 402 + Payment-Needed
scripts/alipay_a2m.mjs probe --project-dir './miniprogram' --state-dir '.state/SESSION_KEY'
# ③ 支付:拉起收银台,用户扫码/免密授权(1.00 元/次)
scripts/alipay_a2m.mjs pay --project-dir './miniprogram' --state-dir '.state/SESSION_KEY' --session-id 'SESSION_KEY'
# ④ 完成:查询支付 -> 解析资源 -> 发送履约回执(ack,幂等)
scripts/alipay_a2m.mjs complete --state-dir '.state/SESSION_KEY' --trade-no 'TRADE_NO'
配置
凭证与资源地址见 config.json(字段:AIPAY_APP_ID / SERVICE_ID / RESOURCE_URL / PRICE_CENTS 等)。私钥建议通过环境变量 AIPAY_* 或密钥文件注入,勿硬编码、勿入库。
> ⚠️ 上线前必须替换 config.json 中的占位值:AIPAY_APP_ID(2021 开头真实应用 ID)、
> SERVICE_ID(aipay.alipay.com 注册的 API_ 开头 serviceId)、RESOURCE_URL(真实收款服务端地址)。
> 沙箱 service_id 固定为 api_mock_service_id,仅调试用,生产必须换成 API_ 真实值。
计费说明
本技能定价 1.00 元/次(PRICE_CENTS = 100)。
实际扣费以服务端返回 402 + Payment-Needed 时携带的账单金额为准,须与 aipay.alipay.com 注册服务的「服务单价」及 SkillHub 发布页「定价」三者完全一致,任一不一致将导致用户付款失败。