H5中实现微信分享

1,146 阅读6分钟

公众号配置说明

  1. 注册公众号,该公众号需要能认证的(企业认证)

  2. 公众号配置

    1. 查看分享接口权限获取:【设置与开发->开发接口管理->接口权限->分享接口
    2. 配置 JS 安全域名 【设置与开发->账号设置->功能设置】
    3. 备注:要添加分享图片链接域名或用oss规定图片域名要跟JS接口安全域名里的域名一致,不然分享图片会有不展示的风险,把校验文件放到项目根目录下。注意,每月只能保存5次,所以需提前整理所有相关域名进行,以避免必要的增加修改

    4. 配置IP白名单 【设置与开发->安全中心->IP白名单】
    5. 分享的服务器外网ip地址,需要添加到白名单中,在调用域名接口及发送微信SDK鉴权时,后端也可通过日志查看;

前端业务说明

  1. 下载微信SDK
npm install weixin-js-sdk --save

或在index.html中通过外链引入

<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>

2. 在util文件写一个通用分享工具方法wxShare.js

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

3. 在相关页面调用

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. H5如果是个链接在微信中打开,分享出去也是个链接,可以通过草料二维码把当前页面链接生成二维码,通过手机扫码打开,也可以把链接发送给任一线上公众号,再次即可实现自定义。
  2. 动态配置相关标题,说明,及分享图片,通过页面加载实现分享功能,目前还无法通过按钮事件调起微信内置分享,且PC端微信暂不支持自定义微信SDK分享H5。

  1. 相关调研文档

    1. vue实现将自己网站(h5链接)分享到微信中形成小卡片(超详细)
    2. 基于vue2开发的html5页面实现微信分享卡片(微信好友+朋友圈+qq好友+qq空间)
    3. 记录--微信调用jssdk全流程详解
    4. 微信公众号JSSDK获取signature签名,史上最全,没有之一

SDK问题说明

调用config 接口的时候传入参数 debug: true 可以开启debug模式,页面会alert出错误信息。以下为常见错误及解决方法:

  1. invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,仅支持80(http)和443(https)两个端口,因此不需要填写端口号(一个appid可以绑定三个有效域名,见 ]目录1.1.1)。 invalid signature签名错误。建议按如下顺序检查:
  2. 确认签名算法正确,可用mp.weixin.qq.com/debug/cgi-b… 页面工具进行校验。
  3. 确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。
  4. 确认url是页面完整的url(请在当前页面alert(location.href.split(’#’)[0])确认),包括’http(s)/‘部分,以及’?‘后面的GET参数部分,但不包括’#'hash后面的部分。
  5. 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
  6. 确保一定缓存access_token和jsapi_ticket。
  7. 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去’#‘hash部分的链接(可用location.href.split(’#’)[0]获取,而且需要encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。
  8. the permission value is offline verifying这个错误是因为config没有正确执行,或者是调用的JSAPI没有传入config的jsApiList参数中。建议按如下顺序检查:
  9. 如果是在页面加载好时就调用了JSAPI,则必须写在wx.ready的回调中。
  10. 确认config的jsApiList参数包含了这个JSAPI。
  11. permission denied该公众号没有权限使用这个JSAPI,或者是调用的JSAPI没有传入config的jsApiList参数中(部分接口需要认证之后才能使用)。