前言说明
前阵子接到一个需求,实现H5页面可以分享微信好友,类似下面这种,可以自定义标题,内容,图片,废话不多说,开淦
准备
- 注册公众号,该公众号需要能认证的(企业认证)
- 公众号配置
2.1 查看分享接口权限获取:【设置与开发->开发接口管理->接口权限->分享接口】
2.2 配置JS安全域名【设置与开发->账号设置->功能设置】
备注:要添加分享图片链接域名或用oss规定图片域名要跟JS接口安全域名里的域名一致,不然分享图片会有不展示的风险,把校验文件放到项目根目录下。注意,每月只能保持5次,所以需提前整理所有相关域名进行,以避免必要的增加修改
2.3 配置IP白名单【设置与开发->安全中心->IP白名单】
公众号前置工作准备完成
前端业务实现
我这边时vue项目,下载相关SDK
npm install weixin-js-sdk --save
当前以可以通过链接方式引入
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
写一个通用工具方法
import Vue from 'vue'
import wx from 'weixin-js-sdk'
// 鉴权接口
import { getSignWx } from '@/api/bus-frp-agg/index.js'
const BaseUrl = window.location.href.split('#')[0]
const imgUrl = BaseUrl + 'share.png'
// 存储各个链接的签名信息
const signMap = new Map()
// 设置默认的分享信息,因为如分享图、请求授权项、隐藏授权项等基本不变,此处设置直接引用,避免使用时繁琐设置
const defaultWxShareConfig = {
// 标题
title: '营销专题页',
// 描述, 微信卡片最多可以展示30个字符 3行
desc: '营销专题页说明',
// 鉴权链接
link: encodeURIComponent(BaseUrl),
// 分享链接
shareLink: encodeURIComponent(BaseUrl),
// 分享图片
imgUrl: imgUrl,
// 请求授权项
jsApiList: [
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline'
]
}
// 存储临时的分享信息
const wxShareConfig = {}
const wxShare = {
// 各个页面加载后,调用此方法,传入的参数config是对象,其属性参考defaultWxShareConfig
updateWxShareConfig(config = {}) {
wxShareConfig.title = config.title || defaultWxShareConfig.title
wxShareConfig.desc = config.desc || defaultWxShareConfig.desc
wxShareConfig.link = config.link || defaultWxShareConfig.link
wxShareConfig.imgUrl = config.imgUrl || defaultWxShareConfig.imgUrl || imgUrl
wxShareConfig.jsApiList = config.jsApiList || defaultWxShareConfig.jsApiList
wxShareConfig.shareLink = config.shareLink || defaultWxShareConfig.shareLink
// 跳转地址
let authUrl = wxShareConfig.link || encodeURIComponent(BaseUrl)
const ua = navigator.userAgent
const isiOS = !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
if (isiOS) {
// os系统,授权地址必须使用第一次打开时候的地址,中途换的地址不识别
authUrl = wxShareConfig.link
}
// 判断是否已经签名了
if (signMap.has(authUrl)) {
// 使用已有签名信息
this.wxConfigJSSDK(signMap.get(authUrl))
} else {
// 请求鉴权接口
this.wxShareAuth(authUrl)
}
},
// 从服务器获取某分享链接的签名信息,并存储起来,注意该接口一定要使用公众号的appid和AppSecret
async wxShareAuth(authUrl) {
const postData = {
url: authUrl
}
const res = await getSignWx(postData)
if (!res) return
// 分享链接授权签名信息
signMap.set(authUrl, res)
// 用微信SDK
this.wxConfigJSSDK(res)
},
// 将签名信息更新到微信的SDK中
wxConfigJSSDK(shareSign) {
wx.config({
debug: false, // 可打开调试,看是否成功和报错信息
appId: shareSign.appId, // 必填,公众号的唯一标识
timestamp: shareSign.timestamp, // 必填,生成签名的时间戳
nonceStr: shareSign.nonceStr, // 必填,生成签名的随机串
signature: shareSign.signature, // 必填,签名
jsApiList: [
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline'
]
})
const { title, desc, shareLink, imgUrl } = wxShareConfig
const shareData = {
title,
desc,
link: shareLink, // 分享链接
imgUrl
}
wx.ready(function (res) {
wx.updateAppMessageShareData({
...shareData,
success: function (res1) {
console.log('分享成功 updateAppMessageShareData', res1)
},
fail: function (err1) {
console.log('分享失败', err1)
}
})
// 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
wx.updateTimelineShareData({
...shareData,
success: function (res1) {
console.log('分享成功 updateTimelineShareData', res1)
},
fail: function (err1) {
console.log('分享失败', err1)
}
})
wx.onMenuShareAppMessage({
...shareData,
success: function (res1) {
console.log('分享成功 onMenuShareAppMessage', res1)
},
fail: function (err1) {
console.log('分享失败', err1)
},
cancel: function () {
console.log('取消分享')
}
})
wx.onMenuShareTimeline({
...shareData,
success: function () {
console.log('分享成功 onMenuShareTimeline')
},
fail: function (err1) {
console.log('分享失败', err1)
},
cancel: function () {
console.log('取消分享')
}
})
})
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
wx.error(function (res) {
console.log('error', res)
console.log('分享失败: error', res)
})
}
}
// 导出工具类
export default wxShare
// 将工具类添加到Vue静态方法方便调用
Vue.prototype.$wxShare = wxShare
在相关页面
created () {
// 我们是hash模式,前端拼接分享链接
const hashCode = this.$route.params?.id || ''
const BASEURL = window.location.href.split('#')[0]
// 拼接分享链接
const url = `${BASEURL}#/cloudLandingPage/${hashCode}`
const config = {
title: '测试标题',
desc: '测试描述',
imgUrl: '',
// 当前网站加密url传参,后端鉴权接收时对应解密
link: encodeURIComponent(BASEURL),
// 分享的url链接,安全域名和这个分享进入的域名要一致
shareLink: url
}
// 启用分享
this.$wxShare.updateWxShareConfig(config)
}
后端业务实现
后端业务代码不太熟,这是找的两个帖子转我们后端,后端根据这上面的讲解实现了
实现方法1
实现方法2
然后就实现啦
说明: H5如果是个链接在微信中打开,分享出去也是个链接,可以通过草料二维码把当前页面链接生成二维码,通过手机扫描方式打开,当前也可以把链接发送给任一市面公众号,再分享也是微信卡片啦,但是微信电脑端转发好像目前不支持自定义哦,好啦,代码比较粗糙,还有一定优化的空间,不过功能基本是可以实现的,有其他问题可以进行一起讨论
问题说明
- 调用config 接口的时候传入参数 debug: true 可以开启debug模式,页面会alert出错误信息。以下为常见错误及解决方法:
- invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,仅支持80(http)和443(https)两个端口,因此不需要填写端口号(一个appid可以绑定三个有效域名,见 ]目录1.1.1)。
invalid signature签名错误。建议按如下顺序检查: - 确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。
- 确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。
- 确认url是页面完整的url(请在当前页面alert(location.href.split(’#’)[0])确认),包括’http(s)😕/‘部分,以及’?‘后面的GET参数部分,但不包括’#'hash后面的部分。
- 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
- 确保一定缓存access_token和jsapi_ticket。
- 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去’#‘hash部分的链接(可用location.href.split(’#’)[0]获取,而且需要encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。
- the permission value is offline verifying这个错误是因为config没有正确执行,或者是调用的JSAPI没有传入config的jsApiList参数中。建议按如下顺序检查:
- 如果是在页面加载好时就调用了JSAPI,则必须写在wx.ready的回调中。
- 确认config的jsApiList参数包含了这个JSAPI。
- permission denied该公众号没有权限使用这个JSAPI,或者是调用的JSAPI没有传入config的jsApiList参数中(部分接口需要认证之后才能使用)。
生成签名的接口,后端没有让我传url,这是能用的吗?
我大致也是你这个写法,可是我的全部属性都没生效是为什么