> 技术文档 > uniapp 微信小程序webview 和 h5数据通信_uniappwebview和h5通信

uniapp 微信小程序webview 和 h5数据通信_uniappwebview和h5通信

项目是uniapp编写,因为是先开发了h5和app,小程序是突然要用的,做兼容开发已经来不及,由于微信小程序webview载入h5 因为通信必须要特殊限制(网页向小程序 postMessage 时,会在以下特定时机触发并收到消息:小程序后退、组件销毁、分享、复制链接(2.31.1)。e.detail = { data },data是多次 postMessage 的参数组成的数组。),不能满足使用,所以搞了一套特别low的通信机制,缺点是通信时候会有一个loading的过渡页面

业务逻辑大致为:
1、微信小程序webview访问h5带参数的url,获取初始的参数,可以携带页面参数或者登录token等,通过reciver接受h5返回的参数。
2、h5通过一个中间html页面存储小程序的通信逻辑,然后在h5页面通过定时器一直获取缓存本地的数据,根据数据信息执行不同的业务逻辑

1、微信小程序项目
(1)微信小程序项目
index.vue

<template> <web-view v-if=\"src\" :src=\"src\" bindload=\"bindload\" binderror=\"binderror\"></web-view></template><script lang=\"ts\">import { cfg } from \'@/cfg\'import Base64 from \'@/utils/Base64\'export default { data() { return { src: \'\', } }, onLoad(e: any) { let loginA = parseInt(e.loginA) console.log(e.loginA) if (loginA) { let self = this wx.login({ success(res: any) { // 自动登录成功 self.msg(Base64.encode64(\'loginA,\' + JSON.stringify([loginA, cfg.mpApp, res.code]))) }, fail(res: any) { // 自动登录失败 self.msg(Base64.encode64(\'loginAFail,\' + JSON.stringify([loginA, res.errMsg]))) }, }) return } this.msg(e.msg) }, methods: { msg(msg: any) { if (msg) { this.src = cfg.mpUrl + \'static/mpMsg.html?uid=\' + cfg.mpid + \'&msg=\' + msg // this.src = \'http://www.baidu.com/#/\' console.log(this.src) // 超时自动关闭 // @ts-ignore this[\'$timer\'] = setTimeout(() => { this.navBack() }, 3000) return } this.navBack() }, bindload() { console.log(\'bindload\') this.navBack() }, binderror() { console.log(\'binderror\') this.navBack() }, navBack() { let pages = getCurrentPages() if (pages[pages.length - 1].$vm == this) { uni.navigateBack() } // @ts-ignore let timer = this[\'$timer\'] if (timer) { // @ts-ignore delete this[\'$timer\'] clearTimeout(timer) } }, },}</script><style></style>

(2)reciver.vue

<template> <view id=\"preloader\"></view></template><script lang=\"ts\">import { App } from \'@/store/app\'import Base64 from \'@/utils/Base64\'export default { data() { return { src: \'\', } }, onLoad(e: any) { try { let msg = e.msg if (msg) { msg = Base64.decode64(msg) let i = msg.indexOf(\',\') let key = msg let val = \'\' if (i > 0) { key = msg.substring(0, i) val = msg.substring(i + 1) } // 如果是pc小程序bridge支付,则直接跳转到支付页面 // const info = uni.getSystemInfoSync() // if ((info?.deviceType == \'pc\' || info?.deviceType == \'PC\') && key == \'pay\') { // uni.redirectTo({ // url: `/pages/index/pay?pay=${Base64.encode64(val)}`, // }) // } else { // uni.navigateBack({ // complete() { // // setTimeout(() => { // App.mpRecieverMsg(key, val) // // }, 100) // }, // }) // } uni.navigateBack({ complete() { // setTimeout(() => { App.mpRecieverMsg(key, val) // }, 100) }, }) return } } catch (e) { console.error(e) } uni.navigateBack() }, methods: {},}</script><style scoped>#preloader { position: absolute; width: 30px; height: 30px; background: rgba(253, 87, 17, 1); border-radius: 50px; left: 0; right: 0; top: 0; bottom: 0; margin: auto; -webkit-animation: preloader_1 1.5s infinite linear; -moz-animation: preloader_1 1.5s infinite linear; -ms-animation: preloader_1 1.5s infinite linear; animation: preloader_1 1.5s infinite linear;}#preloader:after { position: absolute; width: 50px; height: 50px; border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); border-left: 10px solid transparent; border-right: 10px solid transparent; border-radius: 50px; content: \'\'; top: -20px; left: -20px; -webkit-animation: preloader_1_after 1.5s infinite linear; -moz-animation: preloader_1_after 1.5s infinite linear; -ms-animation: preloader_1_after 1.5s infinite linear; animation: preloader_1_after 1.5s infinite linear;}@-webkit-keyframes preloader_1 { 0% { -webkit-transform: rotate(0deg); } 50% { -webkit-transform: rotate(180deg); background: #ff4f11; } 100% { -webkit-transform: rotate(360deg); }}@-webkit-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); }}@-moz-keyframes preloader_1 { 0% { -moz-transform: rotate(0deg); } 50% { -moz-transform: rotate(180deg); background: #ff4f11; } 100% { -moz-transform: rotate(360deg); }}@-moz-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); }}@-ms-keyframes preloader_1 { 0% { -ms-transform: rotate(0deg); } 50% { -ms-transform: rotate(180deg); background: #ff4f11; } 100% { -ms-transform: rotate(360deg); }}@-ms-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); }}@keyframes preloader_1 { 0% { transform: rotate(0deg); } 50% { transform: rotate(180deg); background: #ff4f11; } 100% { transform: rotate(360deg); }}@keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); }}</style>

(3)app.ts

import cfg from \'@/cfg\'import Base64 from \'@/utils/Base64\'export const App = { shareData: {}, mpPostMsg(key: string, val?: string, redirect: boolean = true) { const msg = val ? key + \',\' + val : key if (redirect) { uni.redirectTo({ url: \'/pages/msg/post?msg=\' + Base64.encode64(msg) }) } else { uni.navigateTo({ url: \'/pages/msg/post?msg=\' + Base64.encode64(msg) }) } }, mpRecievers: { userStorageCert(cert: string) { console.log(\'userCert\', cert) if (cert) { uni.setStorageSync(cfg.mpApp + \'userStorageCert\', cert) } }, shareAppMessage(v: string) { let share try { share = JSON.parse(v) if (share.path) { // 使用正则表达式匹配 _i= 后面的字符串 const match1 = share.path.match(/_i=([^&]+)/) // 如果匹配成功,获取匹配到的字符串 if (match1) { const extractedString = match1[1] share.path = \'/pages/index/index?i=\' + extractedString console.log(\' share.path\', share.path) } } } catch (error) {} try { if (share.imageUrl) { share.imageUrl = share.imageUrl.replace(/(w_\\d+)|(h_\\d+)/g, (match: string) => { if (match.startsWith(\'w_\')) {  return \'w_300\' } else if (match.startsWith(\'h_\')) {  return \'h_300\' } }) } } catch (error) {} if (share) { App.shareData = share } }, pay(v: string) { const pay = JSON.parse(v) pay.success = function () { // 需要通知 App.mpPostMsg(\'pay,1\', undefined, false) } // pay.complete = function () { // // 需要通知 // App.mpPostMsg(\'pay,1\', undefined, false) // } pay.fail = function (e: any) { console.log(\'pay fail \' + JSON.stringify(e)) uni.showToast({ title: \'支付失败\', icon: \'none\', duration: 2000, }) } // 支付参数 console.log(JSON.stringify(pay)) const info = uni.getSystemInfoSync() // 如果是pc小程序bridge支付,则延迟掉起,防止不显示支付弹窗 if (info?.deviceType == \'pc\' || info?.deviceType == \'PC\') { uni.showLoading() setTimeout(() => { uni.hideLoading() wx.requestPayment(pay) }, 1000) } else { wx.requestPayment(pay) } }, bindWx() { wx.login({ success: function (res: any) { let data = \'\' if (res) { let appid = \'\' if (cfg.mpApp) {  appid = cfg.mpApp } data = JSON.stringify([appid, res.code]) } App.mpPostMsg(\'bindWx\', data, false) }, fail: function (err: any) { console.log(\'bindWx fail\', err) App.mpPostMsg(\'bindWx\', \'\', false) }, }) }, openLocation(adress: string) { const data = JSON.parse(adress) wx.openLocation({ latitude: Number(data.latitude), longitude: Number(data.longitude), name: data.name, scale: 18, complete: e => { console.log(\'openLocation complete\', e) }, }) console.log(\'openLocation data\', data) }, downloadAndSave(res: string) { const data = JSON.parse(res) const $delay = data[\'$delay\'] if ($delay > 0) { setTimeout(() => { wx.downloadFile({ url: data.url, success: function (res) {  wx.openDocument({ filePath: res.tempFilePath, fileType: \'pdf\', showMenu: true,  }) }, }) }, $delay) } else { wx.downloadFile({ url: data.url, success: function (res) { wx.openDocument({  filePath: res.tempFilePath,  fileType: \'pdf\',  showMenu: true, }) }, }) } }, callFun(res: string) { const data = JSON.parse(res) // @ts-ignore const fun = wx[data[\'$fun\']] if (fun) { delete data[\'$fun\'] const $delay = data[\'$delay\'] if ($delay > 0) { delete data[\'$delay\'] setTimeout(() => { fun.call(wx, data) }, $delay) } else { fun.call(wx, data) } } }, }, mpRecieverMsg(key: string, val?: string) { // @ts-ignore const fun = App.mpRecievers[key] if (fun) { fun(val) return } },}

(3)Base64.ts

// private propertylet _keyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";// private method for UTF-8 encodinglet _utf8_encode = function (str: string) { str = str.replace(/\\r\\n/g, \"\\n\"); let utftext = \"\"; for (let n = 0; n < str.length; n++) { let c = str.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext;}// private method for UTF-8 decodinglet _utf8_decode = function (utftext: string) { let string = \"\"; let i = 0; let c, c1, c2, c3 c = c1 = c2 = 0; while (i < utftext.length) { c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c); i++; } else if ((c > 191) && (c < 224)) { c2 = utftext.charCodeAt(i + 1); string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = utftext.charCodeAt(i + 1); c3 = utftext.charCodeAt(i + 2); string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } } return string;}const Base64 = { // public method for encoding encode(input: string) { let output = \"\"; let chr1, chr2, chr3, enc1, enc2, enc3, enc4; let i = 0; input = _utf8_encode(input); while (i < input.length) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4); } return output; }, // public method for decoding decode(input: string) { let output = \"\"; let chr1, chr2, chr3; let enc1, enc2, enc3, enc4; let i = 0; input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\"); while (i < input.length) { enc1 = _keyStr.indexOf(input.charAt(i++)); enc2 = _keyStr.indexOf(input.charAt(i++)); enc3 = _keyStr.indexOf(input.charAt(i++)); enc4 = _keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); } if (enc4 != 64) { output = output + String.fromCharCode(chr3); } } output = _utf8_decode(output); return output; }, // 编码 encode64(str: string, uri: boolean = true) { str = Base64.encode(str); if (uri) { str = str.replace(/[+|=|/]/g, function (word) { switch (word) { case \"+\": return \"-\"; case \"=\": return \"_\"; case \"/\": return \".\"; } return word; }); } return str; }, // 解码 decode64(str: string, uri: boolean = true) { if (uri) { str = str.replace(/[-|_|.]/g, function (word) { switch (word) { case \"-\": return \"+\"; case \"_\": return \"=\"; case \".\": return \"/\"; } return word; }); } str = Base64.decode(str); return str; },}export default Base64

index.vue

<template> <web-view :src=\"src\" @message=\"receiveMessage\"> </web-view></template><script lang=\"ts\">import { cfg } from \'@/cfg\'import { App } from \'@/store/app\'import Base64 from \'@/utils/Base64\'export default { data() { return { src: \'\', srcP: \'\', shareData: { imageUrl: \'https://yjy.yiyiny.com//static/images/20240122/\' + cfg.mpApp + \'.png?x-oss-process=image/auto-orient,1/resize,m_fixed,w_100,h_100\', }, shareI: \'\', } }, onLoad(e: any) { // e.scene 生成小程序码必须是这个key this.setSrc(cfg.entryUrl, e.i || e.scene) wx.showShareMenu({ withShareTicket: true, menus: [\'shareAppMessage\'], success(res) { console.log(\'mixin share success\', res ? JSON.stringify(res) : res) }, fail(err) { console.log(\'mixin share fail\', err ? JSON.stringify(err) : err) }, }) }, onShow() { cfg.mpSrcP = this.srcP App.shareData = {} }, onShareAppMessage(res: any) { console.log(res) if (res.from === \'button\') { return this.shareData } if (res.from === \'menu\') { return this.shareData || {} } }, onShareTimeline() { let data = { title: \'一乙艺术山庄\', query: \'id=1\', // imageUrl: \'\', } return data // return axCc.vueSelf.shareData || {}; }, onHide() {}, methods: { setSrc(src: string, shareI?: string) { let cert = uni.getStorageSync(cfg.mpApp + \'userStorageCert\') console.log(\'setSrc src\', src) console.log(\'setSrc shareI\', shareI) let i = src.indexOf(\'#\') let j = src.indexOf(\'?\') let srcP = i > 0 && i < j ? src.substring(0, i) : j > 0 ? src.substring(0, j) : src if (srcP && srcP[srcP.length - 1] != \'/\') { srcP = srcP + \'/\' } if (i > 0) { cfg.mpUrl = src.substring(0, i) } else { cfg.mpUrl = cfg.entryUrl } console.log(\'[ cfg.mpUrl ] >\', cfg.mpUrl) this.srcP = srcP cfg.mpSrcP = this.srcP src = j > 0 ? src + \'&_mpid_=\' + cfg.mpid : src + \'?_mpid_=\' + cfg.mpid if (shareI) { src = src + \'&_i=\' + shareI // 分享地址拼接 const startIndex = src.indexOf(\'#\') const endIndex = src.indexOf(\'?\') if (startIndex !== -1 && endIndex !== -1) { src = src.substring(0, startIndex) + src.substring(endIndex) console.log(src) } this.shareI = shareI } src = src + \'&ver=\' + cfg.version if (cert) { src = src + \'&_cert_=\' + encodeURIComponent(cert) } this.src = src console.log(\'setSrc this.src\', this.src) }, // 监听h5 消息 // { merber 用户信息 imageUrl 默认分享图 path 分享地址 title:分享标题 desc } receiveMessage(e: any) { console.log(\'receiveMessage333\', e) let arr = e?.detail?.data let data = arr && arr.length > 0 ? arr[arr.length - 1] : null let url if (data && data?.merber?.id) { url = data?.path ? data.path : cfg.mpName == \'mp_wdysj\' ? \'pages/artisthome/artisthome\' : \'/pagesShop/shop/wHome\' let parms = this.gen(url, false, { mmId: data?.merber.id }, 13050, data?.merber?.id) console.log(\'data222\', data) this.shareData = { path: \'/pages/index/index?i=\' + parms + \'&fk=1\', imageUrl: data?.imageUrl ? data.imageUrl : \'https://yjy.yiyiny.com//static/images/20240122/\' +  cfg.mpApp +  \'.png?x-oss-process=image/auto-orient,1/resize,m_fixed,w_100,h_100\', title: data?.title ? data.title : cfg.mpName, desc: data?.desc ? data.desc : \'\', query: parms, } } else { wx.hideShareMenu() } }, // 地址加密 gen(uri: string, bind: boolean, reg: any, eid?: number, memberId?: number): string { // 标准编码 let ps = [memberId, \'\', false, uri || \'\', reg || \'\', eid] for (let i = ps.length - 1; i >= 0; i--) { if (ps[i]) { let del = ps.length - i - 1 if (del > 0) { ps.splice(i + 1, del) } break } } let _ps: any = ps _ps[0] = _ps[0] || \'\' if (bind) { _ps[2] = uri _ps[3] = \'\' } else { _ps[2] = \'\' } return Base64.encode64(JSON.stringify(ps)) }, },}</script><style></style>

cfg.ts

export const cfg = { mpApp: \'mp_wdysj\', //一乙艺术商城 mpName: \'一乙艺术商城\', mpUrl: \'https://p.yiyiny.com/xxx/\', mpid: \'\', mpSrcP: \'\', version: \'1.0.8\', entryUrl: \'https://p.yiyiny.com/xxx/#/pagesShop/shop/wHome\',}const info = uni.getSystemInfoSync()if (!cfg.mpid) { const host = info.host // @ts-ignore if (host && host.appid) { // @ts-ignore cfg.mpid = host.appid } if (!cfg.mpid) { cfg.mpid = cfg.mpApp }}export default cfg

2、h5端
(1)项目初始化时候h5载入微信sdk
Ainit.ts

 // #ifdef H5 let _mpid_; try { let search = <any>( (launcher.h5Search || ab_.route(false, false, false).search) ); _mpid_ = search[\'_mpid_\']; let _cert_ = search[\'_cert_\']; // 获取小程序传递的证书 if (_cert_) { _cert_ = decodeURIComponent(_cert_) User.status.storage.cert = _cert_ } let app = axConfig.webType || \'web\' if (Weixin.isWeiXin()) { axCc.Loader().wait(\"weixinLogin\"); ab_.reqJs( axCc.https ? \"https://res.wx.qq.com/open/js/jweixin-1.6.0.js\" : \"http://res.wx.qq.com/open/js/jweixin-1.6.0.js\", null, function () { function wxH5() { if (search[\"code\"]) {  let parms: Array<string> = [axConfig.webType, search[\"code\"]];  User.loginProvBack( \"wx\", function (logined) {  console.log(\"微信登陆成功\", logined);  try {  if (logined) {axCc.saveStorage(\"wxLogined\", { token: App.client.plt.headers[\"atoken\"], authPar: User.status.authPar, authParas: User.status.authParas,});  } else {axCc.saveStorage(\"wxLogined\", {});  }  } finally {  axCc.Loader().done(\"weixinLogin\");  // 微信jsConfig  Weixin.wxConfig();  } }, parms, true, true, true  ); } else {  try { // 关闭自动登录 // User.autoLogin = false; let wxLogined = axCc.getStorage(\"wxLogined\"); if (wxLogined && wxLogined.token && wxLogined.authParas && wxLogined.authParas[0] === app) {  User.loginToken(wxLogined.token, (logined) => {  if (logined) {User.status.authPar = wxLogined.authPar;User.status.authParas = wxLogined.authParas;axCc.Loader().done(\"weixinLogin\");  } else {//微信浏览器 吊起微信支付必须要获取openidconsole.log(\"掉起微信支付必须要获取openid\");Weixin.snsapi_base();  }  }); } else {  //微信浏览器 吊起微信支付必须要获取openid  console.log(\"掉起微信支付必须要获取openid\");  Weixin.snsapi_base(); }  } finally { // 微信jsConfig Weixin.wxConfig();  } } } // @ts-ignore if (window.wx) { User.autoLogin = false; try {  // @ts-ignore  if (typeof WeixinJSBridge == \"object\" && typeof WeixinJSBridge.invoke == \"function\") { handleFontSize();  } else { if (document.addEventListener) {  document.addEventListener(\"WeixinJSBridgeReady\", handleFontSize, false);  // @ts-ignore } else if (document.attachEvent) {  // @ts-ignore  document.attachEvent(\"WeixinJSBridgeReady\", handleFontSize);  // @ts-ignore  document.attachEvent(\"onWeixinJSBridgeReady\", handleFontSize); }  }  function handleFontSize() { // 设置网页字体为默认大小 // @ts-ignore WeixinJSBridge.invoke(\'setFontSizeCallback\', { \'fontSize\': 0 }); // 重写设置网页字体大小的事件 // @ts-ignore WeixinJSBridge.on(\'menu:setfont\', function () {  // @ts-ignore  WeixinJSBridge.invoke(\'setFontSizeCallback\', { \'fontSize\': 0 }); });  }  // @ts-ignore  if (wx.miniProgram) { // @ts-ignore wx.miniProgram.getEnv((res) => {  if (res.miniprogram) {  User.status.info.cert = true  User.autoLogin = true;  // && search[\'_mpid_\'] == \"mp_wdysj_shop\"  if (_mpid_) {if ((_mpid_ == \"mp_wdysj_shop\" || _mpid_ == \"mp_wdysj_yiyi_shop\")) { axConfig.pltName = \"商城\" axConfig.home = \"/pagesShop/shop/wHome\" App.shopScoreName = \'商城\' App.client.storeHttp.head(\'platform\', \'mp\') axConfig.appProv = _mpid_ axConfig.appEid = 13061}axConfig.pltApp = _mpid_User.status.info.app = _mpid_  }  // 小程序  Weixin.initWxMpH5(_mpid_, search[\'ver\'])  axCc.Loader().done(\"weixinLogin\");  } else {  wxH5()  } }) return  } } catch (e) {  console.error(e) } wxH5() } else { axCc.Loader().done(\"weixinLogin\"); } }, undefined ); } else { } } catch (e) { console.error(e); } // #endif

2、Weixin.ts

import ab_ from \'axj-ab_\'; //npm install axj-ab_import Base64 from \'../util/Base64\';interface ShareInfo { title: string, desc?: string, link: string, imageUrl?: string, logo?: string,//兼容老项目 imgUrl?: string,//兼容老项目 scene?: string}let weixin = false;let readyReg = false;let wxConfigState = -1;let wxMpH5 = false;let wxMpApp = \'\';// let wxMpToken = \'\';const Weixin = { initStepsArray: [1000, 2000, 4000, 8000, 16000, 32000, 64000], initI: 0, erred: false, readyed: false, shareInfo: <undefined | ShareInfo>undefined, // 如果wx授权失败,则定时再次获取授权 wxConfigRe(e?: any) { console.log(\'wxConfig error \' + e) // alert(\'wxConfig error \' + JSON.stringify(e)) Weixin.erred = true // @ts-ignore setTimeout(Weixin.wxConfig, Weixin.initI < Weixin.initStepsArray.length ? Weixin.initStepsArray[Weixin.initI++] : Weixin.initStepsArray[Weixin.initStepsArray.length - 1]) }, // 通过config接口注入权限验证配置 wxConfig() { let authUrl = location.href wxConfigState++ switch (wxConfigState) { case 1: authUrl = Ainit.h5Href break // case 2: // authUrl = location.protocol + \'//\' + location.host + location.pathname + location.search + location.hash // break default: wxConfigState = 0 break }//调接口授权的方法可以自己写 App.client.plt.reqA(-1, \'C/wxConfig\', [axConfig.webType, authUrl], function (err, rep) { console.log(\'pltClient C/wxConfig err,data:\', err, rep) if (rep && rep.appId) { // rep.debug = true rep.jsApiList = [ \'updateAppMessageShareData\', \'updateTimelineShareData\', \'onMenuShareAppMessage\', \'onMenuShareTimeline\', \"getLocation\", \"scanQRCode\", // \'wx-open-launch-weapp\', // \'chooseWXPay\' ] // rep.debug = true console.log(\'wxready wx.config\') Weixin.erred = false // @ts-ignore wx.config(rep) // @ts-ignore wx.error(Weixin.wxConfigRe) let readyFun = function () { if (Weixin.erred) { return } Weixin.readyed = true } if (readyReg) { setTimeout(readyFun, 1000); } else { readyReg = true // @ts-ignore wx.ready(readyFun) } return; } Weixin.wxConfigRe() }) }, wxShare(v: ShareInfo) { console.log(\'h5 wxShare alert\', v); if (weixin) { // @ts-ignore v = typeof (v) === \'object\' ? v : JSON.parse(v) if (!Weixin.readyed) { Weixin.shareInfo = v return } delete Weixin.shareInfo var share = { title: v.title || \'xx\', // 分享标题 desc: v.desc || \'\', // 分享描述 link: v.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: v.imageUrl || v.logo || v.imgUrl, // 分享图标 success: (e) => { console.log(\'wxShare success \', e) // 显示微信分享 // @ts-ignore // if (window.WeixinJSBridge) { // // @ts-ignore // window.WeixinJSBridge.call(\'showOptionMenu\') // } if (window.wx && window.wx.showMenuItems) { // @ts-ignore window.wx.showMenuItems({  menuList: [ \'menuItem:share:appMessage\', \'menuItem:share:timeline\', \'menuItem:favorite\', \'menuItem:share:qq\', \'menuItem:share:QZone\',  ] }) } }, fail: function (e) { console.log(\'wxShare fail\', e) } } console.log(\'updateWx\', share) // @ts-ignore wx.updateAppMessageShareData(share) // @ts-ignore wx.updateTimelineShareData(share) // WeixinJSBridge.call(\"showOptionMenu\"); } }, // 静默授权 snsapi_base() { var backUri = Ainit.h5Href || location.href console.log(backUri) var redirectUri = axConfig.pltH5 + \'static/wx.html?u=\' + Base64.encode64(backUri, true) redirectUri = \'https://open.weixin.qq.com/connect/oauth2/authorize?appid=\' + (axConfig.webType == \'wdysjh5\' ? \'wxab385cf8a7ec96d8\' : \'wx59a0fb7a9bd076e5\') + \'&redirect_uri=\' + encodeURIComponent(redirectUri) + \'&response_type=code&scope=snsapi_userinfo&state=1\' console.log(redirectUri) location.replace(redirectUri) // setTimeout(() => { // location.replace(redirectUri) // }, 3000); }, isWeiXin() { return weixin; }, isWxMpH5() { return wxMpH5 }, getWxMpApp() { return wxMpApp }, initWxMpH5(mpid: string, ver?: string) { console.log(\'initWxMpH5 \' + mpid) weixin = false wxMpH5 = true if (mpid) { wxMpApp = mpid } else { console.log(\'initWxMpH5 no mpid\' + location.href) console.log(launcher.h5Href) console.log(launcher.h5Search) } Artist.getReviewVersion(`mp-${ver}`) // 消息通道 setInterval(function () { let msg = localStorage.getItem(\'_mpmsg_\') if (msg) { try { msg = JSON.parse(msg) if (!mpid || msg[0] === mpid) { // 是发给我的消息 msg = msg[1] msg = Base64.decode64(msg) let i = msg.indexOf(\',\') if (i > 0) {  Weixin.onWxMpMsg(msg.substring(0, i), msg.substring(i + 1)) } else {  Weixin.onWxMpMsg(msg, \'\') } localStorage.removeItem(\'_mpmsg_\') } } catch (e) { console.error(e) localStorage.removeItem(\'_mpmsg_\') } } }, 100) }, onWxMpMsg(key: string, val?: string) { console.log(\'onWxMpMsg,\' + key + \',\' + val) if (key == \'pay\') { console.log(\'updatePay,更新支付状态\' + key) uni.$emit(\'updatePay\', { msg: \'更新支付状态\' }) } // @ts-ignore wx.miniProgram.navigateBack() let fun = Weixin.onWxMpCenter[key] if (fun) { fun(val) } }, forWxMpToken(back: (err?: any) => void) { if (User.status.authPar) { back && back() return } // @ts-ignore let nextT = ab_.nextT() // @ts-ignore Weixin[\'forWxMpTokenBacks\'] = [nextT, back] // @ts-ignore wx.miniProgram.navigateTo({ url: \'/pages/msg/post?loginA=\' + nextT }) }, onWxMpCenter: { loginA(val: string) { let paras = JSON.parse(val) let nextT = 0 let back: any let loginA = false if (typeof (paras[0]) === \'number\') { loginA = true nextT = paras[0] paras = ab_.args(paras, 1, paras.length) let backs = Weixin[\'forWxMpTokenBacks\'] if (backs) { delete Weixin[\'forWxMpTokenBacks\'] if (backs[0] === nextT) { back = backs[1] } } } let noRep = nextT && User.state.logined User.loginProvBack(\'wx\', (succ, rep) => { console.log(\'loginA \', succ, rep) if (succ) { Page.loginSuccBack() if (loginA) { // @ts-ignore wx.miniProgram.navigateBack() } } else if (!User.state.authing && !nextT) { console.log(\'toLogin--------\') Weixin.postWxMpMsg(\'toLogin\') } // 回调 back && back(User.status.authToken ? undefined : rep) }, paras, false, 2, false, noRep) }, loginAFail(val: string) { let paras = JSON.parse(val) let nextT = paras[0] let backs = Weixin[\'forWxMpTokenBacks\'] if (backs) { delete Weixin[\'forWxMpTokenBacks\'] if (backs[0] === nextT) { backs[1] && backs[1](paras[1]) } } }, loginInfo(val: string) { //let loginInfo = JSON.parse(val) let paras = JSON.parse(val) if (User.status.authToken) { paras[1] = User.status.authToken } User.loginProvBack(\'wx\', (succ) => { if (succ) { Page.loginSuccBack() } else if (!User.state.authing) { User.status.authToken = \'\' } }, paras, true, 2) }, bindWx(val: string) { uni.$emit(\'updateBindWx\', { msg: val }) } }, postWxMpMsg(key: string, val?: string) { console.log(\'postWxMpMsg,\' + key + \',\' + val) if (key === \'toLogin\') { // ios 微信新用户第一次登录 会导致不执行此逻辑 setTimeout(() => { // @ts-ignore wx.miniProgram.navigateTo({ url: \'/pages/index/login?t=\' + User.status.authToken }) }, 400); return } // if (key === \'toLoginA\') { // // @ts-ignore // wx.miniProgram.navigateTo({ url: \'/pages/index/login\' }) // return // } if (key === \'share\') { // @ts-ignore wx.miniProgram.navigateTo({ url: \'/pages/msg/share?s=\' + val }) return } let msg = val ? (key + \',\' + val) : key setTimeout(() => { // @ts-ignore wx.miniProgram.navigateTo({ url: \'/pages/msg/reciver?msg=\' + Base64.encode64(msg) }) }, 400); console.log(\'postWxMpMsg.navigateTo\'); },}// #ifdef H5try { // 微信环境判断 let userAgent: any = window.navigator.userAgent.toLowerCase(); weixin = userAgent.match(/MicroMessenger/i) == \"micromessenger\" && !(window.parent && window.parent !== window); //兼容 微信支付路径 if (weixin) { let h5Uri = location.href; if (h5Uri.indexOf(\'/#/\') < 0) { // axCc.Loader().wait(\"weixinHref\"); try { h5Uri = location.origin + location.pathname + \"#/\" + location.search location.href = h5Uri setTimeout(() => { location.reload() }, 1000); axCc.Loader().wait(\"weixinHref\"); } catch (error) { } } }} catch (e) { console.error(e);}// #endifexport default Weixin;

3、公共h5跳转页

<html> <head> <meta charset=\"utf-8\" /> <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0,maximum-scale=1,viewport-fit=cover\" /> <title>···</title> <style> #loadingBg { width: 100vw; height: 100vh; position: fixed; z-index: 10000; top: 0; } body { margin: 0px; font-size: 12px; } #preloader { position: absolute; width: 30px; height: 30px; background: rgba(253, 87, 17, 1); border-radius: 50px; left: 0; right: 0; top: 0; bottom: 0; margin: auto; -webkit-animation: preloader_1 1.5s infinite linear; -moz-animation: preloader_1 1.5s infinite linear; -ms-animation: preloader_1 1.5s infinite linear; animation: preloader_1 1.5s infinite linear; } #preloader:after { position: absolute; width: 50px; height: 50px; border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); border-left: 10px solid transparent; border-right: 10px solid transparent; border-radius: 50px; content: \"\"; top: -20px; left: -20px; -webkit-animation: preloader_1_after 1.5s infinite linear; -moz-animation: preloader_1_after 1.5s infinite linear; -ms-animation: preloader_1_after 1.5s infinite linear; animation: preloader_1_after 1.5s infinite linear; } @-webkit-keyframes preloader_1 { 0% { -webkit-transform: rotate(0deg); } 50% { -webkit-transform: rotate(180deg); background: #ff4f11; } 100% { -webkit-transform: rotate(360deg); } } @-webkit-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @-moz-keyframes preloader_1 { 0% { -moz-transform: rotate(0deg); } 50% { -moz-transform: rotate(180deg); background: #ff4f11; } 100% { -moz-transform: rotate(360deg); } } @-moz-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @-ms-keyframes preloader_1 { 0% { -ms-transform: rotate(0deg); } 50% { -ms-transform: rotate(180deg); background: #ff4f11; } 100% { -ms-transform: rotate(360deg); } } @-ms-keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } @keyframes preloader_1 { 0% { transform: rotate(0deg); } 50% { transform: rotate(180deg); background: #ff4f11; } 100% { transform: rotate(360deg); } } @keyframes preloader_1_after { 0% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } 50% { border-top: 10px solid rgba(253, 87, 17, 1); border-bottom: 10px solid rgba(253, 87, 17, 1); } 100% { border-top: 10px solid rgba(255, 139, 9, 1); border-bottom: 10px solid rgba(255, 139, 9, 1); } } </style> </head> <script> function getPara(name) { var reg = new RegExp(\"(^|&)\" + name + \"=([^&]*)(&|$)\", \"i\"); var r = window.location.search.substr(1).match(reg); if (r != null) { return unescape(r[2]); } return null; } let uid = getPara(\"uid\"); let msg = getPara(\"msg\"); if (msg) { localStorage.setItem(\"_mpmsg_\", JSON.stringify([uid, msg])); } </script> <body> <div id=\"loadingBg\"> <div id=\"preloader\"></div> <!-- <div>加载中</div> --> </div> </body></html>