fastman3-dfyjapp-jsbridge
Version:
a jsbridge module for dfyj app
556 lines (532 loc) • 21.2 kB
JavaScript
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/*
* @Author: shenzhiwei
* @Date: 2021-04-11 08:09:42
* @Company: orientsec.com.cn
* @Description: 核心逻辑(来自 Fastman1.0 Lib 源码,因此无需修改,请在源码库中对该脚本进行维护工作)
*/
/*eslint-disable*/
import { getAbsoluteUrl, isEmpty } from './util.web';
import { log } from './log';
import { extend } from "fastman3-common-helper";
import { compareVersion } from './version';
// 区分设备系统
var ua = navigator.userAgent;
var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
var isFromApp = !!ua.toLowerCase().match(/DFYJ/i);
// 是否来自于鸿蒙
var isFromHarmonyOS = !!ua.toLowerCase().match(/ArkWeb/i);
// 初始化桥接对象
var init = function init(bridge) {
bridge.init(function (message, responseCallback) {
if (responseCallback) responseCallback(data);
});
return bridge;
};
/**
* 初始化桥接对象
* connectWebViewJavascriptBridge
* @param callback
*/
var ready = function ready(callback) {
var __cb___ = function __cb___(__bridge___) {
callback(__bridge___);
};
if (isFromApp) {
if (ipad || iphone || ipod) {
// 新版本兼容IOS
if (window.WebViewJavascriptBridge) {
return __cb___(WebViewJavascriptBridge);
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(__cb___);
}
window.WVJBCallbacks = [__cb___];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function () {
document.documentElement.removeChild(WVJBIframe);
}, 0);
} else if (android) {
// 旧版本兼容Android
if (window.WebViewJavascriptBridge) {
__cb___(init(WebViewJavascriptBridge));
} else {
document.addEventListener('WebViewJavascriptBridgeReady', function () {
// 以异步形式加载
__cb___(init(WebViewJavascriptBridge));
}, false);
}
} else {
__cb___();
}
} else {
__cb___();
}
};
// 空函数
var noop = function noop() {};
/**
* 成功消息体的包装
* @param payload 成功对象
*/
// const wrapOkPayload = (payload = {}) => ({
// error: false,
// info: 'ok',
// payload: payload,
// })
var wrapOkPayload = function wrapOkPayload() {
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return payload;
};
/**
* 失败消息体的包装
* @param info 错误描述
*/
var wrapNotOkPayload = function wrapNotOkPayload() {
var code = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : -1;
var info = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'error';
return {
// error: true,
code: code,
info: info
};
};
/**
* APP WebView后退,后退到栈的最外层
* @param options
*/
var onBack = function onBack(options) {
// 默认配置
var _options = {
complete: noop
};
// 复制
_options = extend({}, _options, options);
log('onBack->' + JSON.stringify(_options));
if (isFromHarmonyOS) {
HmJsBridge.back(_options);
} else {
WebViewJavascriptBridge.callHandler('back', _options, function (response) {
log('onBack<-' + JSON.stringify(response));
_options.complete(response);
});
}
};
/**
* APP WebView刷新
* @param options
*/
var onRefresh = function onRefresh(options) {
var _options = {
complete: noop
};
_options = extend({}, _options, options);
log('onRefresh->' + JSON.stringify(_options));
if (isFromHarmonyOS) {
console.warn('onRefresh Harmony 暂未实现');
} else {
WebViewJavascriptBridge.callHandler('refresh', _options, function (response) {
log('onRefresh<-' + JSON.stringify(response));
_options.complete(response);
});
}
};
/**
* 设置原生导航条
* @param options
* {
* "title": "xxxxx",
* "type": "0" // 0-默认 1-切换类
* }
*/
var onNavigationBar = function onNavigationBar(options) {
var _options = {
complete: noop
};
_options = extend({}, _options, options);
log('onNavigationBar->' + JSON.stringify(_options));
if (isFromHarmonyOS) {
HmJsBridge.navigationBar(_options);
} else {
WebViewJavascriptBridge.callHandler('navigationBar', _options, function (response) {
log('onNavigationBar<-' + JSON.stringify(response));
_options.complete(response);
});
}
};
/**
* 打开一个新的webview
* @param options
* {
* "title": "xxxxx", // 导航名称,如果html设置title,以html为主
* "uri": "xxxxxxx", // webview请求的路由地址,目前只支持http协议,今后可支持shema协议
* "locktype": 0, // 0-不需要手势密码;1-手势密码锁屏;2-资金账号锁屏;
* }
*/
var onPushView = function onPushView(options) {
var _options = {
title: '',
isFullScreen: false,
isStatusBarLight: true,
ver: 'v1'
};
_options = extend({}, _options, options);
if (_options.isFullScreen == true) {
_options.ver = 'v2';
}
if (!!_options.uri) {
if (_options.uri.indexOf('http') != -1 || _options.uri.indexOf('https') != -1) {} else {
_options.uri = getAbsoluteUrl(_options.uri);
}
}
log('onPushView->' + JSON.stringify(_options));
if (isFromHarmonyOS) {
HmJsBridge.go(_options);
} else {
WebViewJavascriptBridge.callHandler('pushView', _options, function (response) {
log('onPushView<-' + JSON.stringify(response));
});
}
};
/**
* 原生页面将要出现时触发的事件
* @param callback
*/
var pageWillAppear = function pageWillAppear(callback) {
if (typeof callback == 'function') {
if (isFromHarmonyOS) {
HmJsBridge.willAppear(callback);
} else {
WebViewJavascriptBridge.registerHandler("pageWillAppear", callback);
}
}
};
/**
* H5发送通知给客户端
* @param options
*/
var onNotify = function onNotify(options) {
var _options = {
type: 'javascriptNotify'
};
_options = extend({}, _options, options);
log('onNotify->' + JSON.stringify(_options));
if (isFromHarmonyOS) {
console.warn('onNotify Harmony 暂未实现');
} else {
WebViewJavascriptBridge.callHandler('notify', _options, function (response) {
log('onNotify<-' + JSON.stringify(response));
});
}
};
/**
* H5注册通知,由客户端进行通知
* @param type 事件类型名称
* @param callback 回调处理
*/
var notifyQueue = {};
var subscribeNotify = function subscribeNotify(type, callback) {
if (typeof callback == 'function') {
//回调函数存在队列中
var _type = type;
// sae_video: v3思迪视频见证订阅事件名
// result_video: v5思迪视频见证订阅事件名(2025-05-30Added)
if (_type == 'sae_video' || _type == 'result_video') {
_type = 'notify';
}
notifyQueue[_type] = callback;
log('subscribeNotify->' + type);
if (isFromHarmonyOS) {
console.warn('subscribeNotify Harmony 暂未实现');
} else {
WebViewJavascriptBridge.registerHandler(_type, function (data) {
log('subscribeNotify<-' + JSON.stringify(data));
// //获取data.type才是H5定义的type
if (Object.prototype.toString.call(data).toLocaleLowerCase() == '[object String]'.toLocaleLowerCase()) {
data = JSON.parse(data);
}
// 2025-05-30Added:针对5.0视频见证的输出对象payload对安卓端进行Object转换的兼容处理
if (type == 'result_video' && data.payload) {
if (Object.prototype.toString.call(data.payload).toLocaleLowerCase() == '[object String]'.toLocaleLowerCase()) {
data.payload = JSON.parse(data.payload);
}
// 兼容代码:处理iOS和安卓端返回结构不同的兼容
if (ipad || iphone || ipod) {
data.payload = _objectSpread({}, data.payload.params);
}
// 如有驳回样本结果返回,则生成扁平化数组reject_reasons
var rejectReasons = [];
if (data.payload.result && data.payload.result.length) {
// //var rejectReasonSample = [{fields: ["wt_witness_video_reject"], reasons: ["无法接收您的声音或画面,请您确认设备权限后重新连接;目前您的网络环境不太好,请您切换流量和无线网,确定网络环境正常后重新连接"], step: "witness_video", reasontitle: ["无法接收您的声音或画面,请您确认设备权限后重新连接;目前您的网络环境不太好,请您切换流量和无线网,确定网络环境正常后重新连接"]}];
var rejectReasonSample = data.payload.result;
rejectReasonSample.forEach(function (fieldElement) {
if (fieldElement.reasons && Object.prototype.toString.call(fieldElement.reasons) == "[object Array]") {
rejectReasons = rejectReasons.concat(fieldElement.reasons);
}
});
}
data.payload.reject_reasons = rejectReasons.reduce(function (acc, item) {
return acc.concat(item.split(";"));
}, []);
}
if (notifyQueue[_type]) {
if (android) {
// 解决安卓端request=1会调用type=notify的问题
if (data.type == 'sae_video' || data.type == 'result_video') {
log('安卓notify被调用.');
notifyQueue['notify'](data);
} else if (data.type == _type) {
log("\u5B89\u5353".concat(data.type, "\u88AB\u8C03\u7528!"));
notifyQueue[_type](data);
}
} else {
log('iOS notify被调用;');
notifyQueue[_type](data);
}
}
});
}
}
};
/**
* 调用Schema Url
* @param options
*/
var onDynamicLink = function onDynamicLink(options) {
var _options = {
url: ''
};
_options = extend({}, _options, options);
log('onDynamicLink->' + JSON.stringify(_options));
if (isFromHarmonyOS) {
console.warn('onDynamicLink Harmony 暂未实现');
} else {
var $versionCompare = compareVersion('5.22.2');
// 小于5.22.2版本不再支持拉起视频见证,提示升级
if ($versionCompare < 0 && _options.url.indexOf('dl/videoreview') != -1) {
alert("您当前的APP版本过低,请升级至V5.22.2以上版本后,再进行使用");
return;
}
WebViewJavascriptBridge.callHandler('dynamicLink', _options, function (response) {
log('onDynamicLink<-' + JSON.stringify(response));
});
}
};
// 存储Request指令订阅Handlers
var requestHandlerMap = {};
// 是否注册了Request指令订阅Handlers
var requestHandlerRegisterFlag = false;
// 生成从minNum到maxNum的随机数,防 callback 重患
var randomNum = function randomNum(minNum, maxNum) {
switch (arguments.length) {
case 1:
return parseInt(Math.random() * minNum + 1, 10);
break;
case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
//或者 Math.floor(Math.random()*( maxNum - minNum + 1 ) + minNum );
break;
default:
return 0;
break;
}
};
var callbackIds = [];
var _generateCallbackId = function generateCallbackId() {
var callbackId = randomNum(1000, 9999);
if (callbackIds.indexOf(callbackId) !== -1) {
return _generateCallbackId(callbackId);
} else {
callbackIds.push(callbackId);
}
return callbackId;
};
/**
* 调用Request指令(通常作用在一些原生和客户端之间比较特殊的操作)
* @param operationType 操作指令(见文档)
* @param payloadOptions 消息体结构
*/
var onRequest = function onRequest(operationType, payloadOptions, okCallBack, notOkCallBack) {
var _options = {
type: !operationType ? '1' : operationType,
payload: !payloadOptions ? {} : payloadOptions,
callbackId: _generateCallbackId()
};
// 兼容老方案
requestHandlerMap[operationType + '-ok'] = typeof okCallBack === 'function' ? okCallBack : noop;
requestHandlerMap[operationType + '-notok'] = typeof notOkCallBack === 'function' ? notOkCallBack : noop;
// 2020-5-2:修复 callback 在队列中重复的致命缺陷
requestHandlerMap[operationType + '_' + _options.callbackId + '-ok'] = typeof okCallBack === 'function' ? okCallBack : noop;
requestHandlerMap[operationType + '_' + _options.callbackId + '-notok'] = typeof notOkCallBack === 'function' ? notOkCallBack : noop;
// 处理Request指令 回复
var dealRequestResponse = function dealRequestResponse(response) {
if (typeof response == 'string') {
response = JSON.parse(response);
}
// 由于该指令输出的图片base64过长会导致vconsole假死,因此去除输出
if (operationType != "9") {
log('onRequest<-' + JSON.stringify(response));
}
if (response.error || response.error === 'true') {
if (response.callbackId && typeof requestHandlerMap[response.type + '_' + response.callbackId + '-notok'] === 'function') {
requestHandlerMap[response.type + '_' + response.callbackId + '-notok'](wrapNotOkPayload(-1, response.info));
} else if (typeof requestHandlerMap[response.type + '-notok'] === 'function') {
requestHandlerMap[response.type + '-notok'](wrapNotOkPayload(-1, response.info));
}
} else {
if (response.callbackId && typeof requestHandlerMap[response.type + '_' + response.callbackId + '-ok'] === 'function') {
// 防止安卓指令调用成功同步进入的控制
if (ipad || iphone || ipod || isFromHarmonyOS || response.payload) {
requestHandlerMap[response.type + '_' + response.callbackId + '-ok'](wrapOkPayload(response.payload));
}
} else if (typeof requestHandlerMap[response.type + '-ok'] === 'function') {
// 防止安卓指令调用成功同步进入的控制
if (ipad || iphone || ipod || isFromHarmonyOS || response.payload) {
requestHandlerMap[response.type + '-ok'](wrapOkPayload(response.payload));
}
}
}
};
// 鸿蒙处理
if (isFromHarmonyOS) {
HmJsBridge.request(_options, function (response) {
dealRequestResponse(response);
});
return;
}
// IOS同步回调处理
log('onRequest->' + JSON.stringify(_options));
WebViewJavascriptBridge.callHandler('request', _options, function (response) {
dealRequestResponse(response);
});
if (!requestHandlerRegisterFlag) {
// Android异步回调处理
WebViewJavascriptBridge.registerHandler('request', function (response) {
if (typeof response == 'string') {
response = JSON.parse(response);
}
if (response.error || response.error === 'true') {
if (response.callbackId && typeof requestHandlerMap[response.type + '_' + response.callbackId + '-notok'] === 'function') {
requestHandlerMap[response.type + '_' + response.callbackId + '-notok'](wrapNotOkPayload(-1, response.info));
} else if (typeof requestHandlerMap[response.type + '-notok'] === 'function') {
requestHandlerMap[response.type + '-notok'](wrapNotOkPayload(-1, response.info));
}
} else {
if (response.callbackId && typeof requestHandlerMap[response.type + '_' + response.callbackId + '-ok'] === 'function') {
requestHandlerMap[response.type + '_' + response.callbackId + '-ok'](wrapOkPayload(response.payload));
} else if (typeof requestHandlerMap[response.type + '-ok'] === 'function') {
requestHandlerMap[response.type + '-ok'](wrapOkPayload(response.payload));
}
}
});
requestHandlerRegisterFlag = true;
}
};
/**
* 提供给第三方调用中台接口的函数
* @param functionNo 中台功能号
* @param payloadOptions 中台消息体
* @param okCallBack 成功回调函数
* @param notOkCallBack 失败回调函数
*/
var onApiRequest = function onApiRequest(functionNo, payloadOptions, okCallBack, notOkCallBack) {
if (isEmpty(functionNo)) {
throw new Error('functionNo is required ...');
} else {
var _options = {
funcId: functionNo,
payload: !payloadOptions ? {} : payloadOptions
};
}
log('onApiRequest->' + JSON.stringify(_options));
if (isFromHarmonyOS) {
console.warn('onApiRequest Harmony 暂未实现');
return;
}
WebViewJavascriptBridge.callHandler('apiRequest', _options, function (response) {
log('onApiRequest<-' + JSON.stringify(response));
if (typeof response == 'string') {
response = JSON.parse(response);
}
// 2017-12-26:对脚本逻辑做兼容,IOS认为业务异常和系统异常response.error都是true,ANDROID认为业务异常和业务成功时response.error是false,而系统异常response.error是true
// IOS认为业务异常和系统异常response.error都是true,业务成功response.error是false
if (ipad || iphone || ipod) {
if (response.error || response.error === 'true') {
// 接口业务异常
if (response.payload) {
if (typeof notOkCallBack === 'function') {
notOkCallBack(wrapNotOkPayload(response.payload.code, response.payload.info));
}
}
// 客户端自身应用级别错误(ios不给payload字段)
else {
if (typeof notOkCallBack === 'function') {
notOkCallBack(wrapNotOkPayload(-1, response.info));
}
}
} else {
if (typeof okCallBack === 'function') {
var re = {};
if (response.payload) {
if (typeof response.payload.data == 'string') {
re = JSON.parse(response.payload.data);
} else {
re = response.payload.data;
}
}
okCallBack(wrapOkPayload(re));
}
}
}
// ANDROID认为业务异常和业务成功时response.error是false,而系统异常response.error是true
else {
if (response.error || response.error === 'true') {
if (typeof notOkCallBack === 'function') {
notOkCallBack(wrapNotOkPayload(-1, response.info));
}
} else {
var _re = {};
if (typeof response.payload.data == 'string') {
_re = JSON.parse(response.payload.data);
} else {
_re = response.payload.data ? response.payload.data : {};
}
// 业务异常
if (response.payload.code != '0') {
if (typeof notOkCallBack === 'function') {
notOkCallBack(wrapNotOkPayload(response.payload.code, response.payload.info));
}
}
// 业务成功
else {
if (typeof okCallBack === 'function') {
okCallBack(wrapOkPayload(_re));
}
}
}
}
});
};
export { wrapOkPayload, wrapNotOkPayload,
// ready是一个异步操作,如果需要在页面加载时就调用相关接口,则需把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可直接调用,不需要放在ready函数中
// 该函数中有一个bridge变量,与下面的bridge使用上一致,只是调用顺序需要额外注意
ready, onBack, onRefresh, onNavigationBar, onPushView, onNotify,
// H5发送通知给客户端
subscribeNotify,
// 客户端发送通知给H5
onDynamicLink, onRequest,
// 原生生命周期相关事件
pageWillAppear,
// 第三方接口调用
onApiRequest };