参考:https://www.cnblogs.com/liuhongfeng/p/4848851.html

一:介绍。

接口调用请求说明

  1. http请求方式: GET
  2. 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数据包给公众号:

  1. {"access_token":"ACCESS_TOKEN","expires_in":7200}
参数 说明
access_token 获取到的凭证
expires_in 凭证有效时间,单位:秒

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

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

我们可以直接

二:封装基本类。

  1. package com.wx.bean;
  2.  
  3. /**
  4. * 封装token类。
  5. */
  6. public class AccessToken {
  7. //获取到的凭证
  8. private String accessToken;
  9. //凭证有效时间,单位:秒
  10. private int expiresin;
  11.  
  12. public String getAccessToken() {
  13. return accessToken;
  14. }
  15.  
  16. public void setAccessToken(String accessToken) {
  17. this.accessToken = accessToken;
  18. }
  19.  
  20. public int getExpiresin() {
  21. return expiresin;
  22. }
  23.  
  24. public void setExpiresin(int expiresin) {
  25. this.expiresin = expiresin;
  26. }
  27. }

三:如何获取token。

一:直接访问浏览器。替换自己的appid和secret。

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxb05f6ccd16cf38fb&secret=b50d2e0911e255f4723f93d73233b04f

二:编写程序,模拟https连接,获得token。

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

  1. package com.wx.util;
  2.  
  3. import java.security.cert.CertificateException;
  4. import java.security.cert.X509Certificate;
  5. import javax.net.ssl.X509TrustManager;
  6.  
  7. /**
  8. * 类名: MyX509TrustManager </br>
  9. * 描述: 信任管理器 </br>
  10. * 开发人员: 六 </br>
  11. * 发布版本:V1.0 </br>
  12. */
  13. public class MyX509TrustManager implements X509TrustManager {
  14.  
  15. // 检查客户端证书
  16. public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
  17. }
  18.  
  19. // 检查服务器端证书
  20. public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
  21. }
  22.  
  23. // 返回受信任的X509证书数组
  24. public X509Certificate[] getAcceptedIssuers() {
  25. return null;
  26. }
  27. }

微信服务器返回的是json数据,如何从json里面解析出来的值?所以要转换成Java对象。

封装一个通用的Util。

  1. package com.wx.util;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.io.OutputStream;
  7. import java.net.ConnectException;
  8. import java.net.URL;
  9.  
  10. import javax.net.ssl.HttpsURLConnection;
  11. import javax.net.ssl.SSLContext;
  12. import javax.net.ssl.SSLSocketFactory;
  13. import javax.net.ssl.TrustManager;
  14.  
  15. import com.alibaba.fastjson.JSONException;
  16. import com.alibaba.fastjson.JSONObject;
  17. import com.wx.bean.AccessToken;
  18.  
  19. import org.slf4j.Logger;
  20. import org.slf4j.LoggerFactory;
  21.  
  22. /**
  23. * 类名: CommonUtil </br>
  24. * 描述: 通用工具类 </br>
  25. * 开发人员: 六 </br>
  26. * 创建时间: 2018-8-9 </br>
  27. * 发布版本:V1.0 </br>
  28. */
  29. public class CommonUtil {
  30. private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
  31.  
  32. // 凭证获取(GET)
  33. public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
  34.  
  35. /**
  36. * 发送https请求
  37. *
  38. * @param requestUrl 请求地址
  39. * @param requestMethod 请求方式(GET、POST)
  40. * @param outputStr 提交的数据
  41. * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
  42. */
  43. public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
  44. JSONObject jsonObject = null;
  45. try {
  46. // 创建SSLContext对象,并使用我们指定的信任管理器初始化
  47. TrustManager[] tm = { new MyX509TrustManager() };
  48. SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
  49. sslContext.init(null, tm, new java.security.SecureRandom());
  50. // 从上述SSLContext对象中得到SSLSocketFactory对象
  51. SSLSocketFactory ssf = sslContext.getSocketFactory();
  52.  
  53. URL url = new URL(requestUrl);
  54. HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
  55. conn.setSSLSocketFactory(ssf);
  56.  
  57. conn.setDoOutput(true);
  58. conn.setDoInput(true);
  59. conn.setUseCaches(false);
  60. // 设置请求方式(GET/POST)
  61. conn.setRequestMethod(requestMethod);
  62.  
  63. // 当outputStr不为null时向输出流写数据
  64. if (null != outputStr) {
  65. OutputStream outputStream = conn.getOutputStream();
  66. // 注意编码格式
  67. outputStream.write(outputStr.getBytes("UTF-8"));
  68. outputStream.close();
  69. }
  70.  
  71. // 从输入流读取返回内容
  72. InputStream inputStream = conn.getInputStream();
  73. InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
  74. BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
  75. String str = null;
  76. StringBuffer buffer = new StringBuffer();
  77. while ((str = bufferedReader.readLine()) != null) {
  78. buffer.append(str);
  79. }
  80.  
  81. // 释放资源
  82. bufferedReader.close();
  83. inputStreamReader.close();
  84. inputStream.close();
  85. inputStream = null;
  86. conn.disconnect();
  87. jsonObject = JSONObject.parseObject(buffer.toString());
  88. } catch (ConnectException ce) {
  89. log.error("连接超时:{}", ce);
  90. } catch (Exception e) {
  91. log.error("https请求异常:{}", e);
  92. }
  93. return jsonObject;
  94. }
  95.  
  96. /**
  97. * 获取接口访问凭证
  98. *
  99. * @param appid 凭证
  100. * @param appsecret 密钥
  101. * @return
  102. */
  103. public static AccessToken getToken(String appid, String appsecret) {
  104. AccessToken token = null;
  105. String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
  106. // 发起GET请求获取凭证
  107. JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
  108.  
  109. if (null != jsonObject) {
  110. try {
  111. token = new AccessToken();
  112. token.setAccessToken(jsonObject.getString("access_token"));
  113. token.setExpiresin(jsonObject.getInteger("expires_in"));
  114. } catch (JSONException e) {
  115. token = null;
  116. // 获取token失败
  117. log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
  118. }
  119. }
  120. return token;
  121. }
  122. }

然后写个token的测试类就可以获取到token

  1. import java.io.BufferedReader;
  2. import java.io.InputStream;
  3. import java.io.InputStreamReader;
  4. import java.net.URL;
  5.  
  6. import javax.net.ssl.HttpsURLConnection;
  7. import javax.net.ssl.SSLContext;
  8. import javax.net.ssl.SSLSocketFactory;
  9. import javax.net.ssl.TrustManager;
  10.  
  11. import com.wx.bean.AccessToken;
  12. import com.wx.util.CommonUtil;
  13. import com.wx.util.MyX509TrustManager;
  14. import org.junit.Test;
  15.  
  16. public class TokenTest {
  17.  
  18. @Test
  19. public void testGetToken1() throws Exception {
  20. String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxb05f6ccd16cf38fb&secret=b50d2e0911e255f4723f93d73233b04f";
  21. // 建立连接
  22. URL url = new URL(tokenUrl);
  23. HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
  24.  
  25. // 创建SSLContext对象,并使用我们指定的信任管理器初始化
  26. TrustManager[] tm = { new MyX509TrustManager() };
  27. SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
  28. sslContext.init(null, tm, new java.security.SecureRandom());
  29. // 从上述SSLContext对象中得到SSLSocketFactory对象
  30. SSLSocketFactory ssf = sslContext.getSocketFactory();
  31.  
  32. httpUrlConn.setSSLSocketFactory(ssf);
  33. httpUrlConn.setDoOutput(true);
  34. httpUrlConn.setDoInput(true);
  35.  
  36. // 设置请求方式(GET/POST)
  37. httpUrlConn.setRequestMethod("GET");
  38.  
  39. // 取得输入流
  40. InputStream inputStream = httpUrlConn.getInputStream();
  41. InputStreamReader inputStreamReader = new InputStreamReader(
  42. inputStream, "utf-8");
  43. BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
  44. // 读取响应内容
  45. StringBuffer buffer = new StringBuffer();
  46. String str = null;
  47. while ((str = bufferedReader.readLine()) != null) {
  48. buffer.append(str);
  49. }
  50. bufferedReader.close();
  51. inputStreamReader.close();
  52. // 释放资源
  53. inputStream.close();
  54. httpUrlConn.disconnect();
  55. // 输出返回结果
  56. System.out.println(buffer);
  57. }
  58.  
  59. @Test
  60. public void testGetToken2() {
  61. AccessToken token = CommonUtil.getToken("appID","appsecret");
  62. System.out.println("access_token:"+token.getAccessToken());
  63. System.out.println("expires_in:"+token.getExpiresin());
  64. }
  65. }

在项目中的其他类,可以通过调用 TokenThread.accessToken.getToken() 来得到接口访问凭证access_token。

四:问题:但是如何让这个保存工作隔7200 秒进行保存呢?

方案:

做一个定时器。

做一个web实现监听器。

定期获取并存储access_token的流程为:

Web服务器启动时就加载一个Servlet,在Servlet的init()方法中启动一个线 程,在线程的run()方法中通过死循环+Thread.sleep()的方式定期获取access_token,然后将获取到的 access_token保存在public static修饰的变量中。

在工程中创建一个InitServlet类,该类的代码如下:

InitServlet类只重写了init()方法,并没有重写doGet()和doPost()两个方法,

因为我们并不打算让 InitServlet来处理访问请求。

  1. package com.wx.servlet;
  2.  
  3. import javax.servlet.ServletException;
  4. import javax.servlet.annotation.WebInitParam;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7.  
  8. import com.wx.util.CommonUtil;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11.  
  12. /**
  13. * 类名: InitServlet </br>
  14. * 描述: 初始化servlet </br>
  15. * 包:com.wx.servlet</br>
  16. * 开发人员: 六 </br>
  17. * 创建时间: 2018-8-9 </br>
  18. * 发布版本:V1.0 </br>
  19. */
  20.  
  21. @WebServlet(
  22. name = "AccessTokenServlet",
  23. urlPatterns = {"/AccessTokenServlet"},
  24. loadOnStartup = 1,
  25. initParams = {
  26. @WebInitParam(name = "appId", value = "wxb05f6ccd16cf38fb"),
  27. @WebInitParam(name = "appSecret", value = "b50d2e0911e255f4723f93d73233b04f")
  28. })
  29. public class InitServlet extends HttpServlet {
  30. private static final long serialVersionUID = 1L;
  31. private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
  32.  
  33. public void init() throws ServletException {
  34. System.out.println("启动得到Token的Servlet");
  35. // 获取web.xml中配置的参数
  36. TokenThread.appid = getInitParameter("appId");
  37. TokenThread.appsecret = getInitParameter("appSecret");
  38.  
  39. log.info("weixin api appid:{}", TokenThread.appid);
  40. log.info("weixin api appsecret:{}", TokenThread.appsecret);
  41.  
  42. // 未配置appid、appsecret时给出提示
  43. if ("".equals(TokenThread.appid) || "".equals(TokenThread.appsecret)) {
  44. log.error("appid and appsecret configuration error, please check carefully.");
  45. } else {
  46. // 启动定时获取access_token的线程
  47. new Thread(new TokenThread()).start();
  48. }
  49. }
  50. }
  1. package com.wx.servlet;
  2.  
  3. import com.wx.bean.AccessToken;
  4. import com.wx.bean.Ttoken;
  5. import com.wx.util.CommonUtil;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8.  
  9. /**
  10. * 类名: TokenThread </br>
  11. * 描述: 定时获取微信access_token的线程 </br>
  12. * 开发人员: 六 </br>
  13. * 创建时间: 2018-8-9 </br>
  14. * 发布版本:V1.0 </br>
  15. */
  16. public class TokenThread implements Runnable {
  17. private static Logger log = LoggerFactory.getLogger(TokenThread.class);
  18.  
  19. /* @Autowired
  20. TtokenMapper ttokenMapper;
  21. */
  22. // 第三方用户唯一凭证
  23. public static String appid = "";
  24. // 第三方用户唯一凭证密钥
  25. public static String appsecret = "";
  26. public static AccessToken accessToken = null;
  27.  
  28. public void run() {
  29. while (true) {
  30. try {
  31. accessToken = CommonUtil.getToken(appid, appsecret);
  32. if (null != accessToken) {
  33. //调用存储到数据库
  34. System.out.println("Token的值:"+accessToken);
  35. Ttoken ttoken = new Ttoken(3,accessToken.getAccessToken(),accessToken.getExpiresin(),null);
  36. System.out.println("Ttoken的值:"+ttoken);
  37. //ttokenMapper.select();
  38. //ttokenMapper.save(ttoken);
  39. log.info("获取access_token成功,有效时长{}秒 token:{}", accessToken.getExpiresin(), accessToken.getAccessToken());
  40. // 休眠7000秒
  41. Thread.sleep((accessToken.getExpiresin() - 200)*1000);
  42. } else {
  43. // 如果access_token为null,60秒后再获取
  44. Thread.sleep(60 * 1000);
  45. }
  46. } catch (InterruptedException e) {
  47. try {
  48. Thread.sleep(60 * 1000);
  49. } catch (InterruptedException e1) {
  50. log.error("{}", e1);
  51. }
  52. log.error("{}", e);
  53. }
  54. }
  55. }
  56. }

代码中通过while(true){}构造了一个死循环(永久执行);

调用公众平台接口获取access_token;

让线程休眠7000秒再运行,即每隔7000秒获取一次access_token,保证access_token永不失效。

微信公众号开发(二)获取access_token的更多相关文章

  1. Java微信公众号开发----定时获取access_token并保存到redis中

    本人原本是想做微信公众号菜单的创建修改删除等操作的,但是发现需要access_token,通过阅读文档,发现文档要求有以下几点: 1.access_token 获取后有效期是2小时 2.access_ ...

  2. 微信公众号开发及时获取当前用户Openid及注意事项

    目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 (四)微信公众号开发之网页授权获取用户基本信息 (五)微信公众号开发之网页中及 ...

  3. 微信公众号开发系列-获取微信OpenID

    在微信开发时候在做消息接口交互的时候须要使用带微信加密ID(OpenId),下面讲讲述2中类型方式获取微信OpenID.接收事件推送方式和网页授权获取用户基本信息方式获取. 1.通过接收被动消息方式获 ...

  4. tp6微信公众号开发者模式获取access_token

    1:config 文件下新建一个文件wechat.php,将个人id和秘钥写入配置文件 网址: https://developers.weixin.qq.com/doc/offiaccount/Bas ...

  5. 微信公众号开发之获取微信用户的openID

    (注:openID同一用户同一应用唯一,UnionID同一用户不同应用唯一.不同应用指微信开放平台下的不同用户.) 1.  申请测试号(获得appID.appsecret) 2.  填写服务器配置并验 ...

  6. 微信公众号开发前端获取openId

    参考 https://blog.csdn.net/qq_35430000/article/details/79299529

  7. 微信公众号开发用户授权登录报"redirect_uri 参数错误"错误

    微信公众号开发 授权获取用户信息报错 "redirect_uri 参数错误" 出现这个情况要检查下 微信公众号配置了网页授权域名 在这里配置微信公众号redirect_uri中的域 ...

  8. C#微信公众号开发-高级接口-之网页授权oauth2.0获取用户基本信息(二)

    C#微信公众号开发之网页授权oauth2.0获取用户基本信息(一) 中讲解了如果通过微信授权2.0snsapi_base获取已经关注用户的基本信息,然而很多情况下我们经常需要获取非关注用户的信息,方法 ...

  9. 微信公众号开发(三)获取access_token

    微信公众号开发(三)获取access_token 1.说明 access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存.acce ...

  10. 微信公众号开发之网页中及时获取当前用户Openid及注意事项

    目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 (四)微信公众号开发之网页授权获取用户基本信息 (五)微信公众号开发之网页中及 ...

随机推荐

  1. 014-elasticsearch5.4.3【五】-搜索API【三】复合查询boolQuery、constantScoreQuery、disMaxQuery

    一.概述 复合查询包装其他复合或叶子查询,以组合其结果和分数,更改其行为,或从查询切换到筛选器上下文. 1.1.constantScoreQuery 包含另一个查询但在过滤器上下文中执行的查询.所有匹 ...

  2. VMware 虚拟化编程(5) — VixDiskLib 虚拟磁盘库详解之一

    目录 目录 前文列表 VixDiskLib 虚拟磁盘库 虚拟磁盘数据的传输方式 Transport Methods VixDiskLib_ListTransportModes 枚举支持的传输模式 Vi ...

  3. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_08 转换流_4_OutputStreamWriter介绍&代码实现

    父类是Write 需要抛出异常 声明为它的父类IO异常也是可以的 不指定 默认就是utf-8格式的 两个汉字 6个字节 GBK格式 打开文件的位置用文本打开

  4. WinForm 皮肤,自定义控件WinForm.UI

    WinForm.UI https://github.com/YuanJianTing/WinForm.UI WinForm 皮肤,自定义控件 使用方式: BaseForm: public partia ...

  5. spring mvc 接受数组

    @RequestParam(value = "customerIds[]")Integer[] customerIds 加上 requestParam   value设置为 &qu ...

  6. 【ABAP系列】SAP ABAP解析XML的示例程序

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP解析XML的示例 ...

  7. Django报错[WinError 123] 文件名、目录名或卷标语法不正确。: '<frozen importlib._bootstrap

    当你在项目文件中删除app对应的文件 却没有在项目url中删除之前配置的路径 也没有删除setting中配置的app 那么就会报错[WinError 123] 文件名.目录名或卷标语法不正确.: '& ...

  8. JavaSE编码试题强化练习4

    1.编写一个Worker类,为Worker类添加相应的代码,使得Worker对象能正确放入TreeSet中.并编写相应的测试代码. /** * Worker类 */ public class Work ...

  9. hdu-4289.control(最小割 + 拆点)

    Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  10. POJ-2528 Mayor's posters (离散化, 线段树)

    题目传送门: POJ-2528 题意就是在一个高度固定的墙面上贴高度相同宽度不同的海报,问贴到最后还能看到几张?本质上是线段树区间更新问题,但是要注意的是题中所给数据范围庞大,直接搞肯定会搞出问题,所 ...