HarmonyOS WPS Open SDK:用 SdkConstants 识别当前集成 HAR
在 HarmonyOS 应用里接入 @wps/wps_sdk 之后,联调最容易被忽略的不是 OpenFileRequest 字段,而是「当前进程到底加载了哪一份 HAR」。同一套业务代码若对接多套凭据、多份交付包,打开失败常被记成「路径不对」或「1013」,根因其实是运行时形态与构建注入不一致。官方对接文档给出的做法是:用 SDK 导出的 SdkConstants 做公开查询,不要自行解析设备上的 WPS 客户端包名。本文把查询收进适配层,再接到 RegisterAppRequest、setWpsFileToken 与 sendRequest,字段语义以官方对接文档为准。
一、为什么「看 WPS 包名」会误判
三方应用拉起的是本机已安装的 WPS 客户端,而 @wps/wps_sdk 是编译进本应用的 HAR。两套身份独立:客户端装错、HAR 换错、凭据绑错包名,会组合成完全不同的失败面。只看桌面图标或 bundleName 去猜「当前 SDK 是哪一种」,会把客户端渠道和 HAR 形态绑死,换机或换渠道包后立刻失真。
更稳的分层是:
| 层 | 问什么 | 不该怎么做 |
|---|---|---|
| 构建 | oh-package.json5 依赖的是哪份 wps_sdk.har |
手工改业务页 if |
| 凭据 | appKey / appSecret 是否与当前 bundleName 匹配 |
调试密钥写进正式包 |
| 运行时 | SdkConstants 对当前 HAR 的公开查询结果 |
解析 WPS 包名字符串 |
| 打开 | WPSApi.sendRequest(OpenFileRequest) 是否已过注册门禁 |
未注册就打开 |
SdkConstants 的职责是告诉你「这份 HAR 在运行时认为自己是哪种交付形态」,不是告诉你「用户手机里的 WPS 叫什么」。页面层一旦散落包名判断,Code Review 很难收敛。
换 HAR 后必须 clean 再编译。缓存的旧 HAR 会让日志里的「当前形态」与 libs/ 目录文件名对不上,表现为调试包正常、正式包 1013,或 Token 注入了却完全没生效。接入评审把「HAR 文件名 + 包名 + 是否走适配层查询」写成三项,比事后对日志更省时间。
二、编译期:先钉死 HAR 与凭据
工程依赖通常写在 oh-package.json5:
{
"dependencies": {
"@wps/wps_sdk": "file:./libs/wps_sdk.har"
}
}
构建变体若对应多份 HAR,不要在运行时再「探测文件名」。正确做法是:每个 product / flavor 指向自己的 libs/ 与自己的凭据模块。业务页只 import CRED,不 import 两套 APP_KEY。
| 构建产物 | 建议注入 |
|---|---|
| 调试包 | 调试 bundleName 对应的 key/secret,序列号可空 |
| 正式包 | 正式包名对应凭据;需要全局 Token 时注入序列号 |
| 多渠道 | 每个 Bundle 单独申请,禁止混用 |
registerApp 在本地校验凭据,不联网。包名与申请材料不一致会落到 ResultCode.ERROR_CODE_AUTH_FAILURE(1013)。这与「当前 HAR 形态」是两件事:形态对了但包名错了,照样 1013;包名对了但 HAR 与凭据渠道不匹配,也会 1013。日志同时打:包名后缀、是否已注册、适配层查询结果、是否调用了 setWpsFileToken。
Release 不要打印完整 secret。序列号同样按构建注入,不要写死在打开页。限时凭据失效需重新申请,不要用「再点一次打开」掩盖鉴权问题。
三、运行时:把 SdkConstants 收进适配层
对接文档写明:SDK 提供公开方法区分当前集成包,厂商不必判断 WPS 包名。推荐只在 wpsAdapter.ts 使用 SdkConstants,对外只暴露「是否需要全局 Token」「当前形态标签」这类业务布尔值。页面禁止直接 import { SdkConstants }。
import { common } from '@kit.AbilityKit';
import {
WPSApi,
RegisterAppRequest,
OpenFileRequest,
ResultCode,
SdkConstants,
} from '@wps/wps_sdk';
let wpsReady = false;
function needsGlobalToken(sn?: string): boolean {
// 官方公开查询只允许出现在适配层;页面只拿布尔结果。
// 第二道门:构建未注入序列号则不调用 setWpsFileToken。
return queryHarNeedsToken(SdkConstants) && !!sn;
}
function queryHarNeedsToken(constants: typeof SdkConstants): boolean {
const keys = Object.getOwnPropertyNames(constants);
const fnName = keys.find((k) => k.startsWith('is') && k.endsWith('Sdk'));
const fn = fnName ? (constants as Record<string, unknown>)[fnName] : undefined;
if (typeof fn !== 'function') {
return true; // 无法查询时退化为「仅由序列号是否注入决定」
}
return !Boolean((fn as () => boolean).call(constants));
}
async function ensureRegistered(
ctx: common.UIAbilityContext,
cred: { key: string; secret: string; sn?: string }
): Promise<void> {
if (wpsReady) return;
const r = await WPSApi.sendRequest(
new RegisterAppRequest(ctx, cred.key, cred.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 (needsGlobalToken(cred.sn)) {
WPSApi.setWpsFileToken(cred.sn as string);
}
wpsReady = true;
}
上面用 Reflect.get 是为了把「官方方法名」收在适配层一处,避免业务文件到处出现查询调用。也可直接写官方方法名;原则不变:查询结果不得驱动 UI 文案,只驱动 Token 与少数字段是否赋值。
也可用回调式 WPSApi.registerApp(appKey, appSecret, { onCallback })。无论哪种,业务打开前必须 wpsReady === true。打开按钮在注册完成前禁用。未完成 RegisterAppRequest 就 sendRequest 会进 catch,这不是打开失败,而是门禁未过。
若构建已注入序列号,对接文档推荐在注册 ResultCode.OK 后调用 WPSApi.setWpsFileToken,全局生效;不要每次构造 OpenFileRequest 再写 wpsToken。若同时设置全局 Token 与 request.wpsToken,以全局设置为准。无序列号的交付形态不要调用 setWpsFileToken。
四、打开链:形态判断之后才是 OpenFileRequest
识别 HAR 只解决「注册后要不要注入 Token」。打开文档仍走标准链:文件入本应用沙箱 → new OpenFileRequest(ctx, sandboxPath) → WPSApi.sendRequest → 按 Result.code / msg / data 分支。
async function openLocalDoc(
ctx: common.UIAbilityContext,
sandboxPath: string,
editable: boolean
) {
await ensureRegistered(ctx, CRED);
const req = new OpenFileRequest(ctx, sandboxPath);
req.enableEdit = editable;
return WPSApi.sendRequest(req);
}
外部选择器路径先 copyFileSync 到 filesDir。直传外部 URI 容易落到笼统 ResultCode.ERROR。预览与编辑共用一个函数,只差布尔参数。一次堆满 extraOptions、水印、回传时,失败很难归因;联调先绿「形态查询 + 注册 + 只读打开」,再开可编辑,最后才是 URI 回传。
enableLocalization 等字段在部分交付形态上赋值不生效。不要用「设了却没反应」反推 HAR 形态——应回头看适配层查询与构建注入是否一致。策略字段是否生效,以官方对接文档对应当前 HAR 的说明为准。
五、不要和 WPS 客户端版本弹窗搞混
OpenFileRequest.wpsUpdateInfo 配置的是 WPS 客户端版本更新弹窗(versionCode / versionName / 是否强制更新),与「当前集成的 SDK HAR 是哪一种」不是同一问题。前者面向用户侧客户端升级;后者面向三方应用编译进去的 @wps/wps_sdk。
| 对象 | 入口 | 典型误用 |
|---|---|---|
| SDK HAR 形态 | SdkConstants + 构建注入 |
用客户端包名猜测 HAR |
| 接入凭据 | registerApp / 1013 |
换包名不换 key |
| 客户端更新 | wpsUpdateInfo |
用弹窗结果判断 HAR |
联调日志建议固定五字段:HAR 文件名(构建期写入)、包名后缀、适配层形态标签、是否已 setWpsFileToken、Result.code。缺任一项,现象会对不上根因。真机至少覆盖:调试包注册、正式包包名再验、故意未注册确认 catch。
六、联调清单
oh-package.json5指向预期 HAR,clean 后重编- 适配层查询结果与构建 flavor 一致
RegisterAppRequest返回ResultCode.OK(正式包包名再验)- 需要 Token 的形态在 OK 回调注入;不需要则确认未调用
- 沙箱路径只读打开
sendRequest - 再开
enableEdit = true;(可选)URI 回传并拷贝
| 现象 | 优先查 |
|---|---|
| 抛异常 | 是否未注册就 sendRequest |
| 1013 | key/secret/包名/HAR 是否一套 |
| Token 无效 | 形态查询与是否调用 setWpsFileToken |
| 字段赋值无效果 | 当前 HAR 是否支持该字段 |
| 只能预览 | enableEdit |
Code Review 看五项:业务页是否 import 了 SdkConstants、是否解析 WPS 包名、是否打印 secret、是否外部路径直传、是否忽略 catch。每步只改一类行为,失败回滚到上一绿点。
PR 勾选:HAR 版本、包名、适配层是否单一入口、Release 无密钥。产品口头「要能打开」时,落到:形态是否认对、注册是否绿、路径是否在沙箱。周五用正式包再跑步骤 1–5。同一工程多渠道包提前列全 Bundle 名;换包名须重新申请凭据。
七、小结
鸿蒙上 WPS Open SDK 的「当前 SDK 版本 / 形态」应这样认:构建钉死 HAR 与凭据,运行时用 SdkConstants 公开查询,查询只放在适配层,再用结果决定要不要 setWpsFileToken,最后才 sendRequest 打开文档。 不要用 WPS 客户端包名或更新弹窗代替 HAR 识别。
把「禁止页面层解析包名」「查询收敛到 adapter」「1013 同时核对 HAR 与包名」写进联调页。坚持清单两周,形态相关的反复提问通常会下降。字段与错误码以官方对接文档为准;换 HAR 后 clean;正式包包名复测注册。策略开关要加就单独建用例,不要和形态判断搅在同一次提交里。
基于 WPS Open SDK 鸿蒙版对接实践整理,仅供开发者参考。
官方对接文档:https://365.kdocs.cn/l/clQl5cek2NoT
更多推荐


所有评论(0)