线上鸿蒙5、6用户h5页面使用schemeURL跳转小程序失败
情况描述
- ios用户自动跳转成功
- 安卓用户自动跳转成功
- 测试机鸿蒙5、6跳转成功
客户经理提供用户手机截图:
线上用户自动跳转到网址为:weixin://dl/business/?t=xxx的网址了,没有拉起微信小程序
线上用户手机鸿蒙5、6跳转失败
测试机鸿蒙5、6跳转成功获取到的useragent能够自动、点击按钮跳转
访问同事发现,称手机非纯血鸿蒙
userAgent: Mozilla/5.0(Phone;OpenHarmony 6.0; Android 10)AppleWebKit/537.36(KHTML,like Gecko) Chrome/132.0.0.0Safari/537.36 ArkWeb/6.0.0.120MobileHuaweiBrowser/5.1.11.312data"不
支持
问题原因
- 无法确认是纯血鸿蒙还是非纯血鸿蒙原因?
- 是浏览器问题?兼容性或者隐私设置问题?
- 如何区分纯血鸿蒙、非纯血鸿蒙?
以上问题,想和客户求证,还在等负责人推进...
关键代码
// schemeURL密文地址
let url = 'weixin://dl/business/?t=xxx'
window.onload = function () {
setTimeout(() => {
window.location.href = 'weixin://dl/business/?t=xxx';
}, 500);
function jumpTo1(){
window.location.href = url;
}
function jumpTo2(){
const ifr = document.createElement('iframe');
ifr.src = url;
ifr.style.display = 'none';
document.body.appendChild(ifr);
// 可选:延时移除,避免影响
setTimeout(() => {
document.body.removeChild(ifr);
}, 2000);
}
function jumpTo3(){
const a = document.createElement('a');
a.href = url;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
// 可选:延时移除,避免影响
setTimeout(() => {
document.body.removeChild(a);
}, 2000);
}
源代码
jsp页面
<div class="container" id="arcode">
<div class="note">
<strong>温馨提示:</strong>此功能需要在微信外浏览器打开,如手机自带浏览器、Safari或Chrome等。
</div>
<%-- <button class="jump-btn" onclick="loadScheme('develop')">密文开发版本</button>--%>
<%-- <button class="jump-btn" onclick="loadMWScheme()">明文跳转小程序</button>--%>
<div>
<button id="hmbtn" class="jump-btn" onclick="joinWhiteList()" style="display:none"> 进入小程序</button>
<button id="fhmbtn2" class="jump-btn" onclick="loadScheme()" style="display:none"> 进入小程序</button>
<button id="hmbtn2" class="jump-btn" onclick="joinWhiteList()" style="display:none"> 上报设备信息</button>
</div>
<p id="device3" style="color: red"></p>
<p id="device"></p>
<div class="steps">
<p><strong>跳转说明:</strong></p>
<ul>
<li>确保您已安装最新版本的微信App</li>
</ul>
</div>
<div class="qr-code">
<div class="qr-placeholder" v-loading="loading">
<view id="mini"></view>
</div>
<p>如有问题,请联系客服支持</p>
</div>
</div>
<script>
new Vue({
el: '#arcode',
data() {
return {
loading: false,
};
},
});
const baseURL = "<%=basePath%>"
const service = axios.create({
baseURL: baseURL,
timeout: 15000,
withCredentials: true,
})
service.interceptors.request.use(config => {
if (config.method === 'get') {
if (config.params) {
config.params['date'] = new Date().getTime()
} else {
config.url = config.url + `?date=` + new Date().getTime()
}
}
return config
}, error => {
ELEMENT.Message({
message: '错误信息:' + error,
type: 'warning'
});
return Promise.reject(error)
})
service.interceptors.response.use(resData => {
if (resData.headers['content-disposition']) {
resData.data.contentDisposition = resData.headers['content-disposition']
}
if (resData.status >= 200 && resData.status < 300) {
const {code, result, msg} = resData.data
if (code === 1) {
return result
} else if (code === 10012) {
ELEMENT.Message({
message: 'token已过期,请您重新登录!',
type: 'warning'
});
setTimeout(() => location.reload(), 1500);
return Promise.reject(code)
} else {
if (msg == undefined) {
return resData
}
ELEMENT.Message({
message: msg,
type: 'warning'
});
return Promise.reject(code)
}
}
}, error => {
ELEMENT.Message({
message: '错误信息:' + error,
type: 'warning'
});
return Promise.reject(error)
})
function GetWxMiniScheme(code, ticket, version) {
return service({
method: 'GET',
url: '/api/scheme/getWxMiniScheme/' + code + '/' + ticket + '/' + version,
})
}
function AddWhitelist(ticket, model) {
return service({
method: 'GET',
url: '/api/scheme/addWhitelist/' + ticket + '/' + model,
})
}
var ticket = `${ticket}`;
const paramscom = new URLSearchParams(window.location.search);
ticket = paramscom.get('ticket');
// 系统
let ua = navigator.userAgent.toLowerCase();
let isHo = false
// 1. 识别鸿蒙系(优先级最高,避免被安卓识别覆盖)
const isOpenHarmony = /openharmony\s?([0-9._]+)/i.test(ua) || /openharmony\/([0-9._]+)/i.test(ua);
const openHarmonyVersion = (ua.match(/openharmony\s?([0-9._]+)/i) || ua.match(/openharmony\/([0-9._]+)/i) || [])[1] || '';
const isHarmonyOS = /harmonyos\s?([0-9._]+)/i.test(ua) || /harmonyos\/([0-9._]+)/i.test(ua);
const harmonyOSVersion = (ua.match(/harmonyos\s?([0-9._]+)/i) || ua.match(/harmonyos\/([0-9._]+)/i) || [])[1] || '';
// 2. 识别iOS(包含iPhone/iPad/iPod)
const isIOS = /iphone|ipad|ipod|ios/i.test(ua);
const iosVersion = (ua.match(/os\s+(\d+[._]\d+)/i) || [])[1]?.replace('_', '.') || '';
// 3. 识别安卓
const isAndroid = /android|adr/i.test(ua) && !isOpenHarmony && !isHarmonyOS; // 排除鸿蒙(鸿蒙UA含android)
const androidVersion = (ua.match(/android\s+(\d+[._]\d+)/i) || [])[1]?.replace('_', '.') || '';
// 4. 识别Windows Phone
const isWindowsPhone = /windows phone|wp/i.test(ua);
const wpVersion = (ua.match(/windows phone\s+(\d+[._]\d+)/i) || [])[1]?.replace('_', '.') || '';
// 5. 识别其他系统(Linux/MacOS/Windows)
const isLinux = /linux/i.test(ua) && !isAndroid && !isOpenHarmony && !isHarmonyOS;
const isMacOS = /mac os x/i.test(ua);
const isWindows = /windows|win32/i.test(ua);
// 6. 最终系统类型和版本赋值(无Unknown)
let systemType = '';
let systemVersion = '';
if (isOpenHarmony) {
systemType = 'OpenHarmony';
systemVersion = openHarmonyVersion;
isHo = true
} else if (isHarmonyOS) {
systemType = 'HarmonyOS';
systemVersion = harmonyOSVersion;
isHo = true
} else if (isIOS) {
systemType = 'iOS';
systemVersion = iosVersion;
} else if (isAndroid) {
systemType = 'Android';
systemVersion = androidVersion;
} else if (isWindowsPhone) {
systemType = 'Windows Phone';
systemVersion = wpVersion;
} else if (isLinux) {
systemType = 'Linux';
systemVersion = '';
} else if (isMacOS) {
systemType = 'MacOS';
systemVersion = (ua.match(/mac os x\s+(\d+[._]\d+)/i) || [])[1]?.replace('_', '.') || '';
} else if (isWindows) {
systemType = 'Windows';
systemVersion = (ua.match(/windows nt\s+(\d+[._]\d+)/i) || [])[1]?.replace('_', '.') || '';
} else {
// 兜底:仍识别不出则显示「Other」而非Unknown
systemType = 'Other';
systemVersion = '';
}
// 打印最终结果(无Unknown)
console.log('系统类型:', systemType, '版本号:', systemVersion);
const deviceInfo = {
systemType,
systemVersion,
userAgent: navigator.userAgent,
platform: navigator.platform,
time: new Date().toISOString()
};
const p = document.querySelector('#device');
const p3 = document.querySelector('#device3');
p.style.whiteSpace = 'pre-wrap';
p.innerText = '系统类型:' + deviceInfo.systemType + '\n' + '版本号:' + deviceInfo.systemVersion + '\n平台:' + deviceInfo.platform + '\n' + 'UserAgent: ' + deviceInfo.userAgent + 'data"' + (navigator.userAgentData ? JSON.stringify(navigator.userAgentData) : '不支持');
// 页面加载后延迟执行跳转
window.onload = function () {
if (isHo) {
document.getElementById('hmbtn').style.display = 'block';
document.getElementById('hmtext').style.display = 'block';
} else {
// 非鸿蒙系统自动跳转-显示上报信息按钮(加白名单)
setTimeout(() => {
loadScheme()
}, 500);
}
};
// 【核心】全浏览器适配的清理逻辑(含夸克/华为)
function clearH5PageAfterJump() {
// 第一步:识别浏览器类型
const ua = navigator.userAgent.toLowerCase();
const browserType = {
isHuawei: ua.includes('huaweibrowser') || ua.includes('harmony') || ua.includes('huawei'),
isQuark: ua.includes('quark') || ua.includes('quarkmini'),
isChrome: ua.includes('chrome') && !ua.includes('mobile safari'),
isSafari: ua.includes('mobile safari') && !ua.includes('chrome'),
isOther: true
};
// 修正other判断
browserType.isOther = !browserType.isHuawei && !browserType.isQuark && !browserType.isChrome && !browserType.isSafari;
try {
// 1. 华为浏览器:优先调用专属API
if (browserType.isHuawei && window.HuaweiBrowser) {
window.HuaweiBrowser.closeCurrentTab();
}
// 2. 通用关闭尝试(仅部分浏览器生效)
else if (window.close) {
window.close();
setTimeout(() => window.close(), 200);
}
} catch (e) {
console.log('自动关闭失败,执行强制清空', e);
// 第二步:分浏览器强制清空(核心适配夸克)
if (browserType.isQuark) {
// 夸克专属:深度清空+重写页面结构
document.open(); // 打开文档流,清空缓存
document.write('<html class="blank-page"><body class="blank-page"></body></html>');
document.close(); // 关闭文档流,强制渲染
// 替换历史记录+禁止返回
window.location.replace('about:blank');
// 禁用所有交互
document.body.style.pointerEvents = 'none';
// 终止所有异步任务
for (let i = 0; i < 2000; i++) {
clearInterval(i);
clearTimeout(i);
}
// 夸克特殊:延迟再次清空
setTimeout(() => {
document.body.innerHTML = '';
document.documentElement.className = 'blank-page';
}, 100);
}
// 华为浏览器兜底
else if (browserType.isHuawei) {
document.documentElement.innerHTML = '';
document.body.innerHTML = '';
window.location.replace('about:blank');
document.documentElement.style.display = 'none';
document.body.style.display = 'none';
for (let i = 0; i < 1000; i++) {
clearInterval(i);
clearTimeout(i);
}
}
// 其他浏览器通用方案
else {
document.body.innerHTML = '';
window.location.replace('about:blank');
document.documentElement.className = 'blank-page';
}
}
}
// 监听页面隐藏(跳转成功),执行清理
document.addEventListener('visibilitychange', function () {
if (document.hidden) {
console.log('页面隐藏 → 跳转成功,清理H5页面');
// 不同浏览器延迟适配
const ua = navigator.userAgent.toLowerCase();
let delay = 500; // 默认
if (ua.includes('huawei')) delay = 300; // 华为
if (ua.includes('quark')) delay = 200; // 夸克(更快响应)
setTimeout(() => {
clearH5PageAfterJump();
}, delay);
}
});
// 所有系统统一走a标签跳转
function jumpByATag(url) {
const ua = navigator.userAgent.toLowerCase();
const isAndroid = ua.indexOf('android') > -1 || ua.indexOf('adr') > -1;
const isIOS = !!ua.match(/\(i[^;]+;( u;)? cpu.+mac os x/);
const isXiaomi = ua.indexOf('mi ') > -1 || ua.indexOf('xiaomi') > -1 ||
ua.indexOf('redmi') > -1;
if (isIOS) {
window.location.href = url;
} else if (isAndroid || isXiaomi) {
// 安卓(尤其是⼩⽶)⽤iframe中转
const ifr = document.createElement('iframe');
ifr.src = url;
ifr.style.display = 'none';
document.body.appendChild(ifr);
// 可选:延时移除,避免影响
setTimeout(() => {
document.body.removeChild(ifr);
}, 2000);
} else {
const a = document.createElement('a');
a.href = url;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
// 可选:延时移除,避免影响
setTimeout(() => {
document.body.removeChild(a);
}, 2000);
}
}
function loadMWScheme() {
var appid = "wx5728ecf19f0d9405";
var path = "pages/index/index";
var env = "develop";
let code1 = `${code}`;
const params = new URLSearchParams(window.location.search);
ticket = params.get('ticket');
let queryObj = 'source=h5&ticket=' + ticket + '&code=' + code1;
let query = encodeURIComponent(queryObj);
let finalUrl = 'weixin://dl/business/?appid=' + appid + '&path=' + path + '&query=' + query + '&env_version=' + env;
console.log(finalUrl + '明文跳转');
jumpByATag(finalUrl);
}
function loadScheme(version = 'release') {
try {
let code1 = `${code}`;
const params = new URLSearchParams(window.location.search);
ticket = params.get('ticket');
// 鸿蒙系统直接加入白名单
// 否则-
GetWxMiniScheme(code1, ticket, version).then(res => {
const schemeUrl = res.urlScheme;
let jumped = false;
let hasReported = false;
const start = Date.now();
const handleVisibility = () => {
if (document.hidden) {
jumped = true;
console.log('页面隐藏 → 推测跳转成功');
document.removeEventListener('visibilitychange', handleVisibility);
clearH5PageAfterJump();
}
};
document.addEventListener('visibilitychange', handleVisibility);
const interval = setInterval(() => {
const elapsed = Date.now() - start;
if (jumped || hasReported || elapsed > 8000) {
clearInterval(interval);
return;
}
if (elapsed >= 5000 && !jumped) {
console.log('检测 5 秒未跳转,开始上报');
hasReported = true;
reportDeviceInfo(ticket);
clearInterval(interval);
}
}, 1000);
// 统一拼接跳转URL 0为明文跳转
let finalJumpUrl = '';
if (res.status == 0) {
var appid = "wx5728ecf19f0d9405";
var path = "pages/index/index";
var env = version;
let queryObj = 'source=h5&ticket=' + ticket + '&code=' + code1;
let query = encodeURIComponent(queryObj);
finalJumpUrl = 'weixin://dl/business/?appid=' + appid + '&path=' + path + '&query=' + query + '&env_version=' + env;
console.log(finalJumpUrl + '明文跳转', res);
} else {
finalJumpUrl = schemeUrl;
console.log(schemeUrl + ' 密文跳转', res);
}
// 所有系统统一走a标签跳转
jumpByATag(finalJumpUrl);
}).catch(err => {
console.error('获取Scheme失败:', err);
});
} catch (err) {
console.error('loadScheme异常:', err);
}
}
function reportDeviceInfo(ticket1 = ticket) {
console.log(navigator.userAgent, navigator, 'navigator', ticket1)
if (!isHo) {
p3.innerText = '非鸿蒙系统,请从App跳转小程序'
p.innerText = '系统类型:' + deviceInfo.systemType + '\n' + '版本号:' + deviceInfo.systemVersion + '\n平台:' + deviceInfo.platform + '\n' + 'UserAgent: ' + deviceInfo.userAgent + 'data"' + navigator.userAgentData;
console.log('检测设备信息:', deviceInfo, navigator.userAgentData, 'userAgentData', systemType);
ELEMENT.Message({
message: '请点击进入小程序,失败可选择上报设备信息,从小程序进入',
type: 'warning'
});
document.getElementById('hmbtn2').style.display = 'block';
document.getElementById('fhmbtn2').style.display = 'block';
return
}
AddWhitelist(ticket1, systemType + systemVersion).then(res => {
if (res == '')
res = '已经加入白名单,请从访客小程序入口进入'
ELEMENT.Message({
message: res,
type: 'error'
});
}).catch(err => {
console.log(err, 'err')
})
}
function joinWhiteList() {
let ticket1 = ticket
AddWhitelist(ticket1, systemType + systemVersion).then(res => {
if (res == '')
res = '已经加入白名单,请从访客小程序入口进入'
ELEMENT.Message({
message: res,
type: 'error'
});
}).catch(err => {
console.log(err, 'err')
})
}
</script>