实现微信自定义分享(缩略图、标题、描述)

目录

1. 背景描述:

2.实现步骤:

2.1 调用微信js接口前的必要准备工作

2.1.1 方案一:企业级的微信公众号

2.1.2 方案二:测试号

2.2 调用微信js接口

2.2.1 进入微信JSSDK开发文档

2.2.2 查看jssdk使用步骤

步骤一:绑定域名(前面的步骤已完成)

步骤二:引入JS文件

步骤四:通过ready接口处理成功验证

步骤五:通过error接口处理失败验证

步骤六:调用微信分享接口

2.2.3 附上完整代码

3.过程中可能遇到的问题及解决方案


1. 背景描述:

        接到个需求,需要在网页中实现微信分享功能,在网站内,用户可以将喜欢的内容,以小卡片的形式分享到微信中,提升网站的知名度和传播力度。效果如下:

2.实现步骤:

2.1 调用微信js接口前的必要准备工作

        要使用微信js接口,需要准备一个微信公众号,并对微信公众号进行相关配置。考虑到很多小伙伴没有微信公众号,这边准备了两个方案供大家选择。

2.1.1 方案一:企业级的微信公众号

微信公众号平台地址:微信公众平台

1)注册登录公众号平台,【设置与开发】->【公众号设置】->【功能设置】,填写js接口安全域名,就可以在该域名下调用微信的js接口了。

2)在【设置与开发】->【基本配置】中,查看开发者id(AppID)和开发者密码(AppSecret),这个是后续获取access_token的关键,而access_token又是调用微信js接口的必备鉴权参数。

3)设置ip白名单,通过开发者及密码获取access_token时,需要设置访问来源ip为白名单

2.1.2 方案二:测试号

对于没有公众号的小伙伴,可以使用微信提供的测试号。

测试号地址:微信公众平台

1)登陆测试号平台后,查看自己的appID和appsecret。

2)需要准备一个已备案的域名,并设置为js接口安全域名。

注:域名不能包含http://等内容,如:baidu.com。

3)扫描自己的测试号二维码,进行关注,关注后右侧的用户列表里就你了。

2.2 调用微信js接口

2.2.1 进入微信JSSDK开发文档

附上地址:概述 | 微信开放文档

2.2.2 查看jssdk使用步骤

步骤一:绑定域名(前面的步骤已完成)
步骤二:引入JS文件

在需要调用JS接口的页面引入如下JS文件:http://res.wx.qq.com/open/js/jweixin-1.6.0.js

步骤三:通过config接口注入权限验证配置

签名算法:

步骤四:通过ready接口处理成功验证
wx.ready(function(){
  // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
步骤五:通过error接口处理失败验证
wx.error(function(res){
  // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
步骤六:调用微信分享接口

总结来说,引入微信js接口文件,访问页面时,会自动异步调用wx.config方法校验相关配置是否正确,校验通过后,就会调用wx.ready里面的方法,而ready方法里就是各种具体的实现,比如分享微信好友、分享朋友圈等。

2.2.3 附上完整代码

新增一个WeChatShareController,用来获取access_token、ticket、签名等配置



import com.jx.common.utils.WeChatUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Controller
@RequestMapping(value = "/weChatShare")
public class WeChatShareController {

    private final static Logger log = LoggerFactory.getLogger(WeChatShareController.class);

    /**
     * 获取微信配置信息
     */
    @RequestMapping(value = "/getSignature")
    @ResponseBody
    public Map<String, Object> toTranscript(@RequestParam("url")String url) {
        Map<String, Object> wxInfo = new HashMap<>();
        log.info("url:"+url);
        try {
            // 获取access_token 注:因为access_token每天获取的次数有限制,获取之后可以放到redis缓存中,当access_token快过期时,再重新从微信服务器获取
            String accessToken = WeChatUtil.getAccessToken();
            // 获取ticket 注:ticket同access_token一样,正式上线时需放在缓存中
            String jsapiTicket = WeChatUtil.getTicket(accessToken);
            String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
            String timestamp = String.valueOf(System.currentTimeMillis()/ 1000);// 时间戳
            String params = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
            //将字符串进行sha1加密
            String signature = WeChatUtil.getSHA1(params);
            //微信appId
            String appId = WeChatUtil.appIdWx;
            wxInfo.put("appId", appId);
            wxInfo.put("accessToken", accessToken);
            wxInfo.put("jsapi_ticket", jsapiTicket);
            wxInfo.put("timestamp", timestamp);
            wxInfo.put("nonceStr", noncestr);
            wxInfo.put("signature", signature);
            wxInfo.put("msg", "success");
            wxInfo.put("status", "1");
            wxInfo.put("code", "1");
            log.info("微信分享成功");
            log.info("wxInfo:"+wxInfo);
            return wxInfo;
        } catch (Exception e) {
            wxInfo.put("code", "0");
            wxInfo.put("status", "0");
            wxInfo.put("msg", "error");
            log.error("获取微信加密信息" + e.getMessage(), e);
            return wxInfo;
        }
    }
}

新增一个工具类WeChatUtil,用来获取access_token、ticket、签名等:


import com.alibaba.fastjson2.JSONObject;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class WeChatUtil {


    // 微信appid---微信公众平台
    public static final String appIdWx = "你自己的appid";
    // 微信AppSecret---微信公众平台
    public static final String appSecretWx = "你自己的appsecret";

    /**
     * 获取access_token
     *
     * @return
     */
    public static synchronized  String getAccessToken() {
        String access_token = "";
        String grant_type = "client_credential";//获取access_token填写client_credential
        //这个url链接地址和参数皆不能变
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + grant_type + "&appid=" + appIdWx + "&secret=" + appSecretWx;
        try {
            URL urlGet = new URL(url);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            http.connect();
            InputStream is = http.getInputStream();
            int size = is.available();
            byte[] jsonBytes = new byte[size];
            is.read(jsonBytes);
            String message = new String(jsonBytes, "UTF-8");
            JSONObject demoJson = JSONObject.parseObject(message);
            access_token = demoJson.getString("access_token");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return access_token;
    }

    /**
     * 获取jsapi_ticket
     *
     * @param access_token
     * @return
     */
    public static synchronized  String getTicket(String access_token) {
        String ticket = null;
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";//这个url链接和参数不能变
        try {
            URL urlGet = new URL(url);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            http.connect();
            InputStream is = http.getInputStream();
            int size = is.available();
            byte[] jsonBytes = new byte[size];
            is.read(jsonBytes);
            String message = new String(jsonBytes, "UTF-8");
            JSONObject demoJson = JSONObject.parseObject(message);
            System.out.println("JSON字符串:" + demoJson);
            ticket = demoJson.getString("ticket");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ticket;
    }

    /**
     * SHA、SHA1加密
     *
     * @parameter: str:待加密字符串
     * @return: 加密串
     **/
    public static String getSHA1(String str) {
        try {
            MessageDigest digest = java.security.MessageDigest
                    .getInstance("SHA-1"); //如果是SHA加密只需要将"SHA-1"改成"SHA"即可
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexStr = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexStr.append(0);
                }
                hexStr.append(shaHex);
            }
            return hexStr.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
}


新增CodeController,用来生成需要分享的链接的二维码:



import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Encoder;

import java.awt.*;

@RestController
@RequestMapping("/code")
public class CodeController {

    @GetMapping("/generate")
    public String generate() {

        QrConfig config = new QrConfig(200, 200);
        // 设置边距,即二维码和背景之间的边距
        config.setMargin(3);
        // 设置前景色,即二维码颜色(青色)
        config.setForeColor(Color.CYAN.getRGB());
        // 设置背景色(灰色)
        config.setBackColor(Color.GRAY.getRGB());
        // 生成二维码到文件,也可以到流
        String url = "你需要分享的网页地址";

        byte[] bytes = QrCodeUtil.generatePng(url, config);

        String encode = new BASE64Encoder().encode(bytes);
        return encode;
    }
}

在resources/static资源目录新增一个index.html,用来调用微信的js接口,可以封装成一个js文件,以后在你需要进行微信分享的页面里引入就可以了:

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>每日新闻</title>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>

<body>

    <h1>微信自定义分享测试</h1>
    <h3>因为微信现在不支持直接分享链接,如果直接分享链接,分享之后会变成一个字符串链接</h3>
    <h3>需要实现自定义分享的方法有如下几种:</h3>
    <ul>
        <li>1.公众号菜单进入,即绑定公众号,菜单进入打开分享出去</li>
        <li>2.气泡链接进入</li>
        <li>3.先收藏url到微信,从微信收藏中进入</li>
        <li>4.通过微信扫描二维码进入到需要分享的网页</li>
    </ul>
    <h3>上述4钟方法,前两个我没试过,后两种亲测有效。但第3钟方法用户需要先收藏再分享,限制太大,不可取。故我采用了第4钟方法。</h3>
    <h2>获取需要分享的网页链接二维码,二维码图片:</h2>
    <!--二维码图片-->
    <img src="data:image/png;base64,这里放通过二维码接口返回的base64字符串">

    <script>

       // alert等日志打印的方法,是为了开发调试方便,上线时需要去掉
    $(function () {
        // 获取当前网页的url路径
        var winUrl = window.location.href.split("#")[0];

        console.log(window.location.href)
        console.log(window.location.href.split("#")[0])

        // 通过ajax调用后端接口,获取签名等配置信息
        $.ajax({
            type: "get",
            url: "/weChatShare/getSignature?url="+winUrl,
            crossDomain: true,
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: function (msg) {
                console.log(msg)
                console.log(" timestamp:" + msg.timestamp + " ; noncestr:" + msg.nonceStr + ";  signature:" + msg.signature);

                // wx.config方法是微信sdk自动异步调用的,目的是为了检测你的相关配置是否正确,配置校验通过后,会执行wx.ready方法
                wx.config({
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: "你的appid", // 必填,公众号的唯一标识
                    timestamp: msg.timestamp, // 必填,生成签名的时间戳
                    nonceStr: msg.nonceStr, // 必填,生成签名的随机串
                    signature: msg.signature, // 必填,签名,见附录1
                    jsApiList: ['updateAppMessageShareData'
                    ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
                // wx.ready中是微信提供的各种api,如微信分享好友、分享朋友圈等等
                wx.ready(function () {
                    console.log('ready方法执行')
                    alert("ready方法执行")

                    var title = '每日新闻';
                    var share_desc = '我是分享描述';
                    var img_url = '分享之后,在微信上显示的缩略图';
                    //分享给微信好友
                    wx.updateAppMessageShareData({
                        title: title, // 分享标题
                        desc: share_desc, // 分享描述
                        link: winUrl, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                        imgUrl: img_url, // 分享图标
                        success: function () {
                            alert('updateAppMessageShareData执行成功')
                            alert("title:"+title+" desc:"+share_desc+ " link:"+winUrl+" imgUrl:"+img_url)
                            console.log('updateAppMessageShareData执行成功')
                        }
                    });


                    wx.error(function (res) {
                        alert("res:"+ res.errMsg)
                        console.log("res:", res)
                    })
                });


            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("error"+errorThrown)
                console.log("error" + errorThrown);
            }
        });


    })


</script>

</body>

</html>

2.2.4 部署项目

将项目部署到安全域名所在的服务器上,访问,页面如下:

用微信扫描二维码,网页打开后,分享给你的微信好友,我这里分享到文件传输助手,效果如下:

至此,微信自定义分享功能实现完毕。

3.过程中可能遇到的问题及解决方案

过程中遇到了几个问题,在官网文档里基本都找到了原因及解决办法。

常见错误及解决办法,附上地址:概述 | 微信开放文档

  • 11
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值