zoukankan      html  css  js  c++  java
  • 微信公众号开发(二)获取access_token

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

    一:介绍。

    接口调用请求说明

    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"}

    我们可以直接

    二:封装基本类。

    package com.wx.bean;
    
    /**
     * 封装token类。
     */
    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;
        }
    }

    三:如何获取token。

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

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

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

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

    package com.wx.util;
    
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import javax.net.ssl.X509TrustManager;
    
    /**
     * 类名: MyX509TrustManager </br>
     * 描述: 信任管理器 </br>
     * 开发人员: 六 </br>
     * 发布版本:V1.0  </br>
     */
    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;
        }
    }

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

    封装一个通用的Util。

    package com.wx.util;
    
    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 javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    
    import com.alibaba.fastjson.JSONException;
    import com.alibaba.fastjson.JSONObject;
    import com.wx.bean.AccessToken;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    
    /**
     * 类名: CommonUtil </br>
     * 描述: 通用工具类 </br>
     * 开发人员: 六 </br>
     * 创建时间:  2018-8-9 </br>
     * 发布版本:V1.0  </br>
     */
    public class CommonUtil {
        private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
    
        // 凭证获取(GET)
        public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    
        /**
         * 发送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();
                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.parseObject(buffer.toString());
            } catch (ConnectException ce) {
                log.error("连接超时:{}", ce);
            } catch (Exception e) {
                log.error("https请求异常:{}", e);
            }
            return jsonObject;
        }
    
        /**
         * 获取接口访问凭证
         *
         * @param appid 凭证
         * @param appsecret 密钥
         * @return
         */
        public static AccessToken getToken(String appid, String appsecret) {
            AccessToken token = null;
            String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
            // 发起GET请求获取凭证
            JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
    
            if (null != jsonObject) {
                try {
                    token = new AccessToken();
                    token.setAccessToken(jsonObject.getString("access_token"));
                    token.setExpiresin(jsonObject.getInteger("expires_in"));
                } catch (JSONException e) {
                    token = null;
                    // 获取token失败
                    log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return token;
        }
    }

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

    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.URL;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    
    import com.wx.bean.AccessToken;
    import com.wx.util.CommonUtil;
    import com.wx.util.MyX509TrustManager;
    import org.junit.Test;
    
    
    
    public class TokenTest {
    
        @Test
        public void testGetToken1() throws Exception {
            String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxb05f6ccd16cf38fb&secret=b50d2e0911e255f4723f93d73233b04f";
            // 建立连接
            URL url = new URL(tokenUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
    
            // 创建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();
    
            httpUrlConn.setSSLSocketFactory(ssf);
            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
    
            // 设置请求方式(GET/POST)
            httpUrlConn.setRequestMethod("GET");
    
            // 取得输入流
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(
                    inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            // 读取响应内容
            StringBuffer buffer = new StringBuffer();
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            httpUrlConn.disconnect();
            // 输出返回结果
            System.out.println(buffer);
        }
    
        @Test
        public void testGetToken2() {
            AccessToken token = CommonUtil.getToken("appID","appsecret");
            System.out.println("access_token:"+token.getAccessToken());
            System.out.println("expires_in:"+token.getExpiresin());
        }
    }

    在项目中的其他类,可以通过调用 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来处理访问请求。

    package com.wx.servlet;
    
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebInitParam;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    
    import com.wx.util.CommonUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    
    /**
     * 类名: InitServlet </br>
     * 描述: 初始化servlet </br>
     * 包:com.wx.servlet</br>
     * 开发人员: 六 </br>
     * 创建时间:  2018-8-9 </br>
     * 发布版本:V1.0  </br>
     */
    
    @WebServlet(
            name = "AccessTokenServlet",
            urlPatterns = {"/AccessTokenServlet"},
            loadOnStartup = 1,
            initParams = {
                    @WebInitParam(name = "appId", value = "wxb05f6ccd16cf38fb"),
                    @WebInitParam(name = "appSecret", value = "b50d2e0911e255f4723f93d73233b04f")
            })
    public class InitServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
        private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
    
        public void init() throws ServletException {
            System.out.println("启动得到Token的Servlet");
            // 获取web.xml中配置的参数
            TokenThread.appid = getInitParameter("appId");
            TokenThread.appsecret = getInitParameter("appSecret");
    
            log.info("weixin api appid:{}", TokenThread.appid);
            log.info("weixin api appsecret:{}", TokenThread.appsecret);
    
            // 未配置appid、appsecret时给出提示
            if ("".equals(TokenThread.appid) || "".equals(TokenThread.appsecret)) {
                log.error("appid and appsecret configuration error, please check carefully.");
            } else {
                // 启动定时获取access_token的线程
                new Thread(new TokenThread()).start();
            }
        }
    }
    package com.wx.servlet;
    
    
    import com.wx.bean.AccessToken;
    import com.wx.bean.Ttoken;
    import com.wx.util.CommonUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * 类名: TokenThread </br>
     * 描述: 定时获取微信access_token的线程 </br>
     * 开发人员: 六 </br>
     * 创建时间:  2018-8-9 </br>
     * 发布版本:V1.0  </br>
     */
    public class TokenThread implements Runnable {
        private static Logger log = LoggerFactory.getLogger(TokenThread.class);
    
       /* @Autowired
        TtokenMapper ttokenMapper;
    */
        // 第三方用户唯一凭证
        public static String appid = "";
        // 第三方用户唯一凭证密钥
        public static String appsecret = "";
        public static AccessToken accessToken = null;
    
        public void run() {
            while (true) {
                try {
                    accessToken = CommonUtil.getToken(appid, appsecret);
                    if (null != accessToken) {
                        //调用存储到数据库
                        System.out.println("Token的值:"+accessToken);
                        Ttoken ttoken = new Ttoken(3,accessToken.getAccessToken(),accessToken.getExpiresin(),null);
                        System.out.println("Ttoken的值:"+ttoken);
                        //ttokenMapper.select();
                        //ttokenMapper.save(ttoken);
                        log.info("获取access_token成功,有效时长{}秒 token:{}", accessToken.getExpiresin(), accessToken.getAccessToken());
                        // 休眠7000秒
                        Thread.sleep((accessToken.getExpiresin() - 200)*1000);
                    } else {
                        // 如果access_token为null,60秒后再获取
                        Thread.sleep(60 * 1000);
                    }
                } catch (InterruptedException e) {
                    try {
                        Thread.sleep(60 * 1000);
                    } catch (InterruptedException e1) {
                        log.error("{}", e1);
                    }
                    log.error("{}", e);
                }
            }
        }
    }

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

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

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

  • 相关阅读:
    23-10 条件查询
    22-9 聚合函数
    关系抽取snowball
    关系抽取bootstrap
    NER
    GPT
    因果卷积 空洞卷积
    XL-NET
    transoformer-XL
    transoformer
  • 原文地址:https://www.cnblogs.com/bulrush/p/9447550.html
Copyright © 2011-2022 走看看