java微信公众号——定时获取access_token

access_token简介
为了使第三方开发者能够为用户提供更多有价值的个性化服务,微信公众台开放了许多接口,包括自定义菜单接口、客服接口、获取用户信息接口、用户分组接口、群发接口等,开发者调用这些接口是,都需要传入一个相同的参数access_token,他是公众号的全局唯一票据,发是接口的访问凭证。

access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。
access_token的存储至少要保留512个字符空间。
access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的 access_token失效。

公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在微信公众平台官网-开发者中心页中获得(需要已经成为开发者,且帐号没有异常状态)。注意调用所有微信接口时均需使用https协议。

access_token的有效期是7200秒(两小时),在有效期内,可以一直使用,只有当access_token过期时,才需要再次调用接口 获取access_token。在理想情况下,一个7x24小时运行的系统,每天只需要获取12次access_token,即每2小时获取一次。如果在 有效期内,再次获取access_token,那么上一次获取的access_token将失效。

目前,获取access_token接口的调用频率限制为2000次/天,如果每次发送客服消息、获取用户信息、群发消息之前都要先调用获取 access_token接口得到接口访问凭证,这显然是不合理的,一方面会更耗时(多了一次接口调用操作),另一方面2000次/天的调用限制恐怕也不 够用。因此,在实际应用中,我们需要将获取到的access_token存储起来,然后定期调用access_token接口更新它,以保证随时取出的 access_token都是有效的。

我们先看看官方的说明:

接口调用请求说明

http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

参数说明

参数 必须是否 说明
grant_type 获取access_token填写client_credential
appid 第三方用户唯一凭证
secret 第三方用户唯一凭证密钥,即appsecret

返回说明

正常情况下,微信会返回下述JSON数据包给公众号:
{“access_token”:“ACCESS_TOKEN”,“expires_in”:7200}

参数 说明
access_token 获取到的凭证
expires_in 凭证有效时间,单位:秒

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
{“errcode”:40013,“errmsg”:“invalid appid”}

spring boot 编写java代码

1、封装基本类

public class AccessToken
{
    private String accessToken;
    
    // 凭证有效期,单位:秒
    private int expiresIn;
    
    public String getAccessToken()
    {
        return accessToken;
    }
    
    public void setAccessToken(String accessToken)
    {
        this.accessToken = accessToken;
    }
    
    public int getExpiresIn()
    {
        return expiresIn;
    }
    
    public void setExpiresIn(int expiresIn)
    {
        this.expiresIn = expiresIn;
    }
}
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;
    }
}

2、常量类

@Component
@ConfigurationProperties(prefix = "basicsyscodeservice")
public class BasicSysCodeService
{
    /**
     * 获取access_token请求的url
     */
    private static String accessTokenUrl;
    
    private static String appId;
    
    private static String secret;
    
    public static String getAccessTokenUrl()
    {
        return accessTokenUrl;
    }
    @Value("${basicsyscodeservice.accessTokenUrl}")
    public void setAccessTokenUrl(String accessTokenUrl)
    {
        this.accessTokenUrl = accessTokenUrl;
    }
    
    public static String getAppId()
    {
        return appId;
    }
    
    @Value("${basicsyscodeservice.appId}")
    public void setAppId(String appId)
    {
        this.appId = appId;
    }
    
    public static String getSecret()
    {
        return secret;
    }
    
    @Value("${basicsyscodeservice.secret}")
    public void setSecret(String secret)
    {
        this.secret = secret;
    }
    
}

4、配置文件

application-config.yml

basicsyscodeservice:
  accessTokenUrl: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
  appId: wxb30f7903610be618
  secret: a6ccb1547321187572f2e8c66b8140a7

application.yml

server:
  port: 80
  servlet:
    context-path: /weixin
spring:
  profiles:
      include: config

4、定时获取access_token的公共方法

@Component
public class CommonUtil
{
    private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
    
    public static AccessToken accessToken = null;
    
    /**
     * 获取接口访问凭证
     *
     * @return
     */
    @Scheduled(fixedRate = 1000*7200)
    private static AccessToken getAccessToken()
    {
        String requestUrl = String.format(BasicSysCodeService.getAccessTokenUrl(),
            BasicSysCodeService.getAppId(),
            BasicSysCodeService.getSecret());
        // 发起GET请求获取凭证
        JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
        
        if (null != jsonObject)
        {
            try
            {
                accessToken = new AccessToken();
                accessToken.setAccessToken(jsonObject.getString("access_token"));
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
            }
            catch (Exception e)
            {
                accessToken = null;
                // 获取token失败
                log.error(e.getMessage());
            }
        }
        return accessToken;
    }
    
    /**
     * 发送https请求
     *
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */

    private 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();
            conn.setSSLSocketFactory(ssf);
            
            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.fromObject(buffer.toString());
        }
        catch (ConnectException ce)
        {
            log.error("连接超时:{}", ce);
        }
        catch (Exception e)
        {
            log.error("https请求异常:{}", e);
        }
        return jsonObject;
    }
}

5、SpringbootApplication

@SpringBootApplication
@EnableScheduling
public class SpringbootApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringbootApplication.class, args);
	}

}

每个两个小时CommonUtil.accessToken中的access_token将会刷新一次

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