scenario
There is an H5 (VUE project), which needs to realize the jump to the small program by clicking the item. It should be supported both inside and outside wechat. Here we only introduce the jump of H5 outside wechat.
As shown in the picture, inside the red box is a product, that is, click here to jump to the applet:
Configure wechat small program cloud development (cloud function)
1. Open cloud development
Then choose the free amount
2. Cloud development permission setting
Go to the permissions Settings and turn on “user access permissions” here
3. Create a cloud functionopenMiniapp
So here we’re just going to call itopenMiniapp
The cloud function is put here, its code will be written later.
4. Modify cloud function permissions
Add this configuration and make sure the name is the same as the name of the cloud function:
Cloud function code
1. Write cloud function code
For native applets, after cloud development + cloudfunctions are configured, the applets project directory should have an additional directory for cloudfunctions (probably called Cloudbase, but since I am using uniapp, this directory is custom, I set it to wxCloudFunctions) :
Attached: UniAPP configuration cloud function tutorial 1 UniAPP configuration cloud function tutorial 2
Cloud function code:
Package. Json:
{
"name": "GENERAL"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": ""."license": "ISC"."dependencies": {
"wx-server-sdk": "~ 2.3.2." "}}Copy the code
Index. Js:
const cloud = require('wx-server-sdk')
cloud.init()
exports.main = async (event, context) => {
const { path = ' ', queryData = {}, } = event // The parameters I passed in from H5 can be obtained from event
/ / get queryStr
let queryStrArr = []
for (let key in queryData) {
const str = `${key}=${queryData[key]}` // name=tom
queryStrArr.push(str)
}
const queryStr = queryStrArr.join('&')
console.log('path', path)
console.log('queryStr', queryStr)
return cloud.openapi.urlscheme.generate({
jumpWxa: {
path: path ? ('/' + path) : ' '.// Open the small program access path, empty will enter the home page
query: queryStr, // You can use the data passed in by event to make specific parameters, null if not required
},
isExpire: true.If the value is true and the expiration time is required, the default value is false
expire_time: Math.round(new Date().getTime() / 1000) + 3600
// We set the current time to 3600 seconds, that is, 1 hour after expiration
// There is no need to remove these parameters (isExpire, expire_time)})}Copy the code
2. Deploy cloud functions
Right-click and select Create and Deploy.
This completes the deployment of the cloud functions.
H5 part
1.<JumpApp/>
My idea is to write a generic component,
I can do this:
<! - goods -- -- >
<view v-for="item in goodsList ?? []" :key="item.id" class="item_wrap">
<JumpApp
:ghid="jumpAppGhCode"
:appid="jumpAppAppid"
:envid="jumpAppEnvid"
:ready="doctorInfo? .doctorCode"
:path="`pages/product/details/details`"
:queryData="{ dCode: doctorInfo? .developerCode ?? '', skuCode: item.chnlGoodsId, }"
>
<view class="service_package_item">
<image class="service_package_item_icon" :src="item.goodsImg? .split(',')[0] ?? "'"></image>
<view class="service_package_item_content">
<view class="service_package_item_content_title_wrap">
<view class="service_package_item_content_title">{{ item.goodsName }}</view>
<view class="service_package_item_content_price">{{item. GoodsFeeStr}}</view>
</view>
<view class="service_package_item_content_desc">{{ item.goodsDesc }}</view>
</view>
</view>
</JumpApp>
</view>
Copy the code
It could also go like this:
<view class="buy_btn_box">
<customButton v-if="drugListInfo? .disabled == 1" name="List is no longer valid. Please contact the doctor again." :disabled="true" />
<! -- Jump applet -->
<JumpApp
v-else
:ghid="jumpAppGhCode"
:appid="jumpAppAppid"
:envid="jumpAppEnvid"
:ready="jumpInfo.path"
:path="jumpInfo.path"
:queryData="jumpInfo.queryData"
>
<customButton type="primary" name="Buy now, deliver medicine to your door." />
</JumpApp>
</view>
Copy the code
2. Introduce props
props | type | The default value | instructions |
---|---|---|---|
path | string | Jump to the applet path | |
queryData | object | {} | Carrying parameters |
ready | any | The last call to the cloud function is performed only when ready is true, for cases that depend on some asynchronous data | |
callFunctionName | string | ‘openMiniapp’ | The name of the called cloud function |
ghid | string | The original ID of the applet (the one starting with GH) | |
appid | string | Appid of the applet | |
envid | string | Cloud environment ID for cloud development |
Attachment: Location of cloud environment ID:
3. Key code
Configure H5’s cloud function init
methods: {
...
/ / configuration first
async preConfig() {
const self = this
if (isWeixin()) {
// This is the part of wechat H5 configuration WXJSSDK
return await configWx([], ['wx-open-launch-weapp'])}else {
/ / WeChat outside
if (!window.tcb) {
window.tcb = new window.cloud.Cloud({
identityless: true.resourceAppid: self.appid,
resourceEnv: self.envid,
})
}
return await window.tcb.init()
}
},
...
}
Copy the code
window.jumpAppState
Because sometimes there may be multiple
The cloud function actually only needs to be initialized once, because the cloud function is attached to the window. Even for H5 within wechat, the WX JSSDK only needs to be initialized once per page.
The variable window.jumpappState is used to determine whether the current page is being initialized and whether the initialization is complete. Window.location. hash is used as the key to distinguish between different pages.
async mounted() {
console.log('jumpApp mounted')
if (!window.jumpAppState) window.jumpAppState = {}
// console.log(window.jumpAppState[`isReady_${window.location.hash}`])
// console.log(window.jumpAppState[`isGettingReady_${window.location.hash}`])
/ / configuration first
if (!window.jumpAppState[`isReady_The ${window.location.hash}`] &&!window.jumpAppState[`isGettingReady_The ${window.location.hash}`]) {
console.log('Enter configuration')
window.jumpAppState[`isGettingReady_The ${window.location.hash}`] = true
await this.preConfig()
window.jumpAppState[`isGettingReady_The ${window.location.hash}`] = false
window.jumpAppState[`isReady_The ${window.location.hash}`]}// Configure end first
console.log('Configured')
this.isPreConfigFinish = true
},
Copy the code
Call the cloud function openMiniapp and get the openLink
methods: {
...
/ / WeChat outside
async initOutWeixin() {
const self = this
let res
try {
res = await window.tcb.callFunction({
name: self.callFunctionName, // Provide the cloud function name of the UrlScheme service
data: {
path: self.path,
queryData: self.queryData,
},
})
} catch (e) {
console.log('The cloud function failed', e)
}
console.log('Cloud function result', res)
this.minihref = res? .result? .openlink ??' '
this.isInitWechatFinish = true
},
// Click
handleOutWeixinClick() {
if(! isWeixin() &&this.minihref && this.isInitWechatFinish) {
window.location.href = this.minihref
}
},
...
}
Copy the code
A couple of variables that I setisPreConfigFinish
isCanInitWechat
isInitWechatFinish
· isPreConfigFinish indicates whether window. TCB init is complete (if it is in wechat, it indicates whether WX JSSDK config is complete)
· isCanInitWechat is preConfig complete and some external parameters are ready. Because sometimes we jump with parameters that are retrieved asynchronously, such as order number, product code, etc., we set a props. Ready variable. IsCanInitWechat is true only if isPreConfigFinish is true and some asynchronous data is being held (props. Ready)
· isInitWechatFinish means that the cloud function is successfully invoked and openLink is available.
The resulting minihref is something like this: “weixin://dl/business/? Ticket =slejlsdjlf”, we call window.location.href = this.minihref to trigger the jump applet.
Ok Development is complete
The complete code
<JumpApp/>
<template>
<view class="p_1646876870010">
<div class="open_app_div" @click="handleOutWeixinClick" v-html="openWeappBtnHtml"></div>
<slot></slot>
</view>
</template>
<script>
import { ref, onMounted } from 'vue'
import { configWx } from '@/services/wx'
import { jumpAppGhCode } from '@/utils/consts'
import { isWeixin } from '@/utils/utils_h5'
// Since a page can have multiple JumpApp components, use window to keep the status of whether the configuration was successful, and use the current page hash value to distinguish window.location.hash
// window.jumpAppState = {
// [`isGettingReady_${window.location.hash}`]: false,
// [`isReady_${window.location.hash}`]: false,
// }
/** * order: (several variables) * 1, preConfig * 2, external ready 1, isCanInitWechat change to true, init wechat applet jump * * 3, isInitWechatFinish finally successful */
export default {
data() {
return {
isPreConfigFinish: false.// Whether preConfig is complete
isInitWechatFinish: false.// Finally succeeded
/ / WeChat inside
openWeappBtnHtml: ' './ / WeChat outside
minihref: ' ',}},props: {
// Path does not need '/'
path: {
type: String,},queryData: {
type: Object.default: () = >({})},ready: {}, // Do not add WX-open-launch-syndrome or trigger cloud functions until other external data is ready for true
// The name of the called cloud function
callFunctionName: {
type: String.default: 'openMiniapp',},/**
* 微信内
*/
ghid: {
type: String,},/** * wechat */
appid: {
type: String,},// Cloud environment ID
envid: {
type: String,}},computed: {
isCanInitWechat() {
return this.isPreConfigFinish && this.ready
},
},
watch: {
isCanInitWechat(v) {
if (v) {
setTimeout(() = > {
if (isWeixin()) {
this.initInWeixin()
} else {
this.initOutWeixin()
}
}, 0)}}},async mounted() {
console.log('jumpApp mounted')
if (!window.jumpAppState) window.jumpAppState = {}
// console.log(window.jumpAppState[`isReady_${window.location.hash}`])
// console.log(window.jumpAppState[`isGettingReady_${window.location.hash}`])
/ / configuration first
if (!window.jumpAppState[`isReady_The ${window.location.hash}`] &&!window.jumpAppState[`isGettingReady_The ${window.location.hash}`]) {
console.log('Enter configuration')
window.jumpAppState[`isGettingReady_The ${window.location.hash}`] = true
await this.preConfig()
window.jumpAppState[`isGettingReady_The ${window.location.hash}`] = false
window.jumpAppState[`isReady_The ${window.location.hash}`]}// Configure end first
console.log('Configured')
this.isPreConfigFinish = true
},
methods: {
/ / configuration first
async preConfig() {
const self = this
if (isWeixin()) {
return await configWx([], ['wx-open-launch-weapp'])}else {
if (!window.tcb) {
window.tcb = new window.cloud.Cloud({
identityless: true.resourceAppid: self.appid,
resourceEnv: self.envid,
})
}
return await window.tcb.init()
}
},
/ / WeChat inside
async initInWeixin() {
console.log('Inside Wechat')
/ / get queryStr
let queryStrArr = []
for (let key in this.queryData) {
const str = `${key}=The ${this.queryData[key]}` // name=tom
queryStrArr.push(str)
}
const queryStr = queryStrArr.join('&')
const jumpPath = `The ${this.path}?${queryStr}`
this.openWeappBtnHtml = `
<wx-open-launch-weapp
id="launch-btn"
username="The ${this.ghid}"
path="${jumpPath}" style="background-color:transparent;" > <template> <div style="width:800px; padding:100px; color:transparent; background-color:transparent; "> </div> </template> </ wX-open-launch-downloadp > '
this.isInitWechatFinish = true
},
/ / WeChat outside
async initOutWeixin() {
const self = this
let res
try {
res = await window.tcb.callFunction({
name: self.callFunctionName, // Provide the cloud function name of the UrlScheme service
data: {
path: self.path,
queryData: self.queryData,
},
})
} catch (e) {
console.log('The cloud function failed', e)
}
console.log('Cloud function result', res)
this.minihref = res? .result? .openlink ??' '
this.isInitWechatFinish = true
},
// Click
handleOutWeixinClick() {
if(! isWeixin() &&this.minihref && this.isInitWechatFinish) {
window.location.href = this.minihref
}
},
}, // methods end
}
</script>
<style lang="less">
.p_1646876870010 {
position: relative;
overflow: hidden;
.open_app_div {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0; }}</style>
Copy the code
Attached is the code of WXJSSDK for H5 configuration in wechatconfigWx
/ * * *@param {Array<string>} jsApiArr
* @returns* /
export function configWx(jsApiArr = [], openTagArr = []) {
return new Promise(async (resolve, reject) => {
if(! wx)return reject()
wx.ready(function (res) {
All interface calls must be made after the result of the config interface. Config is an asynchronous operation on the client side, so if the relevant interface needs to be called when the page loads, it must be called in the ready function to ensure correct execution. Interfaces that are invoked only when triggered by the user can be invoked directly without being placed in the ready function.
console.log('WX ready I printed', res)
return resolve()
})
wx.error(function (err) {
If the config information fails to be verified, the error function will be executed. For example, the verification fails due to the expiration of the signature. You can view the specific error information in the debug mode of config or in the returned res parameter.
console.log('Wx error I printed', err)
return reject(err)
})
/ / request
let config = null
try {
/** * Apple share will fail to retrieve the signature because: Apple browser mechanism in wechat is different from Android, there are IOS cache problems, and IOS single page optimization problems. * Generally speaking, Android will refresh the current URL when jumping to share the page, but Apple will not, Apple through history records. The URL will not be refreshed so the signature will fail. * * so * get the full href of signUrl for Android, ios only uses */ before #
let signUrl = ' '
if (isIOS()) {
signUrl = window.location.href.split(The '#') [0]}else {
signUrl = window.location.href
}
const res = await request({
url: '/h5/user/jsapi/initConfig'.data: { url: signUrl },
})
config = res?.data ?? {}
} catch (error) {
return reject(error)
}
if (config) {
wx.config({
// debug: getIsProd() ? False: true, // If debug mode is enabled, the return value of all API calls will be displayed in the client alert. If you want to view the parameters passed in, you can open it in the PC, and the parameter information will be printed in the log.
debug: false.appId: appid + ' '.timestamp: config.timestamp + ' '.// Mandatory to generate the timestamp of the signature
nonceStr: config.nonceStr + ' '.// Mandatory to generate a random string of signatures
signature: config.signature + ' '.// Mandatory, signature
jsApiList: ['hideMenuItems'. jsApiArr],// Mandatory, a list of JS interfaces that need to be used
openTagList: [...openTagArr],
})
}
})
}
Copy the code
Reference Documents:
Github web2app.js this is an official example, referring largely to urlscheme.generate