最近网络上又出现了向女朋友推送微信公众号的趋势。那么,其他人有的不是我女朋友也不是O.o,而是简单研究一下微信公众号推送的原理,简单地说,后台服务器做定时任务,定期调用微信公共平台提供的web API接口(HTTP)发送模板消息(JSON数据)即可。技术堆栈和开发过程概述如下:
前端:微信公众号-订单读取号-测试号后端:spring boot rest template 1。配置微信公共平台测试号
单击微信开放平台链接(微信开放平台)注册微信开放测试编号。测试号可以体验到微信公共平台的所有功能API接口,这里主要使用模板消息推送API。但是,测试编号的限制是只能使用基本公共编号名称,功能可以随时下载。有条件的可以申请企业阅读号/服务标签(个人认证的阅读号没有模板消息推送API权限,只有企业可以认证服务标签)。测试编号配置中最重要的部分如下(请参阅开发文档模板消息|微信开放文档):
测试编号信息:包含用于导入令牌和API接口的appID和appsecret的认证用户列表:用于导入订阅用户的Token、推送到大象用户的模板消息接口(您必须先查看此读取编号):构成推送的消息模板内容,包括模板ID(用于接口调用)、用于接口调用的参数(模板标题可用)其中params是后端服务器发送的相应JSON数据变量名,DATA是前端模板消息的固定语法。 //JSON数据传输格式示例
{
Touser''OpenID '
template _ id ' ' ngqipbwh 8 bufcssecmogfxcv 14 j0 tqlepbo 27 ize yty '
Topcolor''#FF0000 '
数据' {
日期' {
值'' 2022-09-04星期日'
Color''#173177 '
},
Remark'{
值' ' '
Color''#173177 '
},
“诗”:
Value
#34;:"北京", "color":"#173177" }, "weather": { "value":"多云转晴", "color":"#173177" }, ... } }2.数据接口封装
在消息推送模板中,我们需要用到的数据包括气候(天气、温度、城市等)、恋爱天数、生日倒计时天数、彩虹屁语句这几部分,数据的获取方式如下:
- 气候(天气、温度、城市等)、彩虹屁语句:使用 天行数据接口Web API( 天行数据TianAPI - 开发者API数据平台 )
- 恋爱天数、生日倒计时天数: 本地封装计算工具
2.1 天行数据接口封装
天行接口数据的获取也是通过Web API 发送请求的方式在response中来获取数据(RestTemplate),接口文档如下:
- 天气接口: 天气预报API接口 - 天行数据TianAPI
- 彩虹屁: 彩虹屁API接口 - 天行数据TianAPI
public class DataUtils {
/**
* 获取 Weather 信息
* @param restTemplate
* @return
*/
public static Weather getWeather(RestTemplate restTemplate){
String responseJson = re, S);
JSONObject responseResult = JSONObject.parseObject(responseJson);
JSONObject jsonObject = re("newslist").getJSONObject(0);
return j);
}
/**
* 获取 RainbowPi 信息
* @param restTemplate
* @return
*/
public static String getRainbow(RestTemplate restTemplate){
String responseJson = re, S);
JSONObject responseResult = JSONObject.parseObject(responseJson);
JSONObject jsonObject = re("newslist").getJSONObject(0);
return j("content");
}
}
2.2 日期计算工具封装
计算生日倒计时和计算恋爱天数的逻辑不同。计算生日倒计时需要判断生日日期是否已过,而计算恋爱天数相对简单,直接统计时间即可。
public class DataUtils {
/**
* 计算生日天数 days
* @return
*/
public static int getBirthDays(String birthday) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Calendar cToday = Calendar.getInstance(); // 存今天
Calendar cBirth = Calendar.getInstance(); // 存生日
int days = 0;
try {
cBir(birthday)); // 设置生日
cBir, cToday.get)); // 修改为本年
if ) < cToday.get)) {
// 生日已经过了,要算明年的了
days = ) - cToday.get)) + cBir);
} else {
// 生日还没过
days = cBir) - cToday.get);
}
} catch (ParseException e) {
e.printStackTrace();
}
return days;
}
/**
* 计算恋爱天数 days
* @return
*/
public static int getLoveDays(String loveday){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
int days = 0;
try {
long time = Sy() - da(loveday).getTime();
days = (int) (time / (24*60*60*1000));
} catch (ParseException e) {
e.printStackTrace();
}
return days;
}
}
3.封装推送逻辑
3.1 封装配置类
@Component
public class WeChatConfigure {
public static String Access_URL = ";appid={0}&secret={1}";
public static String Send_URL = "{0}";
public static String App_ID;
@Value("${WeC}")
public void setAppID(String AppID) {
App_ID = AppID;
}
public static String App_Secret;
@Value("${WeC}")
public void setAppSecret(String AppSecret) {
App_Secret = AppSecret;
}
public static String Open_ID;
@Value("${WeC}")
public void setOpenID(String OpenID) {
Open_ID = OpenID;
}
public static String Template_ID;
@Value("${WeC}")
public void setTemplateID(String TemplateID) {
Template_ID = TemplateID;
}
public static String Top_Color;
@Value("${WeC}")
public void setTopColor(String TopColor) {
Top_Color = TopColor;
}
public static String Weather_API;
@Value("${WeC}")
public void setWeatherAPI(String WeatherAPI) {
Weather_API = WeatherAPI;
}
public static String Rainbow_API;
@Value("${WeC}")
public void setRainbowAPI(String RainbowAPI) {
Rainbow_API = RainbowAPI;
}
public static String Boy_Birthday;
@Value("${WeC}")
public void setBoyBirthday(String BoyBirthday) {
Boy_Birthday = BoyBirthday;
}
public static String Girl_Birthday;
@Value("${WeC}")
public void setGirlBirthday(String GirlBirthday) {
Girl_Birthday = GirlBirthday;
}
public static String Love_Day;
@Value("${WeC}")
public void setLoveDay(String LoveDay) {
Love_Day = LoveDay;
}
}
3.2 封装实体类
//单条数据Item封装
public class DataItem {
private String value;
private String color;
public DataItem(String _value, String _color) {
= _value;
= _color;
}
public String getValue() {
return value;
}
public void setValue(String value) {
= value;
}
public String getColor() {
return color;
}
public void setColor(String color) {
= color;
}
}
//发送数据集result封装
public class ResultVo {
private String touser;
private String template_id;
private String topcolor;
private HashMap<String, DataItem> data;
private ResultVo(String _touser, String _template_id, String _topcolor, HashMap<String, DataItem> _data) {
= _touser;
= _template_id;
= _topcolor;
= _data;
}
public String getTouser() {
return touser;
}
public String getTemplate_id() {
return template_id;
}
public String getTopcolor() {
return topcolor;
}
public HashMap<String, DataItem> getData() {
return data;
}
public static ResultVo initializeResultVo(String _touser, String _template_id, String _topcolor){
return new ResultVo(_touser,_template_id,_topcolor,null);
}
public static ResultVo initializeResultVo(String _touser, String _template_id, String _topcolor,HashMap<String, DataItem> _data){
return new ResultVo(_touser,_template_id,_topcolor,_data);
}
public ResultVo setAttribute(String key, DataItem item){
if(==null) = new HashMap<String,DataItem>();
.put(key,item);
return this;
}
}
3.3 推送逻辑Controller实现
@Controller
public class WeChatController {
@Autowired
RestTemplate restTemplate;
/**
* {
<!-- -->{da}}
* {
<!-- -->{remark.DATA}}
* 所在城市:{
<!-- -->{ci}}
* 今日天气:{
<!-- -->{wea}}
* 气温变化:{
<!-- -->{min_}} ~ {
<!-- -->{max_}}
* 今日建议:{
<!-- -->{}}
* 今天是我们恋爱的第 {
<!-- -->{love_days.DATA}} 天
* 距离xx生日还有 {
<!-- -->{girl_bir}} 天
* 距离xx生日还有 {
<!-- -->{boy_bir}} 天
* {
<!-- -->{rainbow.DATA}}
*/
public void push(){
ResultVo resultVo = Re);
//1.设置城市与天气信息
Weather weather = Da(restTemplate);
re("date",new DataItem() + " " + wea(),"#00BFFF"));
re("city",new DataItem(),null));
re("weather",new DataItem(),"#1f95c5"));
re("min_temperature",new DataItem(),"#0ace3c"));
re("max_temperature",new DataItem(),"#dc1010"));
re("tips",new DataItem(),null));
//2.设置日期相关
int love_days = Da);
int girl_birthday = Da);
int boy_birthday = Da);
re("love_days",new DataItem(love_days+"","#FFA500"));
re("girl_birthday",new DataItem(girl_birthday+"","#FFA500"));
re("boy_birthday",new DataItem(boy_birthday+"","#FFA500"));
//3.设置彩虹屁
String rainbow = Da(restTemplate);
re("rainbow",new DataItem(rainbow,"#FF69B4"));
//4.其他
String remark = "❤";
if(Da) == 0){
remark = "今天是恋爱周年纪念日!永远爱你~";
}else if(girl_birthday == 0){
remark = "今天是傻元宝贝的生日!生日快乐哟~";
}else if(boy_birthday == 0){
remark = "今天是傻鑫的生日!别忘了好好爱他~";
}
re("remark",new DataItem(remark,"#FF1493"));
//5.发送请求,推送消息
String responseStr = re, resultVo, S, Da(restTemplate));
printPushLog(responseStr);
}
/**
* 打印 response log
* @param responseStr
*/
private void printPushLog(String responseStr){
JSONObject jsonObject = JSONObject.parseObject(responseStr);
String msgCode = j("errcode");
String msgContent = j("errmsg");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Sy("[ " + da(new Date()) + " ] : messageCode=" + msgCode + ",messageContent=" + msgContent);
}
}
4.封装定时任务
@Component
public class PushTask {
@Autowired
WeChatController weChatController;
//每日 早上9点 定时推送
@Scheduled(cron = "0 0 9 * * ?")
public void scheduledPush(){
weC();
}
}
5.打包部署腾讯云
项目打包成 jar 包后传到腾讯云服务器上,直接运行即可实现每日推送。
#nohup指令 后台启动jar包,日志信息输出到log.file文件
nohup java -jar xxx-0.0.1-SNAPSHOT.jar > log.file 2>&1 &
来源: