获取access_token是微信api最重要的一个部分,因为调用其他api很多都需要用到access_token。比如自定义菜单接口、客服接口、获取用户信息接口、用户分组接口、群发接口等在请求的时候都需要用到access_token。

(一)access_token的介绍

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

公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在微信公众平台官网-开发者中心页中获得。且一个公众号每天获取access_token的次数上限为2000次。详情请查看微信开发文档“获取access_token”

通过开发者文档我们可以发现access_token的有效期限是2个小时,刷新的时候会导致上次获取的access_token失效,而且一个公众号每天获取access_token的次数上限为2000次。如果我们不做控制,而是选择各个业务逻辑点各自去刷新access_token,那么就可能会产生冲突,导致服务不稳定。所以我们需要有一个地方来保存我们获取到的access_token 和获取时间,每次有请求的时候先到这个地方查看是否已有 access_token,并判断这个access_token是否在有效期内,在的话直接返回,反之则重新调用接口获取access_token,同时在我们保存access_token的地方更新token和时间。

先和大家说一下我保存access_token的思路(目前先实现token的获取,access_token的缓存和更新后期会加上):

1.首先定义一个存放token的数据库表

2.首先,用户在调用需要access_token接口的时候,先查询数据库里保存access_token的值是否存在。

3.如果access_token存在的话,判断此access_token是否有效。如果有效的话,直接返回此值。

4.如果没有效,则调用获取access_token的接口,再次获取,并且更改数据库表中已经存在的access_token值 和 时间。

5.接第一步骤,如果access_token不存在,则调用获取access_token的接口,将获取到的数据保存在数据库表里。

正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):

{"errcode":40013,"errmsg":"invalid appid"}

封装access_token类  Token

 package com.webchat.util.weixin.model;

 /**
* token凭证 签名
*
* @author Administrator
*
*/
public class Token {
//接口访问凭证
private String accessToken;
//有效期限
private int expiresIn;
//获取token的最新时间
private long addTime;
//签名
private String ticket;
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 long getAddTime() {
return addTime;
}
public void setAddTime(long addTime) {
this.addTime = addTime;
}
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
}

接口调用请求地址

https请求方式: 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

对于https请求,我们需要一个证书信任管理器,这个管理器类需要自己定义,但需要实现X509TrustManager接口,首先定义一个MyX509TrustManager 类。

 package com.webchat.util.weixin.utils;

 import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; public class MyX509TrustManager implements X509TrustManager{ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub } public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
} }

定义一个weixin.properties 文件

#wei xin pei zhi
wx_token=mywebchat wx_appid=wx6138e8XXXXXXX
wx_secret=4364283f8XXXXXXXXXXXX

读取配置文件的工具类

 package com.webchat.util.weixin;

 import java.io.IOException;
import java.util.Properties; import org.apache.log4j.Logger;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils; /**
* 读取配置文件工具类
* @author Administrator
*
*/
public class ConfigUtil { private static final Logger LOG = Logger.getLogger(ConfigUtil.class); private static Properties config = null; /**
* 返回weixin.properties配置信息
* @param key key值
* @return value值
*/
public static String getProperty(String key) {
if (config == null) {
synchronized (ConfigUtil.class) {
if (null == config) {
try {
Resource resource = new ClassPathResource("static/weixin/weixin.properties");
config = PropertiesLoaderUtils.loadProperties(resource);
} catch (IOException e) {
LOG.error(e.getMessage(), e);
}
}
}
} return config.getProperty(key);
}
}

获取access_token的工具类:WechatConfig

 package com.webchat.util.weixin;

 import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map; import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager; import com.alibaba.fastjson.JSONObject;
import com.webchat.util.weixin.model.Token;
import com.webchat.util.weixin.utils.MyX509TrustManager; public class WebChatConfig {
// 获取access_token的接口地址(GET) 限2000(次/天)
public final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
// 创建菜单
public static final String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
// 查询自定义菜单
public static final String MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
// 删除自定义菜单
public static final String MENU_DELTE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
// 获取jsapi_ticket的接口地址(GET) 限2000(次/天)
public static final String JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
// 发送模板消息
public static final String SEND_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN"; // 微信appid
public final static String APPID = ConfigUtil.getProperty("wx_appid");
// 微信wx_secret
public final static String SECERT = ConfigUtil.getProperty("wx_secret"); public static void main(String[] args) {
System.out.println(getToken(APPID, SECERT));
} /**
* 获得Token
*
* @param appId
* @param secret
* @return
*/
public static String getToken(String appId, String secret) {
Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
return accessTocken.getAccessToken();
} /**
* 获取access_token
*
* @param appid
* 凭证
* @param appsecret
* 密钥
* @return
*/
public static Token getToken(String appid, String appsecret, long currentTime) {
Token Token = null;
// 调用接口获取token
String requestUrl = ACCESS_TOKEN_URL.replace("APPID", appid).replace("APPSECRET", appsecret);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
Token = new Token();
Token.setAccessToken(jsonObject.getString("access_token"));
// 正常过期时间是7200秒,此处设置3600秒读取一次
// 一天有获取2000次的限制 ,设置1小时获取一次AccessToken防止超出请求限制
Token.setExpiresIn(jsonObject.getIntValue("expires_in") / 2);
Token.setAddTime(currentTime);
}
return Token;
} /**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
private static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
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 httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect(); // 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
// jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
System.out.println("Weixin server connection timed out.");
} catch (Exception e) {
System.out.println("https request error:{}" + e.getMessage());
}
return jsonObject;
}
}

运行里面的main方法查看获取的值即可

好了,到此获取access_token的方法基本结束了

有什么问题请指正^.^

如果在操作过程中有问题,欢迎随时讨论^.^

其他文章关联

(一)Java开发微信公众号(一)---初识微信公众号以及环境搭建

(二)Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发

(三)Java开发微信公众号(三)---微信服务器请求消息,响应消息,事件消息以及工具处理类的封装

(四)Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理

(五)Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token

Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token的更多相关文章

  1. 微信公众号PHP简单开发流程

    原文:微信公众号PHP简单开发流程 微信公众号开发分傻瓜模式和开发者模式两种,前者不要考虑调用某些接口,只要根据后台提示傻瓜式操作即可,适用于非专业开发人员. 开发模式当然就是懂程序开发的人员使用的. ...

  2. 微信公众号平台接口开发:基础支持,获取access_token

    新建Asp.net MVC 4.0项目 WeChatSubscript是项目UI层 WeChatTools是封装操作访问公众号接口的一些方法类库 获取AccssToken 我们要的得到AccessTo ...

  3. 微信公众号平台接口开发:基础支持,获取微信服务器IP地址

    官方说明 目前看不出来这个接口有哪些具体运用,但是既然有这个接口,那我们就试试能不能用 访问接口 修改WeCharBase.cs,新增以下2个方法 public static string Serve ...

  4. JAVA版开源微信管家—JeeWx捷微3.2版本发布,支持微信公众号,微信企业号,支付窗、小程序

    JeeWx捷微3.2微信企业号升级版本发布^_^ JeeWx捷微V3.2——多触点管理平台(支持微信公众号,微信企业号,支付窗.小程序)   JeeWx捷微V3.2.0版本引入了更多新特性,支持微信公 ...

  5. JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗——JAVA版开源微信管家

    支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1——多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗)   JeeWx捷微V3.1.0版本紧跟微信小程序更新,在 ...

  6. JAVA版开源微信管家—JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗

    支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1--多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗) JeeWx捷微V3.1.0版本紧跟微信小程序更新,在原有 ...

  7. JAVA开源微信管家平台——JeeWx捷微V3.3版本发布(支持微信公众号,微信企业号,支付窗)

    JeeWx捷微V3.3版本紧跟微信小程序更新,在原有多触点版本基础上,引入了更多的新亮点:支持微信公众号.微信企业号.支付宝服务窗等多触点开发:采用微服务框架实现,可插拔可集成,轻量级开发:对小程序的 ...

  8. 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...

  9. C#版微信公众号支付|微信H5支付|微信扫码支付问题汇总及解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存.代码在文章结尾处,有需要的 ...

  10. CabloyJS的微信API对接模块:当前支持微信公众号和微信小程序

    Cabloy-微信是什么 Cabloy-微信是基于CabloyJS全栈业务开发框架开发的微信接口模块,当前整合了微信公众号和微信小程序的接口,达到开箱即用的使用效果.在Cabloy-微信的基础上,可以 ...

随机推荐

  1. git剖析

    GIT(分布式版本控制系统) Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. 1.特点 分布式相比于集中式的最大区别在于开发者可以提交到本地,每个开发者通过克隆(g ...

  2. pat乙级1059

    1.c++ 位数不够前面补零: printf("04d", i); 位数不够前面补空格(右对齐): printf("4d", i); 位数不够后面补空格(左对齐 ...

  3. python 线程的调用方式

    python 线程的调用方式 #!/usr/bin/env python #-*- coding:utf-8 -*- # author:leo # datetime:2019/5/24 9:44 # ...

  4. 对mysql快速批量修改,查重

    更新UPDATE mytable SET myfield = CASE id WHEN 1 THEN 'value' WHEN 2 THEN 'value' WHEN 3 THEN 'value' E ...

  5. angular实现全屏显示效果

  6. java面向对象思想1

    1.面向对象是面向过程而言.两者都是一种思想.面向过程:强调的是功能行为.(强调过程.动作)面向对象:将功能封装进对象,强调了具备了功能的对象.(强调对象.事物)面向对象是基于面向过程的.将复杂的事情 ...

  7. SAP 日志管理

    现在项目上自开发的dialog程序越来越多,有很多敏感数据需要像SAP标准的业务一样,能看到所有的修改日志,要想实现日志的功能,有以下几个办法: 办法一.建一个日志表,在原有表的基础上,加上日期和时间 ...

  8. phpstorm —— Xdebug 的配置和使用

    给phpstorm 配置Xdebug(Xdebug 是 PHP 的一个扩展, 用于帮助调试和开发.它包含一个与 ide 一起使用的单步调试器.它升级了 PHP 的 var_dump () 功能) 这篇 ...

  9. django 图片上传与显示

    由于图片上传的需要,学习了一波上传 1. 上传 前端代码 <form action="写上相应的定向位置" method="post" enctype=& ...

  10. thinkphp3.2.3如何只改变地址url中的某一个分隔符,其它保持不变

    今天教大家一个关于使用thinkphp3.2.3改变只改变地址url中的某一个分隔符的方法,首先大家来看看这个地址! 它的原始地址应该是/Home/Index/index/page/2.html,那我 ...