runner-bridge
TypeScript icon, indicating that this package has built-in type declarations

0.0.1-beta.55 • Public • Published

JSBridge wrapper for Runner-base hybird app

WebsiteDocumentation

Table of contents

Installing

Using npm:

$ npm install runner-bridge

Using yarn:

$ yarn add runner-bridge

Using pnpm:

$ pnpm add runner-bridge

Feature

  • 获取设备信息
  • 身份证扫描
  • 图片选择
  • 原生 Loading
  • PDF 预览
  • 跳转系统设置
  • 第三方应用跳转/判断第三方应用是否安装
  • 版本更新
  • 退出应用
  • 系统事件监听
    • 网络状态变化
    • 深色/浅色模式切换
    • 字体大小设置
    • Safe Area 变化(异形屏适配)
    • 自定义事件监听
  • 本地缓存
    • 保存数据
    • 获取数据
    • 移除数据
    • 清空数据
  • 页面导航
    • 设置系统状态栏
    • 设置顶部标题栏
    • 点击事件监听
    • 页面跳转
    • 页面返回
    • 回到首页
    • 设置首页tab
    • 获取首页tab
  • 社会分享
  • 网络请求
  • 人脸核验
  • 一键登录
  • 生物认证
  • 剪切板
  • 定位

Usage

import { installJSBridge } from "runner-bridge";

installJSBridge();

API

获取设备信息

Code Example

import { getDeviceInfo } from "runner-bridge";

async function example() {
  const result = await getDeviceInfo();
  if (result.type === "success") {
      console.info("Device Info", result.value);
  }
}

请求参数: 无 返回值: Promise<Result<DeviceInfo | undefined>>

字段名称 类型 是否必选 描述
platform Platform 平台类型(iOS,Android,等)
deviceCode string 设备唯一标识,应用卸载后不更改
appUniqueIdentifier string 应用唯一标识符,应用卸载重装后发生更改
packageIdentifier string 应用包名
deviceType DeviceType 设备类型
deviceModel string 设备型号
deviceName string 设备名称
osVersion string 系统版本
appVersion string 应用版本
language string 国际化编码
screenInfo ScreenInfo 屏幕信息,宽度-width,高度-height

身份证扫描

打开身份证扫描页

startIDCardScanner(params?: IDCardScannerParams): Promise<Result<string | undefined>>

关闭身份证扫描页面

finishIDCardScanner(): void

Code Example

async function example() {
    const frontResult = await startIDCardScanner({
        scannerType: "front",
    });

    if (frontResult.type === "success" && frontResult.value) {
        console.info("Front", frontResult.value);
        finishIDCardScanner();

        const backResult = await startIDCardScanner({
            scannerType: "back",
        });

        if (backResult.type === "success" && backResult.value) {
            console.info("Back", backResult.value);
        } else {
            console.info("身份证背面扫描失败");
        }
    } else {
        console.info("身份证正面扫描失败");
    }
}

请求参数: IDCardScannerParams

字段名称 类型 是否必选 描述
message string 页面标题
scannerType IDCardScannerType 身份证扫描类型(front-正面,back-背面)

返回值: Promise<Result<string | undefined>> 身份证图片 base64 编码

图片选择

Code Example

async function example() {
  const result = await showImagePicker({
    minCount: 1,
    maxCount: 9,
  });

  console.info("result", result);
}

请求参数: ImagePickerParams | undefined

字段名称 类型 是否必选 描述
maxCount number 最大可选图片数量
minCount number 最少必选图片数量

返回值: Promise<Result<\ImagePickerResult | undefined>>

字段名称 类型 是否必选 描述
images ImageEntry[] 图片列表

ImageEntry

字段名称 类型 是否必选 描述
base64 string 图片 base64 编码
extension string 图片扩展名

原生 Loading

  1. 通用 Loading 展示: show(type: LoadingType, params: LoadingParams): void
  • type: LoadingType: Loading 类型("success" | "info" | "warning" | "danger" | "loading")
  • params: LoadingParams: Loading 参数
    • message: string | undefined: 文案提示
    • config: LoadingConfig | undefined: Loading 配置
      • duration: number | undefined: Loading 持续时间(单位:毫秒)
  1. 专用 Loading 展示
showSuccess(message?: string): void
showInfo(message?: string): void
showWarning(message?: string): void
showError(message?: string): void
showLoading(message?: string): void
  1. 隐藏 Loading: dismissLoading()

Code Example

showSuccess("This loading will disappear in 1 seconds");

setTimeout(() => {
  dismissLoading();
}, 1000);

PDF 预览

prewviewPDF(params: PDFPrewviewParams): void
  • params: PDFPreviewParams
    • url?: string | undefined; PDF 文件地址
    • title?: string | undefined; 文档标题
    • showBottomBtn?: boolean; 是否展示底部按钮,默认false
    • seconds?: number;倒计时,秒数,默认5s
    • disableText?: string; 不可用状态文案
    • enableText?: string; 可用状态文案

Code Example

prewviewPDF({
  title: "对账单11-01",
  url: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
});

Open Setting 跳转系统设置

openSetting(): void

iOS: 打开系统设置 -> 应用设置页 Android: 打开系统设置

OpenURL 第三方应用跳转/判断第三方应用是否安装

openUrl(params: OpenUrlParams): void
  • params: OpenUrlParams: 跳转参数

    • url: string: 跳转地址
    跳转url规则:

    iOS 传应用注册的URL Scheme,如:
    打开微信:wechat://path/to/scanQRCode
    打开支付宝:alipay://mine/payTo

    Android 传应用包名,如:
    打开微信:"com.tencent.mm"
    打开支付宝: "com.eg.android.AlipayGphone"

判断第三方应用是否安装

canOpenUrl(params: OpenUrlParams): Promise<Result<boolean>>

Code Example

const params = { url: "com.tencent.mm" };

const res = await canOpenUrl(params);
if (res) {
    openUrl(params);
}

打开微信小程序

openMiniProgram(params: MiniProgramReq): void
  • params: MiniProgramReq: 跳转参数
    • userName: string; 填小程序原始id
    • path: string; 拉起小程序页面的可带参路径,不填默认拉起小程序首页,对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar"
    • miniprogramType: "TEST" | "PREVIEW" | "RELEASE"; 默认打开正式版,可选打开 PREVIEW-开发版 | TEST-体验版 | RELEASE-正式版

Code Example

openMiniProgram({
    userName: "gh_d43f693ca31f",
    path: "",
    miniprogramType: "RELEASE"
});

版本更新

upgrade()

有版本更新时,弹出对应弹框进行更新;没有更新时,toast提示“当前已为最新版本”

取消隐私及服务协议授权

cancelProtocol()

退出应用

exit(code: number)
  • code: number: 退出码

系统事件监听

网络状态变化

获取网络状态 ReachabilityStatus.(wifi|cellular|unavailable)

NativeBindings.instance().getReachbility()
async function example() {
  const result = await NativeBindings.instance().getReachbility();
  console.info("result", result);
}

监听网络状态变化

listenReachability(callback: ValueCallback<Result>): Subscription
  • callback: ValueCallback<Result>: 网络状态变化回调
// 监听网络状态变化
const subscription = NativeBindings.instance().listenReachability(
  (result) => {
    console.info("result", result);
  }
);

// 取消监听
subscription.cancel();

深色/浅色模式切换

获取颜色模式 dark | light | unknown

NativeBindings.instance().getColorMode()
async function example() {
  const colorMode = await NativeBindings.instance().getColorMode();
  console.info("colorMode", colorMode);
}

监听主题变化

listenColorMode(callback: ValueCallback<Result>): Subscription
// 监听主题设置变化
const subscription = NativeBindings.instance().listenColorMode((colorMode) => {
  console.info("colorMode", colorMode);
});

// 取消监听
subscription.cancel();

字体大小设置

获取字体大小设置 返回一个字体缩放因子,1.0 为正常大小,具体值由系统决定

async function example() {
  const textScale = await NativeBindings.instance().getTextScale();
  console.info("textScale", textScale);
}

监听字体大小变化

listenTextScale(callback: ValueCallback<Result>): Subscription
// 监听系统字体大小变化
const subscription = NativeBindings.instance().listenTextScale((textScale) => {
  console.info("textScale", textScale);
});

// 取消监听
subscription.cancel();

Safe Area 变化(异形屏适配)

获取系统 Safe Area

  • top: number: 顶边距
  • bottom: number: 底边距
  • left: number: 左边距
  • right: number: 右边距
async function example() {
  const result = await NativeBindings.instance().getSafeAreaInsets();
  console.info("result", result);
}

监听系统 Safe Area 变化

listenSafeAreaInsets(callback: ValueCallback<Result>): Subscription
// 监听系统 Safe Area 变化
const subscription = NativeBindings.instance().listenSafeAreaInsets(
  (safeAreaInsets) => {
    console.info("safeAreaInsets", safeAreaInsets);
  }
);

// 取消监听
subscription.cancel();

自定义事件监听

listenEvent(callback: ValueCallback<Result>): Subscription
  • EventInfo

    • type: "onNavigationClick" | "onShare" | "onPdfRead" | "onTabChange" | "onResume" | "onPause"; 事件类型
      • "onNavigationClick" - 标题栏点击事件;
      • "onShare" - 分享结果事件;
      • "onPdfRead" - PDF阅读按钮点击事件;
    • payload: EventInfoMap[K];
      • PositionItem: 定义同上
      • ShareResult: 分享结果
      • PDFReadResult: PDF文件阅读结果
      • TabChangeResult: tab切换结果
  • ShareResult

    • result: "success" | "fail"; 分享结果
    • platform?: "WEIXIN" | "WEIXIN_TIMELINE"; 分享平台
    • errCode?: number; 错误码,详细信息见阿里云官网
    • errMessage?: string; 错误信息
  • PDFReadResult

    • isRead: boolean; 点击PDF确认阅读按钮
  • TabChangeResult

    • tabIndex: number; 切换后的tabIndex

Code Example

// 自定义事件监听
const subscription = NativeBindings.instance().listenEvent(eventInfo => {
    console.info("eventInfo", eventInfo);
});

// 取消监听
subscription.cancel();

本地缓存

putAppCache(key: string, value: object):void

保存数据

  • key: 数据键值
  • value: 数据值
// 缓存数据
putAppCache('token', 'xxxxxx')
getAppCache(key: string):object

根据key值获取本地缓存

  • key: 数据键值
// 获取缓存数据
const token = getAppCache('token')
console.info("token", token);
removeAppCache(key: string):void

根据key值移除本地缓存

  • key: 数据键值
clearAppCache():void

清除所有缓存数据

listenAppCache(callback: ValueCallback<Result>): Subscription

监听App缓存数据变化

Code Example

// 监听App缓存数据变化
const subscription = NativeBindings.instance().listenAppCache(
  (cacheInfo) => {
    console.info("cacheInfo", cacheInfo);
  }
);

// 取消监听
subscription.cancel();

页面导航

setStatusBar(params?: StatusBarParams): void

设置系统状态栏

  • params: StatusBarParams
    • isDarkFont?: boolean: 是否为深色字体

Code Example

// 设置系统状态栏
setStatusBar({ isDarkFont: true })
setTitleBar(titleBar: object):void

设置APP顶部标题栏

  • params: TitleBarParams

    • title?: string | undefined: 标题
    • titleColor?: string | undefined: 标题字体颜色
    • subTitle?: string | undefined: 副标题
    • subTitleColor?: string; 副标题字体颜色
    • background?: string | undefined: 背景色,默认为#FFFFFF
    • showBorder?: boolean; 是否展示边框,默认展示
    • leftPosition?: Array <PositionItem> | undefined: 左侧位置,对象数组,默认为页面返回
    • rightPosition?: Array <PositionItem> | undefined: 右侧位置,对象数组,默认不展示
  • position: PositionItem

    • id?: string : 事件唯一标识
    • type?: string | undefined: 操作类型,back - 页面返回 | share - 分享 | jump - 打开新页面 | video - 视频操作
    • isWebBack?: boolean: 是否web内部返回,默认为false,容器端返回
    • text?: string | undefined: 文案
    • textColor?: string | undefined: 文案字体颜色
    • url?: string | undefined: 跳转路径
    • icon?: string | undefined: 图标,back - 返回 | share - 分享 | question - 问号 | video - 视频
    • extra?: string | undefined: 其他参数

Code Example

// 设置页面标题栏
setTitleBar({
  title: '基金详情',
  subTitle: '003190',
  background: '#D9242D',
  leftPosition: [{ isWebBack: true }],
  rightPosition: [
    {
      icon: 'share',
      type: 'share',
    },
    {
      icon: 'video',
      type: 'jump',
      url: 'https://www.baidu.com/',
    }
  ]
});
navigationTo(url: string, param?: object):Promise<any>

APP页面跳转方法

  • params: NavigationParams
    • url?: string: 页面链接
    • param?: PageParams: 页面参数
      • titleBar?: TitleBarParams | undefined: 顶部标题栏配置,参数同上,为空不展示
      • routerParams?: string | undefined: 路由参数
      • isAutoBackItemEnable?: boolean 是否需要返回操作,默认为true
      • popCount?: number; 返回页面数量
    • callBack?: ResponseCallback<Result<{ isSuccess: boolean }>>: 跳转回调

Code Example

// 页面跳转
navigationTo({
  url: 'https://www.baidu.com/',
  param: { titleBar },
},
(res) => {
    console.log("res", res);
});
navigationBack(params?: BackParams):void

APP页面返回方法

  • params: BackParams
    • popCount: number; 返回页面数量
    • isWebBack?: boolean; 是否web内部返回,默认为false,容器端返回

Code Example

// 页面返回
navigationBack({ isWebBack: true });
navigationBackToRoot():void

回到首页

setHomeTabIndex(index?: number):void

切换首页tab

getHomeTabIndex(): Promise<Result<number>>

获取首页当前tab

社会分享

share(params: ShareParams): void
  • params: ShareParams

    • platform: "WEIXIN" | "WEIXIN_TIMELINE";分享平台 WEIXIN - 微信好友,WEIXIN_TIMELINE - 微信朋友圈
    • shareContent: ShareContent; 分享内容对象
  • ShareContent

    • title?: string; 分享标题
    • content?: string; 分享内容
    • url?: string; 分享跳转的 URL
    • imgUrl?: string; 分享图片地址,微信分享请保证图片小于32KB
    • contentType?: "url" | "image"; 分享类型:"url" 为分享链接,"image" 为分享图片

Code Example

// 分享到微信好友
share({
    platform: "WEIXIN",
    shareContent: {
        title: "share title",
        content: "share content",
        url: "https://www.cloud.alipay.com/products/MPAAS",
        imgUrl: "https://gw.alipayobjects.com/zos/rmsportal/WqYuuhbhRSCdtsyNOKPv.png",
        contentType: "url",
    }
});

网络请求

request(params: RequestParams): Promise<Result<unknown>>

请求参数:

  • params: RequestParams
    • url: string; 请求地址
    • method: "POST" | "GET"; 请求方法
    • params: string; 请求参数, json字符串或加密字符串
    • headers: { [s: string]: string }; 请求头
    • isGM: boolean; 是否发送国密HTTPS请求

返回值:Promise<Result<unknown>>

  • Result<T, E = unknown>
    • { type: "success"; value: T } 成功结果
    • { type: "failure"; error: E } 异常结果

Code Example

const headers = { "App-Code": "CJFLS", "Source-Channel": "ZX" };
const params = { serType: "home" };

const result = await request({
    url: "https://wx.cjhxfund.com/dsapi/ds-business/app/getPrivacyAgreement",
    method: "POST",
    params: JSON.stringify(params),
    headers,
    isGM: false
});

console.log("result:", result);

人脸核验

initFaceVerifySdk(params: FaceVerifyParams): Promise<Result<string, WbFaceError | string>>

请求参数:

  • params: FaceVerifyParams
    • faceId: string; 刷脸 ID 号,由合作方向人脸识别后台拉取获得
    • orderNo: string; 订单号,合作方订单的唯一标识
    • appId: string; 业务流程唯一标识,即 WBappid,可参考 获取 WBappid 指引在人脸核身控制台内申请
    • apiVersion: string; 后台api接口版本号,默认填:1.0.0
    • nonce: string; 满足接入要求的32位随机数,与服务端生成签名的随机数保持一致
    • userId: string; 用户唯一标识, 由合作方自行定义
    • sign: string; 签名信息,获取方式请参考 生成 SDK 接口调用步骤使用签名
    • licence: string; 在人脸核身控制台申请的 SDKlicense
    • videoUpload?: boolean; 是否需要录制上传视频,默认不需要
    • videoCheck?: boolean; 是否对录制视频进行检查,默认不检查
    • playVoice?: boolean; 设置是否打开语音提示,默认关闭

返回值:Promise<Result<string, WbFaceError | string>>

  • WbFaceError
    • domain: string; 错误发生的阶段,只有当 domain=WBFaceErrorDomainCompareServer 时表示用户完成了刷脸,可以通过接口去拉取刷脸结果。其他 domain 表示用户刷脸中途退出或命中了风控逻辑,后端无法查询到刷脸结果
    • code: string; 错误码
    • desc: string; 错误描述,如有需求,可以展示给用户
    • reason: string; 错误信息内容,错误的详细实际原因,主要用于定位问题
startFaceVerify(): Promise<Result<WBFaceVerifyResult, WbFaceError | string>>

请求参数:无

返回值:Promise<Result<WBFaceVerifyResult, WbFaceError | string>>

  • WBFaceVerifyResult 人脸核验成功结果
    • isSuccess: boolean; 人脸核身是否成功
    • sign: string; 签名,供 App 校验人脸核身结果的安全性
    • liveRate: string; 活体检测分数
    • similarity: string; 人脸比对分数,“仅活体检测” 类型不提供此分数
    • error: WbFaceError; 人脸核身错误,人脸核身成功时为空

一键登录

preOauthLogin(): Promise<Result<string, string>>

SDK 预登陆,必须预登陆成功才能调用一键登录

oauthLogin(params: OauthParams): Promise<Result<OauthResult, string>>

唤起一键登录

请求参数: params: OauthParams

  • protocols: { name: string; url: string; }[]; 授权页相关协议数组,最多传3个;
  • name: string; 协议名称
  • url: string; 协议链接

返回值:Promise<Result<OauthResult, string>>

OauthResult 授权结果

  • operation: OperationType; 授权页进行的操作
  • token: string; 登录凭证,登录成功时返回
  • carrier: string; 运营商,移动:mobile, 联通:unicom,电信:telecom,登录成功时返回

OperationType 授权结束类型枚举,登录成功后由H5自行关闭授权页,其余操作类型基座自动关闭授权页

  • LoginComplete:点击登录,授权成功
  • PressBack:页面返回,点击页面图标或手势返回
  • ChangeAccount:点击切换账号
  • Password:点击密码登录
  • VerifyCode:点击手机验证码登录
closeOauthPage(): Promise<Result<string, string>>

关闭登录授权页

Code Example

const params: OauthParams = {
    protocols: [
        {
            name: "隐私政策",
            url: "https://cj-samll-routine.oss-cn-shenzhen.aliyuncs.com/1058280196925185%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96.pdf"
        },
        {
            name: "个人信息使用授权书",
            url: "https://cj-samll-routine.oss-cn-shenzhen.aliyuncs.com/1058280196925184个人信息使用授权书.pdf"
        }
    ]
};

const result = await oauthLogin(params);
if (result.type === "success") {
    const { value } = result;

    switch (value.operation) {
        case OperationType.LoginComplete:
            console.log("token: ", value.token, "\n运营商:", value.carrier);
            // TODO 登录业务逻辑
            closeOauthPage();
            break;

        case OperationType.PressBack:
            // TODO 授权页返回逻辑
            break;

        case OperationType.ChangeAccount:
            // TODO 切换账号逻辑
            break;

        case OperationType.Password:
            // TODO 跳转密码登录页
            break;

        case OperationType.VerifyCode:
            // TODO 跳转手机验证码登录页
            break;

        default:
            break;
    }
} else {
    console.log("授权失败:", result.error);
}

生物认证

getBiometricStatus(): Promise<Result<BiometricStatus>>

在进行指纹/人脸识别前,需要判断当前设备的识别功能是否可用

请求参数: 无

返回值: Promise<Result<BiometricStatus>>

  • BiometricStatus,状态枚举,取值如下:
    • Success:可以进行验证;
    • NotEnrolled:没有录入指纹/人脸
    • NotAvailable:设备不支持指纹/人脸
    • PasscodeNotSet:没有设置设备密码
    • BiometryLockout:超过重试限制,需要进行设备密码解锁后重新激活
    • UserCancel:用户点击了取消按钮
    • UserFallback:用户点击了输入密码按钮
    • SystemCancel:系统强制取消
    • BiometryChanged:系统指纹/人脸发生变更,请重新验证用户身份
getSupportBiometricType(): Promise<Result>

获取当前设别支持的生物识别类型

请求参数:无

返回值:

  • BiometricType 支持生物识别类型
    • touchID:指纹
    • faceID:人脸
    • notSupport:不支持
openLocalAuth(params: AuthParams): Promise<Result<string, AuthError | unknown>>

开启生物认证

描述:业务系统验证用户身份后,调用此方法,开启指纹/人脸登录,系统验证成功后,生成公私钥对,返回公钥给服务器用于验签

请求参数:

  • params: AuthParams; 用户签名参数
    • algorithm: "rsa" | "sm2"; 签名算法

返回值: Promise<Result<string, AuthError | unknown>>

成功返回公钥 publicKey,失败返回错误信息

  • AuthError,错误信息

    • errorCode?: BiometricError & BiometricStatus; 错误码
    • errorMsg?: string; 错误信息
  • BiometricError,状态枚举,取值如下:

    • AuthFailed:验证失败,指纹/人脸不匹配
    • UserCancel:用户点击了取消按钮
    • UserFallback:用户点击了输入密码按钮
    • SystemCancel:系统强制取消
    • Timeout:等待超时
    • OtherError:其他原因,操作失败
localAuth(params: AuthParams): Promise<Result<string, AuthError | unknown>>

生物认证

描述:指纹/人脸验证成功后,使用保存的私钥对用户参数进行签名,返回签名数据传给后端进行验签,确认用户身份

请求参数:

  • params: AuthParams; 用户签名参数
    • signedText: string; 签名文本
    • algorithm: "rsa" | "sm2"; 签名算法

返回值: Promise<Result<string, AuthError | unknown>>

成功返回签名 signature,失败返回错误信息

签名算法

SM2 验签调试地址: https://const.net.cn/tool/sm2/verify/

RSA 验签调试地址: https://8gwifi.org/RSAFunctionality?rsasignverifyfunctions=rsasignverifyfunctions&keysize=2048

RSA 算法前后端统一使用 SHA256withRSA 配置

剪切板

setClipboard(content: string)

设置剪切板内容

getClipboard(): Promise<Result<string, string>>

获取剪切板内容

clearClipboard()

清除剪切板内容

定位

requestLocation(): Promise<Result<LBSLocation, string>>

返回值: Promise<Result<LBSLocation, string>>

  • LBSLocation,定位信息,属性如下:
    • country: string; 国家
    • province: string; 省
    • city: string; 市
    • district: string; 区
    • street: string; 街道
    • latitude: number; 纬度
    • longitude: number; 经度

Readme

Keywords

Package Sidebar

Install

npm i runner-bridge

Weekly Downloads

3

Version

0.0.1-beta.55

License

ISC

Unpacked Size

117 kB

Total Files

60

Last publish

Collaborators

  • mangonob