在 Scenelet 上集成你的应用
把 Scenelet 嵌入你自己的浏览器插件、桌面软件或 Web 工具。你的用户用官方 Scenelet 账户登录,每一次付费操作都按其点数余额计量——登录、计费、分账与远程控制全部由平台托管,你只需专注做功能。
核心概念
两个标识符 + 一个令牌,把你的应用接到平台上。它们职责不同,别混淆。
- app_key
- 标识一个用于计费的资产(你的插件 / 技能)。在你发布资产时签发,价格也定义在这里。每次 execute 调用都要带上它。
- client_id
- 标识发起登录流程的 OAuth 应用,在「开发者应用」面板创建。公开客户端只用 PKCE;机密(服务端)客户端还会拿到一次性密钥。
- Scenelet 令牌
- 登录后为每个用户签发的 Bearer 访问令牌(默认 90 天有效)。SDK 会自动保存它;网关据此解析出要扣点数的用户。
1. 拿到你的凭证
写代码前需要两样东西。
发布资产 → app_key
提交你的插件 / 技能并设置计价模式(免费、按次、订阅或买断)。审核通过后即获得 app_key。你在这里设的价格,是网关唯一会收取的价格。
注册 OAuth 客户端 → client_id
在「开发者应用」面板创建客户端,填入精确的回调地址(Web 回调、桌面端的 127.0.0.1 环回地址,或插件的 chromiumapp.org 地址)。插件与桌面软件选公开(PKCE),能保管密钥的服务端选机密。
2. 安装 SDK
在打包工具里用 npm 包;纯插件或纯页面可直接用 script 标签引入 UMD 构建(暴露 window.Scenelet)。
# npm (bundlers)
npm install @scenelet/sdk
# CDN (plain <script>, exposes window.Scenelet)
<script src="https://api.scenelet.com/sdk/v1/scenelet-sdk.umd.js"></script>import { Scenelet } from '@scenelet/sdk';
const sc = new Scenelet({
appKey: 'app_xxxxxxx', // the asset being billed
clientId: 'cli_xxxxxxx', // your OAuth app (login flow)
});3. 让用户登录
三种流程都是 Authorization Code + PKCE,最终都会签发并保存用户令牌。按你的运行环境选一种。
Web 页面 —— 弹窗
loginViaPopup 弹出官方登录窗口,用户授权后即返回。你自己域名下的回调页只需调用 completePopupCallback()。
// 1) trigger login (e.g. on a button click)
await sc.loginViaPopup({ redirectUri: 'https://yourapp.com/oauth/callback' });
// 2) on https://yourapp.com/oauth/callback :
Scenelet.completePopupCallback('https://yourapp.com');浏览器插件 —— chrome.identity
loginViaChromeIdentity 通过 chrome.identity 完成流程。把 chrome.identity.getRedirectURL() 注册为客户端的回调地址。
// background / service worker / popup script
await sc.loginViaChromeIdentity();
// redirect URI to register: chrome.identity.getRedirectURL()桌面 / 服务端 —— 手动
构造授权 URL,打开系统浏览器,在环回回调上捕获 ?code,再换取令牌。机密客户端还需把密钥传给 exchangeCode()。
const { url, codeVerifier, state } = await sc.buildAuthorizeUrl({
redirectUri: 'http://127.0.0.1:8976/cb',
});
// open `url` in the system browser; capture ?code & ?state on your loopback
const token = await sc.exchangeCode({
code, codeVerifier,
redirectUri: 'http://127.0.0.1:8976/cb',
clientSecret: 'csk_xxxxxxx', // confidential clients only
});4. 为每次付费操作加闸门
在计费操作前调用 gate()。它会向网关请求授权;被拒绝时自动弹出官方充值 / 登录弹窗,你无需渲染任何计费 UI。如果想自己处理结果,改用 checkAuth()。
if (!(await sc.gate())) return; // SDK shows topup / login modal on denial
runMyPaidFeature();
// …or handle the result yourself:
const r = await sc.checkAuth();
if (!r.ok) showMyOwnUI(r.reason, r.message);execute 接口
推荐用 SDK,但这个闸门本质上是一次 HTTP 调用,哪里都能发。把资产 id 作为 app_id 传入,并带上用户的 Bearer 令牌。feature_cost 仅作参考——网关始终按资产在服务端配置的价格计费,客户端无法少报来少付。
POST https://api.scenelet.com/v1/sdk/execute
Authorization: Bearer <scenelet-token>
Content-Type: application/json
{ "app_id": "app_xxxxxxx", "tier": "standard" }{
"ok": true,
"status": "authorized",
"userId": "u_abc",
"remaining_credits": 95,
"runId": "run_xyz",
"actualTier": "standard"
}{
"ok": false,
"status": "forbidden",
"reason": "insufficient_funds",
"message": "需要 50 点,当前 32 点",
"topupUrl": "https://scenelet.com/topup"
}ok:true 表示已扣点、可以执行,请保留 runId。401 表示令牌无效或过期;403 表示触达每日配额;429 表示触达每分钟洪峰限流——请遵守 Retry-After。
拒绝原因
每个非 ok 响应都带有稳定的 reason 字段。处理它们以给用户正确的下一步——SDK 弹窗已内置映射。
| reason | 含义 |
|---|---|
| insufficient_funds | 点数不足以本次运行——引导用户去充值。 |
| not_purchased | 订阅 / 买断类资产,用户尚未购买。 |
| subscription_expired | 订阅已过期——提示续费。 |
| plugin_disabled | 平台已远程禁用此资产(Kill-switch)。 |
| bad_app_key | 未知、未发布或格式错误的 app_key。 |
| no_user_token | 无令牌,或令牌无效 / 过期——提示登录。 |
| rate_limited | 触达每分钟洪峰限流(429)——按响应头重试。 |
| quota_exceeded | 当日分层配额已耗尽(403)。 |
| network_error | SDK 无法连接到网关。 |
计费如何运作
你定价,平台向用户收取点数、拆分收入并向你结算。你这边无需对账。
- 免费 —— 始终放行,不扣费。
- 按次 —— 每次成功运行从用户扣除 priceCredits。
- 订阅 —— 一次性购买,到期前无限次运行。
- 买断 —— 一次性购买,永久无限次运行。
控制与安全
平台对每个集成保有控制手柄——既对你有用(防滥用),也由我们强制执行(政策)。
- 远程 Kill-switch —— 资产可被即时禁用,此后 execute 直接返回 plugin_disabled,SDK 自动弹出提示。你这边无需重新部署。
- 分层配额 —— 匿名 < 会员 < 付费的每日上限(管理员可调)。匿名用户触顶时会收到 trigger_auth_modal,便于你引导注册。
- 洪峰防护 —— 每分钟限流在检查每日配额之前就会返回 429 与 Retry-After。
- 令牌有效期 —— 令牌默认 90 天,且每次调用都实时解析,被吊销或过期的凭证会在数秒内失效。
- 退款安全 —— 扣费在 execute 返回 ok 时落定。若平台的执行后端在下游失败,会通过内部接口冲正这笔扣费,你无需自行调用。
安全须知
- PKCE 仅支持 S256,plain 方法会被拒绝。
- redirect_uri 必须与客户端注册的某个地址精确匹配——不支持通配。
- 授权码一次性使用,60 秒后过期。
- 机密客户端密钥仅显示一次且以哈希存储——轮换请创建新客户端。