Ayy

Ayy

记录微信小程序云开发静态H5页面跳转其他小程序的实现

52
2024-06-19

前言

最近需要实现用户在移动端打开网站的url时,可以跳转到公司的微信小程序页面。官方提供了H5静态网站跳转小程序的技术文档。小程序创建时并没有开通云开发的功能,再改也有些麻烦,就新建了一个新的小程序。使用官方提供的代码,始终无法从云开发的h5页面跳转到另一个小程序,折腾许久之后得以解决。

准备工作

A小程序是开通了云开发的小程序,B小程序是需要跳转到的小程序。A和B是同一主体,在A小程序里开通环境共享,共享给B小程序。云函数和H5页面的代码如下,基于官方的代码进行了一些修改。

相关代码

云函数public

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  switch (event.action) {
    case 'getUrlScheme': {
      return getUrlScheme(event)
    }
  }

  return 'action not found'
}
async function getUrlScheme(event) {
	console.log(event)
  if(event.appid) {
    var clb = cloud.openapi({ appid: event.appid });
  } else{
    var clb = cloud.openapi;
  }
  return clb.urlscheme.generate({
    jumpWxa: {
      path: event.path,
      query: event.query,
    },
    // 如果想不过期则置为 false,并可以存到数据库
    isExpire: false,
    // 一分钟有效期
    expireTime: parseInt(Date.now() / 1000 + 60),
  })
}

静态H5页面

其中资源方是开通云开发的小程序

<html>
	<head>
		<title>h5跳转小程序</title>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
		<script>
			window.onerror = e => {
				console.error(e);
				alert('发生错误:' + e);
			}
		</script>
		<!-- 调试用的移动端 console -->
		<!-- <script src="https://cdn.bootcss.com/eruda/1.2.4/eruda.min.js"></script> -->
		<!-- <script>eruda.init();</script> -->
		<script>
			function getQueryParam(key) {
				const reg = new RegExp('(^|&)' + key + '=([^&]*)(&|$)', 'i');
				const r = window.location.search.substr(1).match(reg);
				if (r != null) {
					return decodeURI(r[2]);
				}
				return null;
			}
			//设置 资源环境ID以及绑定的appid
			var resAppId = 'wxxxxxxxxx40'; // <!-- replace -->
			var resEnv = 'cloud-xxxxxxxxxxxxxxxx'; // <!-- replace -->
			//资源方其它小程序组【AppID,原始id,名称,缺省打开路径】
			var appIDs = [
				['wxxxxxxxxxxxxxxxd9', 'gh_xxxxxxxxxx', '小程序名称', '小程序路径'], // <!-- replace -->
				// ['wxxxxxxxxxxxxxxxd9','gh_xxxxxxxxxx','小程序B',''], // <!-- replace -->                
			];
			//////////////////////////////    
			var launchIdx = getQueryParam('id') || 0;
			var pagepath = launchIdx == 0 ? appIDs[launchIdx][3] : "";
			pagepath = pagepath ? pagepath + (getQueryParam('url') ? "?url=" + encodeURIComponent(getQueryParam('url')) : "") :
				"";
			pagepath = pagepath ? pagepath : (getQueryParam('page') ? getQueryParam('page') : "");
		</script>

		<!-- weui 样式 -->
		<link rel="stylesheet" href="https://res.wx.qq.com/open/libs/weui/2.4.1/weui.min.css" />
		<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
		<script src="https://res.wx.qq.com/open/js/cloudbase/1.1.0/cloud.js"></script>

		<style>
			/* .hidden {
				display: none
			}

			.full {
				position: absolute;
				top: 0;
				bottom: 0;
				left: 0;
				right: 0
			}

			.public-web-container {
				display: flex;
				flex-direction: column;
				align-items: center
			}

			.public-web-container p {
				position: absolute;
				top: 25%
			}

			.public-web-container a {
				position: absolute;
				bottom: 40%
			}

			.wechat-web-container {
				display: flex;
				flex-direction: column;
				align-items: center
			}

			.wechat-web-container p {
				position: absolute;
				top: 40%
			}

			.wechat-web-container wx-open-launch-weapp {
				position: absolute;
				bottom: 40%;
				left: 0;
				right: 0;
				display: flex;
				flex-direction: column;
				align-items: center
			}

			.desktop-web-container {
				display: flex;
				flex-direction: column;
				align-items: center
			}

			.desktop-web-container p {
				position: absolute;
				top: 40%
			} */
			
			.hidden { display: none; }
			  .full { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
			  .weui-btn { width: 200px; }
			  .public-web-container, .wechat-web-container {
			    display: flex;
			    flex-direction: column;
			    align-items: center;
				background: url('imgs/index1.png') center/cover, linear-gradient(to bottom, #032e6d 50%, #f9f9f9 50%);
				background-position: center;
				background-size: contain;
				background-repeat: no-repeat; /* 防止图片重复 */
			  }
			  
			  .public-web-container::before, .wechat-web-container::before {
			      content: ""; /* 必须设置,否则伪元素不会显示 */
			      position: absolute;
			      top: 0;
			      left: 0;
			      right: 0;
			      bottom: 0;
			      background-color: rgba(0, 0, 0, 0.5); /* 灰色遮罩,透明度为50% */
			      z-index: 1; /* 确保遮罩层位于背景图片之上 */
			  }
			  
			  .public-web-container p, .wechat-web-container p {
			    position: absolute;
			    top: 25%; /* 调整文本位置 */
			    width: 100%; /* 确保文本居中 */
			    text-align: center; /* 文本居中对齐 */
			    color: #fff; /* 设置文本颜色为白色,根据需要调整 */
			  }
			  .public-web-container a, .wechat-web-container wx-open-launch-weapp {
			    position: absolute;
			    bottom: 40%; /* 调整按钮位置 */
			    left: 50%; /* 水平居中 */
			    transform: translateX(-50%); /* 精确居中 */
				z-index: 2; /* 确保按钮位于遮罩层之上 */
			  }
			  .desktop-web-container { display: flex; flex-direction: column; align-items: center; }
			  .desktop-web-container p { position: absolute; top: 40%; }
		</style>
	</head>
	<body>
		<div class="page full">
			<div id="public-web-container" class="hidden">
				<!-- <p>正在唤起微信小程序...</p> -->
				<a id="public-web-jump-button" href="javascript:" class="weui-btn weui-btn_primary weui-btn_loading"
					onclick="openWeapp()">
					<span id="public-web-jump-button-loading"
						class="weui-primary-loading weui-primary-loading_transparent"><i
							class="weui-primary-loading__dot"></i></span>点击唤起小程序</a>
			</div>

			<div id="wechat-web-container" class="hidden">
				<script>
					/* document.write('<p>请点击下方按钮</p>'); */
					document.write('<wx-open-launch-weapp id="launch-btn" username="' + appIDs[launchIdx][1] + '" path="' + pagepath +
						'">');
					document.write(
						' <template><button style="width: 240px; height: 45px; text-align: center; font-size: 17px; display: block; margin: 0 auto; padding: 8px 24px; border: none; border-radius: 4px; background-color: #07c160; color:#fff;">打开微信小程序</button></template>'
						);
					document.write('</wx-open-launch-weapp>');
				</script>
			</div>
			<div id="desktop-web-container" class="hidden">
				<p class="font-size:26px;">请在手机上打开本链接</p>
			</div>
		</div>
		<script>
			function docReady(fn) {
				if (document.readyState === 'complete' || document.readyState === 'interactive') {
					fn();
				} else {
					document.addEventListener('DOMContentLoaded', fn);
				}
			}
			docReady(async function() {
				var ua = navigator.userAgent.toLowerCase()
				var isWXWork = ua.match(/wxwork/i) == 'wxwork';
				var isWeixin = !isWXWork && ua.match(/MicroMessenger/i) == 'micromessenger';
				var isMobile = isDesktop = false;
				if (navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|IEMobile)/i)) {
					isMobile = true
				} else {
					isDesktop = true
				}
				var isAndroid = ua.indexOf('android') > -1 || ua.indexOf('Adr') > -1;
				var isOS = ua.indexOf('iPhone') > -1 || ua.indexOf('iPad') > -1 || ua.indexOf('Mac') > -1;
				if (isWeixin) {
					var containerEl = document.getElementById('wechat-web-container');
					containerEl.classList.remove('hidden');
					containerEl.classList.add('full', 'wechat-web-container');

					var launchBtn = document.getElementById('launch-btn');
					launchBtn.addEventListener('ready', function(e) {
						console.log('开放标签 ready');
					});
					launchBtn.addEventListener('launch', function(e) {
						console.log('开放标签 success');
					});
					launchBtn.addEventListener('error', function(e) {
						console.log('开放标签 fail', e.detail);
					});
					wx.config({
						debug: false,
						appId: appIDs[launchIdx][0], // <!-- replace -->
						timestamp: 0, // 必填,填任意数字即可
						nonceStr: 'nonceStr', // 必填,填任意非空字符串即可
						signature: 'signature', // 必填,填任意非空字符串即可
						jsApiList: ['chooseImage'], // 必填,随意一个接口即可
						openTagList: ['wx-open-launch-weapp'], // 填入打开小程序的开放标签名
					})

				} else if (isDesktop) {
					// 在 pc 上则给提示引导到手机端打开
					var containerEl = document.getElementById('desktop-web-container')
					containerEl.classList.remove('hidden')
					containerEl.classList.add('full', 'desktop-web-container')

				} else {
					//腾讯云开发的免鉴权调用
					var containerEl = document.getElementById('public-web-container')
					containerEl.classList.remove('hidden')
					containerEl.classList.add('full', 'public-web-container')

					var c = new cloud.Cloud({
						identityless: true,
						resourceAppid: resAppId, // 资源方宿主 小程序的AppID
						resourceEnv: resEnv, // 资源方环境ID
					})
					await c.init();

					window.c = c;
					var buttonEl = document.getElementById('public-web-jump-button')
					var buttonLoadingEl = document.getElementById('public-web-jump-button-loading')
					try {
						await openWeapp(() => {
							buttonEl.classList.remove('weui-btn_loading');
							buttonLoadingEl.classList.add('hidden');
						})
					} catch (e) {
						console.log('error', e)
						buttonEl.classList.remove('weui-btn_loading')
						buttonLoadingEl.classList.add('hidden');
						throw e
					}
				}
			})

			async function openWeapp(onBeforeJump) {
				var c = window.c
				const res = await c.callFunction({
					name: 'public', // 宿主环境中的云函数,注意开启权限
					data: {
						action: 'getUrlScheme',
						appid: appIDs[launchIdx][0],
						path: pagepath
					},
				})
				if (onBeforeJump) {
					onBeforeJump();
				}
				location.href = res.result.openlink;
			}
		</script>
	</body>
</html>