在 HarmonyOS 工程里接入 @wps/wps_sdk,很多问题并不是出在 OpenFileRequest 的参数上,而是发生在更前面的注册阶段:HAR 已经放进工程,页面也能正常编译,但调用 sendRequest 后立刻被 Promise 拒绝;或者 registerApp 回调直接返回鉴权失败。此时继续调整文档路径、编辑模式或界面按钮,往往只会扩大排查范围。真正需要先确认的是三件事:申请到的接入凭据是否有效、凭据对应的 Bundle 包名是否一致、registerApp 是否已经成功返回。

WPS Open SDK 鸿蒙版把打开文档的入口收敛到 WPSApi。业务侧看起来只需要“注册”和“打开”两个动作,但底层存在明确的前后依赖:应用必须先取得与包名绑定的 appKey / appSecret 和匹配的 HAR,再在运行期完成 registerApp,之后才能发起文档请求。把这条链路拆开验证,比在打开失败后反复猜参数更有效。本文按照申请材料、工程集成、注册封装、异常归因和联调清单的顺序,整理一套可直接落地的实现方式。

一、凭据在调用链中的位置

一次完整的接入通常包含五个节点:

  1. 通过官方渠道提交应用信息与 Bundle 包名,取得 appKey、appSecret 和对应批次的 SDK HAR。
  2. 将 wps_sdk.har 放入工程目录,并在 oh-package.json5 中声明依赖。
  3. 应用启动或进入文档模块时调用 registerApp,等待 ResultCode.OK。
  4. 如果当前交付约定需要激活序列号,在注册成功回调中调用 setWpsFileToken。
  5. 构造 OpenFileRequest,通过 sendRequest 拉起文档,并处理返回的 Result。

这里最容易混淆的是“注册成功”和“打开成功”。注册解决的是应用是否有权调用 SDK;打开解决的是目标文件、客户端环境和请求参数是否可用。两者返回的错误语义不同,日志也应该分开记录。若应用尚未注册成功,sendRequest 会直接抛异常,并不会进入正常的文档打开回调。

接入材料主要作用需要核对的关系
SDK HAR提供 WPSApi、请求模型和结果类型与申请时说明的交付批次一致
appKey / appSecret校验第三方应用接入资格与最终安装包的 Bundle 包名绑定
激活序列号(按交付约定)补齐产品侧授权在注册成功后全局设置
目标文档路径指定待打开文件位于本应用可访问的沙箱目录

这张表也解释了为什么“同一套代码换个项目就不能用”。代码本身可能没有问题,但凭据、包名和 HAR 批次已经发生了变化。接入前先把这些对应关系固定下来,后续联调才有稳定的比较基准。

二、申请邮件应写清哪些字段

申请 SDK 接入材料时,不需要写成长篇方案,但要把工程侧能够核对的字段一次说明白:

  • 应用名称,以及文档模块的实际用途,例如预览、编辑或关闭后回传。
  • 最终安装包的 Bundle 名称,包括调试包与正式包是否使用不同包名。
  • 所需 SDK HAR 的交付说明,确保后续拿到的是同一批次材料。
  • 应用联系人,以及便于回访的官方沟通方式。
  • 若交付方案中包含激活序列号,需明确它会通过另一条渠道确认。

包名是最值得反复确认的字段。代码里的 bundleName、签名配置中的包名、应用市场登记的包名和申请单上的包名必须一致。调试阶段经常出现一种情况:开发包使用 .debug 后缀,而凭据按正式包名签发,结果真机上一注册就返回 ERROR_CODE_AUTH_FAILURE,文档码值通常显示为 1013。这类问题不是密钥字符写错,而是应用身份没有对上。

凭据属于敏感配置,不应硬编码在页面代码中,也不应进入公开仓库或完整打印到 Release 日志。比较稳妥的做法是通过构建配置或 CI 密钥注入,只保留非敏感的核对信息,例如包名、HAR 文件名和 key 的末几位。排障时能够确认“当前运行的是哪套配置”即可,不需要暴露完整 secret。

三、集成 HAR 并建立最小依赖

将 WPS 交付的 wps_sdk.har 放到工程的 libs 目录,然后在模块的 oh-package.json5 中声明本地依赖:

{
  "dependencies": {
    "@wps/wps_sdk": "file:./libs/wps_sdk.har"
  }
}

依赖写入后执行 ohpm install。如果之前集成过其他批次的 HAR,建议先清理构建缓存再重新安装,否则旧类型定义或旧产物可能继续参与编译,导致“代码已更新但行为没变化”的假象。

业务代码从统一包名导入:

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

HAR 集成完成后,先不要急着写复杂的文档页面。可以保留一个最小验证入口,只做注册和状态输出,确认基础依赖可用,再逐渐加入打开、编辑和水印等能力。这样做的好处是,当后续功能出现异常时,可以快速判断问题是在 SDK 基础链路,还是在具体业务参数。

四、用可复用函数封装 registerApp

registerApp 使用回调返回结果,建议在应用内封装为 Promise,并保证同一个进程只发起一次注册。这样页面按钮、冷启动恢复和多个文档入口都可以共享同一个就绪状态。

let readyPromise: Promise<void> | null = null;

function ensureRegistered(
  appKey: string,
  appSecret: string,
  activationSn?: string
): Promise<void> {
  if (readyPromise) {
    return readyPromise;
  }

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

        if (activationSn) {
          WPSApi.setWpsFileToken(activationSn);
        }
        resolve();
      }
    });
  });

  return readyPromise;
}

这段封装有三个关键点。一方面,注册失败时清空 readyPromise,让调用方在修正配置后仍有机会重试,而不是永久停留在一个失败的 Promise 上。另一方面,激活序列号只在注册成功且交付方案确实需要时设置;没有该需求时不要传入无意义的值。此外,序列号通过 setWpsFileToken 全局设置,后续打开请求不需要反复携带 wpsToken。

如果应用存在多个 Ability 或多个文档入口,还应把 SDK 就绪状态提升到共享模块,避免每个页面各自调用注册。重复注册不仅增加状态分支,也可能让日志出现多份互相覆盖的回调,难以判断最终哪一次成功。

五、注册成功后再打开文档

打开入口应把“等待注册完成”作为硬性前置条件。下面的函数在真正发起请求前再次等待 ensureRegistered,可以覆盖用户连续点击、页面恢复和异步初始化等场景:

import { common } from '@kit.AbilityKit';

async function openDocument(
  context: common.UIAbilityContext,
  filePath: string,
  appKey: string,
  appSecret: string,
  activationSn?: string
): Promise<Result> {
  await ensureRegistered(appKey, appSecret, activationSn);

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

  return WPSApi.sendRequest(request);
}

enableEdit 未设置或设置为 false 时,文档以只读方式打开;需要编辑能力时必须显式设为 true。同时,filePath 应指向本应用可访问的沙箱路径。如果文件来自系统选择器或临时授权目录,建议先复制到应用沙箱,再交给 SDK,避免拉起 WPS 后因权限失效出现打开异常。

调用侧还应区分两类异常:registerApp 返回的业务失败码,以及 sendRequest 因未注册而抛出的异常。前者通常指向凭据、包名或交付材料,后者说明调用时序不正确。把两者都显示成“文档打开失败”,会掩盖真正的修复方向。

六、1013 与包名不一致的排查顺序

遇到鉴权失败时,可以按以下顺序检查,而不是先重写打开参数:

  1. 读取运行时实际 bundleName,与申请回执逐字比对。
  2. 确认当前构建变体注入的是否为对应环境的那套 appKey / appSecret。
  3. 确认 HAR 批次与申请材料一致,必要时清理构建缓存后重新安装。
  4. 检查凭据是否过期,或是否存在限时凭据到期的情况。
  5. 确认 registerApp 回调确实返回 OK 后,才允许调用 sendRequest。
现象优先检查项处理方向
注册回调返回 1013包名、key/secret、HAR 批次逐项与申请回执核对
注册回调参数错误key 或 secret 是否为空检查构建注入与环境变量
打开时 Promise 被拒绝是否在注册成功前发起请求将注册改为前置门禁
调试包正常、正式包失败两套包名是否分别申请分开配置凭据与构建参数
曾经可用、近期突然失败凭据有效期、HAR 是否被替换通过官方渠道续期或核验材料

排查日志建议统一加固定前缀,例如 [WPS][auth] 和 [WPS][open],并记录 bundleName、HAR 文件名、错误码和错误信息。不要在日志中输出完整密钥。这样既能支持问题定位,也能避免把敏感信息带到线上环境。

七、联调清单与小结

上线前可以把以下检查项加入工程清单:

  • 申请回执、Bundle 包名、HAR 批次和构建配置能够一一对应。
  • 所有文档入口都经过统一的 ensureRegistered,没有绕过注册状态。
  • 注册成功前不调用 sendRequest,失败后具备明确的提示和重试策略。
  • 需要序列号时只设置一次全局 token,不在每次请求中重复传递。
  • 打开前确认文件已位于应用沙箱,并根据业务要求设置 enableEdit。
  • 鉴权日志不包含完整 secret,正式包不输出调试凭据。

WPS Open SDK 鸿蒙版的能力入口并不复杂,真正影响接入效率的是对前置条件的理解。把凭据申请、HAR 集成、包名绑定和注册状态做成一条可核对的链路,后续打开、编辑、水印和关闭回传才有稳定的基础。遇到 1013 时,优先确认应用身份是否一致,通常比反复尝试不同请求参数更快定位问题。


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

Logo

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

更多推荐