JSSDK实现自定义分享标题和图片

准备工作

  • 已认证的公众号(一定要认证过的!)
    在微信的官方文档常见错误及解决方法中,只有认证的公众号才具有分享相关接口权限

  • 绑定JS域名
    在 微信公众号 >> 功能设置 >> JS接口安全域名 中配置JS接口安全域名
    将MP_verify_1PI6AnuQ7s0acvZv.txt(点击下载)放置在填写的域名目录下

  • 添加IP白名单
    在 微信公众号 >> 基本配置 >> IP白名单 中将访问微信接口的服务器的IP地址添加到白名单中

  • 获取AppID和AppSecret
    将获取的AppID和AppSecret保存
    AppSecret一旦重置,将影响所有使用此AppID的应用,要慎重!

后端工作

参考微信官方文档JS-SDK使用权限签名算法

  • 获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token)
    curl "http://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${secret}"
    注意:curl测试时,url用“”,否则服务器不通
  • 检查生成的签名
    http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

获取生成签名所需参数

  1. appId + secret -------> ACCESS_TOKEN
  2. ACCESS_TOKEN -------> jsapi_ticket
// 1.获取access_token
app.get('/get_access_token', (req, res) => {
  res.header("Access-Control-Allow-Origin",req.headers.origin); // 处理跨域
  request.get({
    url: `http://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${secret}`,
    json: true,
  }, (err, response, body) => {
    console.log(body, 'token')
    try {
      if (err) {
        res.json(err);
      } else {
        // 这里获取到ACCESS_TOKEN 传给getticket获取jsapi_ticket
        res.send(body)
      }
    } catch (error) {
      let data = {
        "code": 500,
        "message": "net error"
      };
      res.send(data);
      LOG.error(req.method, req.url, '===========', error);
    }
  });
})
// 2.根据access_token获取jsapi_ticket
app.get('/get_ticket', (req, res) => {
  res.header("Access-Control-Allow-Origin",req.headers.origin);
  request.get({
    url: `http://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${ACCESS_TOKEN}&type=jsapi`,
    json: true,
  }, (err, response, body) => {
    // console.log(body, 'getticket')
    try {
      if (err) {
        res.json(err);
      } else {
        // 这里生成签名 jsapi_ticket
        res.send(body)
      }
    } catch (error) {
      let data = {
        "code": 500,
        "message": "net error"
      };
      res.send(data);
      LOG.error(req.method, req.url, '===========', error);
    }
  });
})

签名过程

  1. 生成随机字符串
  2. 对象进行ASCII码排序
  3. 将排序后的对象用key1=value1&key2=value2形式拼接
  4. 进行sha1加密
  5. 进行签名算法

// 3.1生成随机字符串
let randomString = (length) => {
  let chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let result = '';
  for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
  return result;
}

// 3.2对象进行ASCII码排序
let sort_ASCII = (obj) => {
  var arr = new Array();
  var num = 0;
  for (var i in obj) {
    arr[num] = i;
    num++;
  }
  var sortArr = arr.sort();
  var sortObj = {};
  for (var i in sortArr) {
    sortObj[sortArr[i]] = obj[sortArr[i]];
  }
  return sortObj;
}

// 3.3将对象用key1=value1&key2=value2形式拼接
let json_to_string = (jsonObj) => {
  let jStr= ''
  for(var item in jsonObj){
      jStr += item + "=" + jsonObj[item]+ "&";
  }
  jStr = jStr.substring(0, jStr.length - 1);
  return jStr
}

// 3.4进行sha1加密
const encrypt = (algorithm, content) => {
  let hash = createHash(algorithm)
  hash.update(content)
  return hash.digest('hex')
}
const sha1 = (content) => encrypt('sha1', content)

// 3.5进行签名算法
let sign = (jsapi_ticket) => {
  let timestamp = Date.parse( new Date() ).toString().substr(0,10)
  let nonceStr = randomString(16)
  let jsonobj = {
    noncestr: nonceStr,
    jsapi_ticket: jsapi_ticket,
    timestamp: timestamp,
    url: shareUrl
  }
  console.log(jsonobj)

  let str = json_to_string(sort_ASCII(jsonobj))

  console.log(str)

  let signature = sha1(str)

  console.log(signature)

  let data = {
      appId: appId, // 必填,公众号的唯一标识
      timestamp: timestamp, // 必填,生成签名的时间戳
      nonceStr: nonceStr, // 必填,生成签名的随机串
      signature: signature,// 必填,签名
      url: shareUrl
    }
  return data
}

前端工作

  • 安装所需wx依赖
    npm install jweixin-module
  • 引入依赖
    let wx = require('jweixin-module')

通过config接口注入权限验证配置

所有需要使用wx的页面都要先注入配置,否则调用wx方法报错“无权限”
此处所有配置参数由后端传入

wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId, // 必填,公众号的唯一标识
        timestamp, // 必填,生成签名的时间戳
        nonceStr, // 必填,生成签名的随机串
        signature, // 必填,签名
        jsApiList: ["updateAppMessageShareData", "updateTimelineShareData"] // 必填,需要使用的JS接口列表
      });

通过ready接口处理成功验证

config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。

分享的链接必须是 http or https ,否则不生效

wx.ready(function() {
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。

        wx.updateAppMessageShareData({
          title: that.shareTitle, // 分享标题
          desc: that.shareDesc, // 分享描述
          link: that.shareUrl, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
          imgUrl: `https://staticai.xxxx.com/img/share.265ee3fb.jpg`, // 分享图标
          success: function() {
            // 设置成功
            // alert("分享朋友成功");
          },
          fail: function(e) {
            console.log(e, "分享朋友失败");
          }
        });

        wx.updateTimelineShareData({
          title: that.shareTitle, // 分享标题
          link: that.shareUrl, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
          imgUrl: `https://staticai.xxx.com/img/share.265ee3fb.jpg`, // 分享图标
          success: function() {
            // 设置成功
            // alert("分享朋友圈成功");
          },
          fail: function(e) {
            console.log(e, "分享朋友圈失败");
          }
        });

        wx.checkJsApi({
          jsApiList: ["updateAppMessageShareData", "updateTimelineShareData"], // 需要检测的JS接口列表,所有JS接口列表见附录2,
          success: function(res) {
            // 以键值对的形式返回,可用的api值true,不可用为false
            // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
          },
          fail: function(e) {
            console.log(e, "检查jsapi失败");
          }
        });

        wx.error(function(res) {
          // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
          console.log(res, "config失败");
        });
      });

END

你可能感兴趣的:(JSSDK实现自定义分享标题和图片)