使用Java搭建微信公众号后端服务--accessToken及存取

文章目录

  • 一.accessToken
    • 1.accessToken是什么
    • 2.accessToken的获取
  • 二.存取accessToken的方法
    • 1.准备httpUtil工具类
      • (1)导入commons-httpclient包
      • (2)创建好发送get、post请求的方法
      • (3)创建定时任务

一.accessToken

1.accessToken是什么

简单的说,accessToken相当于一个通行证,根据微信公众号的规定,这个通行证的有效期时间是7200秒。在与微信交互的时候,得提前亮出这个通行证,微信拿去校验后,才会许可你的操作。

2.accessToken的获取

(1)根据微信的规定,开发者需要使用自己的appid和appsecret去向微信换取accessToken,并将得到的这个数据保存在自己的本地,以便后续交互时使用。
使用Java搭建微信公众号后端服务--accessToken及存取_第1张图片
(2)根据上述要求,我们可以提取出一下几点:

  • 换取accessToken需要微信公众号的appid、appsecret
  • 得到的accessToken需要保存在自己的本地,以便于后续的使用
  • accessToken存在有效期的概念,我们应该提前换取新的accessToken,以防止业务出现中断的情况。

二.存取accessToken的方法

根据上述结论分析,我们可以使用redis来存、取accessToken,因为redis存取快,而且,可以部署在独立的服务器上,如果存在服务器集群或者多个系统之间均需要使用这个accessToken的时候,均可以获取到这个对应的值。再者,使用quartz来定时与微信交互,刷新accessToken的值。

1.准备httpUtil工具类

(1)导入commons-httpclient包

		
            commons-httpclient
            commons-httpclient
            3.1
        

(2)创建好发送get、post请求的方法

这一类的工具类,有很多,大家可以网上搜索一下

public static String sendPost(String url) throws HttpException, IOException {
        // 创建httpClient实例对象
        HttpClient httpClient = new HttpClient();
        // 设置httpClient连接主机服务器超时时间:15000毫秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(2000);
        // 创建post请求方法实例对象
        PostMethod postMethod = new PostMethod(url);
        // 设置post请求超时时间
        postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
        postMethod.addRequestHeader("Content-Type", "application/json");

        httpClient.executeMethod(postMethod);
        String result = postMethod.getResponseBodyAsString();
        postMethod.releaseConnection();
        return result;
    }
    public static String sendGet(String url) throws HttpException, IOException {
        // 创建httpClient实例对象
        HttpClient httpClient = new HttpClient();
        // 设置httpClient连接主机服务器超时时间:15000毫秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);
        // 创建GET请求方法实例对象
        GetMethod getMethod = new GetMethod(url);
        // 设置post请求超时时间
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
        getMethod.addRequestHeader("Content-Type", "application/json");

        httpClient.executeMethod(getMethod);

        String result = getMethod.getResponseBodyAsString();
        getMethod.releaseConnection();
        return result;
    }

(3)创建定时任务

①导入spring-boot-starter-quartz
②配置quartz的一些必要的属性,例如执行时间间隔等等
使用Java搭建微信公众号后端服务--accessToken及存取_第2张图片
我这里偷个懒,直接在项目中写死,最好的方式是将其写在数据库里面,然后读取数据库的时间来执行,但是这个地方,我还没完全搞懂,所以,这里就不拿出来献丑了,取个简单的方法,先实现业务功能,我这里配置的是每五秒执行一次定时任务。
③考虑到一种情况,就是说,当有多个公众号的时候,其实跟微信交互的地址是一样的,唯一的区别再去传递的参数(比如appid、appsecret、accessToken这些不一致)不一致。这个时候,我考虑到将其与微信交互的地址,存入到数据库中去。由此新建一张表,保存与微信交互的地址。
在这里插入图片描述
这里列举了两个请求地址,trade_url为主要字段,在这里是根据trade_type来查询,获取对应的url。
④redis存取值
直接使用最简单的字符类型即可,并设置当前key的过期时间即为当前accessToken的有效期,但是这个有效时间要设置得稍微比7200秒小一点,得保证accessToken一直是有效的。

注入RedisTemplate
取值:
// accessToken值
String accessToken = redisTemplate.boundValueOps(p.getAppId()).get();
// 过期时间
Long lastTime = redisTemplate.getExpire(p.getAppId());

存值:
redisTemplate.boundValueOps(p.getAppId()).set(accessToken);
redisTemplate.expire(p.getAppId(), EXPIRE_TIME, TimeUnit.SECONDS);
这里是根据appid为key来存的

④创建一个RefreshJob类继承QuartzJobBean,并重写executeInternal()来实现自己的业务逻辑

XyyPublicPropertiesExample example = new XyyPublicPropertiesExample();
        example.createCriteria().andIsDeleteEqualTo(0);
        // 获取所有公众号
        List publicList = xyyPublicPropertiesDao.selectByExample(example);
        XyyPublicTradeExample tradeExample = new XyyPublicTradeExample();
        tradeExample.createCriteria().andTradeTypeEqualTo(ConstantsForTradeType.ENUM_TRADE_TYPE.REFRESH_TOKEN.getCode());
        List tradeTypes = xyyPublicTradeDao.selectByExample(tradeExample);
        String requestUrl = "";
        if (CollectionUtils.isNotEmpty(tradeTypes)) {
            // 请求地址
             requestUrl = tradeTypes.get(0).getTradeUrl();
        }
        for (XyyPublicProperties p:publicList) {
            // accessToken值
            String accessToken = redisTemplate.boundValueOps(p.getAppId()).get();
            // 过期时间
            Long lastTime = redisTemplate.getExpire(p.getAppId());
            if (StringUtils.isEmpty(accessToken) || lastTime <= 200) {
                // 不存在accessToken,或者剩余时间太少
                // 2.获取新的accessToken
                requestUrl = requestUrl + "&appid=" + p.getAppId() + "&secret=" + p.getAppSecret();
                String result = "";
                try {
                    result = HttpUtils.sendGet(requestUrl);
                }catch (IOException e) {
                    e.printStackTrace();
                    result = "";
                }
                logger.info("result:{}", result);
                if (StringUtils.isNotEmpty(result)) {
                    JSONObject jsonObject = JSON.parseObject(result);
                    accessToken = jsonObject.getString("access_token");
                    if (StringUtils.isNotEmpty(accessToken)) {
                        int expires_in = jsonObject.getInteger("expires_in");
                        redisTemplate.boundValueOps(p.getAppId()).set(accessToken);
                        redisTemplate.expire(p.getAppId(), EXPIRE_TIME, TimeUnit.SECONDS);
                        logger.info("公众号:{}刷新token完成,token:{}", p.getAppId(), accessToken);
                    } else{
                        String errmsg = jsonObject.getString("errmsg");
                    }

                }
            } else {
                logger.info("公众号:{}刷新token时间未到", p.getAppId());
            }
        }
    }

简单的说,逻辑如下:
1.获取需要刷新token的公众号
2.根据appid查询redis中存储的value值以及到期时间
3.若value值不存在,或者到期时间小于200秒,则组url调微信的接口去获取新的accessToken并存储在本地,否则则认为当前不需要刷新accessToken。

组url是比较简单的,就是字符串的连接,再根据微信获取的结果,来判断是否成功、并取值处理即可。

本期关于accessToken的存取,就分享到这里了,下期将继续分享微信消息体的解析及响应。

你可能感兴趣的:(微信公众号,java)