JAVA微信公众号开发-获取access_token并保证access_token长久有效

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38455201/article/details/80227675

1.access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token,所以这个数据是非常的重要的,首先阅读以下微信开发文档,对于access_token是这样写的。


根据文档的指示,我们的access_token的需求如下:单一获取和刷新access_token的值,全局保存,用到的都去这个地方去拿。定时去刷新(现在是2个小时刷新一次)

2.我们使用redis来全局缓存access_token的值,需要用到access_token的时候就去redis当中去取。并且,这个值每两个小时刷新一次。

    //刷新access_token 100分钟刷新一次,服务器启动的时候刷新一次(access_token有效期是120分钟,我设置的是每100分钟刷新一次)
    @Scheduled(initialDelay = 1000, fixedDelay = 100*60*1000)
    public void get_access_token() {
        try {
            String appid = "填上你公众号的appid";
            String appsecret = "填上你公众号的appsecret";
            String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
            requestUrl = requestUrl.replace("APPID",appid).replace("APPSECRET",appsecret);
            JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl,"GET",null);
            if(jsonObject.getString("access_token")!=null){
                Jedis jedis = jedisPool.getResource();
                try {
                    Map<String,String> map = new HashMap<String,String>();
                    map.put("access_token",jsonObject.getString("access_token"));
                    jedis.hmset(appid, map);
                } catch(Exception e){
                    if(jedis != null){
                        jedis.close();
                        jedis = null;
                    }
                    e.printStackTrace();
                } finally {
                    if(jedis != null){
                        jedis.close();
                    }
                }
            }
            else{
                logger.info("定时刷新access_token失败,微信返回的信息是"+jsonObject.toJSONString());
            }
        }
        catch (Exception e){
            logger.info("更新access_token的过程当中发生了异常,异常的信息是"+e.getMessage());
        }
    }
    /**
     * 发送https请求
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            //HttpURLConnection  con= url.openConnection();
            conn.setSSLSocketFactory(ssf);
            //2017年9月15日16:21:40
            //新设置的,可能是一直在链接导致的程序死亡
            conn.setConnectTimeout(10 * 1000);
            conn.setReadTimeout(50 * 1000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();

            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
            System.out.println("连接超时:{}" + ce);
        } catch (Exception e) {
            System.out.println("https请求异常:{}" + e);
            //log.error("https请求异常:{}", e);
        }
        return jsonObject;
    }
public class MyX509TrustManager implements X509TrustManager {

    // 检查客户端证书
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // 检查服务器端证书
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // 返回受信任的X509证书数组
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

其中jedisPool的配置如下:

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.poolMaxIdle}")
    private int maxIdle;

    @Value("${spring.redis.poolMaxWait}")
    private long maxWaitMillis;

    /*@Value("${spring.redis.password}")
    private String password;*/

    @Bean
    @Scope("singleton")
    public JedisPool redisPoolFactory() {
        System.out.println("jedispool");
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, null);
        logger.info("host:"+host);
        logger.info("port:"+port);
        logger.info("timeout:"+timeout);
        return jedisPool;
    }

这样,我们就把access_token全局进行了缓存,在其他需要使用到access_token的时候,就去redis当中获取数据,调用其他的接口。我们满足了微信开发文档的三点要求

1.全局唯一获取刷新access_token ,全局缓存,需要的都去redis当中去取。

2.定时刷新access_token,不会出现access_token过期的情况

3.access_token有效时间可能会在未来有调整,到时候我们只需要改一下定时器的时间即可。



展开阅读全文

没有更多推荐了,返回首页