微信开发-Token处理

代码中的XXX 是自己的开发者账号申请的appid和secret


/**

 * 

 */

package cn.hofan.weixin.controllers;


import java.io.BufferedReader;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.net.URL;

import java.util.Timer;

import java.util.TimerTask;


import net.sf.json.JSONObject;


import org.apache.log4j.Logger;


import cn.hofan.spat.mvc2.ActionResult;// 公司内部MVC框架,可以使用Spring的MVC代替

import cn.hofan.spat.mvc2.annotation.Path;// 公司内部的MVC框架,可以使用Spring的MVC代替

import cn.hofan.weixin.util.HttpUtil;

import cn.hofan.weixin.util.SignUtil;


/**

 * 微信 access_token 管理

 * 

 * @author Aaron·Li

 * 

 */

@Path("token")

public class TokenController extends CoreController {

private static Logger log = Logger.getLogger(TokenController.class);

/**

* access_token 基础接口token信息

*/

private static String ACCESS_TOKEN = null;


/**

* access_token 基础接口token超时时间

*/

private static Long TOKEN_TIMEOUT = 0L;


/**

* access_token 基础接口token有效时间(毫秒)

*/

private static long ACCESS_TOKEN_TIME = 7000000;


/**

* 检查 access_token 是否超时的定时器

*/

private static Timer tirTokenCheck = null;


/**

* 定时器扫描间隔(5秒钟扫描一次)

*/

private static long timerPeriod = 5000;


/**

* 网页JSAPI接口jsapi_ticket

*/

private static String JSAPI_TICKET = null;


/**

* 网页JSAPI接口jsapi_ticket 超时时间

*/

private static Long JSAPI_TICKET_TIMEOUT = 0L;


/**

* 网页JSAPI接口jsapi_ticket 有效时间(毫秒)

*/

private static long JSAPI_TICKET_TIME = 7000000;


/**

* 基础接口 access_token 获取地址

*/

private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=XXX&secret=XXX";


/**

* 网页JSAPI接口 jsapi_ticket 获取地址

*/

private static final String JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi";


/**

* 基础接口、JSAPI接口token 集合

*/

private static JSONObject tokenInfo = new JSONObject();

/**

* @return

*/

@Path("gettoken")

public ActionResult getToken() {

try {

synchronized (tokenInfo) {

if (System.currentTimeMillis() >= TOKEN_TIMEOUT) {

initToken();

}

tokenInfo.put("sign", createSign(getParameter("url")));// 签名信息

}

} catch (Exception e) {

tokenInfo.put("error", e.getMessage());

log.error("获取 token异常", e);

e.printStackTrace();

}


return this.write(tokenInfo);

}


/**

* 初始化 JSAPI_TICKET,ACCESS_TOKEN 数据

* @throws Exception

* @throws IOException

*/

private static void initToken() throws Exception {

if (tirTokenCheck == null) {

tirTokenCheck = new Timer();

tirTokenCheck.schedule(new TimerTask() {

@Override

public void run() {

try {

initToken();

} catch (Exception e) {

log.error("定时器执行 initToken() 异常", e);

}

}

}, timerPeriod * 12, timerPeriod);// 1分钟后执行,每分钟执行一次initToken();

}


// 检查token 是否超时

// ACCESS_TOKEN 为主要的token,如果主的失效,从的也需要重新获得

if ((System.currentTimeMillis() >= TOKEN_TIMEOUT) || (System.currentTimeMillis() >= JSAPI_TICKET_TIMEOUT)) {

// 为防止服务器意外终止,先读取文件里的token信息 BEGIN

URL url = TokenController.class.getResource("/");// classes 目录

File f = null;

if (url != null) {

f = new File(url.getPath() + "/token.token");

if (!f.exists()) {

f.createNewFile();

} else {

FileReader fr = new FileReader(f);

BufferedReader br = new BufferedReader(fr);

String str = br.readLine();

br.close();

fr.close();

if (str != null && !str.isEmpty()) {

JSONObject json = JSONObject.fromObject(str);

if (json.containsKey("ACCESS_TOKEN")) {

ACCESS_TOKEN = json.getJSONObject("ACCESS_TOKEN").getString("access_token");

TOKEN_TIMEOUT = json.getJSONObject("ACCESS_TOKEN").getLong("TOKEN_TIMEOUT");

ACCESS_TOKEN_TIME = json.getJSONObject("ACCESS_TOKEN").getLong("expires_in") * 1000;// token 有效时间,服务器返回的是秒,需要转换为毫秒

JSAPI_TICKET = json.getJSONObject("JSAPI_TICKET").getString("ticket");

JSAPI_TICKET_TIMEOUT = json.getJSONObject("JSAPI_TICKET").getLong("JSAPI_TICKET_TIMEOUT");

JSAPI_TICKET_TIME = json.getJSONObject("JSAPI_TICKET").getLong("expires_in") * 1000;// token 有效时间,服务器返回的是秒,需要转换为毫秒

tokenInfo.put("ACCESS_TOKEN", json.getJSONObject("ACCESS_TOKEN"));

// JSAPI 调用需要用到的token

tokenInfo.put("JSAPI_TICKET", json.getJSONObject("JSAPI_TICKET"));

} else if (json.containsKey("error")) {

TOKEN_TIMEOUT = 0L;

}

}

}

}

// END

boolean isModify=false;// 是否更新文件信息

if (System.currentTimeMillis() >= TOKEN_TIMEOUT) {// 主token

ACCESS_TOKEN = null;

TOKEN_TIMEOUT = 0L;

long begin = System.currentTimeMillis();

setAccesToken();

long end = System.currentTimeMillis() - begin;

TOKEN_TIMEOUT = System.currentTimeMillis() + ACCESS_TOKEN_TIME - end;

isModify=true;

tokenInfo.getJSONObject("ACCESS_TOKEN").put("TOKEN_TIMEOUT", TOKEN_TIMEOUT);

}

if(System.currentTimeMillis() >= JSAPI_TICKET_TIMEOUT){// JSAPI token

JSAPI_TICKET = null;

JSAPI_TICKET_TIMEOUT = 0L;

long begin = System.currentTimeMillis();

setJsTicket();

long end = System.currentTimeMillis() - begin;

JSAPI_TICKET_TIMEOUT = System.currentTimeMillis() + JSAPI_TICKET_TIME - end;

isModify=true;

tokenInfo.getJSONObject("JSAPI_TICKET").put("JSAPI_TICKET_TIMEOUT", JSAPI_TICKET_TIMEOUT);

}

if(isModify){

// 写入文件

FileWriter fw = new FileWriter(f);

fw.flush();

fw.write(tokenInfo.toString());

fw.close();

}

}

}


/**

* 获取 ACCESS_TOKEN 并设置值

* @throws Exception

*/

private static void setAccesToken() throws Exception {

String ret = HttpUtil.get(ACCESS_TOKEN_URL, "UTF-8");

if (ret != null) {

JSONObject json = JSONObject.fromObject(ret);

if (json.containsKey("access_token")) {

ACCESS_TOKEN = json.getString("access_token");

ACCESS_TOKEN_TIME = json.getLong("expires_in") * 1000;// token 有效时间,服务器返回的是秒,需要转换为毫秒

tokenInfo.put("ACCESS_TOKEN", json);

} else if (json.containsKey("errcode")) {

throw new Exception(json.getString("errmsg"));

}

}

}


/**

* 获取 JSAPI_TICKET 并设置值

* @throws Exception

*/

private static void setJsTicket() throws Exception {

String ret = HttpUtil.get(String.format(JSAPI_TICKET_URL, ACCESS_TOKEN), "UTF-8");

if (ret != null) {

JSONObject json = JSONObject.fromObject(ret);

if (json.containsKey("ticket")) {

JSAPI_TICKET = json.getString("ticket");

JSAPI_TICKET_TIME = json.getLong("expires_in") * 1000;// token 有效时间,服务器返回的是秒,需要转换为毫秒

// JSAPI 调用需要用到的token

tokenInfo.put("JSAPI_TICKET", json);

} else if (json.containsKey("errcode")) {

throw new Exception(json.getString("errmsg"));

}

}

}


/**

* 生成签名信息

* @param requertUrl 待签名的url

* @return

*/

private JSONObject createSign(String requertUrl){

return JSONObject.fromObject(SignUtil.sign(JSAPI_TICKET, requertUrl));

}

@Override

protected void finalize() throws Throwable {

if (tirTokenCheck != null) {

tirTokenCheck.cancel();

tirTokenCheck = null;

}

super.finalize();

}


/**

* 获得基础接口 token

* @return

*/

public synchronized static String getACCESS_TOKEN() {

if(ACCESS_TOKEN==null){

try {

initToken();

} catch (Exception e) {

e.printStackTrace();

}

}

return ACCESS_TOKEN;

}

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值