微信公众号使用cookie存储access_token导致的一直重新获取超次数问题

微信公众号使用cookie存储access_token导致的一直重新获取超次数问题

       最近做了一个项目,包含微信公众号的推送告警功能,在看着微信开发文档的基础上写完了,大概的就是获取access_token、并与openId、template_id和告警内容结合来实现对用户的推送提醒。但是access_token有2小时的过期时限,且有获取次数的限制。所以在获取完之后,我便将其放入到cookies之中,并定义2小时的过期期限,判断是重新获取还是使用原有的access_token。

       在本地tomcat中测试毫无问题,以为已经解决了这个功能点。想想还是太天真。有一天突然发现怎么前一天的告警在下午2点多就不在告警,进入公众号里面却有数据。满怀忐忑的打开微信公众平台,果然2000次的次数已经爆表!

打开后台的调试日志,发现每次都是重新获取了access_token,而没有使用cookie中的access_token。

在这里插入图片描述

       根据前几次的cookies读写错误问题,让我彻底的放弃cookies操作,使用文件进行对access_token的存储。

       以下为公众号推送与access_token文件存取的代码(获取accesstoken方法不是重点,这里便不再累述了):

@RestController
public class PushController  extends BaseController{
	private static Logger log = LoggerFactory.getLogger(PushController.class);

    @RequestMapping("/alarm/push")
    public String alarm_push(HttpServletRequest request,HttpServletResponse response,@RequestBody WechatAlarmPush wechatAlarmPush) throws Exception  { 
    	String result = null;
    	String stationName = wechatAlarmPush.getStationName();
    	String alarmDesc = wechatAlarmPush.getAlarmDesc();
    	String alarmCode = wechatAlarmPush.getAlarmCode();
    	String alarmDateTime = wechatAlarmPush.getAlarmDateTime();
    	String alarmEndDateTime  = "";
    	if(!StringUtils.isEmpty(wechatAlarmPush.getAlarmEndDateTime())) {
    		alarmEndDateTime = wechatAlarmPush.getAlarmEndDateTime();
    	}
    	String openId = wechatAlarmPush.getOpenId();
    	Integer stationId = wechatAlarmPush.getStationId();
    	//Integer systemType = wechatAlarmPush.getSystemType();
    	Integer systemType = 1;
    	ArrayList<Devices> devices = wechatAlarmPush.getDevices();
    	String deviceNames = "";
    	Integer deviceId = 0;
    	for (int i = 0; i < devices.size(); i++) {
    		String deviceName = devices.get(i).getName();
    		deviceId = devices.get(i).getId();
    		if(i != devices.size()-1) {
    			deviceNames = deviceNames+deviceName+"、";
    		}else {
    			deviceNames = deviceNames+deviceName;
    		}
		}
    	Appkey appkey = new Appkey();
    	String appId = appkey.getWechatappid();
		String appsecret = appkey.getWechatappsecret();
		String alarm_template_id = appkey.getalarm_template_id();
    	String access_token = "no_token";
    	String server_url = appkey.getserver_url();
    	String url = "";
    	String unionid ="";
    	url = "跳转的链接";
		alarmDesc = alarmDesc+"("+alarmCode+")";
    	Map<String,Cookie> cookieMap = ReadCookieMap(request);
		log.debug("push access_token cookieMap:" + cookieMap);
		access_token = getOldaccesstoken(appId,appsecret,1);
        result = push_alarm(response,openId,alarm_template_id,url,alarmDesc,alarmDateTime,alarmEndDateTime,deviceNames,stationName,access_token);
		return result;
    }
    
  //获得已经有的access_token
  	public String getOldaccesstoken(String appId,String appsecret,Integer type) {
		final long MAX_TIME = 7200 * 1000;
  		Gson gson=new Gson();
  		String Accesstoken=null;
  		//1.创建一个路径对象,用来保存access_token
  		File file = new File("temp_access_token.temp");
  		//2.如果文件不存在
  		try {
  		if(!file.exists()) {
  			//2.1创建文件
  			file.createNewFile();
  		}
  			//2.2如果文件大小等于0,说明第一次使用,存入Access_token,type为0是重置
  		if (file.length() == 0||type == 0) {
  			String assccesstoken = WeChatAPIProxy.getAccessToken(appId,appsecret);
        	System.out.println("重新获取token是"+assccesstoken);
        	JSONObject data = JSONObject.fromObject(assccesstoken);
        	Integer errcode = 0;
        	errcode = data.optInt("errcode");
        	if(errcode == 0) {
        		Accesstoken = data.optString("access_token");
        		FileOutputStream fos = new FileOutputStream(file, false);
	            //2.2.3实例化一个AccessToken,将access_token和当前时间存进去
        		PushAccessToken accessToken=new PushAccessToken();
	            accessToken.setAccessToken(Accesstoken);
	            accessToken.setExpiresIn(System.currentTimeMillis() + "");
	            //2.2.4转换成json格式的字符串
	            String json = gson.toJson(accessToken);
		        //2.2.5将字符串写入到file文件中,getBytes()将字符串转换成字节数组byte[]
		        fos.write((json).getBytes());
		        fos.close();
		        //2.2.6 返回token值
        	}
	        return Accesstoken;
  		}else {
  		        	//2.3如果文件大小不等于0
  		            //2.3.1实例化FileInputStream对象
  		            FileInputStream fis = new FileInputStream(file);
  		            //2.3.2定义一个数组
  		            byte[] b = new byte[2048];
  		            //2.3.3InputStreamReader的int read(char []cbuf);//将读取到的字符存到数组中。返回读取的字符数。
  		            int len = fis.read(b);
  		            //2.3.4读取到的文件内容
  		            String mJsonAccess_token = new String(b, 0, len);
  		            //2.3.5将json字符串转换成AccessToken类的对象
  		          PushAccessToken accessToken = gson.fromJson(mJsonAccess_token,PushAccessToken.class);
  		            //2.3.6如果expires_in不等于零,进行比较
  		            if (accessToken.getExpiresIn() != null) {
  		            	//获取存入时的时间毫秒数
  		                long saveTime = Long.parseLong(accessToken.getExpiresIn());
  		                //获取现在时间的毫秒数
  		                long nowTime = System.currentTimeMillis();
  		                //做差值
  		                long remianTime = nowTime - saveTime;
  		                //如果差值小于MAX_TIME,token值
  		                if (remianTime < MAX_TIME) {
  		                	/*AccessToken at = gson.fromJson(mJsonAccess_token,AccessToken.class);*/
  		                	Accesstoken = accessToken.getAccessToken();
  		                	fis.close();
  		                	//返回token
  		                	return Accesstoken;
  		                } else {
  		                	//如果大于MAX_TIME,重新获取token
  		                	String assccesstoken = WeChatAPIProxy.getAccessToken(appId,appsecret);
	  		              	JSONObject data = JSONObject.fromObject(assccesstoken);
	  		              	Integer errcode = 0;
	  		              	errcode = data.optInt("errcode");
	  		              	if(errcode == 0) {
	  		              		Accesstoken = data.optString("access_token");
	  		              		FileOutputStream fos = new FileOutputStream(file, false);
	  		      	            //2.2.3实例化一个AccessToken,将access_token和当前时间存进去
	  		              		PushAccessToken accessToken1=new PushAccessToken();
	  		      	            accessToken1.setAccessToken(Accesstoken);
	  		      	            accessToken1.setExpiresIn(System.currentTimeMillis() + "");
	  		      	            //2.2.4转换成json格式的字符串
	  		      	            String json = gson.toJson(accessToken1);
	  		      		        //2.2.5将字符串写入到file文件中,getBytes()将字符串转换成字节数组byte[]
	  		      		        fos.write((json).getBytes());
	  		      		        fos.close();
	  		      		        //2.2.6 返回token值
	  		              	}
	  		      	        return Accesstoken;
	  		                }
  		            }
  		            fis.close();
  		       }
  			} catch (IOException e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
  			return null;
  	}
    
    public String push_alarm(HttpServletResponse response,String openId,String alarm_template_id,String url,String alarmDesc,String alarmDateTime,String alarmEndDateTime,String deviceNames,String stationName,String access_token) {
    	String result = null;
    	JSONObject json = new JSONObject();
		json.put("touser", openId);
		json.put("template_id", alarm_template_id);
		json.put("url", url);
		JSONObject dataJson = new JSONObject();
		PushTemplateData first = new PushTemplateData();
		if(alarmEndDateTime.equals("")) {
			first.setValue("您好,发生告警");
		}else {
			first.setValue("您好,告警已结束");
		}
		first.setColor("#1e90ff");
		dataJson.put("first",first);
		PushTemplateData keyword1 = new PushTemplateData();
		keyword1.setValue(alarmDesc);
		keyword1.setColor("#FF0000");
		dataJson.put("keyword1",keyword1);
		PushTemplateData keyword2 = new PushTemplateData();
		keyword2.setValue(alarmDateTime);
		keyword2.setColor("#1e90ff");
		dataJson.put("keyword2",keyword2);
		PushTemplateData keyword3 = new PushTemplateData();
		keyword3.setValue(deviceNames);
		keyword3.setColor("#1e90ff");
		dataJson.put("keyword3",keyword3);
		PushTemplateData keyword4 = new PushTemplateData();
		keyword4.setValue(stationName);
		keyword4.setColor("#1e90ff");
		dataJson.put("keyword4",keyword4);
		PushTemplateData remark = new PushTemplateData();
		if(alarmEndDateTime.equals("")) {
			remark.setValue("正在告警中,请及时处理。");
			remark.setColor("#FF0000");
		}else {
			remark.setValue("告警于"+alarmEndDateTime+"结束");
			remark.setColor("#1e90ff");
		}
		dataJson.put("remark",remark);
		net.sf.json.JSONObject json_test = net.sf.json.JSONObject.fromObject(dataJson);
		json.put("data", dataJson);
		try {
			result = WeChatAPIProxy.sendTemplateMsg(access_token,json.toString());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//应对不知名情况报错
		JSONObject resultJSON = JSONObject.fromObject(result);
		if(resultJSON.optString("errcode").equals("40001")) {
	    	Appkey appkey = new Appkey();
	    	String appId = appkey.getWechatappid();
			String appsecret = appkey.getWechatappsecret();
			access_token = getOldaccesstoken(appId,appsecret,0);
	        result = push_alarm(response,openId,alarm_template_id,url,alarmDesc,alarmDateTime,alarmEndDateTime,deviceNames,stationName,access_token);
		}
		return result;
	}
    /**
     * 将cookie封装到Map里面
     * @param request
     * @return
     */
    private static Map<String,Cookie> ReadCookieMap(HttpServletRequest request){
    	Map<String,Cookie> cookieMap =new HashMap<String,Cookie>();
    	Cookie[] cookies = request.getCookies();
    	if(null!=cookies){
    		for(Cookie cookie : cookies){
    			cookieMap.put(cookie.getName(), cookie);
    		}
    	}
    	return cookieMap;
    }
}

相对应的PushAccessToken类:

/**
 * 用户授权token
 */
public class PushAccessToken {
	
	private String accessToken;

	private String expiresIn;

	public String getAccessToken() {
		return accessToken;
	}

	public void setAccessToken(String accessToken) {
		this.accessToken = accessToken;
	}

	public String getExpiresIn() {
		return expiresIn;
	}

	public void setExpiresIn(String expiresIn) {
		this.expiresIn = expiresIn;
	}
 
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值