mcpField
T
tiun-sdk

tiun-sdk

github.com/tiun-app开发035 次安装6 天前更新
代码仓库

关于 tiun-sdk

tiun-sdk 是面向 Agent 的指导技能,用于集成或调试 tiun 的 JavaScript 与 React Native SDK。它涵盖订阅、一次性购买和按时计费访问,并分别说明平台用法及安全授权要求。

主要功能

  1. 01指导订阅和一次性购买配置
  2. 02说明按时计费访问流程
  3. 03区分 Web 与 React Native SDK
  4. 04介绍 MCP 的检测与安装
  5. 05指导后端令牌验证

适用场景

  1. 01在 Web 应用集成订阅结账
  2. 02为一次性购买后的内容设置访问限制
  3. 03为付费内容添加按时计费访问
  4. 04排查 SDK 配置或环境不匹配

MCP 相关

该技能要求 Agent 检测 tiun 的 MCP,并在缺少时提供安装选项;不可用或用户拒绝时可改为手动操作。连接并完成认证后,MCP 可列出服务提供方和产品,为集成选择提供依据。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tiun-app/skills --skill tiun-sdk

安装后在 Claude Code 中输入/tiun-sdk确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api-reference.md
discovery.md
events.md
frameworks.md
installation.md
mcp.md
one-time.md
overview.md
react-native.md
server-verification.md
subscriptions.md
time-based.md
troubleshooting.md

详细介绍

tiun SDK 技能

当用户集成、扩展或调试使用 @tiun/sdk 或 @tiun/react-native-sdk 的代码时,请使用此技能。权威上游文档:https://docs.tiun.io/llms-full.txt。

tiun 是什么

tiun 是一个商业后端平台,通过单个 JS SDK 提供身份验证、支付和权益。tiun 单例支持三种流程,具体选择取决于集成者的意图(参见“步骤 0 — 编写代码前先了解需求”):

  • 订阅 — 持久化用户账户(OTP 登录)、周期性账单,以及 user.productAccess[] 中按产品划分的权益。入口:tiun.checkout({ productId })。参见 references/subscriptions.md。
  • 一次性购买 — 与订阅使用相同的账户和入口,但采用单笔固定费用,权益永久有效:没有计费周期、试用期、续订或到期时间。入口:tiun.checkout({ productId })。参见 references/one-time.md。
  • 基于时间 — 按会话提供匿名访问(无需账户),根据用户在付费内容上花费的时间计量。入口:tiun.start() + paywallShow / paywallHide 事件。参见 references/time-based.md。

安装:npm install @tiun/sdk。初始化:应用启动时调用 tiun.init({ snippetId, language: 'en' })(幂等)。

tiun 的线上环境和沙盒环境是两个独立并行的环境。SDK 的 sandbox 标志用于选择环境,参见 references/installation.md。

React Native 使用独立的 SDK。 @tiun/react-native-sdk 使用 <TiunProvider> + useTiun() / useTiunEvent(),通过 host 选择环境(不使用 sandbox 标志),需要 returnUrl 深层链接,并且仅支持订阅和一次性购买。相关内容请参见 references/react-native.md。下方的 tiun.* 代码、最简可用示例和各框架接入方式仅适用于 Web,切勿在 React Native 应用中生成这些内容。

步骤 0 — 编写代码前先完成发现

优先确认平台。 提问前先检查项目:如果 package.json 中有 react-native 依赖(或存在 ios/ + android/ 文件夹),则为 React Native → 在进行此处发现的同时,遵循 references/react-native.md。否则即为 Web SDK。在 React Native 中,按时长计费不可用——如果用户提出此需求,请在 0b 中说明。

编写任何集成代码之前,先确认以下四项。只询问用户尚未说明的内容。如果用户的提示已完整明确(“在 sandbox 中接入产品 p-test-pro 的订阅,以限制 /watch/* 的访问”),则跳过发现步骤。

如果客户端支持结构化提问原语(例如 AskQuestion),请使用;否则直接在聊天中提问。

0a. 检测 MCP;如果缺失,则询问是否安装。 各客户端的安装说明和检测方法见 references/mcp.md。分为三种状态:

  • MCP 已存在且已完成身份验证 → 在 0c 中使用它列出提供商和产品。
  • MCP 已存在,但尚未完成身份验证 → 提示用户完成身份验证一次;如果用户拒绝,则改用手动模式。
  • MCP 不存在 → 询问是否安装(用一句话说明其价值:“直接获取你的 snippetId 和 productIds,避免复制粘贴出错。”)。如果用户拒绝,则改用手动模式。

0b. 确定集成模式。 是订阅、一次性购买、按时长计费,还是组合模式?各模式对应的用户表述线索见 references/discovery.md。不要根据账户中的产品库存推断模式。 某个提供商今天可能只有一种产品类型,但明天也许会计划增加其他类型。

0c. 收集标识符。 根据模式和 MCP 是否可用,问题有所不同:

  • 订阅,MCP 可用 → 列出提供商,让用户选择;列出产品,让用户选择一个或多个套餐;根据提供商的 sandbox/live 标签确认环境。
  • 订阅,MCP 不可用 → 询问 snippetId;询问用户要一个产品还是多个套餐;对每个产品,询问 productId 和标签;确认使用 sandbox 还是 live(p-test-... / p-live-... 前缀是重要线索)。
  • 一次性购买,MCP 可用 → 列出提供商,让用户选择;列出产品,让用户选择要解锁的一个或多个产品;根据提供商的 sandbox/live 标签确认环境。不要询问套餐——一次性产品没有分级套餐。
  • 一次性购买,MCP 不可用 → 询问 snippetId;对每个产品,询问 productId 和标签;确认使用 sandbox 还是 live(前缀是重要线索)。
  • 按时长计费,MCP 可用 → 列出提供商,让用户选择;根据提供商标签确认环境。
  • 按时长计费,MCP 不可用 → 询问 snippetId;确认使用 sandbox 还是 live。

MCP 可用时,提问应基于现有产品库存(“你有一个 sandbox 按时长计费产品 p-test-xxx——要接入这个产品,还是先设置订阅产品?”),而不是盲目提问。

0d. 确定要限制访问的内容。 缺少这一步,Agent 生成的就只是没有目标的样板代码。请询问:

  • 哪些路由、组件或功能需要限制访问?
  • 未登录用户应看到什么?应用的使用流程从何处开始?(商品展示页或定价页 / 先登录、遇到升级提示后再升级的账户优先型应用 / 全屏付费墙 / 预览内容 + 订阅)。保持与应用设计相符的流程。
  • 已通过身份验证但无访问权限的用户应看到什么?(通常沿用相同的体验,只需改用“升级”文案)
  • 是否提供免费预览?(如果有,这通常表明用户真正需要的是按时长计费,而不是订阅——请将此信息反馈到 0b。)
  • 如果有多个套餐:哪些路由或功能对应哪个套餐?

何时查看什么

任务查看
发现、范围界定、MCP 检测、模式选择references/discovery.md
各客户端的 MCP 安装、检测、身份验证references/mcp.md
tiun 是什么、支持的平台、产品模式、托管 UI 的边界references/overview.md
安装 / 初始化 / 配置 / 向各主机注入环境变量references/installation.md
方法或属性查询references/api-reference.md
事件名称和负载references/events.md
订阅门控(账户 + 定期计费)、选择结账还是登录references/subscriptions.md
一次性购买门控(固定费用、永久访问权限)references/one-time.md
基于时长的付费墙(按会话计费、匿名、按量计费)references/time-based.md
可信后端授权references/server-verification.md
框架接入(任意技术栈)+ 生命周期矩阵references/frameworks.md
“覆盖层未显示”、SSR 错误、沙箱不匹配、覆盖层注入失效references/troubleshooting.md
React Native:安装、返回深层链接、TiunProvider、钩子、host、设备测试references/react-native.md

关键规则

  1. tiun.init({ snippetId, language }) 在客户端早期启动阶段运行。 在 Next.js/Nuxt 中,将其封装在仅客户端组件/插件中。切勿在服务端调用。init 具有幂等性——再次调用会合并配置,而不是重新初始化,因此无需设置 isInitialized 检查。
  2. snippetId 不是机密。 它用于标识环境。使用 NEXT_PUBLIC_* / public 运行时配置。
  3. 对于基于结账的访问控制(订阅和一次性购买),应以 userChange 为准,而不是只读取一次 tiun.user。权益会在会话期间发生变化。在 Web SDK 中,载荷包含 event: 'init' | 'login' | 'checkout' | 'logout' | 'update',可用于判断是什么触发了变更。React Native 的载荷没有 event 字段——请改用单独的 login / logout 事件。
  4. 切勿信任客户端进行授权。 对于受保护的服务端资源:tiun.getUserVerificationToken() 会返回一个 JWT(有效期为 5 分钟),将其发送到后端,由后端通过带有 X-TIUN-API-KEY 的 POST /live_api/s2s/v1/users/verification 验证。对于基于时长的访问,请使用 paywallHide 中的 sessionId 调用 PATCH /live_api/s2s/v1/sessions/{sessionId}/status。参见 references/server-verification.md。
  5. 托管 UI 是黑盒——不要重新实现,也不要修改。 tiun 会在 shadow DOM 中渲染结账、登录和连接浮层。使用 tiun.checkout({ productId })、tiun.login() 或 tiun.start() 打开它们,到此为止。切勿穿透 shadowRoot 来查询、追加或观察节点;切勿向其中注入文本、工具提示、徽章或横幅;切勿使用 CSS 定位它(宿主选择器、::part、::slotted、!important 覆盖);切勿重新定位或包装它;切勿读取其输入框中的值。其内部结构没有版本保证,可能随时变更且不另行通知;而且它位于支付流程中——注入内容一旦失效,不会有提示,并会导致结账流程一并中断。唯一受支持的配置项是 init() 配置(language、tone)和控制台设置。如果客户需要额外文案或说明,请将其放在自己的页面上、触发入口旁边,并在浮层打开前展示——不要放在浮层内。配置和控制台未提供的任何功能,都应通过 [email protected] 联系支持团队,而不是打客户端补丁。参见 references/overview.md。
  6. 在 ready 之前调用的方法可能会排队或不执行。 checkout/login/start/setContent/logout 等方法已在内部调用 ensureInitialized() 并执行 await this.waitForReady()——无需再套一层。
  7. 在组件卸载时取消订阅 tiun.on(...) 返回的处理程序,以避免监听器失效。或者,在整个子树即将销毁时调用 tiun.destroy()。
  8. Live 和 sandbox 是相互独立的并行环境。 每个环境都有自己的 snippet ID、产品、产品 ID 前缀(p-live-... 与 p-test-...)、API 密钥和 API 基础 URL(https://api.tiun.live 与 https://api-sandbox.tiun.live)。环境切换项(Web 上的 sandbox 标志,React Native 中的 host)必须与控制台视图及产品 ID 前缀相匹配,否则结账会无提示地失败。Live 环境会阻止 localhost,sandbox 环境默认启用 localhost。每个环境都有自己的 Settings → Environment setup(Web 的 Live 域名,应用的 App scheme)。
  9. 没有运行时产品列表 API。 产品在 tiun 控制台(my.tiun.business)中配置,并通过硬编码的 productId 字符串引用。不要杜撰 tiun.getProducts() 之类的方法或 REST 端点;请引导用户前往控制台。
  10. 没有 Webhook。 tiun 不会发送 Webhook。对于后端集成,请根据 getUserVerificationToken() 返回的 JWT 或 paywallHide 中的 sessionId 驱动状态。不要杜撰 Webhook 端点或事件载荷。
  11. 忠实遵循上游文档。 所有代码示例都必须与 https://docs.tiun.io 一致。如果某种模式未在上游文档中说明(自定义 SSR 接线、多环境设置、其他语言的后端 SDK 等),请引导用户查看上游文档,而不是杜撰代码片段。
  12. 不要根据账户中的产品库存推断集成模式。 始终向用户确认(参见“步骤 0”)。MCP 报告的是当前存在的内容;并不会报告集成者想要构建的内容。
  13. productAccess 中的一次性产品 ID 永久有效。 它在结账时加入,之后永远不会移除——event: 'update' 也不会将其移除。对于一次性产品,不要生成到期、续订、取消、试用或撤销处理逻辑;这些逻辑对应的状态不可能发生,只会成为死代码。续订和取消仅适用于订阅。参见 references/one-time.md。
  14. 不要为了添加 isInitialized / waitForReady 检查而包装 SDK 方法。 tiun.checkout、tiun.login、tiun.start、tiun.setContent 和 tiun.logout 均已在内部完成这两项处理。围绕这些方法编写包装辅助函数只会增加冗余。
  15. 不要向 init() 传入 baseUrl。 这是仅供内部使用的字段,仅供 tiun 自身基础设施使用。在 Web SDK 中,非生产环境请使用 sandbox: true;这是唯一公开的环境切换项,SDK 会自动路由到相应的 API 主机。(React Native 例外:它没有 sandbox 标志,而是通过 host 选择环境——参见 references/react-native.md。)
  16. language 是一个封闭枚举:'en' | 'de' | 'fr',不区分大小写。不受支持的值会触发一次控制台警告,并回退到 'en'。不要生成其他值。
  17. 不要根据 error.code 来分支应用逻辑。 它是字符串,但没有公开的枚举定义;错误代码可能随 SDK 版本变化。向用户显示 err.message,并记录 err.code 以供支持排查。
  18. 将运行时配置写入打包工具实际会加载的文件。 .env.example 只是文档,不会被求值。Vite 会加载 .env / .env.local;Next.js 会加载 .env.local,且客户端可访问的值必须使用 NEXT_PUBLIC_* 前缀;Nuxt 通过 nuxt.config.ts 中的 runtimeConfig.public 加载配置。各宿主的配置表参见 references/installation.md。
  19. 账户入口使用认证,购买使用结账。 注册或登录 → tiun.login();购买产品或方案 → tiun.checkout({ productId });退出登录 → tiun.logout()。根据操作的目的选择,而不是根据它的标签选择。结账会处理购买过程中涉及的认证和回访客户场景,因此购买操作应直接打开结账,而不是先跳转到单独的登录流程。这说的是购买操作应打开什么,不是应用结构——先购买和先进入账户的流程都有效。参见 references/subscriptions.md →“选择 checkout 还是 login”。
  20. React Native 结账需要在三个地方使用同一个 scheme。 控制台的 Settings → Environment setup → App scheme(例如 myapp://)、原生注册(iOS 的 Info.plist + AppDelegate 中的 RCTLinkingManager 转发;Android 的 intent filter + android:launchMode="singleTask"),以及 TiunConfig 中的 returnUrl(例如 myapp://tiun/return)。重用应用现有的 scheme,而不是另行创建,并告知用户在 host 指向的环境对应的控制台中注册该 scheme。任何一处不匹配都会导致支付成功,但结账流程无法返回。参见 references/react-native.md。

最小可用示例

三个基本构件——在所有受支持的环境中都适用。根据你的技术栈调整响应式基本构件(状态钩子、ref、信号、存储、DOM 更新)。

import { tiun } from '@tiun/sdk';

tiun.init({ snippetId: 'YOUR_SNIPPET_ID', language: 'en' });

const off = tiun.on('userChange', ({ event, isAuthenticated, user }) => {
  // push into your framework's reactive primitive
});

document.querySelector('#buy').onclick =
  () => tiun.checkout({ productId: 'p-live-pro' });

// off(); tiun.destroy();

各模式的完整演练请见 references/subscriptions.md、references/one-time.md 和 references/time-based.md。各框架的适配方式请见 references/frameworks.md。

判断线索

  • 用户提到“订阅”“定期”“会员”“付费账户”“产品和套餐” → 订阅流程。引导至 subscriptions.md。
  • 用户提到“买一次”“付一次款”“一次性”“终身”“终身优惠”“单笔付款”“永久解锁”“固定费用”“永久许可证”“无需订阅” → 一次性流程。引导至 one-time.md。
  • 用户提到“文章付费墙”“先看视频再付费”“会话”“无需账户”“捐赠提示”“前 N 秒免费” → 按时长计费流程。引导至 time-based.md。
  • 用户提到“付费墙后的视频”“高级内容”(含义不明确) → 询问用户选择哪种模式。不要猜测。
  • 用户问“如何让我的 Agent 集成 tiun?”/“如何用 AI 编码 Agent 设置这个?” → 指向 docs.tiun.io 上游的 Agent 集成指南,以及 references/mcp.md 中的 npx skills add tiun-app/skills 快速入门。
  • 用户问“如何列出产品?”/“获取所有产品?” → 在 my.tiun.business 控制面板中配置产品;没有运行时产品列表 API。(MCP 会向 Agent 暴露库存信息以供设置;这不是运行时 SDK 功能。)
  • 用户提到“在后端验证”“保护 API”“信任客户端” → 服务端验证(X-TIUN-API-KEY 标头;各环境使用不同的基础 URL)。
  • 用户提到沙盒 / localhost /“为什么在本地无法运行” → 确认设置了 sandbox: true,使用了沙盒代码片段 ID 和 p-test-... 产品 ID(在 localhost 上会硬性阻止正式环境)。
  • 用户要求重新设计覆盖层样式、重命名其字段,或在结账或登录界面内添加帮助文本 / 备注 / 工具提示 → 不支持。覆盖层内部内容不允许更改(规则 5);请将文案放在自己页面的触发控件旁,并将品牌相关请求转交至 [email protected]。
  • 用户正在配置购买、登录或登出操作 → 根据用途分别对应:购买调用 tiun.checkout({ productId }),账户入口调用 tiun.login(),登出调用 tiun.logout()。保留应用现有的用户流程(规则 19)。
  • 遇到“覆盖层未显示”“ready 之前调用了方法”等错误 → 排查问题。
  • 项目使用 React Native,或用户提到 @tiun/react-native-sdk、TiunProvider、useTiun、“iOS/Android 应用”、“深度链接”、“returnUrl”、“结账后无法返回应用” → 查看 references/react-native.md。不要查看 frameworks.md 的 WebView 部分,也不要使用 @tiun/sdk。
  • 用户想在 React Native 应用中按时长计费 → React Native SDK 不支持;请说明这一点,并引导用户联系 [email protected]。

评论

支持 Markdown