微信分享(JS-SDK权限签名算法)-Java实现

1、问题描述

2、解决方案

2.1 官方文档

官方文档才是yyds,首先查看微信开发者文档(
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html),如下:

官 文档简要来说有几点:

(1)获取jsapi_ticket

首先拿appid与secret换取全局的access_token,然后通过access_token获取jsapi_ticket,这两个值的时效都是是7200秒(2个小时),access_token是全局的,简单说类似管理员权限,每天调用次数有限,2000次/日,这个提到全局的,就有局部的,使用过 页权限的(自定义菜单,H5跳转),也有个access_token,调用次数不限;因为access_token和jsapi_ticket每日调用次数有限,需要把这个值进行缓存;

(2)签名加密

排序、加密,需要对noncestr(随机字符串)、 有效的jsapi_ticket, timestamp(时间戳)、 url,对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1,然后sha1加密;

2.2 代码实现

一步一步来说吧,首先说下关于缓存token和jsapi_ticket的问题,很多方案都是直接放到redis中,但是目前项目比较简单,类似前置机的概念,项目周期也短,就这2个值,还的部署下redis,感觉划不来,就直接库放数据中,弄个定时的标签,整点刷一下,一天刷12次,24个值,稳定可靠,关于存储数据库和刷新就不在这里介绍了。

(1)首先获取access_token

    /**     *  获取token     * @return     */    @PostMapping("/getWXaccessToken")    public String getWXaccessToken() {        String url ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret=" +secret;        String resp = restTemplate.getForObject(url, String.class);        JSONObject resJson = JSONObject.parseObject(resp);        return resJson.getString("access_token");    }

简要说明:

这里就是首先new RestTemplate(),然后拼接下appId和secret,就获取access_token,然后把这个access_token存到数据库中,然后提供查询就好了;

(2)获取jsapi_ticket

    /**     *  入参为token,返回ticket     * @param token     * @return     */    @PostMapping("/getWXJsapiTicket")    public String getWXJsapiTicket(String token) {        String ticket = null;        if (StringUtils.isBlank(ticket)) {            String url ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + token +"&type=jsapi";            String resp = restTemplate.getForObject(url, String.class);            JSONObject resJson = JSONObject.parseObject(resp);            return resJson.getString("ticket");        }        return ticket;    }

拼接下access_token,然后把这个access_token存到数据库中,然后提供查询就好了;

(3)随机数

    /**     *  获取随机数     * @param length     * @return     */    @PostMapping("/getRandomStr")    public  String getRandomStr(int length) {        String base ="fdajfkdajsklfjafdkjxjkljfadnfdnamn12687";        int randomNum;        char randomChar;        Random random =new Random();        StringBuffer str =new StringBuffer();        for (int i =0; i < length; i++) {            randomNum = random.nextInt(base.length());            randomChar = base.charAt(randomNum);            str.append(randomChar);        }        return str.toString();    }

(4) 获取签名,完结

  /**     *   入参为url     * @param reqJson     * @return     */    @PostMapping("/getWXSign")    public String getWXSign(@RequestBody JSONObject reqJson) {        String url = reqJson.getString("url");        long timeStampSec = System.currentTimeMillis() /1000;        String timestamp = String.format("%010d", timeStampSec);        String nonceStr = getRandomStr(8);        String[] urls = url.split("#");        String newUrl = urls[0];        JSONObject respJson =new JSONObject();        String[] signArr =new String[]{"url=" + newUrl,"jsapi_ticket=" + getWXJsapiTicket(getWXaccessToken()),"noncestr=" + nonceStr,"timestamp=" + timestamp};        Arrays.sort(signArr);        String signStr = StringUtils.join(signArr,"&");        String resSign = DigestUtils.sha1Hex(signStr);        respJson.put("appId", appId);        respJson.put("timestamp", timestamp);        respJson.put("nonceStr", nonceStr);        respJson.put("signature", resSign);        return respJson.toJSONString();    }

简要说明:简单来说就是获取jsapiticket,然后值排序,做下sha1加密就可以了。


完整类:

测试,使用的使用根据自己业务场景,稍作改动吧

@RestController@RequestMapping("/api/wx")@Api(value = "测试")public class WXShareController {    private static final Logger logger = LoggerFactory.getLogger(WXShareController.class);    private static final String appId ="ruanjianlaowang";    private static final String secret ="dashuaige";    RestTemplate restTemplate = new RestTemplate();    /**     *   入参为url     * @param reqJson     * @return     */    @PostMapping("/getWXSign")    public String getWXSign(@RequestBody JSONObject reqJson) {        String url = reqJson.getString("url");        long timeStampSec = System.currentTimeMillis() /1000;        String timestamp = String.format("%010d", timeStampSec);        String nonceStr = getRandomStr(8);        String[] urls = url.split("#");        String newUrl = urls[0];        JSONObject respJson =new JSONObject();        String[] signArr =new String[]{"url=" + newUrl,"jsapi_ticket=" + getWXJsapiTicket(getWXaccessToken()),"noncestr=" + nonceStr,"timestamp=" + timestamp};        Arrays.sort(signArr);        String signStr = StringUtils.join(signArr,"&");        String resSign = DigestUtils.sha1Hex(signStr);        respJson.put("appId", appId);        respJson.put("timestamp", timestamp);        respJson.put("nonceStr", nonceStr);        respJson.put("signature", resSign);        return respJson.toJSONString();    }    /**     *  入参为token,返回ticket     * @param token     * @return     */    @PostMapping("/getWXJsapiTicket")    public String getWXJsapiTicket(String token) {        String ticket = null;        if (StringUtils.isBlank(ticket)) {            String url ="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + token +"&type=jsapi";            String resp = restTemplate.getForObject(url, String.class);            JSONObject resJson = JSONObject.parseObject(resp);            return resJson.getString("ticket");        }        return ticket;    }    /**     *  获取token     * @return     */    @PostMapping("/getWXaccessToken")    public String getWXaccessToken() {        String url ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret=" +secret;        String resp = restTemplate.getForObject(url, String.class);        JSONObject resJson = JSONObject.parseObject(resp);        return resJson.getString("access_token");    }    /**     *  获取随机数     * @param length     * @return     */    @PostMapping("/getRandomStr")    public  String getRandomStr(int length) {        String base ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";        int randomNum;        char randomChar;        Random random =new Random();        StringBuffer str =new StringBuffer();        for (int i =0; i < length; i++) {            randomNum = random.nextInt(base.length());            randomChar = base.charAt(randomNum);            str.append(randomChar);        }        return str.toString();    }}

更多信息请关注@软件老王,关注不迷路,软件老王和他的IT朋友们,分享一些他们的技术见解和生活故事。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年7月4日
下一篇 2021年7月4日

相关推荐