微信公众号-自定义微信分享(vue)(JS-SDK)

1.需求描述

日常公众号开发中,业务部门对于微信内置分享(右上角->分享到朋友等)效果不太满意,需要我们自定义相关分享效果

1.1微信默认分享效果展示

 

 

 1.2通过自定义分享后效果展示

 

1.3微信官方文档

JS-SDK说明文档:

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

 

2.具体实现

2.1后端(这里只展示大概代码,具体实现根据自己业务为准)

2.1.1Controller层

@RequestMapping("/getSignature")
    private MsgData getSignature(String url, HttpServletResponse response, HttpServletRequest request) throws Exception {
        MsgData msg = MsgData.successMsg();
        String jsapi_ticket = wechatUtil.getJsapiTicket();if (jsapi_ticket == null || jsapi_ticket == "") {
            msg.fail("失败");
            return msg;
        }
        String nonceStr = UUID.randomUUID().toString();
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String str = "";
        String signature = "";
        str += "jsapi_ticket=" + jsapi_ticket;
        str += "&noncestr=" + nonceStr;
        str += "&timestamp=" + timestamp;
        str += "&url=" + url;
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(str.getBytes("UTF-8"));
        signature = byteToHex(crypt.digest());
        Map<String, String> ret = new HashMap<String, String>();
        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonceStr);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("appId", WechatConstant.APP_ID);
        msg.setData(ret);
        return msg;
    }

    private String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

2.1.2工具类wechatUtil

public String getJsapiTicket() {
        if (redisService.hasKey(WechatConstant.JSAPI_TICKET_REDIS)) {
            return (String) redisService.get(WechatConstant.JSAPI_TICKET_REDIS);
        }
        return getServerJsapiTicket();
    }

    private synchronized String getServerJsapiTicket() {
        try {
            if (redisService.hasKey(WechatConstant.JSAPI_TICKET_REDIS)) {
                return (String) redisService.get(WechatConstant.JSAPI_TICKET_REDIS);
            }
            String accessToken = getAccessToken();
            if (accessToken == null || accessToken == "") {
                return null;
            } else {
                String jsurl = WechatConstant.JSAPI_TICKET_URL;
                String url = String.format(jsurl, accessToken);
                String strTicket = ConnectionUtil.getUrlResult(url, null, "GET");
                if (StringUtils.isBlank(strTicket)) {
                    return null;
                }
                JSONObject json = JSONObject.parseObject(strTicket);
                if (json.containsKey("ticket")) {
                    String ticket = json.getString("ticket");
                    redisService.set(WechatConstant.JSAPI_TICKET_REDIS, ticket);
                    redisService.expire(WechatConstant.JSAPI_TICKET_REDIS, 60 * 110);// 110分钟过期
                    return ticket;
                }
            }
        } catch (Exception e) {
            logger.error("JsapiTicket-错误", e);
        }
        return null;
    }

2.1.2工具类ConnectionUtil(HTTP接口工具,可根据项目自行封装)

public static String getUrlResult(String uri, String data, String method) {
        StringBuffer sbf = new StringBuffer();
        BufferedReader reader = null;
        HttpURLConnection connection = null;
        try {

            URL url = new URL(uri);
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod(method);
            connection.setConnectTimeout(8 * 1000);
            connection.setReadTimeout(8 * 1000);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded; charset=UTF-8");
            if (data != null && data.trim().length() != 0) {
                OutputStream outwritestream = null;
                try {
                    byte[] writebytes = data.getBytes();
                    // 设置文件长度
                    connection.setRequestProperty("Content-Length",
                            String.valueOf(writebytes.length));
                    outwritestream = connection.getOutputStream();
                    outwritestream.write(data.getBytes("UTF-8"));
                    outwritestream.flush();

                } catch (Exception e) {
                    logger.error(e.getMessage());
                } finally {
                    try {
                        outwritestream.close();
                    } catch (Exception e) {
                    }
                }
            }
            connection.connect();
            reader = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String lines;
            while ((lines = reader.readLine()) != null) {
                sbf.append(lines);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                logger.error(e.getMessage());
            }
            try {
                connection.disconnect();
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }
        return sbf.toString();
    }

 

注意:

  • 由于微信获取api_ticket接口次数有限,建议将【api_ticket 】存储在本地缓存服务器中(这里使用的是redis)

 

 

2.2前端(vue)

2.2.1封装公共工具方法

/**
 * 配置微信js-sdk
 * @param {Object} shareData
 * link:路径
 * title:标题
 * desc:描述
 * imgUrl:图片链接
 */
const wxJsSdkConfig = function(shareData) { //配置微信js-sdk
  let url = window.location.href.split('#')[0];
  if (url != null && url != "") {
    tcmAxios({
      method: 'post',
      url: requestUrl.getSignature,
      data: {
        url: url
      },
      then: function(response) {
        if (response.success) {
          let data = response.data;
          let appId = data.appId;
          let timestamp = Number(data.timestamp);
          let nonceStr = data.nonceStr;
          let signature = data.signature;
          let jsApiList = ["updateAppMessageShareData",
            "updateTimelineShareData"
          ];
          wx.config({
            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: appId, // 必填,公众号的唯一标识
            timestamp: timestamp, // 必填,生成签名的时间戳
            nonceStr: nonceStr, // 必填,生成签名的随机串
            signature: signature, // 必填,签名
            jsApiList: jsApiList // 必填,需要使用的JS接口列表
          });
          wx.ready(function() { //需在用户可能点击分享按钮前就先调用
            wx.updateAppMessageShareData({
              title: shareData.title, // 分享标题
              desc: shareData.desc, // 分享描述
              link: shareData.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
              imgUrl: shareData.imgUrl, // 分享图标
              success: function() {
                
              }
            });
            wx.updateTimelineShareData({
              title: shareData.title, // 分享标题
              link: shareData.link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
              imgUrl: shareData.imgUrl, // 分享图标
              success: function() {
                // 设置成功
              }
            })
          });
        }
      },
    });
  }
}

2.2.2使用

let shareData = {
          link:window.location.href,
          title:"标题",
          desc:"描述",
          imgUrl:"图片链接",
        };
        wxJsSdkConfig(shareData);

注意:

  • 在用户点击分享之前调用

 

posted @ 2022-06-24 10:16  丿似锦  阅读(729)  评论(0编辑  收藏  举报