当前位置:   article > 正文

微信自定义分享功能实现_微信分享功能实现

微信分享功能实现

微信自定义分享功能实现

一、实现的关键

新手应明白一个概念:微信前台已经写好了所有微信功能的代码,如:微信分享给朋友、分享到朋友圈、拍照或从手机相册中选图接口。微信一开始调用的是默认的接口方法,我们只需给这些接口传递一些参数即可达到自定义功能的实现,本质上还是依赖微信前台的接口方法。就如同下面的任务需求:

在这里插入图片描述

要想实现目标需求就需要给微信的分享方法传递参数(标题、简介、图片):
在这里插入图片描述

但我们想前台能调用这些接口实现,就必须先进行权限验证。前台必须通过参数验证,才可调用微信接口,通过config方法验证:

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

1.后端的任务

后台的任务就是将下面标明的四个参数传到前台:

在这里插入图片描述

2.前台的任务

(1)在下面标明的列表里加上你想传参或调用的微信接口:

(2)下面是自定义分享的实现例子:

<script type="text/javascript">
    var shareUrl = decodeURIComponent(location.href.split('#')[0]);
    var shareTitle="huilong资讯";
    var shareImgUrl='https://up.enterdesk.com/edpic_360_360/5b/c6/9a/5bc69a3ccf8b5b5ffd33bcdea05c7ec2.jpg';
    var timestamp;
    var noncestr;
    var signature;
    var appId;

    //获取签名
    $.ajax({
        type: "POST",
        url: "/wx/share",
        data:{url:shareUrl},
        success: function(result){
            timestamp=result.data.timestamp;
            noncestr=result.data.noncestr;
            signature=result.data.signature;
            appId=result.data.appId;
            wxShare();
        }
    });
    function wxShare() {
        //微信接口权限验证
        wx.config({
            debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: appId, // 和获取Ticke的必须一样------必填,公众号的唯一标识
            timestamp: timestamp, // 必填,生成签名的时间戳
            nonceStr: noncestr, // 必填,生成签名的随机串
            signature: signature,// 必填,签名,见附录1
            jsApiList: [
                'updateTimelineShareData'
            ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        });

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

            wx.updateTimelineShareData({
                title: 'sdasd', // 分享标题
                link: shareUrl, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                imgUrl: shareImgUrl, // 分享图标
                success: function () {
                    // 设置成功
                }
            })
    })
    }
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

二、实现具体步骤

1、js安全域名配置(被分享的网址必须实现)

在这里插入图片描述
在这里插入图片描述

上面的第三步springBoot可以这么实现:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YkNWDgrv-1641282568865)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\1639836366387.png)]

2、添加服务器配置(成为开发者)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IjG0XDyy-1641282568865)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\1639836497706.png)]
在这里插入图片描述

详细看文档微信开发文档的接入指南

配置文件上需要填写AppId( 开发者ID )、AppSecret( 开发者密码)、token(自定义):

# 微信开发环境配置
wx:
  config:
    appid: wx8368a21c304999ed
    secret: a6a55025b0c8a16f43b64e985c3ccdd7
    token: huilong
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2)controller层:

@RequestMapping(value = "/wx/checkWx")
    public String checkWx(WxSendMsgRequest wxSendMsgRequest){
        return weiXinService.checkWxUrl(wxSendMsgRequest);
    }
  • 1
  • 2
  • 3
  • 4

(3)service层:

@RequestMapping(value = "/wx/share",method = RequestMethod.POST)
    public Result<WxShareResponse> checkWx(String url){
        WxShareResponse wxShareResponse = weiXinService.queryWxShare(url);
        System.out.println(JSON.toJSON(wxShareResponse));
        Result<WxShareResponse> result = new Result<>();
        if (wxShareResponse!=null){
            result.setCode(0);
            result.setData(wxShareResponse);
        }else {
            result.setCode(500);
        }
        return result;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3、生成签名signature

下一节有后台全部代码。

(1)获取access_Token

详细看文档:微信开发文档的获取access_Token方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HJoyFBJj-1641282568868)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\1639839838530.png)]

(2)获取 jsapi_ticket :

步骤和上面差不多

详细看文档: 微信开发文档 看附录一
在这里插入图片描述

(3)用sha1加密算法得到signature:

详细看文档: 微信开发文档 看附录
在这里插入图片描述
在这里插入图片描述

4、将参数发送到前台:

(1)后台总体方法:

application配置文件:

# 微信开发环境配置
wx:
  config:
    appid: wx8368a21c304999ed
    secret: a6a55025b0c8a16f43b64e985c3ccdd7
    token: huilong
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1.service层:

@Service
public class WeiXinServiceImpl implements WeiXinService {

    @Value("${wx.config.token}")
    private String token;

    @Value("${wx.config.appid}")
    private String appId;

    @Value("${wx.config.secret}")
    private String secret;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private RestTemplate restTemplate;
    

    /**
     * 微信安全验证
     * 微信要录入服务器配置
     *
     * @param wxSendMsgRequest 微信验证携带的参数
     * @return
     */
    @Override
    public String checkWxUrl(WxSendMsgRequest wxSendMsgRequest) {
        System.out.println("进入验证");
        try{
            String msg[] =new String[]{token,wxSendMsgRequest.getNonce(),wxSendMsgRequest.getTimestamp()};
            Arrays.sort(msg);
            String checkStr=msg[0]+msg[1]+msg[2];
            //用sha1加密算法
            String sign= getSha1(checkStr);

            if (wxSendMsgRequest.getSignature().equals(sign)){
                return wxSendMsgRequest.getEchostr();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 微信分享
     *
     * @param url
     * @return 返回微信分享所需参数
     */
    @Override
    public WxShareResponse queryWxShare(String url) {
        WxShareResponse wxShareResponse =new WxShareResponse();
        //从缓存中获取ticket
        String ticket;
        String accessToken;

        //调用微信api接口获取accessToken
        String getTokenUrl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+secret;
        WxConfigResponse wxToken = restTemplate.getForObject(getTokenUrl, WxConfigResponse.class);


        accessToken=wxToken.getAccess_token();
        if (wxToken.getErrcode()!=null&&wxToken.getErrcode()!=0){
            wxShareResponse.setErrcode(wxToken.getErrcode());
            wxShareResponse.setErrmsg(wxToken.getErrmsg());
            return wxShareResponse;
        }

        String getTicketUrl="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken+"&type=jsapi";
        WxConfigResponse wxTicket = restTemplate.getForObject(getTicketUrl, WxConfigResponse.class);

        ticket=wxTicket.getTicket();
        System.out.println(wxTicket);
        if (wxTicket.getErrcode()!=null&&wxTicket.getErrcode()!=0){
            wxShareResponse.setErrcode(wxTicket.getErrcode());
            wxShareResponse.setErrmsg(wxTicket.getErrmsg());
            return wxShareResponse;
        }

        //结合url、ticket等生成加密签名
        String noncestr= UUID.randomUUID().toString();
        String timestamp= Long.toString(System.currentTimeMillis()/1000);

        String getSign="jsapi_ticket="+ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;
        String signature=getSha1(getSign);
        wxShareResponse.setNoncestr(noncestr);
        wxShareResponse.setTimestamp(timestamp);
        wxShareResponse.setSignature(signature);
        wxShareResponse.setAppId(appId);

        return wxShareResponse;
    }

    //sha1加密方法
    public static String getSha1(String inStr)  {
        MessageDigest sha = null;
        byte[] byteArray;
        try {
            sha = MessageDigest.getInstance("SHA");
            byteArray= inStr.getBytes("UTF-8");
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
            return "";
        }


        byte[] md5Bytes = sha.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123

2.controller层:

@RestController
public class WeiXinController {
    @Autowired
    private WeiXinServiceImpl weiXinService;

    @RequestMapping(value = "/wx/checkWx")
    public String checkWx(WxSendMsgRequest wxSendMsgRequest){
        return weiXinService.checkWxUrl(wxSendMsgRequest);
    }

    @RequestMapping(value = "/wx/share",method = RequestMethod.POST)
    public Result<WxShareResponse> checkWx(String url){
        WxShareResponse wxShareResponse = weiXinService.queryWxShare(url);
        System.out.println(JSON.toJSON(wxShareResponse));
        Result<WxShareResponse> result = new Result<>();
        if (wxShareResponse!=null){
            result.setCode(0);
            result.setData(wxShareResponse);
        }else {
            result.setCode(500);
        }
        return result;
    }


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
(2)前台JavaScript代码:
//获取签名
    $.ajax({
        type: "POST",
        url: "/wx/share",
        data:{url:shareUrl},
        success: function(result){
            timestamp=result.data.timestamp;
            noncestr=result.data.noncestr;
            signature=result.data.signature;
            appId=result.data.appId;
        }
    });

        //微信接口权限验证
        wx.config({
            debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
            appId: appId, // 和获取Ticke的必须一样------必填,公众号的唯一标识
            timestamp: timestamp, // 必填,生成签名的时间戳
            nonceStr: noncestr, // 必填,生成签名的随机串
            signature: signature,// 必填,签名,见附录1
            jsApiList: [
                'updateTimelineShareData'
            ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

三、踩过的坑:

(1)获取access_token时报错,提示某某IP不在白名单内:

要配置ip白名单,将报错的IP地址添加到这:
在这里插入图片描述

(2)公众号是个人订阅的,是没有调用分享接口权限的,除非微信认证过:

这里看一看自己公众号的权限:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/268021
推荐阅读
相关标签
  

闽ICP备14008679号