包含的能力
都在控制台里配置,应用通过一个 SDK 读取。
49 套付费墙模板
按语言改文字、价格和图片,发布后立即生效,不用发版。
转化漏斗
按回答分岔的多屏引导,支持 2–20 组 A/B 实验。
月付与年付套餐
升级立即生效并按差额补款,降级等到当前周期结束。
给 AI 功能按量计费
月度额度、积分包,每次扣减只算一次。
优惠券与定向优惠
优惠码和定向发放,与 Stripe 自动对账。
按事件和人群展示付费墙
按事件触发、按人群定向,并限制展示频率。
一次调用拿到权益
应用只问客户现在能用什么,答案来自 Stripe 确认过的状态。
由数据库保证
权限写在数据库策略里,而不是靠隐藏按钮。
按回答分支的引导流程
页面设计一次,每位客户按自己的回答走不同路径。

文字与故事 · 自然流量 · A/B → 经典: 选择创作方向 → 按回答选择路径 → 文字路径 → 为你命名 → 准备就绪 → 按来源分流 → 付费墙 A/B 实验 → 经典付费墙 → 登录 → 结账 → 完成
画面与设计 · 广告流量 → 折扣: 选择创作方向 → 按回答选择路径 → 视觉路径 → 为你命名 → 准备就绪 → 按来源分流 → 折扣付费墙 → 登录 → 结账 → 完成
这条漏斗用到:回答分支 · 来源分流 · A/B 实验(2–20 组) · 登录 · 结账
49 套付费墙模板
由 SDK 渲染,中英文都有。
显示 8 / 43 套模板
MUSEAI 工具
PATCHAI 工具
FRAMEAI 工具
DRAFTAI 工具
PRISMAI 工具
STILL精选主题
FOLIO精选主题
RIDGELINE精选主题
49 套模板中 43 套的 SDK 实际渲染(1440 × 900 桌面视口),另外 6 套基础起步模板未展示。价格为模板示例。
四个调用完成接入
三个在服务端,一个在浏览器。
npm install ./vendor/groove-grow-current.tgz密钥只留在你的服务端;浏览器只拿到客户令牌,默认 10 分钟有效。
import { createGrooveServer } from "@tinkerlandai/indiana-sdk/server"; const groove = createGrooveServer({ baseUrl: "https://grow.your-domain.example", apiKey: process.env.GROOVE_SECRET_KEY!, // gg_sk_…,只放在服务端 scope: { projectId: "your-app-uuid", environment: "sandbox", },}); // verifiedUser 来自你自己验证过的登录会话const { customer, created } = await groove.getOrCreateCustomer({ externalUserId: verifiedUser.id, name: verifiedUser.name, email: verifiedUser.email,});{ "created": true, "customer": { "id": "…", "externalUserId": "user_1021", "attributes": { "tags": [] } }}// 例如你自己的 GET /api/groove-session:只为已登录用户签发const user = await requireSignedInUser(request); // 未登录直接返回 401const { customer } = await groove.getOrCreateCustomer({ externalUserId: user.id,});const { customerToken, expiresAt } = await groove.createCustomerSession(customer.id); return Response.json( { customerToken, expiresAt }, { headers: { "Cache-Control": "no-store" } },);{ "customerToken": "gg_ct_…", "expiresAt": "2026-10-03T08:10:00.000Z"}import { createFunnelRunController, showFunnelRun } from "@tinkerlandai/indiana-sdk"; // Your backend retains the original start request and run credential.export async function openFunnel(container: HTMLElement) {const response = await fetch("/api/groove-funnel", { method: "POST", credentials: "same-origin", cache: "no-store",});if (!response.ok) throw new Error("Funnel bootstrap failed");const { runToken } = await response.json();const client = createFunnelRunController({ baseUrl: "https://grow.your-domain.example", scope: { projectId: "your-app-uuid", environment: "sandbox" }, runToken,});const handle = await showFunnelRun(container, { client, onAuthenticate: async () => obtainCurrentUserCustomerToken(), onCheckout: ({ url }) => window.location.assign(url), onOpenUrl: ({ url }) => window.location.assign(url), onError: reportError,});// Keep the host's original bootstrap across navigation and payment returns.// Destroy removes UI; close is an explicit server command.return { handle, client, destroy() { handle.destroy(); client.reset(); } };}// On route leave: flow.destroy(). On explicit dismissal: await flow.handle.close().{ "run": { "status": "running", "nodeType": "screen", "revision": 1 }}// 一次生成完成后,在服务端按实际用量扣减const { receipt: spend } = await groove.mutateBalance({ customerId: customer.id, command: { operation: "consume", entitlementId, quantity: "1", properties: {}, idempotencyKey: `job:${job.id}`, // 重试同一个任务不会重复扣 },}); if (!spend.accepted) { // 额度不足:在这里投放升级付费墙}{ "accepted": true, "id": "…", "reason": null}常见问题
其他细节见接入文档。
Indiana 和 Stripe 是什么关系?
Stripe 负责收钱。Indiana 负责套餐、付费墙、投放和权益,并从已验签的 Stripe 通知读取订阅状态。
现在能收真实的钱吗?
还不能。公开测试期间,支付只在 Stripe Sandbox 中运行,不产生真实扣款。测试结束后开放 Live 收款。
客户能在月付和年付之间切换吗?
可以。月付转年付是升级,立即生效,Stripe 按差额补款。换到月均价更低的套餐是降级,默认在当前周期结束时生效。
改付费墙需要重新发版吗?
不需要。付费墙在展示时才从服务端获取,发布后的下一次展示就是新版本。
要把 API Key 放进浏览器吗?
不要,也放不进去。浏览器 SDK 只接受客户令牌,遇到以 gg_sk_ 开头的 Key 会直接报错。
改套餐会影响已有客户吗?
不会。每次发布都生成新版本,已有客户保留原来的版本;更换默认免费版本也只影响之后新识别的客户。
