在 HarmonyOS 应用里接入文档能力时,业务往往先问「能不能打开 Word」。真正开始联调后会发现:打开只是入口,后面还有只读/可编辑、水印、菜单开关、关窗回传等一串字段。WPS Open SDK 鸿蒙版把这些能力收在同一套对外模型里——依赖以 HAR 交付,入口是单例 WPSApi,打开统一走 OpenFileRequest,结果落在 Result。本文按接入主线做概述:先看调用链位置,再落到注册、打开、策略与回传,最后给出可复用封装与联调清单。字段语义以官方对接文档为准。

一、SDK 在工程里的位置

典型时序固定为:集成 @wps/wps_sdkregisterApp 成功 →(按凭据约定)可选 setWpsFileToken → 构造 OpenFileRequestWPSApi.sendRequest 拉起 WPS →(若开启回传)关窗后 Promise 兑现 Result.data

层级 职责 主要入口
依赖层 HAR、凭据、包名绑定 @wps/wps_sdk
接入层 应用注册、可选激活序列号 registerApp / setWpsFileToken
打开层 沙箱路径、只读/可编辑 OpenFileRequest.enableEdit
策略层 水印、修订、菜单、落地相关 wpsWaterMarkParams / extraOptions / enableLocalization
结果层 关窗后拿回文件 wpsTransferType / Result.data

概述阶段最容易踩的坑,是把「能打开」当成验收终点。工程上更稳的做法是:页面只依赖「注册是否就绪」与「打开函数」,能力按层叠加;不要为预览、编辑、带水印打开再复制三份请求构造逻辑。

二、接入层:registerApp 与可选序列号

对接文档要求:registerApp 回调未到 ResultCode.OK 之前调用 sendRequest 会抛异常。这不是「打开失败」,而是请求链尚未就绪。注册成功后,若当前凭据形态需要激活序列号,再调用 setWpsFileToken;是否注入序列号应依据 HAR / 凭据约定,不要用包名猜测。

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

let wpsReady = false;

function ensureRegistered(
  appKey: string,
  appSecret: string,
  activationSn?: string
): Promise<void> {
  return new Promise((resolve, reject) => {
    if (wpsReady) {
      resolve();
      return;
    }
    WPSApi.registerApp(appKey, appSecret, {
      onCallback: (result: Result): void => {
        if (result.code === ResultCode.ERROR_CODE_AUTH_FAILURE) {
          reject(new Error(`1013: ${result.msg ?? ''}`));
          return;
        }
        if (result.code !== ResultCode.OK) {
          reject(new Error(`register ${result.code}: ${result.msg ?? ''}`));
          return;
        }
        if (activationSn && activationSn.length > 0) {
          WPSApi.setWpsFileToken(activationSn);
        }
        wpsReady = true;
        resolve();
      }
    });
  });
}

冷启动可在 Ability 初始化阶段 await ensureRegistered;首页「打开文档」在 wpsReady 前禁用。Release 包不要打印完整 appSecret。换 HAR 或换构建变体后务必 clean,核对 bundleName 与申请凭据一致,否则会出现调试包正常、正式包 1013

三、打开层:OpenFileRequest 与沙箱路径

无论后续叠多少策略,打开请求都是同一个类型。常用字段职责如下:

字段 作用
构造参数 filePath 建议为本应用沙箱可读路径
enableEdit true 可编辑;默认/false 只读
wpsWaterMarkParams 水印
wpsRevisionParams 修订
extraOptions 分享、打印、导出等菜单级开关
enableLocalization 是否允许文档在 WPS 侧落地缓存
wpsTransferType 关窗回传方式(URI / FD)

默认只读是能力语义,不是缺陷:未设或为 false 时以只读打开;只有显式 true 才是可编辑。预览入口与编辑入口应共用同一打开函数,只差布尔参数。

import { common } from '@kit.AbilityKit';
import fs from '@ohos.file.fs';

function toSandbox(ctx: common.UIAbilityContext, src: string): string {
  const dir = `${ctx.filesDir}/wps_overview`;
  fs.mkdirSync(dir, true);
  const dest = `${dir}/${Date.now()}.docx`;
  fs.copyFileSync(src, dest);
  return dest;
}

async function openDocument(
  ctx: common.UIAbilityContext,
  src: string,
  editable: boolean,
  withTransfer: boolean
): Promise<Result> {
  await ensureRegistered(APP_KEY, APP_SECRET, ACTIVATION_SN_OR_EMPTY);
  const path = toSandbox(ctx, src);
  const request = new OpenFileRequest(ctx, path);
  request.enableEdit = editable;
  if (withTransfer) {
    request.wpsTransferType = TransferType.TRANSFER_TYPE_URI;
  }
  return WPSApi.sendRequest(request);
}

路径侧建议先把选择器文件拷到 filesDir 再传沙箱路径。直接传外部 URI 时,权限不足常落到泛化的 ResultCode.ERROR,日志里又看不到明确「权限」文案,联调成本很高。ACTIVATION_SN_OR_EMPTY 用构建配置注入:需要序列号的变体传真实值,不需要的变体传空,让 ensureRegistered 跳过 setWpsFileToken

四、策略层:水印、extraOptions 与落地相关字段

水印通过 wpsWaterMarkParams 注入文字、角度、颜色与字号。修订通过 wpsRevisionParams 控制作者名与是否进入修订模式。菜单级能力走 extraOptions:分享、云文档、打印、导出、截图、复制粘贴等,仅显式赋值的字段生效。未赋值不要假设「默认全关」。

落地相关字段(如 enableLocalization)按当前 HAR / 凭据形态生效。方案评审时应先确认约定,再讨论菜单矩阵;否则真机上会出现「改了开关却没变化」。实践里按这个顺序叠加更稳:

  1. 只读打开,验证注册与路径
  2. enableEdit = true,验证可编辑
  3. 水印 / 修订,验证策略注入
  4. extraOptions,只赋需要改的项
  5. 落地相关字段,确认当前凭据是否支持后再测
  6. 回传,关窗后处理 Result.data

一次写满所有开关,出了 ResultCode.ERROR 很难归因。

五、结果层:关闭回传与错误码

需要关窗拿结果时,打开 wpsTransferType(如 URI)。可编辑与回传是两个独立开关:别默认「能编辑就一定回传」,也别默认「回传就必须可编辑」,按入口语义组合。成功时关注 Result.code === ResultCode.OK,并从 Result.data 取回文件信息;拿到 WPS 侧路径后,通常还要再拷贝到本应用沙箱再使用。

现象 优先排查
sendRequest 直接抛异常 registerApp 尚未成功
ResultCode.ERROR_CODE_AUTH_FAILURE(1013) appKey/appSecret、包名与申请是否一致
打开失败、文案含参数不完整 路径是否为空、Context 是否有效
改了策略字段无变化 字段是否显式赋值;当前凭据是否支持该能力
回传后路径不可用 是否已从 WPS 侧路径拷回本应用沙箱

联调时把 codemsg 打全,比只打「打开失败」四个字有用。正式包不要打印完整 appSecret

六、可复用封装与联调清单

把「注册就绪」与「打开文档」拆成两个稳定入口,页面只调用它们:

export class WpsOverviewFacade {
  private ready = false;

  async prepare(appKey: string, appSecret: string, sn?: string): Promise<void> {
    if (this.ready) {
      return;
    }
    await ensureRegistered(appKey, appSecret, sn);
    this.ready = true;
  }

  async open(
    ctx: common.UIAbilityContext,
    sandboxPath: string,
    enableEdit: boolean,
    withTransfer = false
  ): Promise<Result> {
    if (!this.ready) {
      throw new Error('call prepare first');
    }
    const req = new OpenFileRequest(ctx, sandboxPath);
    req.enableEdit = enableEdit;
    if (withTransfer) {
      req.wpsTransferType = TransferType.TRANSFER_TYPE_URI;
    }
    return WPSApi.sendRequest(req);
  }
}

上线前建议至少核对:

  • 全仓是否只剩一处 new OpenFileRequest
  • 是否还残留逐次 request.wpsToken
  • Release 是否打印完整 secret
  • 正式包包名与申请凭据是否一致
  • 关窗回传是否在真机验过 Result.data

这样即便后续要叠加水印或菜单开关,也只需扩展 open 的可选参数,而不会在多个页面复制请求构造。统一调用链的价值,正是把学习成本压在一次模型理解上。

七、小结

鸿蒙侧 WPS Open SDK 的二开接入,可以概括为五句话:HAR 集成、单例 WPSApi、先 registerAppsendRequest、打开统一用 OpenFileRequest、结果统一看 Result。工程落地时,用可选步骤与字段生效范围表达差异,用 Facade 收敛页面调用。联调按「注册 → 路径 → 只读 → 可编辑 → 策略 → 回传」推进,比一次写满参数更易定位问题。字段与错误码请以官方对接文档为准,随 SDK 版本核对。


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

Logo

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

更多推荐