在鸿蒙应用里接入 WPS Open SDK,文档打不开时,很多团队会先去检查文件路径、enableEdit 或水印参数,却忽略了更靠前的一步:应用是否已经完成注册。WPSApi.registerApp 不是一个可选的初始化调用,而是后续所有文档请求的准入条件。回调尚未返回 ResultCode.OK 时调用 sendRequest,得到的是 Promise 异常,不是一次正常的打开失败。把注册设计成应用级门禁,通常比在每个页面重复调用更容易维护。

本文从实际接入顺序出发,拆解 registerApp 的输入、返回值和常见错误,并给出一套可复用的初始化封装。示例重点处理两个问题:应用启动阶段如何保证只注册一次,以及页面打开文档时如何确认 SDK 已经就绪。

一、注册解决的是调用资格问题

WPS Open SDK 会用 appKey 和 appSecret 校验当前应用是否具备调用资格。校验在本地完成,不依赖临时网络请求,但这并不意味着可以省略注册。凭据由 WPS 签发,并与申请时填写的 Bundle 包名绑定;运行时包名、HAR 批次或凭据任意一项不匹配,都可能让注册停在认证失败。

注册成功后,SDK 才允许业务代码发起 OpenFileRequest。因此整条链路可以写成:

HAR 集成 → registerApp → ResultCode.OK → OpenFileRequest → sendRequest

这里的 ResultCode.OK 是明确的门槛。页面层可以展示“文档能力初始化中”,但不能在回调到达前抢先发起请求。否则日志里常见的现象是:业务提示“文档打开失败”,底层实际抛出“应用尚未注册”的异常,排查方向从一开始就偏了。

二、registerApp 的输入与返回值

入口签名为 WPSApi.registerApp(appKey, appSecret, callback)。第三个参数必须包含 onCallback,结果通过 Result 返回。业务侧至少要记录 result.code 与 result.msg,但不要打印完整的 appSecret。

返回情况含义处理方式
ResultCode.OK注册成功标记 SDK 就绪,允许后续请求
ResultCode.ERROR参数错误等通用失败先检查 key、secret 是否为空
1013 / ERROR_CODE_AUTH_FAILURE接入凭据校验失败对照包名、凭据与 HAR 批次
Promise reject未注册成功就调用 sendRequest回到初始化门禁,不要重试打开参数

需要激活序列号的交付包,应在注册成功回调中调用 WPSApi.setWpsFileToken(token),一次设置后作用于后续请求。不要在每个 OpenFileRequest 上重复写 wpsToken,也不要让页面层自行决定是否注入序列号。注册模块统一处理,调用方只消费“是否就绪”。

三、把注册收成幂等初始化

注册最适合放在应用启动或首个文档能力入口之前,而不是绑定在“打开文档”按钮的点击事件里。按钮可能被快速点击多次,页面也可能重建,如果每次点击都调用注册,容易出现重复回调和状态不一致。

下面的封装同时保存就绪状态与进行中的 Promise,保证并发调用只触发一次注册:

import { WPSApi, Result, ResultCode } from '@wps/wps_sdk';

let sdkReady = false;
let booting: Promise<void> | null = null;

export function ensureWpsReady(
  appKey: string,
  appSecret: string,
  activationSn?: string
): Promise<void> {
  if (sdkReady) {
    return Promise.resolve();
  }
  if (booting) {
    return booting;
  }

  booting = new Promise<void>((resolve, reject) => {
    WPSApi.registerApp(appKey, appSecret, {
      onCallback: (result: Result) => {
        if (result.code !== ResultCode.OK) {
          booting = null;
          reject(new Error(`registerApp ${result.code}: ${result.msg ?? ''}`));
          return;
        }

        if (activationSn) {
          WPSApi.setWpsFileToken(activationSn);
        }
        sdkReady = true;
        resolve();
      },
    });
  });

  return booting;
}

export function isWpsReady(): boolean {
  return sdkReady;
}

booting 的存在解决了两个页面同时初始化时的竞态;失败后将其清空,则允许下一次用户操作重新尝试。错误信息中保留 code 和 msg,方便设备日志直接定位到认证失败或参数缺失。

四、打开侧只消费就绪状态

业务页面不需要理解注册细节。它只需先等待 ensureWpsReady(),再构造文档请求。下面的 helper 把未注册异常和打开失败分开记录:

import { common } from '@kit.AbilityKit';
import { OpenFileRequest, Result, ResultCode, WPSApi } from '@wps/wps_sdk';
import { ensureWpsReady } from './WpsBootstrap';

export async function openDocument(
  context: common.UIAbilityContext,
  sandboxPath: string,
  appKey: string,
  appSecret: string
): Promise<Result> {
  await ensureWpsReady(appKey, appSecret);

  const request = new OpenFileRequest(context, sandboxPath);
  request.enableEdit = true;

  try {
    const result = await WPSApi.sendRequest(request);
    if (result.code !== ResultCode.OK) {
      console.error('[WPS] open rejected', result.code, result.msg);
    }
    return result;
  } catch (error) {
    console.error('[WPS] open exception', error);
    throw error;
  }
}

这样做还有一个好处:页面可以把“WPS 尚未就绪”和“WPS 已就绪但文件无法打开”展示成不同提示。前者通常是初始化或凭据问题,后者才需要继续检查沙箱路径、文件权限和请求参数。

五、凭据、包名与序列号的边界

接入凭据与包名绑定,是接入阶段最容易被忽略的约束。调试包、内测包和正式包的 Bundle 名称只要不同,就应分别确认凭据是否覆盖对应包名。把调试环境可用的 key/secret 直接带进正式包,却在出现 1013 后反复调整 OpenFileRequest,通常不会解决问题。

激活序列号则是另一条独立链路。需要它的交付包应在注册成功后设置,不需要的形态不应额外注入。建议把两类配置分开管理:

  1. appKey / appSecret:只用于 registerApp,与包名强绑定。
  2. 激活序列号:仅在对应交付形态下,于注册成功回调内设置。
  3. OpenFileRequest:只承载文件路径、编辑模式和文档能力参数,不再重复设置序列号。

发布构建中不要把完整 secret 写入日志。更稳妥的做法是打印凭据来源、HAR 文件名、运行时 Bundle、注册 code/msg,这些信息已经足够完成大部分定位。

六、1013 与未注册异常要分层处理

1013 表示接入凭据校验失败。遇到它时,先暂停水印、修订和功能开关实验,按下面顺序对表:

  • 运行时 Bundle 名称是否与申请凭据时填写的一致。
  • 当前 HAR 是否来自同一个交付批次,是否混用了旧版本。
  • appKey 与 appSecret 是否成对,是否包含多余空格。
  • 凭据是否仍在有效期内,近期是否更换过包名或签名配置。

而“应用尚未注册”的异常说明时序不对:sendRequest 在注册成功前被执行。它和 1013 的区别是,前者要修初始化顺序,后者要修身份配置。把两种错误合并成一条“文档打开失败”,会让现场日志失去价值。

七、上线前的回归顺序

注册相关改动建议按固定顺序回归,避免一次放入太多变量:

  1. 冷启动应用,确认注册回调返回 ResultCode.OK。
  2. 确认需要激活序列号的交付包已在成功回调中完成设置。
  3. 用应用沙箱中的测试文件执行一次只读打开。
  4. 再开启编辑模式,验证 sendRequest 返回成功。
  5. 如启用关闭回传,最后检查结果文件是否转入业务沙箱。
  6. 更换 HAR 或包名后,从注册步骤重新开始,不跳过前置检查。

把注册模块、打开 helper 和页面状态拆开后,升级 SDK 时通常只需要回归两个文件。日志统一使用 [WPS] register、[WPS] open 前缀,也能让远程协助快速区分初始化问题与文档参数问题。对于鸿蒙 WPS 二开项目,这套门禁比在业务页面散落注册调用更容易长期维护。


基于 WPS Open SDK 鸿蒙版对接实践整理,仅供开发者参考。
官方对接文档:https://365.kdocs.cn/l/clQl5cek2NoT

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐