微信自定义分享功能实现

微信自定义分享功能实现

一、实现的关键

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

在这里插入图片描述

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

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

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

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、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

(2)controller层:

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

(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;
    }

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.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();
    }


}

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


}
(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)获取access_token时报错,提示某某IP不在白名单内:

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

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

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

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GG非常废

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值