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

调用模块方法

平台应用前端通过标准 SDK 和 App Gateway 逐方法路由调用已授权的 Runtime 模块方法。

平台应用前端调用模块能力时,统一通过 app-gateway。页面不能直接请求模块服务地址或平台内部接口。

当前部署的对外 App Gateway 前缀是 /app-gateway/api/lowcode3/api 是历史或其他 部署形态的路径,不能作为当前环境的 API 地址。完整的网关选择、授权链和配置方法见 App Gateway 接入与配置

调用协议

POST /app-gateway/api/workspace-runtime/apps/{installId}/invoke
Authorization: Bearer {appClientToken}
Content-Type: application/json

installId 是当前工作区的平台应用安装标识。请求中的 targetmethod 必须与当前不可变 Platform Application 版本的 methodDefinitions 完全一致。标准 SDK 从启动会话取得 installId

请求参数

POST 请求体包含声明目标、方法名和模块方法参数对象:

POST /app-gateway/api/workspace-runtime/apps/pia_xxx/invoke
Authorization: Bearer ag1_xxx
Content-Type: application/json
{
  "target": {
    "type": "module",
    "bundleId": "course-management",
    "moduleId": "course-directory"
  },
  "method": "createCourse",
  "params": {
    "code": "COURSE-001",
    "name": "高等数学",
    "teacherId": 123,
    "tags": [
      "必修",
      "一年级"
    ]
  }
}

params 是方法参数对象,其中字段与模块方法 paramDefinitions 中的参数名称一一对应:

  • 必填、类型、对象结构和数组元素服从模块方法定义。
  • 无参数方法的 params 也必须是 JSON 空对象 {}
  • 不要传递 Runtime servicemethodBodyuserId 或平台身份请求头。
  • methodBody 只描述特定模块实现如何访问后端 HTTP 服务,不属于前端调用协议。

例如 createCourse 定义了 codenameteacherIdtags,页面就发送同名 JSON 字段。模块内部是否把 teacherId 转换为 teacher_id,属于模块实现,不影响 页面协议。

module 与 interface

固定依赖应直接使用 Module 领域引用。声明和调用使用同一个 target:

{
  "target": {
    "type": "module",
    "bundleId": "course-management",
    "moduleId": "course-directory"
  },
  "methods": [
    "listWorkspaceUsers",
    "createCourse"
  ]
}

只有当业务明确需要可替换实现时才使用 interface。例如版本声明:

{
  "target": {
    "type": "interface",
    "name": "course-directory"
  },
  "methods": ["listWorkspaceUsers", "createCourse"]
}

Bundle 平台应用资源声明的接口来源为:

{
  "interfaceBindings": {
    "course-directory": {
      "bundleId": "course-management",
      "moduleId": "course-directory"
    }
  }
}

安装计划根据当前 Bundle 及其依赖 Bundle 的模块领域引用 解析接口。具体 Runtime service 绑定值和 调用身份只保存在安装态,由平台动态维护,不进入平台应用源码、Bundle Manifest 或浏览器。 无论选择 module 还是 interface,原始 service、具体 businessId* 通配声明都不能用于新版本。

查询当前工作区用户

平台应用没有“登录后可以任意调用平台后端模块”的权限。平台已经通过 workspace-core工作区管理 Module 提供 listWorkspaceMembers;业务 Bundle 必须显式依赖 workspace-core, 平台应用版本再声明并绑定这个方法。页面仍然通过标准 SDK 调用:

const members = await client.call(
  {
    type: "module",
    bundleId: "workspace-core",
    moduleId: "2108",
  },
  "listWorkspaceMembers",
  {},
);

方法从经过验证的调用上下文取得当前工作区和当前用户,不接受页面传入的 workspaceIduserId 作为可信身份。依赖声明、真实 领域引用、应用能力绑定、发布安装和验证步骤见 示例:查询工作区成员

响应

调用成功时,app-gateway 返回统一 CModel 响应,模块方法返回值位于 data

{
  "contractVersion": "1.0.0",
  "errorCode": "0",
  "data": {
    "id": 1001,
    "code": "COURSE-001",
    "name": "高等数学"
  }
}

调用方收到 HTTP 200 后,根据 errorCode 判断业务结果,再读取成功响应的 data。常见失败边界由稳定错误码表达:

错误码类别含义
参数错误target、method 或 JSON 参数格式错误
未授权缺少、过期或无效的 appClientToken
禁止访问token 不属于当前安装、应用未声明方法,或当前用户没有方法权限
上游失败模块运行时或内部调用链返回失败

业务组件只在 SDK 确认 App Gateway 会话失效并清空 client.getSession() 后重新授权。后端业务 CModel UNAUTHORIZED 不代表登录失效,即使 HTTP 状态为 401 也应保留会话。详见 错误与会话处理

使用标准 SDK

业务组件不得自行拼接授权头、平台地址或调用 URL,应复用应用启动时创建的标准客户端:

const course = await client.call(
  {
    type: "module",
    bundleId: "course-management",
    moduleId: "course-directory",
  },
  "createCourse",
  {
    code: "COURSE-001",
    name: "高等数学",
    teacherId: 123,
    tags: ["必修", "一年级"],
  },
);

客户端由 @baijimu/platform-application-sdk 提供。它读取当前安装会话、发送 Bearer token、解析严格 CModel 响应,并在 401 时清除当前会话。不同部署环境的 appGatewayApiBase 由应用部署配置注入, 不能在业务组件中散落生产域名。

调用前提

一次调用只有同时满足以下条件才会执行:

  1. appClientToken 有效且属于 URL 中的 installId
  2. 安装记录处于启用状态,并具有对应运行态应用。
  3. 当前平台应用版本声明了请求中的 targetmethod
  4. module 或 interface target 已在安装态解析到具体 Runtime 服务,并具有有效的安装态调用身份。
  5. 当前工作区用户拥有调用该模块方法的权限。
  6. 目标模块已由当前 Bundle 或其已解析依赖 Bundle 安装物化且方法可用。

App Gateway 通过这些检查并完成安装态解析后,才把方法和请求参数转换为内部运行时调用。前端不需要 了解内部调用信封或模块的后端 HTTP 实现。

新应用统一使用结构化 target 调用入口;/services/{service}/methods/{method} 只服务历史 SDK 2.x 应用。不要把历史 /lowcode3/api、静态站点域名或 其他环境地址拼接为当前应用的 API 地址。

本页内容