springboot+微信公众号 实现给女盆友定时发送消息
1.准备工作
申请微信公众号的测试平台,地址:
https://mp.weixin.qq.com/
注意保存以上三个部分,第一个是公众号的ID和秘钥;第二个是扫码关注你的公众号
也就是消息的接收方;第三个是发送消息的模板,可以在这里自定义自己的发送内容,需要记住模板的ID;
申请天行数据接口
https://www.tianapi.com/
2.开始编码
天气接口的实体类
/**
* 天气api返回信息
*/
@Data
public class WeatherInfo {
/**
* 地区
*/
private String area;
/**
* 日期
*/
private String date;
/**
* 星期
*/
private String week;
/**
* 早晚天气变化
*/
private String weather;
/**
* 天气图标
*/
private String weatherimg;
/**
* 实时天气
*/
private String real;
/**
* 最低温
*/
private String lowest;
/**
* 最高温
*/
private String highest;
/**
* 风向
*/
private String wind;
/**
* 风向360°角度
*/
private String winddeg;
/**
* 风速,km/h
*/
private String windspeed;
/**
* 风力
*/
private String windsc;
/**
* 日出时间
*/
private String sunrise;
/**
* 日落时间
*/
private String sunset;
/**
* 月升时间
*/
private String moonrise;
/**
* 月落时间
*/
private String moondown;
/**
* 降雨量
*/
private String pcpn;
/**
* 降雨概率
*/
private String pop;
/**
* 紫外线强度指数
*/
private String uv_index;
/**
* 能见度,单位:公里
*/
private String vis;
/**
* 相对湿度
*/
private String humidity;
/**
* 生活指数提示
*/
private String tips;
}
发送消息的实体
/**
* 发送消息实体
*/
@Data
public class WechatSendMsgVo implements Serializable {
/**
* 接收人id
*/
private String touser;
/**
* 模板id
*/
private String template_id;
/**
* 模板数据
*/
private Map<String, WechatTemplateVo> data;
/**
* 语言类型 默认中文
*/
private String lang = "zh_CN";
}
模板消息(可以自定义消息字体的颜色)
/**
* 模板消息内容值
*/
@Getter
@Setter
public class WechatTemplateVo implements Serializable {
/**
* 值
*/
private String value;
/**
* 颜色
*/
private String color;
public WechatTemplateVo(String value, String color){
this.value = value;
this.color = color;
}
}
需要使用的接口地址的定义
/**
* URL常量
*/
public class UrlConstant {
//获取accessToken
public final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&";
//微信推送模板消息
public final static String SEND_TEMPLATE = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";
//获取关注用户信息
public final static String GET_USER_LIST = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=";
//彩虹屁接口
public final static String CAI_HONG_API = "http://api.tianapi.com/caihongpi/index?key=";
//早安接口
public final static String MORNING_API = "http://api.tianapi.com/zaoan/index?key=";
//天气接口
public final static String TIAN_QI_API = "http://api.tianapi.com/tianqi/index?key=";
//笑话接口
public final static String JOKE_API = "http://api.tianapi.com/joke/index?key=";
//土味情话接口
public final static String SAY_LOVE_API = "http://api.tianapi.com/saylove/index?key=";
//诗句-----wjg
public final static String SCWD_API = "http://api.tianapi.com/scwd/index?key=";
}
配置文件
#公众号配置
wechat:
appId: 公众号ID
appSecret: 秘钥
tempId: 模板id
drinkTempId: 模板id
offDutyTempId: 模板id
shiTempId: 模板id
myBirthday:
babyBirthday:
loveDay:
newYear:
#彩虹屁接口
#天行api配置
tianapi:
appKey: 在天行数据找到
area: 北京
/**
* 天行api配置
*/
@Component
@Data
public class TianApiConfig {
@Value("${tianapi.appkey}")
private String appKey;
@Value("${tianapi.area}")
private String area;
}
/**
* 微信配置
*/
@Component
@Data
public class WechatConfig {
@Value("${wechat.appId}")
private String appId;
@Value("${wechat.appSecret}")
private String appSecret;
@Value("${wechat.tempId}")
private String tempId;
@Value("${wechat.myBirthday}")
private String myBirthday;
@Value("${wechat.babyBirthday}")
private String babyBirthday;
@Value("${wechat.loveDay}")
private String loveDay;
@Value("${wechat.drinkTempId}")
private String drinkTempId;
@Value("${wechat.offDutyTempId}")
private String offDutyTempId;
@Value("${wechat.shiTempId}")
private String shiTempId;
@Value("${wechat.newYear}")
private String newYear;
}
业务层
public interface WeiXinService {
//获取accessToken
String getAccessToken(String appId, String appSecret);
//获取用户信息
List<String> getUserList(String accessToken);
//发送模板消息
JSONObject sendMsg(WechatSendMsgVo sendMsgVo,String token, String openId);
//彩虹屁信息
String getCaiHongPiInfo(String appKey);
//早安
String getZaoAnInfo(String appKey);
//天气信息
WeatherInfo getWeatherInfo(String appKey, String city);
//笑话
String getJoke(String appKey);
//土味情话
String getSayLove(String appKey);
//wjg--诗句
String getScwd(String appKey) throws IllegalAccessException;
}
@Service
public class WeiXinServiceImpl implements WeiXinService {
Logger logger = LoggerFactory.getLogger(WeiXinServiceImpl.class);
@Override
public String getAccessToken(String appId, String appSecret) {
String requestUrl = UrlConstant.ACCESS_TOKEN_URL + "appid=" + appId + "&secret=" + appSecret;
String resp = HttpUtil.get(requestUrl);
JSONObject result = JSONUtil.parseObj(resp);
logger.info("获取access_token:" + resp);
String token = result.getStr("access_token");
logger.info("token:" + token);
return token;
}
@Override
public List<String> getUserList(String accessToken) {
String requestUrl = UrlConstant.GET_USER_LIST+ accessToken;
String resp = HttpUtil.get(requestUrl);
JSONObject result = JSONUtil.parseObj(resp);
logger.info("用户列表:" + resp);
JSONArray openIdJsonArray = result.getJSONObject("data").getJSONArray("openid");
List<String> openIds = JSONUtil.toList(openIdJsonArray, String.class);
return openIds;
}
@Override
public JSONObject sendMsg(WechatSendMsgVo sendMsgVo, String token, String openId) {
//请求路径
String requestUrl = UrlConstant.SEND_TEMPLATE + token;
//参数转json
String json = JSONUtil.parseObj(sendMsgVo).toString();
String resp = HttpUtil.createPost(requestUrl).body(json).execute().body();
JSONObject result = JSONUtil.parseObj(resp);
logger.info("发送消息:" + resp);
return result;
}
@Override
public String getCaiHongPiInfo(String appKey) {
//请求地址
String requestUrl = UrlConstant.CAI_HONG_API + appKey;
String resp = HttpUtil.createGet(requestUrl).contentType("application/x-www-form-urlencoded;charset=UTF-8").charset("UTF-8").execute().body();
JSONObject obj = JSONUtil.parseObj(resp);
logger.info("obj"+obj.toString());
JSONArray newslist = obj.getJSONArray("newslist");
String content = ((JSONObject) newslist.get(0)).getStr("content");
return content;
}
@Override
public String getZaoAnInfo(String appKey) {
//请求地址
String requestUrl = UrlConstant.MORNING_API + appKey;
String resp = HttpUtil.createGet(requestUrl).contentType("application/x-www-form-urlencoded;charset=UTF-8").charset("UTF-8").execute().body();
JSONObject obj = JSONUtil.parseObj(resp);
logger.info("obj"+obj.toString());
JSONArray newslist = obj.getJSONArray("newslist");
String content = ((JSONObject) newslist.get(0)).getStr("content");
return content;
}
@Override
public WeatherInfo getWeatherInfo(String appKey, String city) {
//请求地址
String requestUrl = UrlConstant.TIAN_QI_API + appKey + "&city=" + city;
String resp = HttpUtil.createGet(requestUrl).contentType("application/x-www-form-urlencoded;charset=UTF-8").charset("UTF-8").execute().body();
JSONObject obj = JSONUtil.parseObj(resp);
logger.info("obj"+obj.toString());
JSONArray newslist = obj.getJSONArray("newslist");
List<WeatherInfo> weatherInfos = JSONUtil.toList(newslist, WeatherInfo.class);
return weatherInfos.get(0);
}
@Override
public String getJoke(String appKey) {
//请求地址
String requestUrl = UrlConstant.JOKE_API + appKey + "&num=1";
String resp = HttpUtil.createGet(requestUrl).contentType("application/x-www-form-urlencoded;charset=UTF-8").charset("UTF-8").execute().body();
JSONObject obj = JSONUtil.parseObj(resp);
logger.info("obj"+obj.toString());
JSONArray newslist = obj.getJSONArray("newslist");
String content = ((JSONObject) newslist.get(0)).getStr("content");
return content;
}
@Override
public String getSayLove(String appKey) {
//请求地址
String requestUrl = UrlConstant.SAY_LOVE_API + appKey;
String resp = HttpUtil.createGet(requestUrl).contentType("application/x-www-form-urlencoded;charset=UTF-8").charset("UTF-8").execute().body();
JSONObject obj = JSONUtil.parseObj(resp);
logger.info("obj"+obj.toString());
JSONArray newslist = obj.getJSONArray("newslist");
String content = ((JSONObject) newslist.get(0)).getStr("content");
return content;
}
@Override
public String getScwd(String appKey) throws IllegalAccessException {
//请求地址
String requestUrl = UrlConstant.SCWD_API+ appKey;
String resp = HttpUtil.createGet(requestUrl).contentType("application/x-www-form-urlencoded;charset=UTF-8").charset("UTF-8").execute().body();
JSONObject obj = JSONUtil.parseObj(resp);
logger.info("obj"+obj.toString());
JSONArray newslist = obj.getJSONArray("newslist");
StringBuffer content = new StringBuffer();
JSONObject toJSONObject=null;
for (int i = 0; i <newslist.size(); i++) {
toJSONObject = newslist.getJSONObject(i);
}
// String content = ((JSONObject) toJSONObject.get(0)).getStr("question");
if(toJSONObject.getStr("question")!=null){
content.append( toJSONObject.getStr("question")+"\n");
}
if(toJSONObject.get("answer_a")!=null){
content.append(toJSONObject.get("answer_a")+"\n");
}
if(toJSONObject.get("answer_b")!=null){
content.append(toJSONObject.get("answer_b")+"\n");
}
if(toJSONObject.get("answer_c")!=null){
content.append(toJSONObject.get("answer_c")+"\n");
}
if(toJSONObject.get("answer")!=null){
content.append(toJSONObject.get("answer")+"\n");
}
if(toJSONObject.get("analytic")!=null){
content.append(toJSONObject.get("analytic")+"\n");
}
return content.toString();
}
}
定时任务
/**
* 微信定时任务
*/
@Configuration
@EnableScheduling
public class WechatTask {
@Resource
private WeiXinService weiXinService;
@Resource
private WechatConfig wechatConfig;
@Resource
private TianApiConfig tianApiConfig;
//线程池
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
return taskScheduler;
}
/**
* 微信模板消息推送
* @throws ParseException
*/
@Scheduled(cron="0 30 6 ? * * ")
public void sendTemplateMsg() throws ParseException {
//配置及数据
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(new Date());
String appId = wechatConfig.getAppId();
String appSecret = wechatConfig.getAppSecret();
String babyBirthday = wechatConfig.getBabyBirthday();
String myBirthday = wechatConfig.getMyBirthday();
String loveDay = wechatConfig.getLoveDay();
String appKey = tianApiConfig.getAppKey();
String area = tianApiConfig.getArea();
String newyear=wechatConfig.getNewYear();
//获取微信token
String token = weiXinService.getAccessToken(appId,appSecret);
//获取关注用户
List<String> userList = weiXinService.getUserList(token);
for (String openId : userList) {
//发送消息实体
WechatSendMsgVo sendMsgVo = new WechatSendMsgVo();
//设置模板id
sendMsgVo.setTemplate_id(wechatConfig.getTempId());
//设置接收用户
sendMsgVo.setTouser(openId);
Map<String, WechatTemplateVo> map = new HashMap<>();
//获取早安语句
String zaoAnInfo = weiXinService.getZaoAnInfo(appKey);
map.put("morning", new WechatTemplateVo("老婆大人~~~ 早安!"+zaoAnInfo,"#ff6666"));
//获取天气
WeatherInfo weatherInfo = weiXinService.getWeatherInfo(appKey, area);
//日期
map.put("date", new WechatTemplateVo(weatherInfo.getDate(),null));
//星期
map.put("week",new WechatTemplateVo(weatherInfo.getWeek(),null));
//城市
map.put("city",new WechatTemplateVo(weatherInfo.getArea(),"#9900ff"));
//天气
map.put("weather",new WechatTemplateVo(weatherInfo.getWeather(),"#CD96CD"));
//最低气温
map.put("lowest",new WechatTemplateVo(weatherInfo.getLowest(),"#A4D3EE"));
//最高气温
map.put("highest",new WechatTemplateVo(weatherInfo.getHighest(),"#CD3333"));
//降水概率
if(weatherInfo.getPop()==null){
map.put("pop",new WechatTemplateVo(0+"%","#A4D3EE"));
}else
{ map.put("pop",new WechatTemplateVo(weatherInfo.getPop()+"%","#A4D3EE"));}
//今日建议
map.put("tips",new WechatTemplateVo(weatherInfo.getTips(),"#FF7F24"));
//相爱天数
int loveDays = fun(loveDay, date);
map.put("loveDay",new WechatTemplateVo(loveDays+"","#EE6AA7"));
//我的生日
int myDay = fun2(myBirthday, date);
map.put("myBirthday",new WechatTemplateVo(myDay+"","#EE6AA7"));
//宝贝生日
int babyDay = fun2(babyBirthday, date);
map.put("babyBirthday",new WechatTemplateVo(babyDay+"","#EE6AA7"));
//过年
int newyear1 =fun2(newyear,date);
map.put("newyear", new WechatTemplateVo(newyear1+"","#EE6AA7"));
//彩虹屁
String caiHongPiInfo = weiXinService.getCaiHongPiInfo(appKey);
map.put("pipi",new WechatTemplateVo(caiHongPiInfo,"#E066FF"));
sendMsgVo.setData(map);
JSONObject entries = weiXinService.sendMsg(sendMsgVo,token, openId);
}
}
@Scheduled(cron = "0 0 10,14,16 * * ? ")
public void sendDrinkMsg() {
//配置及数据
String appId = wechatConfig.getAppId();
String appSecret = wechatConfig.getAppSecret();
String appKey = tianApiConfig.getAppKey();
//获取微信token
String token = weiXinService.getAccessToken(appId, appSecret);
//获取关注用户
List<String> userList = weiXinService.getUserList(token);
for (String openId : userList) {
//发送消息实体
WechatSendMsgVo sendMsgVo = new WechatSendMsgVo();
//设置喝水模板id
sendMsgVo.setTemplate_id(wechatConfig.getDrinkTempId());
//设置接收用户
sendMsgVo.setTouser(openId);
Map<String, WechatTemplateVo> map = new HashMap<>();
//获取笑话
String joke = weiXinService.getJoke(appKey);
map.put("joke", new WechatTemplateVo(joke, "#ff6666"));
sendMsgVo.setData(map);
JSONObject entries = weiXinService.sendMsg(sendMsgVo, token, openId);
}
}
@Scheduled(cron = "0 01 17 ? * *")
public void sendoffDutyMsg(){
String content = "卸载上班的压力,删除上班的烦恼,设置明天的斗志,下载轻松的话题,安装快乐的心情,播放灿烂的笑容。";
//配置及数据
String appId = wechatConfig.getAppId();
String appSecret = wechatConfig.getAppSecret();
String appKey = tianApiConfig.getAppKey();
//获取微信token
String token = weiXinService.getAccessToken(appId,appSecret);
//获取关注用户
List<String> userList = weiXinService.getUserList(token);
for (String openId : userList) {
//发送消息实体
WechatSendMsgVo sendMsgVo = new WechatSendMsgVo();
//设置喝水模板id
sendMsgVo.setTemplate_id(wechatConfig.getOffDutyTempId());
//设置接收用户
sendMsgVo.setTouser(openId);
Map<String, WechatTemplateVo> map = new HashMap<>();
//获取笑话
String sayLove = weiXinService.getSayLove(appKey);
map.put("tips",new WechatTemplateVo(content,"#ff6666"));
map.put("sayLove", new WechatTemplateVo(sayLove,"#E066FF"));
sendMsgVo.setData(map);
JSONObject entries = weiXinService.sendMsg(sendMsgVo,token, openId);
}
}
@Scheduled(cron = "0 0 0/1 * * ? ")
public void sendscwdMsg() throws IllegalAccessException {
//配置及数据
String appId = wechatConfig.getAppId();
String appSecret = wechatConfig.getAppSecret();
String appKey = tianApiConfig.getAppKey();
//获取微信token
String token = weiXinService.getAccessToken(appId,appSecret);
//获取关注用户
List<String> userList = weiXinService.getUserList(token);
for (String openId : userList) {
//发送消息实体
WechatSendMsgVo sendMsgVo = new WechatSendMsgVo();
//设置喝水模板id
sendMsgVo.setTemplate_id(wechatConfig.getShiTempId());
//设置接收用户
sendMsgVo.setTouser(openId);
Map<String, WechatTemplateVo> map = new HashMap<>();
//获取笑话
String shi = weiXinService.getScwd(appKey);
map.put("shi",new WechatTemplateVo(shi,"#ff6666"));
sendMsgVo.setData(map);
JSONObject entries = weiXinService.sendMsg(sendMsgVo,token, openId);
}
}
public int fun(String s1,String s2) throws ParseException {
//指定格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//获取Date
Date t1 = simpleDateFormat.parse(s1);
Date t2 = simpleDateFormat.parse(s2);
//获取时间戳
Long time1 = t1.getTime();
Long time2 = t2.getTime();
Long num = time2- time1;
Long day= num/24/60/60/1000;
//返回相差天数
return day.intValue();
}
public int fun2(String s1,String s2) throws ParseException {
//指定格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//获取Date
Date t1 = simpleDateFormat.parse(s1);
Date t2 = simpleDateFormat.parse(s2);
//获取时间戳
Long time1 = t1.getTime();
Long time2 = t2.getTime();
Long num = time1- time2;
Long day= num/24/60/60/1000;
//返回相差天数
return day.intValue();
}
}
最后打成jar包,部署到linux云服务器即可,就可以定时发送了~~~~~
3.出现的问题
在部署到云服务器上时发现同一时间只能执行一个定时任务,后排查得知,使用springboot自带的定时任务,默认是单线程的,最后我写了一个线程池,完美解决!!~~