百积木文档
开发指南平台应用、模块与 Bundle 开发平台应用开发

Web 接入与运行态调用

使用百积木标准浏览器 SDK 完成平台应用启动、PKCE、会话和 Runtime 方法调用。

环境托管应用必须使用公共 npm 包 @baijimu/platform-application-sdk 接入平台。不要在项目中复制 sdk.js,也不要由每个平台应用分别实现授权跳转、PKCE、token 存储、CModel 解析和 Runtime URL 拼接。

安装标准 SDK

pnpm add --save-exact @baijimu/platform-application-sdk@7.0.0

提交项目锁文件,保证构建和回滚使用已解析的精确依赖版本。SDK 是应用的构建时依赖,不会在目标环境 部署新服务,也不会改变 Bundle 安装内容。

通过 PLATFORM_APPLICATION 项目类型新建的项目应已经包含 SDK、bootstrap() 入口、部署配置文件和 平台应用声明。若项目中仍存在自实现的 PKCE、token 缓存或 Gateway client,不能只在旁边新增 SDK;应删除 重复实现,让授权生命周期和逐方法调用统一经过 SDK。

读取同源环境配置

环境托管应用使用 SDK 的专用初始化入口:

import { createPlatformApplicationClientFromHostedConfiguration } from "@baijimu/platform-application-sdk";

const client = await createPlatformApplicationClientFromHostedConfiguration(applicationDefinition.id);

applicationDefinition.id 是当前应用稳定的 platformAppId。SDK 只从当前 HTTPS origin 的 /.well-known/baijimu-platform-application.json 读取配置,并校验应用身份和精确 origin。 该文件由平台在 Bundle 安装或升级时的托管流程自动提供,开发者无需创建静态站点或手工部署配置文件,也不能让应用构建归档覆盖它。 历史 STATIC_SPA 站点需要完成 环境托管迁移,只升级 npm 依赖不会生成同源配置。

新应用在独立 origin 的根路径运行,配置不含 releasePath。已有 SDK 6 部署继续使用原配置;历史 SDK 6 归档首次安装到新环境需要升级 SDK、重新构建并发布新应用版本。应用版本与 Bundle 安装、升级和回滚不变。

配置字段如下:

字段来源与含义
contractVersion同源配置合同版本,SDK 7 使用 2.0.0
platformAppId当前平台应用的稳定身份
applicationOrigin该应用在当前环境的 HTTPS origin
appGatewayApiBase当前环境的 App Gateway API 地址
authorizationUrl当前环境的网页授权地址
managementUrl可选的当前环境管理入口

SDK 拒绝配置重定向、缺失字段、未知字段和身份不匹配,不缓存配置,也不从 URL 参数或公共 SaaS 地址回退。 配置不包含 installId、工作区、用户、token 或密钥;真实安装选择器由启动 URL 提供,服务端负责权限校验。 只升级 SDK 不会让外部站点取得平台授权,应用还必须按环境托管方式创建新版本并升级 Bundle。

旧项目应删除 window.__APP_CONFIG__ 手工地址注入、签名启动初始化和自实现授权逻辑。 createPlatformApplicationClient(config) 仅用于显式受控集成或本机测试,不能用它绕过平台托管要求; 外部自托管应用使用自己的后台授权。

在业务页面之前启动

const session = await client.bootstrap();

bootstrap() 统一执行以下状态机:

读取 installId
  -> 有 code:校验 state 并兑换本次授权 token
  -> 当前 client 已有未过期内存会话:进入应用
  -> 都没有:创建 PKCE 请求并跳转网页授权页

SDK 会校验返回 token 的 workspaceIdruntimeAppIdinstallIdplatformAppId 和过期时间, token 只保存在当前 client 实例的内存中。每个页面使用一个 client,同一实例的重复或并发 bootstrap() 不重复发起授权。新开页面或刷新必须重新经过平台授权页,以当前平台登录身份兑换 新 token,不能恢复上次打开时的应用身份。SDK 会删除当前应用和安装的旧 localStorage token。

不要把 token 写入 localStorage、sessionStorage、Cookie 或 URL,也不要通过自有缓存跳过 SDK 初始化。 PKCE verifier 和预期 state 仍需在 sessionStorage 中跨授权跳转保存;它们不是应用登录 token。 授权成功后删除 PKCE 临时数据,并从地址栏移除授权参数。 它只移除一次性的 codestate,会保留平台入口要求的 installId。业务代码不要再次清空整个查询串。

迁移 SDK 6

SDK 6.0.0 取消持久化应用会话。更新依赖和锁文件后,必须重新构建并发布平台应用、更新 Bundle 引用, 已打开的旧页面需要重新加载。发布 npm 包本身不会改变已部署的 JavaScript。

旧应用除了更新依赖,还需删除自实现的 token 缓存。SDK 2.x/3.x 的初始化应迁移到同源托管配置入口; SDK 4.x 的调用需检查 /invoke 及结构化 target 的兼容性。目标网关须支持 SDK 5 起采用的领域调用协议。

新开或刷新会重新核验平台当前身份。已打开应用不会因另一个域名的平台账号切换自动收到通知; 即时退出和账号切换联动需要平台的可信会话失效机制,不得信任 URL 或任意跨域消息中传来的 userId。 clearSession() 只清客户端状态,服务端撤销使用 revoke()

验收至少覆盖:浏览器已有账号 A 的旧应用缓存、平台切换为账号 B、重新打开/刷新应用后接口身份为 B; 同时验证 PKCE 回跳、并发初始化、token 过期和授权途中退出。SDK 不自动重放失败的业务请求。

调用模块方法

业务组件只传平台应用版本已声明的结构化 target、method 和方法参数:

const projects = await client.call(
  {
    type: "module",
    bundleId: "project-directory",
    moduleId: "project-directory",
  },
  "listProjects",
  { offset: 0, limit: 50 },
);

SDK 使用规范调用路由,并生成包含 target、method 和 params 的请求体:

POST {appGatewayApiBase}/workspace-runtime/apps/{installId}/invoke

新应用不得提交 Runtime service/services/{service}/methods/{method} 只服务历史 SDK 2.x 应用。 App Gateway 会校验 token、安装、默认 Runtime 绑定、平台应用版本的 方法声明和工作区权限;前端不选择后端实例、不读取具体 businessId,也不持有模块服务凭证。完整协议见 调用模块方法

错误与会话处理

import {
  CModelFailureError,
  PlatformApplicationSdkError,
} from "@baijimu/platform-application-sdk";

try {
  await client.call(
    { type: "module", bundleId: "project-directory", moduleId: "project-directory" },
    "listProjects",
    {},
  );
} catch (error) {
  // 由 SDK 判定会话失效;不要仅凭业务 errorCode 或 HTTP 状态重登。
  if (!client.getSession()) {
    client.restartAuthorization();
    throw error;
  }
  if (error instanceof CModelFailureError) {
    console.error(error.errorCode);
  } else if (error instanceof PlatformApplicationSdkError) {
    console.error(error.code);
  }
}

SDK 6.0.0 在 App Gateway 返回 APP_GATEWAY_UNAUTHORIZED 时清除当前安装会话,也会处理网关返回的非结构化 HTTP 401。 后端业务返回合法 CModel UNAUTHORIZED 时,即使 HTTP 状态是 401,SDK 仍保留会话;应用应展示业务错误,不能重新授权。 参数错误、能力未声明、目标服务异常和网络失败同样不能触发登录循环。以 client.getSession() 是否已由 SDK 清空作为重新授权的依据, 不要维护另一份会话状态,也不要在捕获到业务 UNAUTHORIZED 时自行清理 SDK 会话或自动重放业务请求。 需要主动注销时调用 await client.revoke();需要重新授权时调用 client.restartAuthorization()

平台应用没有另一套 PLATFORM_APPLICATION token,也不通过通用 HTTP 代理访问平台内部 API。需要新增 能力时,应先把能力定义为 Runtime 模块方法并发布不可变模块版本,再把该方法加入平台应用版本的 methodDefinitions

分享与管理入口

面向其他用户分享通用功能时,使用 Manager 的 /bundle-app/{bundleId}/{platformAppId} 路由。 分享当前工作区的具体页面时,使用 /workspace/{workspaceId}/bundle-app/{bundleId}/{platformAppId}, 并通过 URL 编码后的 target 参数携带原生应用内地址,例如 /orders/123?tab=items/#/orders/123?tab=items。这是普通 href,可以本地拼接,无需链接生成请求,详见 用普通 href 打开应用内页面。 不要分享包含当前工作区 installId 的应用启动地址。应用配置了 managementUrl 后,可以使用 client.openManagementRoute(route) 打开管理页面;未配置时 SDK 会明确失败,不会猜测 Manager 地址。

会话失效

以下情况应终止当前应用会话并重新授权:

  • token 已到期或被撤销。
  • Bundle 安装已经停用、卸载或升级后使旧 token 失效。
  • 返回的 token 与当前 workspaceIdruntimeAppIdinstallId 不一致。
  • App Gateway 明确拒绝当前会话,SDK 已将其清空。

不要在所有业务错误上盲目跳转授权页。参数错误、目标服务异常和能力未声明应分别展示真实错误,避免形成授权循环。

本地开发

本地回跳地址必须与实际托管入口同源。若入口是已部署域名,本地 localhost 回跳不会通过同源校验。托管初始化要求真实 HTTPS 同源配置;本地页面展示可使用明确的测试配置,但完整授权联调应发布到目标测试环境并从该环境的安装入口启动,不能用外部 URL 替代环境托管。验证时保证:

  • 页面可以从入口参数取得真实 installId
  • HTTPS、端口和域名与登记入口一致。
  • Hash Router 和普通查询参数都能正确读取回跳字段。
  • 浏览器刷新后不会丢失 PKCE 会话。
  • 本地配置明确指向本次开发环境,不回退到公共 SaaS。

本页内容