最近VUE3前端项目开发过程中,调用微信扫码时,在安卓华为等手机上能正常使用,但是在苹果手机IOS系统签名验证会报错,出现了异常。经过AI分析查询,原因是因为IOS系统和安卓系统的微信验证网址不同,安卓系统的验证地址是当前的URL地址,而IOS系统的验证地址则是第一次进入到网页或应用的URL地址。
安卓系统验证地址:location.href.split('#')[0]
IOS系统验证地址:window.entryUrl
相关代码判断系统
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent)
let signUrl = isIOS ? window.entryUrl : location.href.split('#')[0]
而window.entryUrl的值我们可以在APP.vue页面的 onLaunch 下获取,相关代码如下:
<script>
export default {
onLaunch: function() {
console.log('App Launch')
// URL将用于iOS 微信的 JS-SDK 签名
if (!window.entryUrl) {
window.entryUrl = location.href.split('#')[0];
}
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
同时我们可以把验证的做为一个统一的wechat.js,在业务页面直接调用即可
// 引用wechat.js
import wechatManager from '@/utils/wechat.js'
// 扫码
handleScan() {
if (!this.isWechat) {
uni.showToast({
title: '请在微信中打开',
icon: 'none'
})
return
}
wechatManager.scan({
needResult: 1,
scanType: ['barCode', 'qrCode']
})
.then(res => {
// 扫码结果
console.log(res.resultStr)
})
.catch(err => {
console.error('扫码失败:', err)
uni.showToast({
title: err.message || '扫码失败,请重试',
icon: 'none',
duration: 3000
})
})
}
wechat.js代码
import wx from 'weixin-js-sdk'
import {
getWxmpJsapiTicket
} from '@/api/user.js'
class WechatManager {
constructor() {
this.configReady = false
this.configPending = false
this.configPromise = null
this.ticketData = null
}
/**
* 初始化微信配置(只执行一次)
*/
init() {
// 如果已经配置完成,直接返回成功
if (this.configReady) {
return Promise.resolve(true)
}
// 如果正在配置中,返回现有的 Promise
if (this.configPending && this.configPromise) {
return this.configPromise
}
// 检查是否在微信环境
if (!/MicroMessenger/i.test(navigator.userAgent)) {
return Promise.reject(new Error('非微信环境'))
}
this.configPending = true
// 判断系统,选择正确的 URL
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent)
let signUrl = isIOS ? window.entryUrl : location.href.split('#')[0]
//signUrl = encodeURIComponent(signUrl)
this.configPromise = getWxmpJsapiTicket(signUrl)
.then(res => {
if (res.code !== 200) {
throw new Error(res.message || '获取签名失败')
}
this.ticketData = res.data
return this.configWx()
})
.then(() => {
this.configReady = true
this.configPending = false
console.log('微信配置完成')
return true
})
.catch(err => {
this.configReady = false
this.configPending = false
this.configPromise = null
console.error('微信配置失败:', err)
throw err
})
return this.configPromise
}
/**
* 执行 wx.config
*/
configWx() {
return new Promise((resolve, reject) => {
const data = this.ticketData
wx.config({
debug: false, // 调试时改为 true
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: ['checkJsApi', 'scanQRCode']
})
wx.ready(() => {
resolve(true)
})
wx.error((err) => {
reject(err)
})
})
}
/**
* 扫码(自动确保配置完成)
*/
scan(options = {}) {
return this.init()
.then(() => {
return new Promise((resolve, reject) => {
// 检查 API
wx.checkJsApi({
jsApiList: ['scanQRCode'],
success: (res) => {
if (!res.checkErrMsg || res.checkErrMsg === 'scanQRCode:ok') {
// 执行扫码
wx.scanQRCode({
needResult: options.needResult || 1,
scanType: options.scanType || ['barCode', 'qrCode'],
success: (result) => {
resolve(result)
},
fail: (err) => {
reject(err)
}
})
} else {
reject(new Error('扫码API不可用: ' + res.checkErrMsg))
}
},
fail: (err) => {
reject(err)
}
})
})
})
}
/**
* 重置配置(用于切换页面或重新配置)
*/
reset() {
this.configReady = false
this.configPending = false
this.configPromise = null
this.ticketData = null
}
}
export default new WechatManager()