iOS微信JSSDK授权签名错误及图片选择兼容
转载请注明出处:https://blog.csdn.net/hx7013/article/details/143502680
一、项目概述
Vue3
+Vite
+Vue-Router 4
+JS-SDK 1.6
由于之前开发调试都是在微信开发者工具及 Android
平台,后上线前测试发现 iOS
平台会出现 invalid signature
及图片选择后预览失败的问题。
查询资料后逐步解决,重新整理了下问题原因,及修复的详细代码和说明。
二、iOS 签名错误 invalid signature
由于我 vue-router
使用的是 history
模式,页面跳转后在iOS使用 window.location.href
获取到的地址签名后 wx.config
会报错 invalid signature
,使用 微信 JS 接口签名校验工具 对比过,确认签名无误,但是还是会报该错误。各种查询后得知传给后端签名的URL地址 iOS
在 vue-router
history
模式下,需要传刚进入的页面url
, Android
可以实时window.location.href
取当前url。
-
解决方法1:
vue-router
改为hash
模式。(实际就是保证了地址的不变,但是不推荐该做法,对于我这边来说,对现有项目影响较大) -
解决方法2:
存储首次启动时的地址,获取JSSDK签名时判断是iOS
还是Android
,区别传入首次进入的地址或当前地址即可。
解决方法2代码:
- 工具类
WxUtils.ts
/**
* iOS微信内JSSDK授权需提交启动地址
*/
export const WX_ENTRY_URL_TAG = 'wxEntryUrl'
/**
* 是否为微信浏览器
*/
export function isWxBrowser() {
const ua = navigator.userAgent.toLocaleLowerCase()
return /micromessenger/.test(ua)
}
/**
* 是否为iOS浏览器
*/
export function isIOSBrowser() {
const ua = navigator.userAgent.toLocaleLowerCase()
return /iphone|ipad|ipod/.test(ua)
}
/**
* 获取JSSDK授权地址
* App.vue -> sessionStorage.setItem(WX_ENTRY_URL_TAG, window.location.href)
*/
export function loadJSSDKUrl(): string {
let sdkUrl = window.location.href
const sessionWxEntryUrl = sessionStorage.getItem(WX_ENTRY_URL_TAG)
if (isIOSBrowser() && sessionWxEntryUrl && sessionWxEntryUrl.length > 0) {
sdkUrl = sessionWxEntryUrl
}
return sdkUrl.split('#')[0]
}
App.vue
<script setup lang="ts">
import { WX_ENTRY_URL_TAG, loadJSSDKUrl } from './utils/WxUtils';
/**
* iOS微信内JSSDK授权需提交启动地址
* {@link loadJSSDKUrl}
*/
sessionStorage.setItem(WX_ENTRY_URL_TAG, window.location.href)
</script>
- 使用,在需要授权的页面使用
loadJSSDKUrl()
获取地址即可
<script setup lang="ts">
import { isWxBrowser, loadJSSDKUrl } from '../../../utils/WxUtils'
... //忽略其它import
const wxEntryUrl = ref(window.location.href)
... // 忽略其它代码
function loadJSAuthorization() {
Net.post<JSAuthor>('/xxx', ???, { url: wxEntryUrl.value ?? window.location.href })
.then(resp => initJSSDK(resp.data))
.catch(err => {
pageState.value = PageState.Failed
pageMessage.value = `加载失败: ${err}`
})
}
onMounted(() => {
wxEntryUrl.value = loadJSSDKUrl()
... // 忽略其它代码
})
三、iOS 选择图片
授权后使用 wx.chooseImage
,按文档说明“返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片”,实际测试 Android
是可以显示的,但是 iOS
却不能显示。
具体原因为 iOS
中 WKWebView
及 UIWebView
的WebView内核不同导致的,详细可查看官方文档 iOS WKWebview网页开发适配指南。
后使用wx.chooseImage
+ wx.getLocalImgData
直接获取图片Base64后交给 <img>
标签显示。但是在获取图片Base64时又发现新的问题,iOS
获取时会携带data:image/...
数据头,但是 Android
又不携带,所以在 wx.getLocalImgData
中又需要进行一次处理。
最后兼容 iOS
及 Android
的代码如下:
<script setup lang="ts">
const imageBase64 = ref('')
function onSelectImage() {
const loading = showLoadingToast({ message: '获取图片中', forbidClick: true })
wx.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['camera'],
success(res) {
wx.getLocalImgData({
localId: res.localIds[0],
success(res) {
let localImage = res.localData
localImage = localImage.startsWith('data:image') ? localImage.replace('data:image/jgp;', 'data:image/jpeg;') : `data:image/jpeg;base64,${localImage}`
imageBase64.value = localImage.replace(/\r|\n/g, '')
},
fail(err) {
showNotify({ type: 'warning', message: `获取图片失败: ${err}` })
},
complete() {
loading.close()
},
})
},
cancel() {
loading.close()
},
fail(err) {
loading.close()
showNotify({ type: 'warning', message: `选择图片失败: ${err.errMsg}` })
},
})
}
</script>
<template>
<img v-else class="object-cover self-center rounded-lg w-[60%] h-28" :src="imageBase64" @click="onSelectImage" />
</template>
其中涉及逻辑为:先判断获取的base64
开头是否有 data:image
数据头,没有的话加上data:image/jpeg;base64,
。如果有数据头,判断是否为 iOS
的 data:image/jgp;
,是的话需替换为 data:image/jpeg;
,最后赋值时替换掉全部的换行及回车 /\r|\n/g
。
转载请注明出处:https://blog.csdn.net/hx7013/article/details/143502680
涉及资料:
标签:const,JSSDK,微信,image,iOS,window,data From: https://blog.csdn.net/hx7013/article/details/143502680