import router from '@ohos.router';
import common from '@ohos.app.ability.common';
import { TencentQianWebViewConfig } from './model/TencentQianWebViewConfig';
import { OnSignResult, OnSdkEvent } from './model/SignCallback';
import { SignResultParser } from './scheme/SignResultParser';
import { IntentBridge } from './internal/IntentBridge';
import { TencentQianWebViewPrewarmer } from './TencentQianWebViewPrewarmer';
/**
* TencentQianWebView SDK 主入口。
*
* **典型用法**:
* ```ts
* TencentQianWebView.open(
* getContext(this) as common.UIAbilityContext,
* 'https://example.com/sign?flowId=xxx',
* new TencentQianWebViewConfig(),
* (result) => {
* console.log('sign result', result.action, result.result);
* }
* );
* ```
*/
export class TencentQianWebView {
/**
* 自检页 URL 常量(SDK 默认 beta 环境,兼容性测试无需切生产)。
*/
public static readonly COMPATIBILITY_TEST_URL: string =
'https://quick.beta.qian.tencent.cn/compatibilityTest';
/** 容器内置页面的注册名(配套 router_map.json)。 */
private static readonly INTERNAL_PAGE_NAME: string = 'TencentQianWebViewPage';
/**
* 在 SDK 内置容器页面中打开 H5 URL(页面形态,主推)。
*
* SDK 自动接管整个签署生命周期:
* - 内置顶栏、进度条、关闭确认对话框
* - 拦截 `qianapp://` 协议,触发 `onSignResult` 回调并自动关闭页面
* - 处理权限申请、文件选择、下载、JS 弹窗
*
* 调用后立即返回,签署结果通过 `onSignResult` 异步回调。
*
* @param context UIAbility/页面 context
* @param url 目标 H5 URL
* @param config 容器配置(可省,使用默认)
* @param onSignResult 签署结果回调(必填)
* @param onSdkEvent SDK 事件回调(可选,用于日志/埋点)
*/
public static async open(
context: common.UIAbilityContext,
url: string,
config: TencentQianWebViewConfig | null,
onSignResult: OnSignResult,
onSdkEvent?: OnSdkEvent
): Promise<void> {
const effectiveConfig: TencentQianWebViewConfig =
config !== null && config !== undefined ? config : new TencentQianWebViewConfig();
// 预热环境错配检测(best-effort,仅告警,不阻断)
TencentQianWebViewPrewarmer.warnIfEnvironmentMismatch(url);
IntentBridge.set({
url: url,
config: effectiveConfig,
onSignResult: onSignResult,
onSdkEvent: onSdkEvent
});
try {
await router.pushNamedRoute({
name: TencentQianWebView.INTERNAL_PAGE_NAME
});
} catch (e) {
IntentBridge.clear();
const reason: string = (e instanceof Error) ? e.message : String(e);
console.error('[TencentQianWebView] router.pushNamedRoute failed: ' + reason);
}
}
/**
* 打开 SDK 自检页,用于在客户 App 中快速验证 SDK 集成情况
* (UA 注入、scheme 拦截、文件上传、协议跳转等)。
*
* 默认走 SDK 内置 beta 环境地址,客户也可通过 `config.compatibilityTestUrl` 自定义。
*
* @param context UIAbilityContext
* @param config 容器配置(可省)
* @param onSignResult 签署结果回调(可省,自检页通常不关心)
* @param onSdkEvent SDK 事件回调(可省)
*/
public static async openCompatibilityTest(
context: common.UIAbilityContext,
config?: TencentQianWebViewConfig,
onSignResult?: OnSignResult,
onSdkEvent?: OnSdkEvent
): Promise<void> {
const effectiveConfig: TencentQianWebViewConfig =
config !== null && config !== undefined ? config : new TencentQianWebViewConfig();
const url: string = effectiveConfig.compatibilityTestUrl !== null
&& effectiveConfig.compatibilityTestUrl !== undefined
&& effectiveConfig.compatibilityTestUrl.length > 0
? effectiveConfig.compatibilityTestUrl
: TencentQianWebView.COMPATIBILITY_TEST_URL;
// 自检页若客户不关心 sign result,提供空回调
const callback: OnSignResult = onSignResult !== undefined
? onSignResult
: (_r): void => {
// no-op
};
await TencentQianWebView.open(context, url, effectiveConfig, callback, onSdkEvent);
}
/** 当前 SDK 版本号字符串。 */
public static sdkVersion(): string {
return '1.2.0';
}
/**
* 判断给定 URL 是否是 SDK 可识别的 `qianapp://` 协议。
*
* 用于客户在自有 Web 组件的 `onLoadIntercept` 中先做判断,然后决定是否
* 转交 SDK 解析(配置模式集成方式),避免容器外的导航被静默吞掉。
*/
public static canHandle(url: string): boolean {
return SignResultParser.isQianAppScheme(url);
}
// ArkTS 类禁止实例化
private constructor() {}
}
|