首页 > 编程语言 >java版微信公众号开发(八)获取jsapi_ticket,生产JS-SDK签名

java版微信公众号开发(八)获取jsapi_ticket,生产JS-SDK签名

时间:2024-05-30 13:58:14浏览次数:20  
标签:版微信 info java String url jsapi connection ticket logger

jsapi_ticket是公众号用于调用微信JS接口的临时票据。只用正确的签名才能使用JS调用微信接口,小编在这里整理一个一套完整的获取方法。废话不多说,直接上干货。

    //import java.security.MessageDigest;
     /*** 获取位置信息签名
     * @Author FM_南风
     * @Date 2024/3/12 15:52
     **/
    @Override
    public JsonResult getSign(String url) {
        logger.info("获取微信授权ticket,用于前端获取客户位置信息:===>【{}】", url);
        //url必须是调用JS接口页面的完整URL。
        String ticket = TokenUtil.getTicket(redis, APP_ID, APP_SECRET);
        logger.info("ticket:===>【{}】", ticket);
        //生成11位时间戳
        long time11 = System.currentTimeMillis() / 1000;
        String timestamp = String.valueOf(time11);
        //生成16位随机字符串
        String nonce = StringUtil.create16String();
        String string1 = "jsapi_ticket=" + ticket + "&noncestr=" + nonce + "&timestamp=" + timestamp + "&url=" + url;
        // 2.1这里利用了hutool的加密工具类
        logger.info("使用sha1加密前的细信息:===>【{}】", string1);
        String signature = "";
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = PswUtil.encryptSha1(crypt.digest());
        } catch (Exception e) {
            logger.info(e.getMessage());
        }
        logger.info("signature:===>【{}】", signature);
        Map<String, String> map = new HashMap<>();
        map.put("signature", signature);
        map.put("timestamp", timestamp);
        map.put("nonce", nonce);
        map.put("url", url);
        map.put("ticket", ticket);
        logger.info("将生成sign信息返回给前端:===>【{}】", map);
        return JsonResult.ok(map);
    }

其中用到了工具类:TokenUtil.getTicket

public class TokenUtil {
    private static final Logger logger = LoggerFactory.getLogger(TokenUtil.class);
    
    /*** 
     * 获取微信ticket签名
     **/
    public static String getTicket(redia, String appId, String appSecret) {
        String ticket  = redis.getTicket();
        if(ticket != null && !ticket.isEmpty()){
            return ticket;
        }
        String token ="token";//你自己的token获取逻辑
        String result = HttpUtil.doGet(String.format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi", token));
        logger.info("获取ticket返回结果:===>【{}】", result);
        JSONObject jsonObject = JSONObject.parseObject(result);
        int code = jsonObject.getIntValue("errcode");
        ticket = jsonObject.getString("ticket");
        if (code == 40014 || code == 40001 || code == 42001) {
            logger.info("微信access_token过期或无效,需要重新获取token并生成ticket");
            redis.deleteWxToken();
            logger.info("删除微信access_token,递归调用生成ticket");
             return  getTicket(redis, appId, appSecret);
        }
        redis.saveTicket(ticket);
        return ticket;
    }
}
HttpUtil.doGet
public class HttpUtil {

    /**
     * get方式的http请求
     * @param httpUrl 请求地址
     * @return 返回结果
     */
    public static String doGet(String httpUrl) {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        String result = null;// 返回结果字符串
        try {
            // 创建远程url连接对象
            URL url = new URL(httpUrl);
            // 通过远程url连接对象打开一个连接,强转成httpURLConnection类
            connection = (HttpURLConnection) url.openConnection();
            // 设置连接方式:get
            connection.setRequestMethod("GET");
            // 设置连接主机服务器的超时时间:15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取远程返回的数据时间:60000毫秒
            connection.setReadTimeout(60000);
            // 发送请求
            connection.connect();
            // 通过connection连接,获取输入流
            if (connection.getResponseCode() == 200) {
                inputStream = connection.getInputStream();
                // 封装输入流,并指定字符集
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                // 存放数据
                StringBuilder sbf = new StringBuilder();
                String temp;
                while ((temp = bufferedReader.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append(System.getProperty("line.separator"));
                }
                result = sbf.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();// 关闭远程连接
            }
        }
        return result;
    }
}
StringUtil.create16String();
public class StringUtil {
    /*** 
     * 生成16位随机大小写加数字的字符串
     **/
    public static String create16String(){
        String a = "ZXCVBNMASDFGHJKLQWERTYUIOPzxcvbnmasdfghjklqwertyuiop0123456789";
        StringBuilder con = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            con.append(a.charAt(random.nextInt(62)));
        }
        return con.toString();
    }
}
PswUtil.encryptSha1
public class PswUtil {
    
    /*** 
     * 生成微信sha1方法签名
     **/
    public static String encryptSha1(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
}

这就是一个完整的获取jsapi_ticket生成签名的过程。

注意事项

  1. 签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。

  2. 签名用的url必须是调用JS接口页面的完整URL。

  3. 出于安全考虑,开发者必须在服务器端实现签名的逻辑
     

标签:版微信,info,java,String,url,jsapi,connection,ticket,logger
From: https://blog.csdn.net/weixin_70044963/article/details/139321958

相关文章

  • 数据结构之栈(Java,C语言的实现)以及相关习题巩固
    目录栈概念以及代码实现例题232.用栈实现队列1614.括号的最大嵌套深度234.回文链表1614.括号的最大嵌套深度LCR123.图书整理I206.反转链表402.移掉K位数字844.比较含退格的字符串LCR036.逆波兰表达式求值[面试题03.01.三合一](栈概念以及代码实现栈是仅限于在......
  • 数据结构 顺序表(C语言 与 Java实现)以及部分练习题
    目录数据结构数组(顺序表)特点使用Java实现更高级的数组C语言实现总结优点缺点例题26.删除有序数组中的重复项1.两数之和27.移除元素153.寻找旋转排序数组中的最小值485.最大连续1的个数414.第三大的数2656.K个元素的最大和LCP06.拿硬币2057.值相等的最小索引26.删......
  • 基于Java+Vue的园区智能化管理系统:综合管控,推进数字化转型(代码分享)
    前言:智慧园区管理平台是一个集成了多种功能的综合性系统,旨在通过信息化、智能化手段提升园区的管理效率和服务质量。以下是针对系统的各个功能模块的简要描述:一、楼栋管理会务管理:管理园区内的会议预约、会议室使用等。园区信息:展示园区的基本信息,如位置、面积、规划等。楼......
  • Java中Comparable接口和Comparator接口的区别(如果想知道Java中Comparable接口和Compar
        前言:在Java中,Comparable接口和Comparator接口都用于对象之间的比较和排序,但它们在使用和设计上存在一些关键的区别。✨✨✨这里是秋刀鱼不做梦的BLOG✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客        本篇文章主要讲解的是J......
  • JavaSE 面向对象程序设计 文件File 介绍练习加千行代码详解
    介绍在Java中,File类是用于表示文件和目录路径的抽象。它提供了一组方法来创建、删除、重命名、检查文件/目录的存在性、以及查询文件/目录的属性等功能。File类可以用于执行文件系统操作,如创建新文件、删除文件、检查文件是否存在等。目的是把字符串先表示为路径然后转化......
  • Java 五种内部类演示及底层原理详解
    内部类什么是内部类在A类的内部定义B类,B类就被称为内部类发动机类单独存在没有意义发动机为独立个体可以在外部其他类里创建内部类的对象去调用方法类的五大成员属性方法构造方法代码块内部类内部类的访问特点内部类可以直接访问外部类的成员,包括私有外部类要......
  • java+sql企业固定资产管理系统
    摘要:本文主要介绍的是固定资产管理系统的整个设计过程。第1章的绪论包括选题的背景,目的和意义,国内外现状;第2章平台简介包括JBuilder2005和SQLServer数据库的介绍;第3章系统分析,需求分析,数据流与数据字典,功能需求;第4章系统设计部分包括系统总体设计,功能模块设计,数据库设计;第5章......
  • 使用Java API 操作MongoDB
    除了通过启动mongo进程进入Shell环境访问数据库外,MongoDB还提供了其他基于编程语言的数据库访问方法。MongoDB官方提供了编程语言的驱动包,利用这些驱动包可以使用编程方法连接并操作MongoDB数据库。想要使用 Java程序操作 MongoDB,需要确保您的电脑上已经安装了Mong......
  • 为何Java抽象类是代码架构的基石?
    效率工具推荐一个程序员的常用工具网站,效率加倍嘎嘎好用:程序员常用工具云服务器云服务器限时免费领:轻量服务器2核4G腾讯云:2核2G4M云服务器新老同享99元/年,续费同价阿里云:2核2G3M的ECS服务器只需99元/年,续费同价为何Java抽象类是代码架构的基石?Java抽象类是面向对象编......
  • Java毕业设计-基于springboot开发的旅游网站-毕业论文(附毕设源代码)
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求/流程分析3、系统功能结构三、系统实现展示1、用户信息管理2、旅游动态管理3、景点信息管理4、公告信息管理四、毕设内容和源代码获取总结Java毕业设计-基于springboot开发的旅游网站-......