借鉴:https://blog.csdn.net/m0_38130105/article/details/126160873?spm=1001.2014.3001.5506
官方消息推送文档地址:https://mp.weixin.qq.com/debug/cgi-bin/readtmpl?t=tmplmsg/faq_tmpl
效果图预览
一、 注册微信测试账号
-
微信扫码登录 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login ,登录成功后,就会生成测试账号的appid和appsecret
-
需要让想要收到消息的用户扫描并关注此测试账号,消息推送需要使用相对应用户的openId
-
新增要推送的消息模板
/**
* 模板内容示例
* 模板中参数内容必须以".DATA"结尾,否则视为保留字;
* 模板保留符号"{{ }}"
* 版本更新后{{XX.DATA}}不可以单独作为一行展示,所以尽量都是和文字在一行呈现,可以在代码中使用'\r'实现换行效果
*/
今天是{{date.DATA}}
今日份天气:{{weather.DATA}} {{ext.DATA}}
最低温度:{{low.DATA}} 度 {{lowExt.DATA}}
最高温度:{{high.DATA}} 度 {{highExt.DATA}}
今天是我们相识的第{{meet.DATA}}天
今日份彩虹屁奉上🌈{{caihongpi.DATA}}
- 新增模板成功后,获取到templateId,等会消息推送会用到。
二、搭建springBoot项目
- 搭建一个普通的springBoot项目即可,在pom文件中需要加入微信模板消息推送的sdk
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>3.3.0</version>
</dependency>
- 编写核心代码,对应的工具类代码等下会单独描述
public void push(String openId){
// 获取天气 --- 工具类等下放到下方
JSONObject todayWeather = Tianqi.getNanjiTianqi();
// 拼接跳转路径 --- 模板消息可以实现点击后跳转到某个固定的路径,这里是我做的页面,等下在下方单独描写
String url = getUrl(todayWeather,openId);
// 初始化消息模板
// openId就是对应用户关注测试号后生成的openId -- 根据个人情况修改
// Constant.templateId就是模板消息的templateId -- 根据个人情况修改
// url就是点击模板是跳转的路径, 如果不需要跳转可以不写
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
.toUser(openId)
.templateId(Constant.templateId)
.url(url)//点击模版消息要访问的网址
.build();
/**
* 下方开始填写模板中的变量信息
* WxMpTemplateData构造函数的第一个参数是变量名称,也就是{{date.DATA}}中的前半部分,后方DATA不需要
* WxMpTemplateData构造函数的第二个参数是想要给变量赋的值,根据个人情况填写
* WxMpTemplateData构造函数的第三个参数是字体颜色,不过现在更新后已经不支持修改颜色了,所以写不写无所谓
*/
templateMessage.addData(new WxMpTemplateData("date",todayWeather.getString("date") + " "+ todayWeather.getString("week"),"#00BFFF"));
templateMessage.addData(new WxMpTemplateData("weather",todayWeather.getString("text_day"),"#00FFFF"));
// 可以根据不同的天气情况给{{ext.DATA}}赋值扩展
if (todayWeather.getString("text_day").contains("雨")) {
templateMessage.addData(new WxMpTemplateData("ext",",********","#00FFFF"));
}
// 可以根据天气获取到的最高、最低温度给{{highExt.DATA}} {{lowExt.DATA}}赋值扩展
templateMessage.addData(new WxMpTemplateData("low",todayWeather.getString("low") + "","#173177"));
if (Integer.parseInt(todayWeather.getString("low")) < 10) {
templateMessage.addData(new WxMpTemplateData("lowExt",",低温","#173177"));
}
templateMessage.addData(new WxMpTemplateData("high",todayWeather.getString("high")+ "","#FF6347" ));
if (Integer.parseInt(todayWeather.getString("high")) > 30) {
templateMessage.addData(new WxMpTemplateData("highExt",",高温","#FF6347"));
}
// 获取彩虹屁 --- 彩虹屁方法等下代码块单独提供
String caiHongPi = getCaihongpi();
// 版本更新后不允许变量单独成行,所以设置模板时变量需要和文字在一行,想换行需要在拼接模板是使用'\r'换行
templateMessage.addData(new WxMpTemplateData("caihongpi","\r\r" + caiHongPi,"#FF69B4"));
// 计算某个纪念日的日期,根据个人情况修改,代码等下单独提供
templateMessage.addData(new WxMpTemplateData("meet", JiNianRi.getLianAi()+"","#FF1493"));
// 消息推送 -- 等下单独提供
ToolUtil.sendMessage(templateMessage);
}
- 获取天气
首先需要接入百度天气的api,地址为:https://lbsyun.baidu.com/apiconsole/center#/home;
具体接口地址为:https://lbs.baidu.com/faq/api?title=webapi/weather/base;
申请成功后会返回一个ak用于请求接口;
之后需要在文档中找到城市接口代码,需要作为参数查询自己当前城市的编码;
代码示例如下:
public class Tianqi {
private static String ak = "申请api成功后的ak值";
private static String district_id = "城市代码的district_id";
public static JSONObject getNanjiTianqi() {
String result = null;
JSONObject today = new JSONObject();
try {
result = HttpUtil.getUrl("https://api.map.baidu.com/weather/v1/?district_id=" + district_id + "&data_type=all&ak=" + ak);
JSONObject jsonObject = JSONObject.parseObject(result);
if (jsonObject.getString("message").equals("success")) {
JSONArray arr = jsonObject.getJSONObject("result").getJSONArray("forecasts");
today = arr.getJSONObject(0);
}
} catch (Exception e) {
e.printStackTrace();
}
return today;
}
}
- 获取彩虹屁
首先需要接入彩虹屁的api,地址为:https://www.tianapi.com/
具体接口地址:https://www.tianapi.com/apiview/181
代码示例如下:
public class CaiHongPi {
private static final String key = "申请成功后提供的key";
private static final String url = "http://apis.tianapi.com/caihongpi/index?key=";
private static List<String> jinJuList = new ArrayList<>();
private static final String name = "因为有些彩虹屁中会带名字,所以这里替换成接收消息的用户名称";
public static String getCaiHongPi() {
//默认彩虹屁
String str = "盯着你看的每一个瞬间,我都想和你有以后";
try {
JSONObject jsonObject = JSONObject.parseObject(HttpUtil.getUrl(url+key).replace("XXX", name));
if (jsonObject.getIntValue("code") == 200) {
str = jsonObject.getJSONObject("result").getString("content");
}
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
- 计算纪念日日期
代码示例如下:
public class JiNianRi {
/**
* 纪念日日期
*/
static String lianAi = "2024-02-14";
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
/**
* 已经过去date多少天
* @param date
* @return
*/
public static int after(String date) {
int day = 0;
try {
long time = System.currentTimeMillis() - simpleDateFormat.parse(date).getTime();
day = (int) (time / 86400000L);
} catch (ParseException e) {
e.printStackTrace();
}
return day;
}
public static int getLianAi() {
return after(lianAi);
}
}
- 消息推送
代码示例如下:
public static void sendMessage(WxMpTemplateMessage templateMessage) {
WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();
// 测试号的appId
wxStorage.setAppId(Constant.appId);
// 测试号的secret
wxStorage.setSecret(Constant.secret);
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxStorage);
try {
System.out.println(templateMessage.toJson());
// 消息推送
System.out.println(wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage));
// 自己想看下效果或者想同样收到一份提醒的可以给自己也发一份
templateMessage.setToUser("换成自己的openId");
wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
} catch (Exception e) {
System.out.println("推送失败:" + e.getMessage());
e.printStackTrace();
}
}
- 定时任务推送
@Component
public class JobWorker {
Map<String, Send> strategyMap = new HashMap<>();
public JobWorker() {
// 初始化策略映射
strategyMap.put("normal", SpringUtil.getBean(Normal.class));
strategyMap.put("teacher", SpringUtil.getBean(Teacher.class));
strategyMap.put("birthday", SpringUtil.getBean(Birthday.class));
}
@Scheduled(cron = "0 30 8 * * ?")
public void goodMorning(){
push(null);
}
/**
* 推送
*/
public void push(String openId) {
// 我这里是因为不同的节日要推送不同的模板,所以直接搞了一个策略模式,只有一个模板的直接调用上述推送消息方法即可
LocalDate now = LocalDate.now();
String date = "normal";
if (now.getMonthValue() == 9 && now.getDayOfMonth() == 10) {
// 教师节
date = "teacher";
} else if (now.getMonthValue() == 10 && now.getDayOfMonth() == 24) {
// 生日
date = "birthday";
}
strategyMap.get(date).push(StringUtils.isBlank(openId) ? Constant.openId : openId);
}
}