限时折扣 处理任务状态 定时任务

公众号 通知消息处理
This commit is contained in:
wangw 2025-10-22 09:26:27 +08:00
parent 022dafec0b
commit 3658dce209
4 changed files with 98 additions and 18 deletions

View File

@ -1,20 +1,25 @@
package com.czg.controller; package com.czg.controller;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.entity.UserInfo; import com.czg.account.entity.UserInfo;
import com.czg.account.service.UserInfoService; import com.czg.account.service.UserInfoService;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/** /**
* 公众号 通知 * 公众号 通知
@ -52,18 +57,31 @@ public class NotifyController {
else if ("POST".equals(request.getMethod())) { else if ("POST".equals(request.getMethod())) {
log.info("接收到微信 POST 消息请求 - signature: {}, timestamp: {}, nonce: {}", log.info("接收到微信 POST 消息请求 - signature: {}, timestamp: {}, nonce: {}",
signature, timestamp, nonce); signature, timestamp, nonce);
// 读取 POST 请求体中的 XML 数据微信推送的消息格式为 XML // 1. 读取请求体中的 XML 数据
String xmlData = readPostXml(request); String xmlData = readPostXml(request);
JSONObject jsonObject = JSON.parseObject(xmlData); if (xmlData.isEmpty()) {
log.info("微信 POST 消息内容: {}", jsonObject); log.error("微信 POST 消息体为空");
return "";
}
log.info("微信 POST 消息 XML 原始内容: {}", xmlData);
// 2. 解析 XML Map便于获取字段
Map<String, String> messageMap;
try {
messageMap = parseXmlToMap(xmlData);
} catch (DocumentException e) {
log.error("XML 解析失败,原始内容: {}", xmlData, e);
return "";
}
log.info("微信 POST 消息内容: {}", messageMap);
// 获取消息类型 event // 获取消息类型 event
String msgType = jsonObject.getString("MsgType"); String msgType = messageMap.get("MsgType");
// 获取事件类型 unsubscribe用户取消关注 subscribe用户关注 // 获取事件类型 unsubscribe用户取消关注 subscribe用户关注
String event = jsonObject.getString("Event"); String event = messageMap.get("Event");
// 获取用户 OpenID // 获取用户 OpenID
String openId = jsonObject.getString("FromUserName"); String openId = messageMap.get("FromUserName");
//携带参数 //携带参数
String eventKey = jsonObject.getString("EventKey"); String eventKey = messageMap.get("EventKey");
Long userId = null; Long userId = null;
log.info("解析结果 - 消息类型: {}, 事件类型: {}, 用户 OpenID: {} 携带参数: {}", msgType, event, openId, eventKey); log.info("解析结果 - 消息类型: {}, 事件类型: {}, 用户 OpenID: {} 携带参数: {}", msgType, event, openId, eventKey);
if (eventKey != null && eventKey.startsWith("qrscene_")) { if (eventKey != null && eventKey.startsWith("qrscene_")) {
@ -114,4 +132,47 @@ public class NotifyController {
return xmlSb.toString(); return xmlSb.toString();
} }
// XML 字符串解析为 Map<String, String>
private static Map<String, String> parseXmlToMap(String xmlData) throws DocumentException {
Map<String, String> resultMap = new HashMap<>(16);
Document document = DocumentHelper.parseText(xmlData);
Element rootElement = document.getRootElement();
// 遍历所有子节点将节点名和文本值存入 Map
Iterator<Element> elementIterator = rootElement.elementIterator();
while (elementIterator.hasNext()) {
Element childElement = elementIterator.next();
resultMap.put(childElement.getName(), childElement.getTextTrim());
}
return resultMap;
}
public static void main(String[] args) {
String str = "<xml><ToUserName><![CDATA[gh_11fc27b7ef34]]></ToUserName><FromUserName><![CDATA[owWHW7Tzeh2gx3WmFsFSxBq2JUTk]]></FromUserName><CreateTime>1761095747</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[subscribe]]></Event><EventKey><![CDATA[qrscene_275]]></EventKey><Ticket><![CDATA[gQGF8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyUTZDVHRTMXhmbUoxYUlYdk5GY2sAAgSsLvhoAwQAjScA]]></Ticket></xml>";
// 2. 解析 XML Map便于获取字段
Map<String, String> messageMap = new HashMap<>();
try {
messageMap = parseXmlToMap(str);
} catch (DocumentException e) {
log.error("XML 解析失败,", e);
}
log.info("微信 POST 消息内容: {}", messageMap);
//携带参数
String eventKey = messageMap.get("EventKey");
Long userId = null;
if (eventKey != null && eventKey.startsWith("qrscene_")) {
try {
// 截取 "qrscene_" 前缀后的字符串长度为 8并转为 Long
String numberStr = eventKey.substring("qrscene_".length());
userId = Long.parseLong(numberStr);
} catch (NumberFormatException e) {
log.error("EventKey 后缀不是有效数字eventKey: {}", eventKey, e);
}
}
System.out.println("userId: " + userId);
}
} }

View File

@ -42,13 +42,13 @@ public class AAMarketTasks {
memberTask.task(); memberTask.task();
} }
//满减活动定时任务 //满减活动/限时折扣 处理任务状态 定时任务
@Resource @Resource
private DiscountActivityTask discountActivityTask; private ActivityStatusTask activityStatusTask;
//每天0点 0分 1秒 执行 //每天0点 0分 1秒 执行
@Scheduled(cron = "1 0 0 * * ? ") @Scheduled(cron = "1 0 0 * * ? ")
public void discountActivityTask() { public void activityStatusTask() {
discountActivityTask.task(); activityStatusTask.task();
} }

View File

@ -1,7 +1,9 @@
package com.czg.task; package com.czg.task;
import com.czg.market.entity.MkDiscountActivity; import com.czg.market.entity.MkDiscountActivity;
import com.czg.market.entity.MkLimitTimeDiscount;
import com.czg.market.service.MkDiscountActivityService; import com.czg.market.service.MkDiscountActivityService;
import com.czg.market.service.MkLimitTimeDiscountService;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -17,14 +19,17 @@ import java.time.LocalDateTime;
*/ */
@Slf4j @Slf4j
@Component @Component
public class DiscountActivityTask { public class ActivityStatusTask {
@Resource @Resource
private MkDiscountActivityService discountActivityService; private MkDiscountActivityService discountActivityService;
@Resource
private MkLimitTimeDiscountService limitTimeDiscountService;
/** /**
* 满减活动 过期 * 满减活动/限时折扣 任务状态更新任务
*/ */
public void task() { public void task() {
//满减活动
discountActivityService.update(new MkDiscountActivity().setStatus(2), discountActivityService.update(new MkDiscountActivity().setStatus(2),
new QueryWrapper() new QueryWrapper()
.eq(MkDiscountActivity::getStatus, 1) .eq(MkDiscountActivity::getStatus, 1)
@ -34,5 +39,17 @@ public class DiscountActivityTask {
discountActivityService.update(new MkDiscountActivity().setStatus(3), discountActivityService.update(new MkDiscountActivity().setStatus(3),
new QueryWrapper().le(MkDiscountActivity::getValidEndTime, LocalDateTime.now()) new QueryWrapper().le(MkDiscountActivity::getValidEndTime, LocalDateTime.now())
); );
//限时折扣
limitTimeDiscountService.update(new MkLimitTimeDiscount().setStatus(2),
new QueryWrapper()
.eq(MkLimitTimeDiscount::getStatus, 1)
.le(MkLimitTimeDiscount::getValidStartTime, LocalDateTime.now())
.gt(MkLimitTimeDiscount::getValidEndTime, LocalDateTime.now())
);
limitTimeDiscountService.update(new MkLimitTimeDiscount().setStatus(3),
new QueryWrapper().le(MkLimitTimeDiscount::getValidEndTime, LocalDateTime.now())
);
} }
} }

View File

@ -9,6 +9,7 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
@ -27,6 +28,7 @@ import java.time.LocalTime;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Table("mk_limit_time_discount") @Table("mk_limit_time_discount")
@Accessors(chain = true)
public class MkLimitTimeDiscount implements Serializable { public class MkLimitTimeDiscount implements Serializable {
@Serial @Serial