百积木文档
开发指南Bundle 开发平台应用开发

App Gateway 接入与配置

为复用百积木用户与工作区体系的平台应用选择 App Gateway,并完成入口、授权、能力、调用和发布配置。

App Gateway 是平台应用复用百积木登录用户、工作区安装态和权限体系的标准业务入口。 只要应用由 Bundle 安装到工作区,并且页面代表当前平台用户调用该安装可用的能力,就应 使用 App Gateway。

最常见的场景是:团队开发一个独立部署的前端应用,但用户仍从百积木工作区打开它。 此时应创建独立的 Platform Application,使用 TRUSTED_EXTERNAL_APP 入口,通过 网页授权和 PKCE 获取 appClientToken,再从公开平台 API 前缀调用 App Gateway。

选择平台应用入口

entryType适用场景App Gateway 接入方式
PLATFORM_ROUTE平台管理端已经内置的页面继承平台管理端当前登录态,不执行外部应用 PKCE
TRUSTED_EXTERNAL_APP独立部署、复用平台用户和工作区的 Web 应用通过网页授权 + PKCE 获取 appClientToken
EXTERNAL_URL不访问平台能力的普通链接不接入 App Gateway

App Gateway 应用凭证

可信外部平台应用调用 App Gateway 时使用 appClientToken。该 token 由网页 授权码兑换流程签发,并绑定当前用户、工作区、默认 Runtime 应用、平台应用安装和 授权范围。

调用链

百积木平台用户
  -> 从工作区打开平台应用 accessUrl
  -> 网页授权页校验登录态、工作区访问权和安装记录
  -> PKCE 授权码兑换 appClientToken
  -> 浏览器请求公开前缀 /app-gateway/api
  -> App Gateway 校验逻辑接口、方法、用户、安装和版本
  -> 按安装记录 interfaceBindings 解析具体 Runtime businessId
  -> 校验工作区方法权限并调用 backend-instance
  -> 返回统一响应

应用前端只依赖公开、稳定的 https://api.baijimu.com/app-gateway/api 契约。不要在 业务代码中硬编码 gateway2、backend-instance、内部网关地址、单台服务 IP 或端口。 这些属于平台内部路由和运行态实现,不是应用协议。平台应用方法调用不经过主站 /lowcode3/api,也不由前端直接访问 gateway2。

App Gateway 负责完整的应用调用边界:

  • 确认“谁在调用、属于哪个安装、当前版本允许调用什么逻辑接口和方法”。
  • 调用平台应用安装服务,把逻辑接口按当前安装的 interfaceBindings 解析成具体 Runtime businessId
  • 使用解析后的具体服务完成工作区方法权限校验和 backend-instance 运行态调用。

前端不得读取、缓存或提交具体 businessId,也不自行拼接内部调用信封。

配置一:创建独立平台应用

每个可独立发布的平台应用都应有稳定的 platformAppId 和独立的平台项目。不要把前端 页面仅作为 Bundle 中一个匿名 URL;否则平台无法为它管理版本、安装、能力和用户授权。

独立部署且复用平台身份的前端使用:

{
  "platformAppId": "example-platform-app",
  "entryType": "TRUSTED_EXTERNAL_APP",
  "entryUrlTemplate": "https://app.example.com/?installId={installId}",
  "openMode": "WORKSPACE_TAB"
}

入口模板只携带 {installId}workspaceIduserIdappClientToken、业务密钥 和内部服务地址都不能放进入口 URL。

如果页面本来就是平台管理端源码中的内置路由,才使用:

{
  "entryType": "PLATFORM_ROUTE",
  "entryUrlTemplate": "/workspace/example"
}

完整的入口选择规则见 入口类型与应用清单

配置二:声明最小能力

平台应用版本必须声明实际使用的逻辑接口和模块方法。新平台应用统一使用 interface, 由安装时的 interfaceBindings 选择具体模块实现:

[
  {
    "interface": "wechat-official-account",
    "methods": ["authorizationUrl", "listAuthorizedAccounts", "createDraft"]
  }
]

安装记录保存平台生成的绑定,不进入前端配置:

{
  "interfaceBindings": {
    "wechat-official-account": "m-baijimu-2157"
  }
}

service 形式仅用于仍然锁定具体 Runtime businessId 的存量版本,不应作为新平台应用 的调用合同,更不能让前端读取该值。

不要声明通配权限,也不要把未来可能使用的管理方法提前加入当前版本。平台应用不能用 methodDefinitions 代替平台内部 HTTP API 授权;它只能声明已安装 Runtime 模块的方法。

能力声明、安装绑定和用户授权同时生效;其中任何一层不满足,App Gateway 都应拒绝 调用。字段规则见 声明应用能力

配置三:使用网页授权 + PKCE 取得应用身份

TRUSTED_EXTERNAL_APP 从 URL 读取 installId 后,跳转统一授权页:

https://console.baijimu.com/#/platform-app-authorize
  ?installId=pia_xxx
  &redirectUri=https%3A%2F%2Fapp.example.com%2F
  &codeChallenge=...
  &codeChallengeMethod=S256
  &state=...

平台网页授权页校验登录用户、工作区权限、应用安装和授权范围,然后只向同源 redirectUri 回传一次性 code。页面校验 state 后兑换 token:

POST https://api.baijimu.com/app-gateway/api/workspace-runtime/apps/{installId}/token/exchange
Content-Type: application/json

{
  "code": "authorization-code",
  "codeVerifier": "original-code-verifier"
}

返回的 appClientToken 同时绑定用户、工作区、默认 Runtime 应用、平台应用安装和 授权范围,不能跨 Runtime 或跨安装复用。完整流程见 平台应用授权与 PKCE

配置四:统一公开 API 前缀

前端应由一个接入层集中管理平台地址:

const platformApiBase =
  window.__APP_CONFIG__?.platformApiBase ??
  "https://api.baijimu.com/app-gateway/api";

不同部署环境通过环境配置替换 platformApiBase,业务组件不要散落生产域名。标准入口 如下:

用途请求
授权码兑换POST /workspace-runtime/apps/{installId}/token/exchange
调用模块方法POST /workspace-runtime/apps/{installId}/services/{service}/methods/{method}

除 token exchange 外,调用都携带:

Authorization: Bearer {appClientToken}

模块方法的 POST 请求体直接使用方法参数,不再包装 servicemethodparams

export async function callModule({
  platformApiBase,
  installId,
  appClientToken,
  logicalService,
  method,
  params = {},
}) {
  const path =
    `${platformApiBase}/workspace-runtime/apps/${encodeURIComponent(installId)}` +
    `/services/${encodeURIComponent(logicalService)}` +
    `/methods/${encodeURIComponent(method)}`;

  const response = await fetch(path, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${appClientToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(params),
  });
  const payload = await response.json();

  if (!response.ok || payload.errorCode !== "0") {
    throw new Error(payload.value || `模块调用失败:HTTP ${response.status}`);
  }
  return payload.data;
}

完整请求和响应协议见 调用模块方法, 启动状态机见 Web 接入与运行态调用

发布与安装

平台应用配置以不可变版本发布,再由 Bundle 引用精确版本:

{
  "platformApplications": [
    {
      "platformAppId": "example-platform-app",
      "version": "1.2.0"
    }
  ]
}

修改入口、方法能力或回跳同源范围后,需要依次发布平台应用新版本、冻结 Bundle 新版本 并升级目标工作区。只修改前端文件、且入口和方法声明不变时,可以从同一平台项目 commit 构建新 Artifact 并热更新原站点,不需要新平台应用版本;只发布平台应用版本则不会自动 升级已经安装的 Bundle 资源。

验收清单

  1. 平台应用有稳定 platformAppId 和独立项目。
  2. 独立前端使用 TRUSTED_EXTERNAL_APP,入口模板包含 {installId}
  3. 网页授权回跳只携带一次性授权码,不在 URL 中传 token。
  4. token exchange 返回的工作区、runtimeAppId 和安装信息与当前入口一致。
  5. 前端只通过公开 /app-gateway/api 前缀访问平台能力。
  6. 前端在 {service} 路径段传平台应用声明的逻辑接口名,不传 Runtime businessId
  7. App Gateway 能按当前安装的 interfaceBindings 解析具体 Runtime 服务。
  8. 已声明的方法可调用,未声明的方法被拒绝。
  9. 不同用户、工作区和安装之间不会复用 token。
  10. appClientToken 不出现在入口 URL、日志、埋点或错误上报中。
  11. 业务系统密钥不进入平台应用前端。
  12. 新平台应用版本已被 Bundle 精确引用,并已升级到目标工作区。

排障时先判断失败发生在入口、网页授权、token exchange、App Gateway 权限校验、 运行态解析还是目标模块执行。不要因为某一层配置错误就绕开 App Gateway 的安装和授权 校验;应在实际失败层修复配置或实现。

本页内容