顺便说一下微信公共测试号的申请,不需要准备任何材料,除了部分需要认证的接口,大部分都可以调用,提供一下链接点我获取
官方文档点击查看
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功
可以用redis、mc这种去缓存,或者直接保存到数据库,或者直接保存为application
提供个保存到数据库的方法,redis缓存,目前我已经弃用数据库保存了,连定时任务都不需要了
一、access_token实体类
package com.phil.wechatauth.entity;
import com.phil.common.entity.AbstractEntity;
/**
* 微信的access_token
* @author phil
* @date 2017年7月9日
*
*/
public class WechatAccessToken extends AbstractEntity {
/**
*
*/
private static final long serialVersionUID = 123771404997810930L;
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
二、获取并保存
package com.phil.wechatauth.service.impl;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.phil.common.config.WechatConfig;
import com.phil.common.util.DateTimeUtil;
import com.phil.common.util.HttpReqUtil;
import com.phil.common.util.JsonUtil;
import com.phil.common.util.UUIDGenerator;
import com.phil.wechatauth.dao.WechatAccessTokenMapper;
import com.phil.wechatauth.entity.WechatAccessToken;
import com.phil.wechatauth.model.resp.AccessToken;
import com.phil.wechatauth.service.AuthTokenService;
/**
* AuthToken Service
* @author phil
* @date 2017年7月9日
*
*/
@Service
public class AuthTokenServiceImpl implements AuthTokenService {
private static final Logger logger = Logger.getLogger(AuthTokenServiceImpl.class);
@Autowired
private WechatAccessTokenMapper wechatAccessTokenMapper;
@Transactional(readOnly=true)
public String findlastestToken() {
String accessToken = wechatAccessTokenMapper.findlastestToken();
if(StringUtils.isNotBlank(accessToken)){
logger.info("accessToken of search is " + accessToken.substring(0, 10) + "...");
}
return accessToken;
}
@Override
@Transactional(readOnly=false)
public void saveToken() throws Exception {
TreeMap<String, String> map = new TreeMap<String, String>();
map.put("grant_type", "client_credential");
map.put("appid", WechatConfig.APP_ID);
map.put("secret", WechatConfig.APP_SECRET);
String result = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.GET_METHOD, WechatConfig.TOKEN_PATH, map, "");
AccessToken accessToken = JsonUtil.fromJson(result, AccessToken.class);
try {
if(accessToken.getAccess_token()==null){
throw new Exception("");
}
} catch (Exception e) {
e.printStackTrace();
}
WechatAccessToken wechatAccessToken = new WechatAccessToken();
wechatAccessToken.setId(UUIDGenerator.generate().toString());
wechatAccessToken.setToken(accessToken.getAccess_token());
wechatAccessToken.setCreateTime(DateTimeUtil.currentTime());
wechatAccessTokenMapper.saveToken(wechatAccessToken);
}
}
三、项目启动初始化
package com.phil.common.listener;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import com.phil.wechatauth.service.AuthTokenService;
/**
* 初始化生成微信token
*
* @author phil
* @date 2017年7月9日
*
*/
@Component
public class InitWechatAuthListener implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger logger = Logger.getLogger(InitWechatAuthListener.class);
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private AuthTokenService authTokenService;
private static boolean isStart = false; // 防止二次调用
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (!isStart) {
isStart = true;
String token = authTokenService.findlastestToken();
if (StringUtils.isBlank(token)) {
logger.info("token is null in db");
try {
authTokenService.saveToken();
token = authTokenService.findlastestToken();
} catch (Exception e) {
e.printStackTrace();
}
}
// 添加一个 key
ValueOperations<String, Object> value = redisTemplate.opsForValue();
value.set("phil_token", token, 7200, TimeUnit.SECONDS); // 7200秒有效期
}
}
}
四、定时刷新
package com.phil.common.task;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.phil.wechatauth.service.AuthTokenService;
/**
* Spring调度,指定时间执行 利用了spring中使用注解的方式来进行任务调度。
* @author phil
* @date 2017年7月9日
*
*/
@Component
@Lazy(false)
public class SpringTaskController {
private static final Logger logger = Logger.getLogger(SpringTaskController.class);
@Autowired
private AuthTokenService authTokenService;
/**
* 每小时抓取一次
*/
@Scheduled(cron = "0 0 0/1 * * ? ")
public void scheduleSaveToken(){
try {
authTokenService.saveToken();
} catch (Exception e) {
logger.info("抓取失败,please check");
/**** 发邮件/电话 ****/
e.printStackTrace();
}
}
}
spring配置
<!-- 定时器 -->
<task:annotation-driven />
<bean class="com.phil.common.task.SpringTaskController" />