# SuperSDK 使用指南
SuperSDK 是面向前端业务开发的 JavaScript SDK,提供与原生 App 交互的能力。
## 快速开始
### 引入 SDK
```html
```
引入后,SDK 会自动挂载到 `window.SuperSDK`。
### 环境检测
```javascript
if (SuperSDK.isInApp()) {
// 在 App 内运行
} else {
// 在浏览器中运行
}
```
## 非端环境降级(浏览器兼容)
SuperSDK 支持在非 App 环境(如浏览器)中运行,提供合理的降级行为,使前端项目在浏览器中也能基本运行和调试。
### initFallback(config)
在非端环境下初始化降级配置。配置会先校验,端内(有 appbridge)的合法调用才会被忽略。
```javascript
SuperSDK.initFallback({
baseUrls: ['https://api.supersdk.com/superapi'], // 服务端地址列表(用于 reportEvent 上报;业务 path 追加到 baseUrl 后)
baseUrl: 'https://api.supersdk.com/superapi', // 兼容旧字段;未传 baseUrls 时使用,可省略 /superapi
spid: 'ab12cd34', // 替换为控制台签发的真实 spid(8 位小写字母数字)
environment: 'staging', // 可选,缺省 prod;1..10 位小写字母数字
appName: 'MyApp', // 应用名称
appIcon: '', // 应用图标 Base64(可选)
deviceId: '', // 设备标识(可选,不传则自动生成)
});
```
**行为规则**:
- `config` 必须是 plain object,`spid` 必须匹配 `^[a-z0-9]{8}$`;`environment` 省略时为 `prod`,显式传入时必须匹配 `^[a-z0-9]{1,10}$`
- 旧 `aid` 字段不兼容;不 trim、不转换大小写,非法输入立即抛错且不修改已生效配置
- 端内(有 appbridge)也会先执行上述校验;合法时忽略 fallback 配置,所有 API 走原有端内逻辑
- 可多次调用,采用 merge 语义(只更新本次传入的字段,未传入字段保留前次值)
- `baseUrls` 优先于 `baseUrl`;未配置时默认 `['https://api.supersdk.com/superapi']`;旧 `baseUrl` 字段会兼容补齐 `/superapi`
- 请求会优先使用上次成功的 baseUrl,其余候选随机排序;HTTP 非 2xx 或网络错误时切换下一个 baseUrl
- 不调用 `initFallback` 时,环境配置类 API 返回默认空值(不会 reject)
**deviceId 说明**:
- 未传入时自动生成 UUID 并存入 `localStorage`(key: `supersdk_device_id`),跨会话保持一致
- 清除方式:`localStorage.removeItem('supersdk_device_id')`
- 隐私模式下 localStorage 可能受限,deviceId 退化为内存存储(每次会话不同)
### isFallbackMode()
判断当前是否处于降级模式。
```javascript
if (SuperSDK.isFallbackMode()) {
// 非端环境且已调用 initFallback
// 可用于条件渲染(如隐藏不支持的功能按钮)
}
```
返回 `true` 的条件:非端环境(无 appbridge)且已调用 `initFallback`。
### 各 API 降级行为
| 分类 | API | 降级行为 | 需要 initFallback |
|------|-----|----------|:-----------------:|
| **页面导航** | `openPage` / `openExternal` / `openWithBrowser` / `openBrowser` | `window.open(url, '_blank')` | 否 |
| | `closePage` | `window.close()` 或 `history.back()` | 否 |
| **UI 反馈** | `showToast(msg)` | `console.log('[SuperSDK Toast]:', msg)` | 否 |
| | `share(content)` | `console.log('[SuperSDK Share]:', content)` | 否 |
| **环境配置** | `getEnv()` | resolve `{ os:'web', spid, environment, appName, deviceId, ... }` | 否(有配置返回更多字段) |
| | `setAPIEnvironment(env)` / `getAPIEnvironment()` | web 降级下可运行时切换项目环境;端内 set reject(环境由原生宿主控制)、get 透传原生值 | set 是(需先 initFallback) |
| | `getAppName()` / `getAppIcon()` | resolve 配置值或 `""` | 否 |
| | Settings 系列 | resolve `{}` 或 `null` | 否 |
| **埋点上报** | `reportEvent(name, params)` | `fetch` POST 到 `{baseUrl}/v2/reportEvent`;body 带 `basic_data.host_spid/env`,header 带 `X-Aid=` 与 `X-Super-API-ENV` | 是(需 baseUrl/baseUrls + spid) |
| **用户反馈** | `submitFeedback(params)` | `fetch` POST 到 `{baseUrl}/v2/feedback`;body 带 `spid/env/platform=web`,header 带 `X-Aid=` 与 `X-Super-API-ENV`;业务拒绝(`INVALID_REQUEST`/`NOT_FOUND`)不换线路 | 是(需 baseUrl/baseUrls + spid) |
| **事件监听** | `subscribe` / `onForeground` / `onBackground` 等 | 正常注册(但不会收到 Native 推送) | 否 |
| **不可降级** | `callHostMethod` / `requestShortUrl` / `downloadWithCache` / 文件操作 / ZIP / 归因 / 支付 / nativeBlock 等 | reject,错误信息 `"Not in app environment..."` | - |
---
## API 参考
### API 概览
| 分类 | 方法 | 说明 | 异步 |
|------|------|------|:----:|
| **降级配置** | `initFallback(config)` | 初始化非端环境降级配置 | - |
| | `isFallbackMode()` | 判断是否处于降级模式 | - |
| **环境与配置** | `isInApp()` | 检测是否在 App 内运行 | - |
| | `getEnv()` | 获取运行环境信息(版本、设备、离线包等) | ✓ |
| | `setAPIEnvironment(env)` | 设置项目环境(web 降级模式生效;端内 reject) | ✓ |
| | `getAPIEnvironment()` | 获取当前项目环境(端内透传原生值) | ✓ |
| | `getAppName()` | 获取宿主 App 名称 | ✓ |
| | `getAppIcon()` | 获取宿主 App 图标(Base64) | ✓ |
| | `getHostSettings(configName?)` | 获取宿主云控配置 | ✓ |
| | `getHostSettingsByKey(key, configName?)` | 根据 key 获取宿主配置 | ✓ |
| **宿主方法** | `callHostMethod(name, params)` | 调用宿主自定义方法 | ✓ |
| | `reportEvent(name, params)` | 上报埋点事件 | ✓ |
| | `addEventCommonParam(key, value)` | 设置埋点公共参数 | - |
| | `submitFeedback(params)` | 提交用户反馈(控制台「业务运营 → 用户反馈」可查) | ✓ |
| | `openBrowser(url, title)` | 打开浏览器页面 | - |
| | `showToast(message)` | 显示 Toast 提示 | - |
| | `setStatusBarDarkMode(isDark)` | 设置状态栏深/浅色 | - |
| | `showKeyboard(selector)` | 唤起软键盘(Android 空实现) | - |
| **页面导航** | `openPage(url, options)` | 新页面打开 URL | - |
| | `closePage()` | 关闭当前页面 | - |
| | `openExternal(url)` | 系统方式打开 URL(应用商店、电话等) | - |
| | `openWithBrowser(url)` | 系统浏览器打开 URL | - |
| **安全区域** | `getSafeArea()` | 获取安全区域(状态栏/导航栏高度) | - |
| **分享** | `share(content)` | 调用系统分享 | - |
| | `requestShortUrl(url, baseUrl?)` | 长链接生成短链 | ✓ |
| | `requestShortUrlWithHtml(html, baseUrl?)` | HTML 内容生成短链(直出渲染) | ✓ |
| **生命周期** | `onForeground(callback)` | 监听进入前台事件 | - |
| | `onBackground(callback)` | 监听进入后台事件 | - |
| **WebView 通信** | `publish(key, data, targetId)` | 向其他 WebView 发送消息 | - |
| | `subscribe(key, callback)` | 监听广播消息 | - |
| **返回键** | `onBackPressed(callback)` | 监听返回键(可拦截) | - |
| | `offBackPressed()` | 取消返回键监听 | - |
| **文件下载** | `downloadFile(options)` | 下载文件(支持进度回调) | ✓ |
| | `downloadWithCache(fileUrl, fileMd5, cacheTts, fileCacheKey?)` | 下载并缓存文件,命中缓存直接返回本地路径 | ✓ |
| **文件操作** | `fileExists(path)` | 检查文件是否存在 | ✓ |
| | `getFileMd5(path)` | 获取文件 MD5 | ✓ |
| | `deleteFile(path)` | 删除文件或目录 | ✓ |
| | `moveFile(src, dest)` | 移动/重命名文件 | ✓ |
| | `createDir(path)` | 创建目录 | ✓ |
| | `listDir(path)` | 列出目录内容 | ✓ |
| | `readFile(path)` | 读取文本文件 | ✓ |
| | `writeFile(path, content)` | 写入文本文件 | ✓ |
| **ZIP** | `unzipFile(zipPath, destPath)` | 解压 ZIP 文件 | ✓ |
| | `zipDir(sourcePath, zipPath)` | 压缩目录为 ZIP | ✓ |
| **登录** | `getAuthProviders()` | 获取支持的三方登录方式列表 | ✓ |
| | `requestLogin(options)` | 触发三方登录 | ✓ |
| **支付**
`SuperSDK.pay.*` | `pay.purchase(payConfig)` | 发起购买(唯一入口 · 聚合 createOrder→pay · 返回三态) | ✓ |
| | `pay.getProviders()` | 探测宿主支持的支付方式列表 | ✓ |
| | `pay.registerProvider(name, provider)` | 注册 Provider(Web 收银台 / Native IAP override) | - |
| | `pay.restorePurchases(options)` | 客户端恢复购买(F036 PurchaseResult[] · provider 可选实现) | ✓ |
| **归因** | `getAttribution(onlyFirst)` | 获取归因数据 | ✓ |
| **Native Block** | `nativeBlock.init()` | 初始化,扫描静态 `` | - |
| | `nativeBlock.create(options)` | 动态创建原生组件 | ✓ |
| | `nativeBlock.destroy(blockId)` | 销毁指定组件 | - |
| | `nativeBlock.destroyAll()` | 销毁所有组件 | - |
| | `nativeBlock.updatePositions()` | 手动更新组件位置 | - |
| **响应编码** | `getSuEncCapabilities()` | 查询本端支持的 suenc codec | - |
| | `decodeSuEnc(encodedData, codec)` | 解码 suenc 响应体 | - |
---
### 环境与配置
#### getEnv()
获取当前运行环境信息。
```javascript
const env = await SuperSDK.getEnv();
console.log(env);
// {
// webviewId: "a1b2c3d4",
// versionName: "1.0.0",
// versionCode: 1010203,
// channel: "local_test",
// spid: "ab12cd34", // 替换为控制台签发的真实 spid
// environment: "prod",
// deviceId: "xxx-xxx-xxx",
// platform: "android",
// osVersion: "14",
// deviceModel: "Pixel 8",
// wappVersion: "1.0.0", // 当前 WApp(离线包)版本,非离线包页面为 ""
// wappBuildTime: 1740198896 // 离线包构建时间(秒级时间戳),非离线包页面为 0
// }
```
#### setAPIEnvironment(environment) / getAPIEnvironment()
项目环境对应控制台顶栏的 env(如 `prod` / `staging`),决定 settings 拉取与埋点上报归属的环境。
```javascript
// web 降级模式:运行时切换项目环境(需先 initFallback)
await SuperSDK.setAPIEnvironment('staging');
// 切换后 getHostSettings 请求的 env 参数、reportEvent 的
// basic_data.env 与 X-Super-API-ENV header 均使用新值;
// settings 请求缓存按环境隔离,切回旧环境命中原缓存。
// 读取当前项目环境(Promise;web 未初始化时 resolve "prod")
const env = await SuperSDK.getAPIEnvironment();
```
**规则:**
- 取值限 1–10 位小写字母/数字(`^[a-z0-9]{1,10}$`),非法值 reject `INVALID_ARGUMENT` 且状态不变;web 未 `initFallback` 时 set reject `NOT_INITIALIZED`
- 切换前会尽力冲刷旧环境的待发埋点事件,再换值
- **端内(App 内)**:`setAPIEnvironment` 一律 reject `UNSUPPORTED` —— 端内环境由原生宿主经 `SuperSDK.setAPIEnvironment`(Android)/ `SuperSDKManager.setAPIEnvironment`(iOS)控制;`getAPIEnvironment` 经 `getEnv` 透传原生当前值
- `initFallback(config)` 的 `environment` 字段仍作为 web 模式的初始环境
#### getAppName()
获取宿主 App 名称。
```javascript
const appName = await SuperSDK.getAppName();
// "MyApp"
```
#### getAppIcon()
获取宿主 App 图标(Base64 格式)。
```javascript
const iconBase64 = await SuperSDK.getAppIcon();
// "data:image/png;base64,iVBOR..."
// 可直接用于
```
#### getHostSettings(configName?)
获取宿主配置信息。`configName` 是配置名称,不传则端上请求不带 `configName` 参数。
```javascript
const hostSettings = await SuperSDK.getHostSettings();
const featureSettings = await SuperSDK.getHostSettings('feature_flags');
// { code: 'SUCCESS', msg: '', data: { ... } } 与服务端 settings 响应形态一致
```
**参数**:`configName` (string, 可选) — 配置名称;不传则请求不带 `configName` 参数。
**返回值**:`Promise