微信公众号开发之获取access_token

获取access_token可参照微信公众平台之获取access_token

因为access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。而且每天获取的次数是有限制的,所以可以做一个缓存。缓存方式根据自己需求而定。

我的具体代码实现如下:

AccessToken.java

public class AccessToken {
    private String id;
    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 String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
    
}

AccessTokenCache.java

/**
 * 单例设计模式 缓存 accessToken expires_in
 */
public class AccessTokenCache {
    //缓存accessToken的Map,map中包含accessToken,expiresIn和缓存的时间戳time
    private Map<String, String> map = new HashMap<String,String>();
    private static AccessTokenCache accessTokenCache = null;

    private AccessTokenCache() { }
    // 静态工厂方法
    public static AccessTokenCache getInstance() {
        if (accessTokenCache == null) {
            accessTokenCache = new AccessTokenCache();
        }
        return accessTokenCache;
    }

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    /**
     * 获取 accessToken expires_in
     * @param appid 第三方用户唯一凭证
     * @param appsecret 第三方用户唯一凭证密钥
     * @return
     */
    public Map<String,Object> getAcessTokenAndExpiresIn(String appid, String appsecret) {
        Map<String,Object> result = new HashMap<String,Object>();
        AccessTokenCache accessTokenCache = AccessTokenCache.getInstance();
        Map<String, String> map = accessTokenCache.getMap();
        String time = map.get("time");
        String accessToken = map.get("access_token");
        String expiresIn = map.get("expires_in");
        Long nowDate = new Date().getTime();
        if (accessToken != null && time != null && expiresIn!=null) {
            //这里设置过期时间为微信规定的过期时间减去5分钟
            int outTime = (Integer.parseInt(expiresIn)-300) * 1000;
            if (nowDate - Long.parseLong(time) < outTime) {
                System.out.println("-----从缓存读取access_token:" + accessToken);
                //从缓存中拿数据为返回结果赋值
                result.put("access_token", accessToken);
                result.put("expires_in", expiresIn);
            }
        } else {
            AccessToken info = WeiXinUtil.getAccessToken(appid, appsecret);//实际中这里要改为你自己调用微信接口去获取accessToken和expires_in
            System.out.println("-----通过调用微信接口获取access_token:" + info.getAccessToken());
            //将信息放置缓存中
            map.put("time", nowDate + "");
            map.put("access_token", info.getAccessToken());
            map.put("expires_in", info.getExpiresIn()+"");
            //为返回结果赋值
            result.put("access_token", info.getAccessToken());
            result.put("expires_in", info.getExpiresIn());
        }
        return result;
    }
}

调用微信接口获取accessToken的方法。WeiXinUtil.java

// 获取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 class WeiXinUtil {
    private static Logger log = LoggerFactory.getLogger(WeiXinUtil.class);
    /**
     * 获取access_token
     * @param appid 凭证
     * @param appsecret 密钥
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret) {
        AccessToken accessToken = null;
        String requestUrl = WXConstants.access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        // 如果请求成功
        if (null != jsonObject) {
            try {
                accessToken = new AccessToken();
                accessToken.setAccessToken(jsonObject.getString("access_token"));
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
            } catch (JSONException e) {
                accessToken = null;
                // 获取token失败
                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return accessToken;
    }
    /**
     * 描述:  发起https请求并获取结果
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public 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.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("Weixin server connection timed out.");
        } catch (Exception e) {
            log.error("https request error:{}", e);
        }
        return jsonObject;
    }
}
MyX509TrustManager.java
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
 * 编写程序,模拟https连接,获得token,对于https请求,我们需要一个证书信任管理器,这个管理器类需要自己定义,但需要实现X509TrustManager接口
 * 描述: 证书信任管理器(用于https请求)
 */
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;
    }
}
// 可在main方法中调用AccessTokenCache获取access_token
Map<String,Object> map = AccessTokenCache.getInstance().getAcessTokenAndExpiresIn(WXConstants.APPID, WXConstants.APPSECRET);
String accessToken = (String)map.get("access_token");

控制台打印结果:


猜你喜欢

转载自blog.csdn.net/qq_23543983/article/details/80222702