关于 freemius-troubleshooting
这是一项面向 Freemius 集成开发者的诊断技能,围绕结账、Webhook、SDK 和配置中的常见故障组织内容。它将症状对应到可能原因和专项参考指南,并链接至相关 Freemius 技能。
主要功能
- 01症状到修复方案索引
- 02Webhook 与重定向诊断
- 03SDK 类型和事件指引
- 04结账与客户门户检查
- 05关联技能交叉引用
适用场景
- 01排查结账后未获得访问权限
- 02调查 Webhook 签名验证失败
- 03解决 SDK 类型或事件错误
- 04检查门户、升级或权益问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ freemius/ freemius-ai --skill freemius-troubleshooting安装后在 Claude Code 中输入/freemius-troubleshooting确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/checkout-and-portal.mdsdk-types-and-events.mdstack-and-porting.mdwebhooks-and-redirect.md详细介绍
Freemius 故障排查
Freemius 集成出现故障时,问题几乎总是出在以下五个环节之一:Webhook/重定向配置、SDK 类型/事件、技术栈/移植层、结账/门户接线,或 密钥/控制面板配置。此 Skill 是一份诊断索引——找到对应症状,跳转到参考资料并应用修复方案。
源 FAQ: https://freemius.com/help/documentation/ai/lovable/#troubleshooting
如何使用此 Skill
- 在下表中找到对应的症状。
- 打开链接的参考资料,了解根本原因和修复方案。
- 如果问题涉及
freemius-core/freemius-checkout/freemius-customer-portal,参考资料会指引你回到这些 Skill 中的具体章节。
症状 → 修复方案索引
| 症状 | 可能原因 | 参考 |
|---|---|---|
| 结账已完成,但用户始终无法获得访问权限 | 未配置重定向 URL 或 webhook / 配置的 URL 不是公开的 | references/webhooks-and-redirect.md |
| Webhook 签名验证失败 | 将原始请求正文解析后才传给监听器 | references/webhooks-and-redirect.md |
TS 错误:Entitlement type 上出现 Type '"lifetime"' is not assignable | Entitlement 的 type 是 subscription | oneoff,而不是 lifetime | references/sdk-types-and-events.md |
订阅 license.quota.changed 没有作用 / 出现类型错误 | @freemius/[email protected] 中不存在该事件 | references/sdk-types-and-events.md |
Webhook 处理程序中 license 出现 TS 错误:Object is possibly 'false' | 数组订阅中的 license 是一个联合类型,其中包含已删除的类型形态 | references/sdk-types-and-events.md |
prisma generate / 客户端因需要驱动适配器而失败;url 被拒绝 | Prisma 7 移除了经典的 datasource url,请固定使用 Prisma 6 | references/stack-and-porting.md |
浏览器中的 process.env.NEXT_PUBLIC_* 是 undefined | Vite 使用 import.meta.env.VITE_*,而不是 process.env | references/stack-and-porting.md |
无法解析 @/... 或 @shared/... 导入 | vite.config.ts 和 tsconfig paths 中缺少别名 | references/stack-and-porting.md |
通过 npx skills add 安装了 skills,但 Claude Code(CLI)看不到它们 / 缺少斜杠命令 | Claude Code 不是默认安装目标;skills 被安装到了 ~/.agents/skills/,但没有创建 ~/.claude/skills/ 符号链接 | references/stack-and-porting.md |
在 Claude Desktop(Claude.ai 应用)中尝试使用 npx skills add … -a claude-code CLI 方式,但不适用 | CLI / -a claude-code 标记仅适用于 Claude Code;Desktop 需通过 Customize → Skills → "+" → Upload a skill,以每个 Skill 一个 .zip 的方式安装(先安装 core;在 Settings → Capabilities 中启用 Code execution) | references/stack-and-porting.md |
| 密钥 / API token 泄露到浏览器,或 Freemius 返回 401 | 在客户端而不是服务器端调用了 Freemius | references/checkout-and-portal.md |
| 结账浮层打开后为空 / 未配置 | 浮层未使用服务器创建的 CheckoutSerialized 进行初始化 | references/checkout-and-portal.md |
| 升级路由返回 500:「不允许为终身许可证更新付款方式」 | checkout.create({ licenseId }) 会调用一个拒绝续订许可证(expiration: null)的付款方式更新端点——请使用 setLicenseUpgradeByKey | references/checkout-and-portal.md |
| 用户“已升级”,但现在有两个订阅 / 被重复收费 | 向已有订阅的用户提供了普通订阅结账——请使用许可证升级结账(setLicenseUpgradeByKey)和支持 entitlement 的界面 | references/checkout-and-portal.md |
| Portal 操作返回 404 / token 无效 | 一个 /api/portal 端点必须同时提供数据和签名操作 | references/checkout-and-portal.md |
| 一次性 / 终身购买的行为与订阅演示不同 | 购买方式不同——请使用 billing_cycle: 'lifetime',类型为 oneoff | references/checkout-and-portal.md |
| 已升级到 Lifetime,但仍受限 / 仍扣除额度 / 未显示为有效(发票正确) | freemius.entitlement.getActive() 会筛选 type: 'subscription'——一次性 Lifetime 行不可见,因此 getUserEntitlement() 返回 null | references/sdk-types-and-events.md |
使用优惠券的订阅显示约 100 年后才“续订”(USD 0 · renews 2126) | 100% 折扣的优惠券范围设为“首次付款及续订” | references/checkout-and-portal.md |
| 取消后无法重新订阅(提示“已有有效订阅”) | 管理员取消了许可证,但订阅仍处于有效状态,成为孤立记录 | references/checkout-and-portal.md |
已订阅的用户仍看到付费墙 / 返回 402,尽管订阅有效;user_fs_entitlement 表为空 | 结账使用了裸托管重定向,没有浮层 purchaseCompleted 同步,也没有配置 Dashboard 结账重定向 URL——因此从未写入 entitlement 行 | references/checkout-and-portal.md |
所有用户的 user_fs_entitlement 都为空;同步 POST 返回 400 "License ID is required in the request body"(前端 .catch() 隐藏了错误) | 浮层 purchaseCompleted POST 被路由到了 checkout.request.createProcessor / processRedirect(或 syncEndpoint 指向 /api/checkout/redirect?action=process_purchase)。该路径需要浮层负载中没有的签名重定向 / 正文中的 license_id。浮层同步必须是普通的 POST /api/purchase,从负载中读取许可证 → syncEntitlementByLicenseId——与托管的 GET /api/checkout/redirect 使用不同的端点 | freemius-checkout → references/checkout-provider.md |
| 受限功能(例如 Premium 上的图像 OCR)显示通用错误 "OCR failed. Please try another file." | 服务器的层级 / entitlement 限制(带有 tier_upgrade_required / image_requires_pro 等原因的 403 / 402)被吞并到兜底错误中。限制并非失败——应根据状态码和原因进行分支处理,并打开提供升级路径的付费墙,而不是显示错误 toast | freemius-checkout → references/paywall.md |
| 购买成功,但没有定价页面 / 用户必须先触发付费墙才能浏览或购买方案 | 构建时交付了付费墙,却漏掉了独立的定价路由——专用的 /pricing 页面(包含来自 GET /api/checkout/pricing 的 Subscribe + Topup 表格)和导航链接是必需交付项 | freemius-checkout → references/pricing-tables.md |
| 购买订阅后,成功 toast 显示 "credits added to your account"(或 Lifetime 的文案错误) | 购买后文案未根据同步后的购买类型进行分支处理——请使用重新获取的 entitlement 层级:lifetime → "Lifetime access unlocked",subscription → "<tier> unlocked",额度包 → "page credits added" | freemius-checkout → references/checkout-provider.md |
| OCR(按量计费)运行后额度余额仍显示旧值,直到手动刷新页面 | 服务器正确扣除了额度(credit -= pages),但按量操作的成功处理程序从未刷新显示的余额——徽标会一直显示旧值,直到完整重新加载。无需重新加载即可刷新显示:可以从操作响应中读取新余额,或者 await 购买流程使用的同一个 refreshEntitlement()(GET /api/entitlement → credit)。这与购买后刷新 entitlement 相对应,是消费流程中的同类刷新 | freemius-checkout → references/paywall.md |
Lifetime / 最高层级用户打开 /pricing 时页面空白(“什么都不显示了”) | 所有购买入口都被正确隐藏了(用户已拥有最高层级),但全部隐藏后就留下了空白页面。应显示友好的“您已拥有全部内容”空状态——绝不能显示空白页面。(仅有额度的用户仍必须看到 Subscribe + Topup。) | freemius-checkout → references/pricing-tables.md |
| 账户页面中的 "Change plan" 显示为没有内边距的单独下划线链接,与 Cancel 错位 | "Change plan" 是一个使用按钮类(例如 btn-outline)的路由 <Link>,但该类仅从基础 .btn 类继承内边距 / 圆角 / text-decoration:none——单独应用于 <a> 时,这些样式都会丢失。请让按钮 / outline 类包含所需的全部样式,或者在 <Link> 上同时添加基础类和修饰类 | freemius-customer-portal → references/subscription-and-upgrade.md |
| 留存优惠券:点击 "Apply discount & keep my plan" 后向导关闭,没有任何操作,Dashboard 显示 0 次兑换 | 应用 POST 发送了一个空的 {} 正文——SDK 的续订优惠券操作需要 { couponId: <coupons[0].coupon_id> },否则会返回 400;并且向导没有检查 res.ok,因此失败的请求也会像成功一样关闭。请发送真实的 couponId 并检查 res.ok(失败时显示错误并保持窗口打开) | freemius-customer-portal → references/cancellation-and-coupon.md |
托管结账 / 升级后,浏览器跳转到 /checkout-result?success=true,显示只有页头的空白页面 | 服务器 GET 重定向处理程序跳转到了 /checkout-result,但 SPA 路由器(App.tsx 的 <Routes>)没有匹配的客户端路由——重定向目标是一个实际页面,但构建时漏掉了它。请添加 /checkout-result 路由,在挂载时读取 success、刷新一次 entitlement、显示确认信息,并导航回应用 | freemius-core → references/purchase-processing.md |
| 取消 / 续订后 entitlement 没有更新;webhook 看似失效——但处理程序、URL 和签名检查均正常 | 生命周期事件触发时,Dashboard 中的 webhook URL 尚未启用 / 尚未生效——事件从未送达(也不会补发) | references/webhooks-and-redirect.md |
优先检查项(Lovable 常见问题解答基准)
官方常见问题解答的首要建议,适用于此技术栈:
- 让 Agent 重新运行失败的步骤。 这些 Skills 是模块化的——重新调用特定参考文档(例如
freemius-core→purchase-processing.md),而不是重新执行整个集成。 - Webhook 和结账重定向是两条关键路径。 先端到端验证这两项;大多数“付款后无法访问”的报告都与其中一项配置错误有关。Webhook 处理失败时,Freemius 会给你发送邮件——将邮件内容粘贴给 Agent,以便定位故障。
- 发布/部署后,更新所有 URL。 仍指向
localhost(或旧域名)的重定向 URL 或 Webhook URL 会导致流程在不报错的情况下失效。PUBLIC_APP_URL必须设置为正式域名。 - 一次性购买需要采用不同于订阅流程的方案——关于
lifetime模式,请参阅结账/门户参考文档。 - 仍然卡住? 联系 Freemius 支持([email protected]),并提供产品 ID、失败步骤和截图。
记录新条目
此 Skill 会不断完善。在验证关卡中发现 Skill 缺陷时,请将其记录在关卡的“发现的 Skill 缺陷”表格中,修复有问题的 Skill,然后在此处添加故障排查条目(症状 → 原因 → 修复方法),让后续集成人员避免重蹈覆辙。
评论
支持 Markdown