评论

H5如何实现分享微信小卡片

在vue项目,H5页面实现分享微信小卡片

前言说明

前阵子接到一个需求,实现H5页面可以分享微信好友,类似下面这种,可以自定义标题,内容,图片,废话不多说,开淦

准备

  1. 注册公众号,该公众号需要能认证的(企业认证)
  2. 公众号配置
    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如果是个链接在微信中打开,分享出去也是个链接,可以通过草料二维码把当前页面链接生成二维码,通过手机扫描方式打开,当前也可以把链接发送给任一市面公众号,再分享也是微信卡片啦,但是微信电脑端转发好像目前不支持自定义哦,好啦,代码比较粗糙,还有一定优化的空间,不过功能基本是可以实现的,有其他问题可以进行一起讨论

草料二维码
调研借鉴1
调研借鉴2

问题说明

SDK说明

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

1 个评论

  • 海底捞月
    海底捞月
    12-07

    生成签名的接口,后端没有让我传url,这是能用的吗?

    我大致也是你这个写法,可是我的全部属性都没生效是为什么

    12-07
    赞同
    回复 1
    • 怦然心动
      怦然心动
      12-09
      你把debug打开看下报错信息是?我们签名是前端把参数加密给后端进行鉴权的,不知道仅后端单独写死鉴权域名有没有啥影响
      12-09
      回复
登录 后发表内容