如何定制微信分享页面和链接 (微信分享链接带参数)

一,微信分享概述

有时候我们需要微信分享内容,尤其是一个链接,但是呢,分享后希望看到的是下面的样式,就是一种卡片的形式,不希望看到的是一种链接的形式,只有一个标题,这样会让人产生误解,不敢点击,所以,卡片的形式是为了希望看到比较友好的效果,这个就需要借助微信平台公众号来实现

希望的:

微信分享链接配置,如何定制微信分享页面和链接

目前的:

微信分享链接配置,如何定制微信分享页面和链接

二,实现思路

公众号配置js域名和白名单

写一个静态页面,用于分享的页面

后端返回签名数据

1,注册公众号,并设置公众号的js域名以及IP白名单(就是获取签名的ticket的时候,调用的服务器)

微信分享链接配置,如何定制微信分享页面和链接

微信分享链接配置,如何定制微信分享页面和链接

2,公众号的js文档

文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

微信分享链接配置,如何定制微信分享页面和链接

2.1:绑定域名

见1

2.2:引入js文件

http://res.wx.qq.com/open/js/jweixin-1.6.0.js

vue 直接安装就可以:npm install weixin-js-sdk

2.3:配置公众号的数据

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

2.4:分享执行

     wx.ready(function (){
       wx.onMenuShareAppMessage({ //需在用户可能点击分享按钮前就先调用
         title: "test", // 分享标题
         desc: "test分享,用于查看内容", // 分享描述
         link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
         imgUrl: '', // 分享图标 链接
         success: ()=> {
           // 设置成功
           console.log("分享好友设置成功");
         }
       })
       alert('已注册获取“发送给朋友”状态事件');
   });

三,具体代码

1,后端返回ticket

先调用微信接口获取token,然后根据token获取到ticket,然后根据ticket 获取签名

public class WeChatSignatureUtils {

    public static String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    public static String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
//获取签名
    public static WeChatSignatureDTO sign(String jsapiTicket, String url) {
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        WeChatSignatureDTO weChatSignatureDTO = new WeChatSignatureDTO();
        //注意这里参数名必须全部小写,且必须有序
        String string1 = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url;
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            weChatSignatureDTO.setNonceStr(nonce_str);
            weChatSignatureDTO.setTimestamp(timestamp);
            weChatSignatureDTO.setSignature(byteToHex(crypt.digest()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return weChatSignatureDTO;
    }
//获取ticket 一般要进行缓存
    public static String getTicket(String appId, String secret) {
        log.info("getTicket appId:{},secret:{}", appId, secret);
        String tokenUrl = TOKEN_URL + "?grant_type=client_credential&appid=" + appId + "&secret=" + secret;
        JSONObject jsonObject = sendGet(tokenUrl);
        String accessToken = jsonObject.getString("access_token");
        String ticketUrl = TICKET_URL + "?access_token=" + accessToken + "&type=jsapi";
        JSONObject ticketResponse =sendGet(ticketUrl);
        return ticketResponse.getString("ticket");
    }
//发送get请求
    public static JSONObject sendGet(String url) {
        try {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            // 设置请求的header
            httpGet.addHeader("Content-Type", "application/json;charset=utf-8");
            // 执行请求
            HttpResponse response = httpClient*ex.e**cute(httpGet);
            // 打印执行结果
            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));
            log.info("sendGetUrl:{}, sendGetResult:{}",url, JSON.toJSONString(jsonObject));
            return jsonObject;
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static 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;
    }

    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

}

2,获取签名返回数据

    public WeChatSignatureDTO getWechatSignature(WeChatSignatureParam param) {
        //获取ticket
        String verifyKey = Constants.JSAPI_TICKET_KEY;
        String jsapiTicket = redisService.getCacheObject(verifyKey);
        if (StringUtils.isBlank(jsapiTicket)) {
            jsapiTicket = WeChatSignatureUtils.getTicket(config.getDzsAppId(), config.getDzsSecret());
            if (StringUtils.isBlank(jsapiTicket)) {
                throw new ServiceException("获取签名失败");
            }
            redisService.setCacheObject(verifyKey, jsapiTicket, 7100L, TimeUnit.SECONDS);
        }
        WeChatSignatureDTO result = WeChatSignatureUtils.sign(jsapiTicket, param.getUrl());
        result.setAppId(config.getDzsAppId());
        result.setImgUrl(config.getDzsImgUrl());
        return result;
    }
public class WeChatSignatureDTO implements Serializable {
    private String nonceStr;
    private String timestamp;
    private String signature;
    private String appId;
    /**
     * 分享的图标
     */
    private String imgUrl;

    public String getNonceStr() {
        return nonceStr;
    }

    public void setNonceStr(String nonceStr) {
        this.nonceStr = nonceStr;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }
}
public class WeChatSignatureParam implements Serializable {
  //这个url要和分享的页面link保持一致
    private String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

3,前端代码

<template>
  <div class="app-container">
system
  </div>
</template>
<script>
import wx from 'weixin-js-sdk'
import { getSignature } from '@/api/login'
export default {
  name: "Secret",
  data() {
    return {
     info: {}
    };
  },
  created() {
 var res = await getSignature();
    if (res.code === 200) {
      var da = res.data;
      this.info = res.data;
      wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: da.appId, // 必填,公众号的唯一标识
        timestamp: da.timestamp, // 必填,生成签名的时间戳
        nonceStr: da.nonceStr, // 必填,生成签名的随机串
        signature: da.signature,// 必填,签名
        jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareAppMessage'], // 必填,需要使用的JS接口列表
      });
      //然后 调用wxShare方法
      this.wxShare();
  },
  methods: {
   wxShare() {
    console.log("wxShare begin")
     //通过ready接口处理成功验证 ,通过error接口处理失败验证
     wx.ready(function (){
       wx.updateAppMessageShareData({ //需在用户可能点击分享按钮前就先调用
         title: "test", // 分享标题
         desc: "test分享,用于查看内容", // 分享描述
         link: location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
         imgUrl: this.info.imgUrl, // 分享图标
         success: ()=> {
          console.log("wxShare end")
           // 设置成功
           console.log("分享好友设置成功");
         }
       })
   });
  }}
};
</script>

四,注意事项

1,前端的link必须是和后端传入获取签名的url 一致

2,分享的页面和link传入的url一致

3,分享链接需要从公众号种分享或者生成二维码进行分享

4,对ticket需要进行缓存,因为7200s换一次

5,绑定的域名一定要和分享的url的域名一致

6,调试可以使用微信开发者工具

微信分享链接配置,如何定制微信分享页面和链接

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Web_Developer_Tools.html

7,先配置验证签名,然后点击分享的时候会调用分享的数据设置,这个微信会缓存数据的

五,开发者大概流程

1,获取签名

2,使用微信js-sdk调用配置和分享方法即可