在 HarmonyOS 业务应用里接入 @wps/wps_sdk 时,验收口径往往不止「能打开 Word」。合规场景通常还要求:文档尽量不在 WPS 侧持久化缓存、打开页带水印、分享/打印/导出等入口可控,以及关窗后结果回到本应用沙箱。这些能力分别落在注册层与 OpenFileRequest 的不同字段上。本文按调用链说明如何把策略写进一次打开请求,字段语义以官方对接文档为准。
一、策略在调用链中的位置
推荐时序:registerApp 成功 →(按凭据约定)setWpsFileToken → 文件入本应用沙箱 → 构造带策略的 OpenFileRequest → sendRequest →(可选)关窗回传后拷贝。
| 层级 | 目标 | 主要入口 |
|---|---|---|
| 接入 | 鉴权通过 | RegisterAppRequest |
| 授权 | 激活序列号(若凭据要求) | setWpsFileToken |
| 打开策略 | 不落地 / 水印 / 菜单 | enableLocalization / wpsWaterMarkParams / extraOptions |
| 结果 | 关窗拿回文件 | wpsTransferType |
一次堆满所有开关时,ResultCode.ERROR 很难归因。联调应先绿「可编辑打开」,再叠不落地与水印,最后才开回传。页面层只传业务策略对象,字段装配收在 Facade,便于 Code Review 与复测。
二、注册与序列号:先就绪再叠策略
未注册完成就 sendRequest 会 reject ,须 try/catch。appKey/appSecret 与 bundleName 绑定,调试包与正式包包名不同须分别申请,否则常见 1013。
若申请材料含激活序列号,对接文档推荐在注册 ResultCode.OK 后调用 WPSApi.setWpsFileToken,全局生效;不要每次打开再写 wpsToken。
typescript
let wpsReady = false;
async function ensureRegistered(
ctx: UIAbilityContext,
activationSn?: string
): Promise<void> {
if (wpsReady) return;
const r = await WPSApi.sendRequest(
new RegisterAppRequest(ctx, APP_KEY, APP_SECRET)
);
if (r.code === ResultCode.ERROR_CODE_AUTH_FAILURE) {
throw new Error(`1013: ${r.msg ?? ''}`);
}
if (r.code !== ResultCode.OK) {
throw new Error(`register ${r.code}`);
}
if (activationSn) {
WPSApi.setWpsFileToken(activationSn);
}
wpsReady = true;
}
换 HAR 后 clean;Release 不打印 secret。正式包包名再验一次注册。
三、不落地:enableLocalization 与强制关闭
「不落地」表示文档在 WPS 中打开后,不在 WPS 侧持久化缓存副本,并限制可能导致外泄的能力。在当前 HAR / 凭据约定下,该字段通常生效 ;默认未设置或 false 表示不落地,true 表示允许落地。
enableLocalization |
落地 | 敏感能力 |
|---|---|---|
未设置 / false |
不落地 | 被 SDK 强制关闭(即使 extraOptions 打开也无效) |
true |
可落地 | 不再强制关闭,由 extraOptions 细控 |
不落地时被强制关闭的能力包括:云文档/登录/收藏、分享、历史版本、另存为/打印/导出 PDF、复制粘贴剪切、文档截图、自动上传等。合规默认建议保持不落地;仅当业务明确需要落地缓存时再设 true,并同步收紧 extraOptions。
typescript
const req = new OpenFileRequest(ctx, sandboxPath);
req.enableEdit = true;
// 不落地(默认可不写);允许落地时:
// req.enableLocalization = true;
若同时开了 URI 回传,拷贝到本应用沙箱后,可按约定删除 WPS 侧临时文件;删除失败只打日志,勿挡住已得到的本应用路径。
四、水印与 extraOptions:策略层细控
水印通过 wpsWaterMarkParams(如 Enable、WaterMaskText、Angle)在打开时注入。功能开关用 OpenFileExtraOptions 控制分享、云文档、打印等入口。注意:不落地模式下部分开关会被强制关闭,联调时不要误判为「extraOptions 没生效」。
typescript
req.wpsWaterMarkParams = {
Enable: true,
WaterMaskText: '内部资料',
Angle: -30,
};
const opt = new OpenFileExtraOptions();
// 可落地时再按需关闭分享/打印等;不落地时部分项会被强制关
req.extraOptions = opt;
预览入口与编辑入口共用 Facade,只差布尔与策略对象,避免复制两套 new OpenFileRequest。
五、回传与沙箱:结果必须先拷贝
合规闭环通常还要求编辑结果回到本应用。显式设置 wpsTransferType = TransferType.URI(或 FD)后,Promise 会等到用户关窗;result.data.fileUri 在 WPS 沙箱,必须拷贝到本应用目录再上传/归档。未开回传时 OK 且 data 空属正常。
路径打开前先把选择器文件拷入 filesDir。外部 URI 直传易落到笼统 ERROR。页面层不要自己猜 data 为何为空:未开回传与开了回传是两种等待语义。Facade 建议同时返回 result 与 localPath,业务只消费本应用路径。
并发打开两份文档时,拷贝目录按时间戳隔离,避免互相覆盖。清理临时文件失败不应把用户带到失败页------本应用路径已经可用。日志固定打:是否不落地、是否已设 Token、是否已开回传、code/msg。
六、联调清单
- 注册 OK;需要序列号则已
setWpsFileToken - 沙箱可编辑打开(先不叠策略)
- 确认不落地默认;再验水印可见
- 可落地时再测 extraOptions 单项
- URI 回传 + 拷贝成功;(可选)清理 WPS 临时文件
- 正式包包名复测 1013 与不落地
| 现象 | 优先查 |
|---|---|
| 1013 | key/secret/包名/HAR |
| extraOptions 无效 | 是否处于不落地强制关闭 |
| 只能预览 | enableEdit |
| OK 且 data 空 | 是否未开回传 |
Code Review 看四项:是否绕开 ensureRegistered、是否打印 secret、是否外部路径直传、是否一次堆满策略导致无法归因。换 HAR 后 clean;Token 只在注册成功后注入。
七、小结
合规打开策略 = 注册就绪 +(按需)序列号 + 不落地默认 + 水印/菜单细控 + 回传拷贝。把差异收在 Facade,页面只传业务策略对象。字段以官方对接文档为准;换 HAR 后 clean;周五用正式包再验注册与不落地各一次。
坚持分层联调,比一次堆满开关更省时间。注释写清「不落地时部分 extraOptions 会被强制关闭」,可减少误报工单。把「默认不落地」「回传先拷贝」「正式包包名复测」写进联调页,新人合入会稳很多。细节更新时先改 Facade,再改页面。
基于 WPS Open SDK 鸿蒙版对接实践整理,仅供开发者参考。