// 开启调试模式,但不包括#hash后面的部分。
但是如果你是从别人分享的蓝色链接打开网址那么就百分之一亿分享不出来卡片 从别人发送/分享的蓝色链接打开网址只能分享出同样的蓝色链接 从上面的链接进入时只能分享出链接地址 从分享的卡片打开网址或扫码打开网址都可以分享出卡片给微信好友 从上面的卡片进入时可以正常分享出卡片 上面两个大坑花费了我无数根头发才发现的文档完全没提这事着实是坑爹啊 附录代码全文 除去上面几个大坑之外代码实现起来还是很简单的照官方文档抄过来就行,success: () {// 设置成功现在用户点击右上角三个点进行分享时可以分享出来卡片了}}) }) // 通过error接口处理config失败的情况 wx.error(function (res) {popupVisible.value false // 隐藏popup弹窗ElMessage.error(分享失败请稍后再试 res.errMsg) })}// 工具函数 /** * description 复制内容到粘贴板 * */function copyToClipboard (text: string, // 必填生成签名的随机串signature: res.data.signature, // 必填生成签名的时间戳nonceStr: res.data.nonce_str。
流程概述 运营同学 在微信公众平台中为微信公众号/服务号添加JS安全域名如下图 前端同学 1. 引入微信JS-SDK // npmnpm i weixin-js-sdk// Vite import wx from weixin-js-sdk 2. 判断用户此时是否处于微信浏览器中weixin-js-sdk仅支持微信浏览器环境 // 判断当前web浏览器是否是微信环境 (此函数在微信小程序中返回true但微信小程序不支持weixin-js-sdk)export const isWeChatBrowser () { // 获取 userAgent 信息 const userAgent navigator.userAgent.toLowerCase() // 检查是否包含 micromessenger 字样 return userAgent.indexOf(micromessenger) ! -1} 3. 向后端服务器请求签名等参数信息 // 处理微信分享事件const handleWechatShare async () { // 1、向后端请求微信配置信息目的是为了获取签名等信息 来初始化微信sdk的权限验证信息 let url encodeURIComponent(location.href.split(#)[0]) // 只用#之前的内容 if (getDeviceOS() IOS) {// ios手机会把首次进入的url当做wx.config中的realAuthUrl所以需要在入口文件将该链接存下来 而不能是当前页面的链接let t localGet(firstVisitUrl).split(#)[0]url encodeURIComponent(t) } const res await getWechatSDKConfig({ url }) // 调用后端同学的后端接口 获取签名等参数信息 let wxConfig {debug: true, 我们主要使用微信JS-SDK里面的 updateAppMessageShareData 方法该方法的功能是允许开发者把右上角的分享样式从链接变为卡片样式并可以自定义 标题、描述和右侧的icon图标,duration: 1500})}).catch(() {// console.error(复制失败, 老板希望在H5手机端浏览器中实现类似于APP的微信分享功能就像这样 但是呢微信官方在 1.40及后续JS-SDK中取消了H5浏览器直接调起微信分享的API所以这个方案是无法实现的只能采用替代方案 在微信内置 webview中引导用户点击右上角的菜单按钮并选择分享微信好友 在非微信内置浏览器中禁止用户分享微信好友或者提示用户使用微信打开本链接, 按照weixin-js-sdk官方文档说法签名必须在服务端进行计算具体签名计算方法请参考微信官方文档 特别注意事项 需要特别注意的是iOS系统中微信SDK的wx.config方法会把用户首次进入的url当做wx.config中的realAuthUrl 比如Android手机中用户在login页面登录然后跳转到A页面进行微信分享代码都在A页面此时后端只要根据 当前A页面的路径 来进行签名计算即可 但如果是iOS手机那么用户在login页面登录在A页面进行分享必须用 首次进入的login页面路径 进行签名计算 这是微信SDK自身bug无法避免 所以如果 在调试过程中iOS设备出现invalid signature签名错误一定要小心是否是这个bug导致的, isShowSuccessMsg: boolean true): void { if (!text.trim()) {ElMessage.warning(文本不存在)return } // 兼容非安全域非安全域下不可使用navigator.clipboard.writeText if (navigator.clipboard window.isSecureContext) {navigator.clipboard.writeText(text).then(() {isShowSuccessMsg ElMessage({message: 复制成功, 确保你获取用来签名的url是动态获取的动态页面可参见实例代码中php的实现方式, // 必填生成签名的时间戳nonceStr: res.data.nonce_str, 概念说明 微信官方的JS-SDK是 面向网页开发者提供的基于微信内的网页开发工具包内置了很多微信API但基本只能在微信内置浏览器中调用非微信浏览器不支持, duration: 1500 }) }}/** * description 获取当前设备系统 * returns string - 设备类型 */function getDeviceOS(){ const userAgent navigator.userAgent if (/android/i.test(userAgent)) {return Android } else if (/iPad|iPhone|iPod/.test(userAgent)) {return IOS } else {return unknown // 无法确定或非移动操作系统 }}// 判断当前web浏览器是否是微信环境 注意微信小程序返回true但微信小程序不支持weixin-js-sdkfunction isWeChatBrowser(){ // 获取 userAgent 信息 const userAgent navigator.userAgent.toLowerCase() // 检查是否包含 micromessenger 字样 return userAgent.indexOf(micromessenger) ! -1}/** * description 获取localStorage * param {String} key Storage名称 * returns {String} */function localGet(key: string) { const value window.localStorage.getItem(key) try {return JSON.parse(window.localStorage.getItem(key) as string) } catch (error) {return value }}/scriptstyle scoped langscss.wechat-share-popup { .popup-content {padding: 20px;margin-bottom: 50px;.popup-title {text-align: center;font-size: 16px;color: #333;margin-bottom: 20px;}.share-list {display: flex;justify-content: space-around;align-items: center;.share-box {display: flex;flex-direction: column;align-items: center;row-gap: 10px;cursor: pointer;:hover {.box-title {color: var(--el-color-primary);}}.box-icon {width: 60px;height: 60px;}.box-title {font-size: 14px;color: #333;}}} }}.wechat-share-mask { width: 100vw; height: 100vh; position: absolute; top: 0; left: 0; z-index: 999; background: rgba(0, 确认config中nonceStrjs中驼峰标准大写S,而且需要encodeURIComponent因为页面一旦分享微信客户端会在你的链接末尾加入其它参数如果不是动态获取当前链接将导致分享后的页面签名失败, imgUrl: }// 初始化分享信息const initShareInfo (info: { title: string; link: string; desc?: string; imgUrl?: string }) { shareInfo.title info.title shareInfo.desc info.desc || shareInfo.link info.link shareInfo.imgUrl info.imgUrl || ${location.origin}/logo.png popupVisible.value true}defineExpose({ initShareInfo })// 处理分享事件const handleShare (type: weChat | link) { if (type link) {copyToClipboard(shareInfo.link, updateTimelineShareData] // 必填需要使用的JS接口列表 } // 2、注入权限验证信息初始化权限信息目的是为了能够调用微信的相关api wx.config(wxConfig) // 3、初始化微信自定义分享信息目的是为了在用户点击右上角分享的时候把分享的内容从链接 变成 自定义内容的卡片 initWechatShareData(shareInfo)}// 判断设备OS类型const getDeviceOS () { const userAgent navigator.userAgent if (/android/i.test(userAgent)) {return Android } else if (/iPad|iPhone|iPod/.test(userAgent)) {return IOS } else {return unknown // 无法确定或非移动操作系统 }} 4. 使用 wx.updateAppMessageShareData 方法 自定义要分享的内容 const popupVisible ref(false)const maskVisible ref(false)interface ShareInfo { // 分享链接该链接域名必须在公众号JS安全域名列表中仅需配置父域名即可如在安全域名中配置https://a.com在这里可以写入 https://a.com/xxx/xxx link: string title: string // 分享标题 desc: string // 分享描述 imgUrl: string // 分享图标请使用类似于 https://xxx.png 网络图片地址}const shareInfo: ShareInfo { title: Hello World,success: () {// 设置成功现在用户点击右上角三个点进行分享时可以分享出来卡片了popupVisible.value false // 隐藏popup弹窗maskVisible.value true // 引导用户点击右上角三个点菜单按钮}})// 自定义分享朋友圈信息wx.updateTimelineShareData({...shareInfo。
desc: 这里是描述内容这里是描述内容。
success: () {// 设置成功现在用户点击右上角三个点进行分享时可以分享出来卡片了popupVisible.value false // 隐藏popup弹窗maskVisible.value true // 引导用户点击右上角三个点菜单按钮}})// 自定义分享朋友圈信息wx.updateTimelineShareData({...shareInfo, 效果预览 对方视角 步骤流程 1、用户点击分享按钮弹出分享弹窗 2、用户点击转发给微信好友图标引导用户点击右上角菜单非微信浏览器仅允许用户复制链接 3、用户选中一个微信好友确定发送完成分享, 0.6); .share-arrow {position: absolute;top: 0;right: 0;max-width: 100vw;max-height: 80vh; }}/style 。
imgUrl: https://xxx.png}// 初始化微信自定义分享信息const initWechatShareData (shareInfo: ShareInfo) { // wx.config没有success回调事件通过ready接口保证后续代码都是在config执行成功后再执行的 wx.ready(() {// 自定义分享朋友信息wx.updateAppMessageShareData({...shareInfo,。
false)ElMessage.success(复制成功快去分享吧)popupVisible.value false } else if (type weChat) {handleWechatShare() }}let wxConfig: any null// 微信分享const handleWechatShare async () { // 1、向后端请求微信配置信息目的是为了获取签名等信息 来初始化微信sdk的权限验证信息 let url encodeURIComponent(location.href.split(#)[0]) if (getDeviceOS() IOS) {// ios手机会把首次进入的url当做wx.config中的realAuthUrl所以需要在入口文件将该链接存下来 而不能是当前页面的链接let t localGet(firstVisitUrl).split(#)[0]url encodeURIComponent(t) } const res await getWechatSDKConfig({ url }) // 调用后端同学的后端接口 获取签名等参数信息 wxConfig {debug: false, 0。
// 必填公众号的唯一标识timestamp: res.data.timestamp, // 必填生成签名的随机串signature: res.data.signature,如果是html的静态页面在前端通过ajax将url传到后台签名前端需要用js获取当前页面除去#hash部分的链接可用location.href.split(#)[0]获取, // 必填签名jsApiList: [updateAppMessageShareData,appId: res.data.app_id, 解决方案 在入口文件中记录用户进入时的路径存储在localStorage中在代码中判断是否是ios设备如果是则使用localStorage中的路径否则使用当前页面的路径, 包括 先跳转到小程序再手动分享 和 各种.js原生分享方案经实验要么繁琐程度相同要么无法广泛兼容 安卓和IOS设备广大前端er如有更好解决方案欢迎打脸 代码实现 如果你已经跟产品经理确定这个方案下用户体验和浏览器限制确实可以接受那么下面笔者将详细说明如何实现此效果并带你避过路上所有大坑。
0,success: () {// 设置成功现在用户点击右上角三个点进行分享时可以分享出来卡片了}}) }) // 通过error接口处理config失败的情况 wx.error(function (res) {popupVisible.value false // 隐藏popup弹窗ElMessage.error(分享失败请稍后再试 res.errMsg) })} 5. 引导遮罩出现用户手动点击微信浏览器右上角的菜单按钮进行分享 后端同学 根据前端给你的url地址计算出sdk签名和公众号APPID等信息一同提供给前端即可。
type: success。
updateTimelineShareData] // 必填需要使用的JS接口列表 } // 2、注入权限验证信息初始化权限信息目的是为了能够调用微信的相关api wx.config(wxConfig) // 3、初始化微信自定义分享信息目的是为了在用户点击右上角分享的时候把分享的内容从链接 变成 自定义内容的卡片 initWechatShareData(shareInfo)}const initWechatShareData (shareInfo: ShareInfo) { // wx.config没有success回调事件通过ready接口保证后续代码都是在config执行成功后再执行的 wx.ready(() {// 自定义分享朋友信息wx.updateAppMessageShareData({...shareInfo。
timestamp一致, type: success, 此外另外一个需要特别注意的是 从别人微信分享的蓝色链接打开网址的用户是无法分享出来卡片的只有规避掉蓝色链接才能分享出来卡片 这是微信另一个Bug导致的你从别人分享的卡片打开网址然后分享给其他人采用笔者上述方法是完全可以分享出来卡片的, timestamp与用以签名中的对应noncestr。
确认url是页面完整的url(请在当前页面alert(location.href.split(#)[0])确认)包括http(s)://部分以及后面的GET参数部分,卡片形式可以显示公司Logo、标题和描述 体验更好 只能分享当前页面的链接无法自定义分享的链接内容限制较大 不够灵活 ,调用的所有api的返回值会在客户端alert出来若要查看传入的参数可以在pc端打开参数信息会通过log打出仅在pc端时才会打印。
location.href) // 记录首次访问地址// 分享页面代码实际运行页面 let url encodeURIComponent(location.href.split(#)[0]) // 只用#之前的内容 if (getDeviceOS() IOS) {// ios手机会把首次进入的url当做wx.config中的realAuthUrl不能是当前页面的链接let t localGet(firstVisitUrl).split(#)[0]url encodeURIComponent(t) }// 向后端请求微信配置信息目的是为了获取签名等信息 来初始化微信sdk的权限验证信息 const res await getWechatSDKConfig({ url }) wx.config其余逻辑代码...... 如果并非这个原因出现invalid signature签名错误官方文档推荐按照以下顺序进行检 确认签名算法正确可用 页面工具进行校验, link: 。
// 必填公众号的唯一标识timestamp: res.data.timestamp。
link: https://a.com/mobile/xxx, // 开启调试模式。
desc: ,调用的所有api的返回值会在客户端alert出来appId: res.data.app_id, 从手机底部出现一个弹窗的UI我直接用的是vant的popup组件UI没有任何功能意义纯粹只是为了代码整洁简单自行替换即可 !-- 微信浏览器 - 分享弹窗组件 --template div classwechat-share-popup!-- 圆角弹窗底部 --van-popup v-model:showpopupVisible round positionbottomdiv classpopup-contentdiv classpopup-title分享到/divdiv classshare-listdiv v-ifisWeChatBrowser() classshare-box clickhandleShare(weChat)img classbox-icon src/assets/images/mobile/appwx_logo.png alt /div classbox-title转发给微信/div/divdiv classshare-box clickhandleShare(link)img classbox-icon src/assets/images/mobile/copy-link.png alt /div classbox-title复制链接/div/div/div/div/van-popup!-- 引导用户点击微信右上角的分享遮罩层 --div classwechat-share-mask v-showmaskVisible clickmaskVisible falseimg classshare-arrow src/assets/images/mobile/roll-line-arrow.png alt请点击右上角菜单按钮并进行分享 //div /div/templatescript setup langtsimport { ref } from vueimport wx from weixin-js-sdkimport { ElMessage } from element-plusimport { getWechatSDKConfig } from /api/modules/Mobile/weChatconst popupVisible ref(false)const maskVisible ref(false)interface ShareInfo { link: string // 分享链接该链接域名必须在当前页面对应的公众号JS安全域名列表中仅需配置父域名即可如在安全域名中配置https://a.com在这里可以写入 https://a.com/xxx/xxx title: string // 分享标题 desc: string // 分享描述 imgUrl: string // 分享图标请使用类似于 https://xxx.png 网络图片地址}const shareInfo: ShareInfo { title: , 确保一定缓存access_token和jsapi_ticket, // 必填签名jsApiList: [updateAppMessageShareData, 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致, // 入口文件Vue是App.vue文件 localSet(firstVisitUrl, 这时候可能有人会说了这不是脱裤子放屁吗本来微信右上角菜单就可以分享好友只要引导用户点击菜单就行了为什么还要写一篇博客专门探究这种事 此言差矣其实还是有些差别的 不采用任何额外措施直接引导用户点击右上角菜单并进行分享只能分享链接给微信好友而无法是卡片形式, error)}) } else {const textarea document.createElement(textarea)textarea.value textdocument.body.appendChild(textarea)textarea.select()document.execCommand(copy)document.body.removeChild(textarea)isShowSuccessMsg ElMessage({ message: 复制成功, 链接分享效果 卡片分享效果 如果你的产品经理接受这种方案期望用户可以在微信浏览器中分享卡片视图给微信好友那么你可以接着阅读下面的内容 如果产品经理说不行 用户还要手动点击两下分享出来的只能是微信卡片而且不支持非微信浏览器 那么很抱歉经过我多方面深入研究H5浏览器基本不可能完成非微信浏览器调起微信分享好友功能可以到此为止了。
