自定义微信分享链接

之前都很少涉及到微信相关的开发,最近公司要做一个微信公众号,且其中涉及到自定义页面的分享,故在此记录下自定义分享信息链接的过程。
至于微信公众号的申请及认证在此就不多说。

微信公众号JSSDK文档 的步骤来,步骤一、二就不说了,说下步骤三的config参数的获取,
config需要的参数入上图,时间戳跟签名随机串后台直接生成就好,注意时间戳单位是秒不是毫秒,jsApiList是你要调用哪些接口,在JSSDK找到你需要的相应的接口;然后主要就是signature的获取;要想获取signature需要经过三步

  1. 通过公众号的 APPIDSECRET 先获取到 access_token (要注意的是access_token每日的获取次数是有限制的,且access_token每次请求都有2个小时时效,根据具体情况需做缓存);
  2. 通过 access_token 去再去请求获取jsapi_ticket接口,获得 ticket;
  3. 将 ticket,时间戳,随机串,还有你需要分享的页面的URL,四个参数按照字段名的 ASCII 码从小到大排序(字典序)后做sha1加密最后得到 signature。
    以下是签名说明:
    在这里插入图片描述接下来是步骤四,微信分享重写,相关参数都有说明也很容易理解:
    在这里插入图片描述
最后贴上我的代码实现

这是前端 js


$(function(){
    var $url = location.href.split('#')[0];

    $.ajax({
        type: "post",
        url: "/获取signature的路径",
        data: {"pageUrl":$url},
        traditional:true,
        success: function (data) {
            console.log(data);
            if (data.code == 1) {
                wx_fxconfig(data.result);
            } else {
                jqalert({
                    title: '提示',
                    content: '获取信息失败,请刷新页面重试'
                })
            }
        },
        error: function (xhr) {
            console.log(xhr);
            jqalert({
                title: '提示',
                content: '获取信息异常,请刷新页面重试'
            })
        }
    });
});

function wx_fxconfig ($result) {
    wx.config({
        //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: $result.appid, // 必填,公众号的唯一标识
        timestamp: $result.timestamp, // 必填,生成签名的时间戳
        nonceStr: $result.noncestr, // 必填,生成签名的随机串
        signature: $result.signature,// 必填,签名
        jsApiList: ['updateAppMessageShareData','updateTimelineShareData'] // 分享朋友及朋友圈及qq
    });

    /*微信分享重写*/
    wx.ready(function(){

        var title = "";
        var desc = "";
        var imgUrl = "";
        var link = "";    

        //分享朋友
        wx.updateAppMessageShareData({
            title: title,//分享标题
            link: link,//分享链接
            imgUrl: imgUrl,// 分享图标
            desc: desc, // 分享描述
            success: function () {
                // 设置成功
            }
        });

        //分享朋友圈
        wx.updateTimelineShareData({
            title: title,// 分享标题
            link: link,//分享链接
            imgUrl: imgUrl,// 分享图标
            success: function () {
                // 设置成功
            }
        });

		//获取用户所在位置经纬度
        wx.getLocation({
            type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
            success: function (res) {
                var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
                var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
                var speed = res.speed; // 速度,以米/每秒计
                var accuracy = res.accuracy; // 位置精度
                $('#addInfo').val(longitude + "," + latitude);
            }
        });

    });
}

这是后端获取signature签名

 	@RequestMapping(value = "/getWxConfig", method = RequestMethod.POST)
    public Result getWxConfig (String pageUrl, HttpServletRequest request) {

        String accessToken = null;
        String ticket = null;
        try {

            accessToken = getAccessToken();
        } catch (Exception e) {
            logger.error("请求accessToken异常");
            return Result.error("获取accessToken异常");
        }

        try {

            String ticketUrl = TICKET_URL + accessToken;
            JSONObject ticketObj = readRespFromGet(ticketUrl);
            if (ticketObj == null) {
                return Result.error("获取ticket失败");
            }
            if ("0".equals(ticketObj.getString("errcode"))) {
                ticket = ticketObj.getString("ticket");
            } else {
                logger.info("获取ticket失败:{}", ticketObj.getString("errmsg"));
                return Result.error("获取ticket失败");
            }

        } catch (Exception e) {
            logger.error("请求ticket异常");
            return Result.error("获取ticket异常");
        }

        Map<String, String> returnMap = new HashMap<>();

        try {
            String noncestr = UUID.randomUUID().toString();
            String timestamp = String.valueOf(System.currentTimeMillis()/1000);
            SortedMap itemMap  = new TreeMap();
            itemMap.put("jsapi_ticket", ticket);
            itemMap.put("url", pageUrl);
            itemMap.put("noncestr", noncestr);
            itemMap.put("timestamp", timestamp);
            String signature = SignUtil.signature(itemMap);

            returnMap.put("signature", signature);
            returnMap.put("noncestr", noncestr);
            returnMap.put("timestamp", timestamp);
            returnMap.put("appid", APPID);

        } catch (Exception e) {
            logger.info("生成签名失败:{}", e);
            return Result.error("生成签名失败");
        }
        
        return Result.success(returnMap);
    }

    private JSONObject  readRespFromGet(String getUrl) throws IOException {
        JSONObject object = null;

        if (StringUtils.isBlank(getUrl)) {
            return object;
        }
        String respStr = HttpRequestUtils.readContentFromGet(getUrl);
        if (StringUtils.isBlank(respStr)) {
            logger.info("===请求返回空参数===");
            return object;
        }
        object = JSONObject.parseObject(respStr);

        return object;
    }

    private String getAccessToken() throws Exception {

        String accessToken = redisService.get(APPID);
        if (StringUtils.isNotBlank(accessToken)) {
            return accessToken;
        }

        String accessTokenUrl = ACCESS_TOKEN_URL + APPID + "&secret=" + SECRET;
        JSONObject tokenObj = readRespFromGet(accessTokenUrl);
        if (tokenObj == null) {
            logger.info("获取token失败");
            throw new Exception("获取token失败");
        }
        accessToken = tokenObj.getString("access_token");

        if (StringUtils.isBlank(accessToken)) {
            logger.info("获取access_token失败:{}", tokenObj.getString("errmsg"));
            throw new Exception("获取token失败");
        }

        Integer expiresIn = tokenObj.getInteger("expires_in");
        if (expiresIn != null) {
            redisService.set(APPID, accessToken);
            redisService.expire(APPID, expiresIn);
        }

        return accessToken;
    }

下面是SignUtil工具类:

public class SignUtil {
	
    public static String signature(SortedMap<String,String> items){
    	StringBuilder forSign= new StringBuilder();
    	for(String key:items.keySet()){
    		forSign.append(key).append("=").append(items.get(key)).append("&");
    	}
    	forSign.setLength(forSign.length()-1);
    	String result = encryptSHA1(forSign.toString());
    	return result;
    }
    
    public static String encryptSHA1(String content){
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(content.getBytes());
            byte messageDigest[] = digest.digest();
            StringBuffer hexString = new StringBuffer();
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
}
最后,在你需要分享的相关页码引入以上js文件及JSSDK步骤二中说明的需要引入的js文件 http://res2.wx.qq.com/open/js/jweixin-1.4.0.js

以上,自己记录下,也希望帮到有需要的你们。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的自定义微信和 QQ 分享组件的案例: 1. 引入相应的 SDK 或插件,并在 HTML 中添加分享按钮。 ```html <!-- 引入微信 SDK --> <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> <!-- 引入 QQ SDK --> <script src="http://qzonestyle.gtimg.cn/qzone/qzact/act/qqconnect.js"></script> <!-- 添加分享按钮 --> <button class="share-btn" data-type="wx">分享微信</button> <button class="share-btn" data-type="qq">分享到QQ</button> ``` 2. 在 JavaScript 中配置分享内容和分享接口。 ```javascript // 配置微信分享 wx.config({ appId: 'your_app_id', timestamp: 'your_timestamp', nonceStr: 'your_nonce_str', signature: 'your_signature', jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'] }); // 配置 QQ 分享 QC.api("share", { title: "分享标题", desc: "分享描述", imgUrl: "分享图片链接", url: "分享链接" }); // 监听分享按钮点击事件 document.querySelectorAll('.share-btn').forEach(function(btn) { btn.addEventListener('click', function(e) { var type = e.target.dataset.type; if (type === 'wx') { // 分享微信 wx.updateAppMessageShareData({ title: '分享标题', desc: '分享描述', link: '分享链接', imgUrl: '分享图片链接', success: function () { // 分享成功后的回调函数 } }); } else if (type === 'qq') { // 分享到 QQ QC.share(); } }); }); ``` 注意:以上代码仅作为示例,实际应用中需要根据具体的需求进行调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值