Commit e9223bf3406ddb651590ad044ea0c57849bb14d2
1 parent
dc302772
主体代码编写完成
Showing
21 changed files
with
552 additions
and
82 deletions
fw-hestia-common/src/main/java/cn/fw/hestia/common/constant/MessageStr.java
fw-hestia-domain/src/main/java/cn/fw/hestia/domain/db/MessageHistory.java
1 | 1 | package cn.fw.hestia.domain.db; |
2 | 2 | |
3 | -import cn.fw.hestia.domain.enums.SendStateEnum; | |
3 | +import cn.fw.hestia.domain.enums.MessageStateEnum; | |
4 | 4 | import com.baomidou.mybatisplus.annotation.*; |
5 | 5 | import com.baomidou.mybatisplus.extension.activerecord.Model; |
6 | 6 | import lombok.Data; |
... | ... | @@ -65,7 +65,11 @@ public class MessageHistory extends Model<MessageHistory> { |
65 | 65 | /** |
66 | 66 | * 发送状态 |
67 | 67 | */ |
68 | - private SendStateEnum sendState; | |
68 | + private MessageStateEnum state; | |
69 | + /** | |
70 | + * 是否有效 | |
71 | + */ | |
72 | + private Boolean yn; | |
69 | 73 | /** |
70 | 74 | * 创建时间 |
71 | 75 | */ | ... | ... |
fw-hestia-domain/src/main/java/cn/fw/hestia/domain/enums/SendStateEnum.java renamed to fw-hestia-domain/src/main/java/cn/fw/hestia/domain/enums/MessageStateEnum.java
... | ... | @@ -11,15 +11,15 @@ import lombok.Getter; |
11 | 11 | * @description : 发送状态 |
12 | 12 | * @date: 2020-08-11 17:37 |
13 | 13 | */ |
14 | -public enum SendStateEnum implements IEnum<Integer> { | |
14 | +public enum MessageStateEnum implements IEnum<Integer> { | |
15 | 15 | /** |
16 | - * 等待回调 | |
16 | + * 未处理 | |
17 | 17 | */ |
18 | - OK(1, "发送成功"), | |
18 | + MADA(1, "未处理"), | |
19 | 19 | /** |
20 | - * 完成回调 | |
20 | + * 已处理 | |
21 | 21 | */ |
22 | - FAIL(2, "发送失败"), | |
22 | + SUMI(2, "已处理"), | |
23 | 23 | ; |
24 | 24 | |
25 | 25 | /** |
... | ... | @@ -32,7 +32,7 @@ public enum SendStateEnum implements IEnum<Integer> { |
32 | 32 | @Getter |
33 | 33 | private final String name; |
34 | 34 | |
35 | - SendStateEnum(final Integer value, final String name) { | |
35 | + MessageStateEnum(final Integer value, final String name) { | |
36 | 36 | this.value = value; |
37 | 37 | this.name = name; |
38 | 38 | } |
... | ... | @@ -41,8 +41,8 @@ public enum SendStateEnum implements IEnum<Integer> { |
41 | 41 | * 根据枚举值获取枚举对象 |
42 | 42 | */ |
43 | 43 | @JsonCreator |
44 | - public static SendStateEnum ofValue(final Integer value) { | |
45 | - for (final SendStateEnum stateEnum : SendStateEnum.values()) { | |
44 | + public static MessageStateEnum ofValue(final Integer value) { | |
45 | + for (final MessageStateEnum stateEnum : MessageStateEnum.values()) { | |
46 | 46 | if (stateEnum.value.equals(value)) { |
47 | 47 | return stateEnum; |
48 | 48 | } |
... | ... | @@ -68,7 +68,7 @@ public enum SendStateEnum implements IEnum<Integer> { |
68 | 68 | */ |
69 | 69 | @JsonCreator |
70 | 70 | public static String getNameByVale(final Integer value) { |
71 | - for (final SendStateEnum stateEnum : SendStateEnum.values()) { | |
71 | + for (final MessageStateEnum stateEnum : MessageStateEnum.values()) { | |
72 | 72 | if (stateEnum.value.equals(value)) { |
73 | 73 | return stateEnum.getName(); |
74 | 74 | } | ... | ... |
fw-hestia-domain/src/main/java/cn/fw/hestia/domain/vo/Demo.java deleted
fw-hestia-domain/src/main/java/cn/fw/hestia/domain/vo/HistoryQuery.java
0 → 100644
1 | +package cn.fw.hestia.domain.vo; | |
2 | + | |
3 | +import cn.fw.common.page.BasePageQuery; | |
4 | +import cn.fw.common.web.annotation.LoginContextField; | |
5 | +import lombok.Data; | |
6 | +import lombok.EqualsAndHashCode; | |
7 | +import lombok.ToString; | |
8 | + | |
9 | +/** | |
10 | + * @author : kurisu | |
11 | + * @className : HistoryQuery | |
12 | + * @description : 查询条件 | |
13 | + * @date: 2021-09-25 10:45 | |
14 | + */ | |
15 | +@Data | |
16 | +@ToString(callSuper = true) | |
17 | +@EqualsAndHashCode(callSuper = true) | |
18 | +public class HistoryQuery extends BasePageQuery { | |
19 | + | |
20 | + @LoginContextField(LoginContextField.Name.USER_ID) | |
21 | + private Long memberId; | |
22 | +} | ... | ... |
fw-hestia-domain/src/main/java/cn/fw/hestia/domain/vo/MessageHistoryVO.java
0 → 100644
1 | +package cn.fw.hestia.domain.vo; | |
2 | + | |
3 | +import cn.fw.hestia.domain.db.MessageHistory; | |
4 | +import lombok.Data; | |
5 | +import lombok.ToString; | |
6 | + | |
7 | +import java.util.Date; | |
8 | +import java.util.Objects; | |
9 | + | |
10 | +/** | |
11 | + * @author : kurisu | |
12 | + * @className : Demo | |
13 | + * @description : | |
14 | + * @date: 2021-09-23 15:26 | |
15 | + */ | |
16 | +@Data | |
17 | +@ToString | |
18 | +public class MessageHistoryVO { | |
19 | + private Long messageId; | |
20 | + /** | |
21 | + * 会员id | |
22 | + */ | |
23 | + private Long memberId; | |
24 | + /** | |
25 | + * 消息内容 | |
26 | + */ | |
27 | + private String title; | |
28 | + /** | |
29 | + * 备注 | |
30 | + */ | |
31 | + private String remark; | |
32 | + /** | |
33 | + * 是否已读 | |
34 | + */ | |
35 | + private Boolean readz; | |
36 | + /** | |
37 | + * 发送时间 | |
38 | + */ | |
39 | + private Date messageTime; | |
40 | + | |
41 | + public static MessageHistoryVO with(MessageHistory history) { | |
42 | + if (Objects.isNull(history)) { | |
43 | + return null; | |
44 | + } | |
45 | + MessageHistoryVO vo = new MessageHistoryVO(); | |
46 | + vo.setMessageId(history.getId()); | |
47 | + vo.setMemberId(history.getMemberId()); | |
48 | + vo.setTitle(history.getTitle()); | |
49 | + vo.setReadz(history.getReadz()); | |
50 | + vo.setRemark(history.getRemark()); | |
51 | + vo.setMessageTime(history.getCreateTime()); | |
52 | + return vo; | |
53 | + } | |
54 | +} | ... | ... |
fw-hestia-rpc/src/main/java/cn/fw/hestia/rpc/passport/TemplateMessageService.java
1 | 1 | package cn.fw.hestia.rpc.passport; |
2 | 2 | |
3 | 3 | import cn.fw.data.base.domain.common.Message; |
4 | +import cn.fw.hestia.common.constant.MessageStr; | |
4 | 5 | import cn.fw.hestia.common.utils.StringUtils; |
5 | 6 | import cn.fw.hestia.rpc.passport.dto.TMParam; |
6 | 7 | import cn.fw.passport.sdk.api.WxMpTemplateMessageApi; |
7 | 8 | import cn.fw.passport.sdk.api.param.WxMpTempMessageData; |
8 | 9 | import cn.fw.passport.sdk.api.param.WxMpTempMessageParam; |
9 | -import lombok.Getter; | |
10 | +import com.alibaba.fastjson.JSONArray; | |
10 | 11 | import lombok.extern.slf4j.Slf4j; |
11 | 12 | import org.springframework.stereotype.Service; |
12 | 13 | |
13 | -import java.util.Arrays; | |
14 | 14 | import java.util.List; |
15 | 15 | |
16 | 16 | /** |
... | ... | @@ -31,12 +31,6 @@ public class TemplateMessageService { |
31 | 31 | } |
32 | 32 | |
33 | 33 | /** |
34 | - * 消息模板Code | |
35 | - */ | |
36 | - @Getter | |
37 | - private final String templateCode = "OPENTM412432053"; | |
38 | - | |
39 | - /** | |
40 | 34 | * 发送消息通知 |
41 | 35 | * |
42 | 36 | * @param messageParam |
... | ... | @@ -46,34 +40,33 @@ public class TemplateMessageService { |
46 | 40 | try { |
47 | 41 | WxMpTempMessageParam param = new WxMpTempMessageParam(); |
48 | 42 | param.setCusId(messageParam.getMemberId()); |
49 | - param.setTempCode(getTemplateCode()); | |
43 | + param.setTempCode(messageParam.getTemplateCode()); | |
50 | 44 | WxMpTempMessageData remark = new WxMpTempMessageData(); |
51 | 45 | remark.setValue(messageParam.getRemark()); |
52 | - remark.setColor("#a61b29"); | |
53 | 46 | param.setRemark(remark); |
54 | 47 | param.setTitle(new WxMpTempMessageData(messageParam.getTitle())); |
55 | - List<WxMpTempMessageData> keywords = Arrays.asList( | |
56 | - new WxMpTempMessageData(messageParam.getChangeType()), | |
57 | - //门店 | |
58 | - new WxMpTempMessageData(messageParam.getChangeResult()) | |
59 | - //到期时间 | |
60 | - ); | |
61 | - param.setKeyWordList(keywords); | |
62 | - param.setPagePath(getPagePath(messageParam.getPath(), messageParam.getSceneToken())); | |
48 | + if (StringUtils.isValid(messageParam.getKeywords())) { | |
49 | + List<WxMpTempMessageData> keywords = JSONArray.parseArray(messageParam.getKeywords(), WxMpTempMessageData.class); | |
50 | + param.setKeyWordList(keywords); | |
51 | + } | |
52 | + String pagePath = getPagePath(messageParam.getPath(), messageParam.getSceneToken()); | |
53 | + if (StringUtils.isValid(pagePath)) { | |
54 | + param.setPagePath(pagePath); | |
55 | + } | |
63 | 56 | Message<?> msg = wxMpTemplateMessageApi.send(param); |
64 | 57 | if (!msg.isSuccess()) { |
65 | 58 | log.error("【passport系统】发送模板消息失败:{}", msg.getResult()); |
66 | 59 | return msg.getResult(); |
67 | 60 | } |
68 | - return ""; | |
61 | + return MessageStr.SUCCEED_STR; | |
69 | 62 | } catch (Exception e) { |
70 | 63 | log.error("发送模板消息失败", e); |
71 | - return "系统异常"; | |
64 | + return "系统调用异常"; | |
72 | 65 | } |
73 | 66 | } |
74 | 67 | |
75 | 68 | |
76 | - private String getPagePath(String path, String sceneToken) { | |
69 | + private String getPagePath(String path, Long sceneToken) { | |
77 | 70 | if (StringUtils.isEmpty(path)) { |
78 | 71 | return null; |
79 | 72 | } | ... | ... |
fw-hestia-rpc/src/main/java/cn/fw/hestia/rpc/passport/dto/TMParam.java
... | ... | @@ -28,26 +28,20 @@ public class TMParam { |
28 | 28 | * 标题 |
29 | 29 | */ |
30 | 30 | private String title; |
31 | + | |
32 | + private String keywords; | |
31 | 33 | /** |
32 | 34 | * 备注 |
33 | 35 | */ |
34 | 36 | private String remark; |
35 | - /** | |
36 | - * 变更类型 | |
37 | - */ | |
38 | - private String changeType; | |
39 | - /** | |
40 | - * 变更结果 | |
41 | - */ | |
42 | - private String changeResult; | |
37 | + | |
43 | 38 | /** |
44 | 39 | * 如需跳转小程序,则是小程序页面路径 |
45 | 40 | */ |
46 | 41 | private String path; |
47 | - /** | |
48 | - * 跳转小程序所携带的参数 | |
49 | - */ | |
50 | - private Map<String, String> paramMap; | |
51 | 42 | |
52 | - private String sceneToken; | |
43 | + | |
44 | + private Long sceneToken; | |
45 | + | |
46 | + private String templateCode; | |
53 | 47 | } | ... | ... |
fw-hestia-sdk/src/main/java/cn/fw/hestia/sdk/api/IMessageCenterService.java
... | ... | @@ -3,10 +3,12 @@ package cn.fw.hestia.sdk.api; |
3 | 3 | import cn.fw.data.base.domain.common.Message; |
4 | 4 | import cn.fw.hestia.sdk.params.TemplateMessageParam; |
5 | 5 | import org.springframework.cloud.openfeign.FeignClient; |
6 | +import org.springframework.web.bind.annotation.DeleteMapping; | |
6 | 7 | import org.springframework.web.bind.annotation.PostMapping; |
7 | 8 | import org.springframework.web.bind.annotation.RequestBody; |
8 | 9 | |
9 | 10 | import javax.validation.Valid; |
11 | +import javax.validation.constraints.NotNull; | |
10 | 12 | |
11 | 13 | /** |
12 | 14 | * @author : kurisu |
... | ... | @@ -16,19 +18,22 @@ import javax.validation.Valid; |
16 | 18 | */ |
17 | 19 | @FeignClient(value = "fw-hestia", path = "/api/hestia/mc") |
18 | 20 | public interface IMessageCenterService { |
21 | + | |
19 | 22 | /** |
20 | - * 异步发送模板消息 | |
23 | + * 发送模板消息 | |
24 | + * | |
21 | 25 | * @param templateMessageParam |
22 | 26 | * @return |
23 | 27 | */ |
24 | - @PostMapping("/asynSend") | |
25 | - Message<Long> asynSend(@Valid @RequestBody TemplateMessageParam templateMessageParam); | |
28 | + @PostMapping("/send") | |
29 | + Message<Long> send(@Valid @RequestBody TemplateMessageParam templateMessageParam); | |
26 | 30 | |
27 | 31 | /** |
28 | - * 同步 | |
29 | - * @param templateMessageParam | |
32 | + * 撤回消息 | |
33 | + * | |
34 | + * @param sceneToken | |
30 | 35 | * @return |
31 | 36 | */ |
32 | - @PostMapping("/send") | |
33 | - Message<Long> send(@Valid @RequestBody TemplateMessageParam templateMessageParam); | |
37 | + @DeleteMapping("/send") | |
38 | + Message<Boolean> revokeMessage(@NotNull(message = "Token不能为空") Long sceneToken); | |
34 | 39 | } | ... | ... |
fw-hestia-sdk/src/main/java/cn/fw/hestia/sdk/params/TemplateMessageParam.java
... | ... | @@ -3,6 +3,8 @@ package cn.fw.hestia.sdk.params; |
3 | 3 | import lombok.Data; |
4 | 4 | import lombok.ToString; |
5 | 5 | |
6 | +import javax.validation.constraints.NotBlank; | |
7 | +import javax.validation.constraints.NotNull; | |
6 | 8 | import java.util.Map; |
7 | 9 | |
8 | 10 | /** |
... | ... | @@ -15,6 +17,12 @@ import java.util.Map; |
15 | 17 | * 变更结果:{{keyword2.DATA}} |
16 | 18 | * {{remark.DATA}} |
17 | 19 | * |
20 | + * 示例: | |
21 | + * 尊敬的客户,您的业务状态已经发生变更 变更详情如下: | |
22 | + * 变更类型:组局地点 | |
23 | + * 变更结果:由清水河改为滨江 | |
24 | + * 如有疑问,请拨打客服电话 | |
25 | + * | |
18 | 26 | * @author kurisu |
19 | 27 | */ |
20 | 28 | @Data |
... | ... | @@ -23,10 +31,12 @@ public class TemplateMessageParam { |
23 | 31 | /** |
24 | 32 | * 会员id |
25 | 33 | */ |
34 | + @NotNull(message = "会员id不能为空") | |
26 | 35 | private Long memberId; |
27 | 36 | /** |
28 | - * 标题 对应「first」字段 | |
37 | + * 标题内容 对应「first」字段 | |
29 | 38 | */ |
39 | + @NotBlank(message = "标题内容不能为空") | |
30 | 40 | private String title; |
31 | 41 | /** |
32 | 42 | * 备注 |
... | ... | @@ -35,10 +45,12 @@ public class TemplateMessageParam { |
35 | 45 | /** |
36 | 46 | * 变更类型 |
37 | 47 | */ |
48 | + @NotBlank(message = "变更类型不能为空") | |
38 | 49 | private String changeType; |
39 | 50 | /** |
40 | 51 | * 变更结果 |
41 | 52 | */ |
53 | + @NotBlank(message = "变更结果不能为空") | |
42 | 54 | private String changeResult; |
43 | 55 | /** |
44 | 56 | * 如需跳转小程序,则是小程序页面路径 | ... | ... |
fw-hestia-sdk/src/main/java/cn/fw/hestia/sdk/result/MessageSendMq.java
0 → 100644
1 | +package cn.fw.hestia.sdk.result; | |
2 | + | |
3 | +import lombok.AllArgsConstructor; | |
4 | +import lombok.Data; | |
5 | +import lombok.NoArgsConstructor; | |
6 | + | |
7 | +import java.util.Date; | |
8 | + | |
9 | +/** | |
10 | + * @author : kurisu | |
11 | + * @className : MessageSendMQ | |
12 | + * @description : 消息发送成功的通知 | |
13 | + * @date: 2021-09-25 09:27 | |
14 | + */ | |
15 | +@Data | |
16 | +@AllArgsConstructor | |
17 | +@NoArgsConstructor | |
18 | +public class MessageSendMq { | |
19 | + public final static String TOPIC = "message_send"; | |
20 | + /** | |
21 | + * 唯一标识 | |
22 | + */ | |
23 | + private Long sceneToken; | |
24 | + /** | |
25 | + * 发送时间 | |
26 | + */ | |
27 | + private Date sendTime; | |
28 | +} | ... | ... |
fw-hestia-server/src/main/java/cn/fw/hestia/server/controller/api/MessageCenterServiceImpl.java
... | ... | @@ -4,13 +4,15 @@ import cn.fw.common.web.annotation.ControllerMethod; |
4 | 4 | import cn.fw.data.base.domain.common.Message; |
5 | 5 | import cn.fw.hestia.sdk.api.IMessageCenterService; |
6 | 6 | import cn.fw.hestia.sdk.params.TemplateMessageParam; |
7 | +import cn.fw.hestia.service.buz.MessageCenterBizService; | |
7 | 8 | import lombok.extern.slf4j.Slf4j; |
8 | -import org.springframework.web.bind.annotation.PostMapping; | |
9 | -import org.springframework.web.bind.annotation.RequestBody; | |
10 | -import org.springframework.web.bind.annotation.RequestMapping; | |
11 | -import org.springframework.web.bind.annotation.RestController; | |
9 | +import org.springframework.beans.factory.annotation.Autowired; | |
10 | +import org.springframework.web.bind.annotation.*; | |
12 | 11 | |
13 | 12 | import javax.validation.Valid; |
13 | +import javax.validation.constraints.NotNull; | |
14 | + | |
15 | +import static cn.fw.common.web.util.ResultBuilder.success; | |
14 | 16 | |
15 | 17 | /** |
16 | 18 | * @author : kurisu |
... | ... | @@ -22,18 +24,24 @@ import javax.validation.Valid; |
22 | 24 | @RestController |
23 | 25 | @RequestMapping("/api/hestia/mc") |
24 | 26 | public class MessageCenterServiceImpl implements IMessageCenterService { |
27 | + private final MessageCenterBizService messageCenterBizService; | |
25 | 28 | |
26 | - @PostMapping("/asynSend") | |
27 | - @Override | |
28 | - @ControllerMethod("保存进站记录") | |
29 | - public Message<Long> asynSend(@Valid @RequestBody TemplateMessageParam templateMessageParam) { | |
30 | - return null; | |
29 | + @Autowired | |
30 | + public MessageCenterServiceImpl(final MessageCenterBizService messageCenterBizService) { | |
31 | + this.messageCenterBizService = messageCenterBizService; | |
31 | 32 | } |
32 | 33 | |
33 | 34 | @PostMapping("/send") |
34 | 35 | @Override |
35 | - @ControllerMethod("保存进站记录") | |
36 | + @ControllerMethod("发送模板消息") | |
36 | 37 | public Message<Long> send(@Valid @RequestBody TemplateMessageParam templateMessageParam) { |
37 | - return null; | |
38 | + return success(messageCenterBizService.saveMessage(templateMessageParam)); | |
39 | + } | |
40 | + | |
41 | + @Override | |
42 | + @DeleteMapping("/revoke") | |
43 | + @ControllerMethod("撤回消息") | |
44 | + public Message<Boolean> revokeMessage(@NotNull(message = "Token不能为空") Long sceneToken) { | |
45 | + return success(messageCenterBizService.revokeMessage(sceneToken)); | |
38 | 46 | } |
39 | 47 | } | ... | ... |
fw-hestia-server/src/main/java/cn/fw/hestia/server/controller/wx/MessageCenterController.java
0 → 100644
1 | +package cn.fw.hestia.server.controller.wx; | |
2 | + | |
3 | +import cn.fw.common.page.AppPage; | |
4 | +import cn.fw.common.web.annotation.ControllerMethod; | |
5 | +import cn.fw.common.web.auth.PassportAuthBean; | |
6 | +import cn.fw.common.web.auth.annotation.CurrentUser; | |
7 | +import cn.fw.data.base.domain.common.Message; | |
8 | +import cn.fw.hestia.domain.vo.HistoryQuery; | |
9 | +import cn.fw.hestia.domain.vo.MessageHistoryVO; | |
10 | +import cn.fw.hestia.service.buz.MessageCenterBizService; | |
11 | +import cn.fw.security.auth.client.annotation.Authorization; | |
12 | +import cn.fw.security.auth.client.enums.AuthType; | |
13 | +import lombok.extern.slf4j.Slf4j; | |
14 | +import org.springframework.beans.factory.annotation.Autowired; | |
15 | +import org.springframework.validation.annotation.Validated; | |
16 | +import org.springframework.web.bind.annotation.GetMapping; | |
17 | +import org.springframework.web.bind.annotation.RequestMapping; | |
18 | +import org.springframework.web.bind.annotation.RestController; | |
19 | + | |
20 | +import javax.validation.constraints.NotNull; | |
21 | +import java.util.Map; | |
22 | + | |
23 | +import static cn.fw.common.web.util.ResultBuilder.success; | |
24 | + | |
25 | +/** | |
26 | + * @author : kurisu | |
27 | + * @className : MessageCenterController | |
28 | + * @description : | |
29 | + * @date: 2021-09-23 15:39 | |
30 | + */ | |
31 | +@Slf4j | |
32 | +@Validated | |
33 | +@RestController | |
34 | +@Authorization(AuthType.WECHAT) | |
35 | +@RequestMapping("/wx/message") | |
36 | +public class MessageCenterController { | |
37 | + private final MessageCenterBizService messageCenterBizService; | |
38 | + | |
39 | + @Autowired | |
40 | + public MessageCenterController(final MessageCenterBizService messageCenterBizService) { | |
41 | + this.messageCenterBizService = messageCenterBizService; | |
42 | + } | |
43 | + | |
44 | + @GetMapping("/unread") | |
45 | + @ControllerMethod("查询消息未读数") | |
46 | + public Message<Integer> send(@CurrentUser PassportAuthBean user) { | |
47 | + return success(messageCenterBizService.unreadCount(user.getUserId())); | |
48 | + } | |
49 | + | |
50 | + @GetMapping("/query/pageParams") | |
51 | + @ControllerMethod("查询小程序页面的参数") | |
52 | + public Message<Map<String, String>> queryPageParams(@NotNull(message = "sceneToken不能为空") final Long sceneToken) { | |
53 | + return success(messageCenterBizService.queryPageParams(sceneToken)); | |
54 | + } | |
55 | + | |
56 | + @GetMapping("/query/history") | |
57 | + @ControllerMethod("查询消息历史记录") | |
58 | + public Message<AppPage<MessageHistoryVO>> queryHistory(HistoryQuery query) { | |
59 | + return success(messageCenterBizService.queryHistory(query)); | |
60 | + } | |
61 | +} | ... | ... |
fw-hestia-server/src/main/java/cn/fw/hestia/server/task/SendMessageTask.java
0 → 100644
1 | +package cn.fw.hestia.server.task; | |
2 | + | |
3 | +import cn.fw.hestia.domain.db.MessageHistory; | |
4 | +import cn.fw.hestia.domain.enums.MessageStateEnum; | |
5 | +import cn.fw.hestia.service.buz.MessageCenterBizService; | |
6 | +import cn.fw.hestia.service.data.MessageHistoryService; | |
7 | +import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |
8 | +import org.springframework.beans.factory.annotation.Autowired; | |
9 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |
10 | +import org.springframework.scheduling.annotation.Scheduled; | |
11 | +import org.springframework.stereotype.Component; | |
12 | +import org.springframework.transaction.annotation.Transactional; | |
13 | +import org.springframework.util.CollectionUtils; | |
14 | + | |
15 | +import java.util.Date; | |
16 | +import java.util.List; | |
17 | + | |
18 | +/** | |
19 | + * @author : kurisu | |
20 | + * @className : FollowNoticeTask | |
21 | + * @description : 服务号消息定时任务 | |
22 | + * @date: 2020-08-25 16:57 | |
23 | + */ | |
24 | +@Component | |
25 | +@ConditionalOnProperty(prefix = "task", name = "switch", havingValue = "on") | |
26 | +public class SendMessageTask { | |
27 | + private final MessageCenterBizService messageCenterBizService; | |
28 | + private final MessageHistoryService messageHistoryService; | |
29 | + | |
30 | + private final static int MAX_FREQUENCY = 5; | |
31 | + | |
32 | + @Autowired | |
33 | + public SendMessageTask(final MessageCenterBizService messageCenterBizService, | |
34 | + final MessageHistoryService messageHistoryService) { | |
35 | + this.messageCenterBizService = messageCenterBizService; | |
36 | + this.messageHistoryService = messageHistoryService; | |
37 | + } | |
38 | + | |
39 | + /** | |
40 | + * 发送模板消息 | |
41 | + */ | |
42 | + @Scheduled(initialDelay = 1000 * 10, fixedRate = 1000 * 10) | |
43 | + @Transactional(rollbackFor = Exception.class) | |
44 | + public void sendNotice() { | |
45 | + List<MessageHistory> list = messageHistoryService.list(Wrappers.<MessageHistory>lambdaQuery() | |
46 | + .eq(MessageHistory::getState, MessageStateEnum.MADA) | |
47 | + .eq(MessageHistory::getYn, Boolean.TRUE) | |
48 | + .lt(MessageHistory::getFrequency, MAX_FREQUENCY) | |
49 | + .lt(MessageHistory::getSendTime, new Date()) | |
50 | + ); | |
51 | + if (CollectionUtils.isEmpty(list)) { | |
52 | + return; | |
53 | + } | |
54 | + for (MessageHistory history : list) { | |
55 | + messageCenterBizService.sendMessage(history); | |
56 | + } | |
57 | + } | |
58 | +} | ... | ... |
fw-hestia-server/src/main/resources/application.yml
... | ... | @@ -37,7 +37,7 @@ spring: |
37 | 37 | max-wait: 1S |
38 | 38 | min-idle: 3 |
39 | 39 | port: 6379 |
40 | - database: 3 | |
40 | + database: 4 | |
41 | 41 | rest-result-processor: |
42 | 42 | enabled: false |
43 | 43 | servlet: |
... | ... | @@ -91,7 +91,7 @@ jedis: |
91 | 91 | test-while-idle: true |
92 | 92 | host: 192.168.0.8 |
93 | 93 | port: 6379 |
94 | - db: 3 | |
94 | + db: 4 | |
95 | 95 | mybatis-plus: |
96 | 96 | configuration: |
97 | 97 | cache-enabled: false | ... | ... |
fw-hestia-service/src/main/java/cn/fw/hestia/component/SendMsgProducer.java
0 → 100644
1 | +package cn.fw.hestia.component; | |
2 | + | |
3 | +import cn.fw.hestia.sdk.result.MessageSendMq; | |
4 | +import lombok.extern.slf4j.Slf4j; | |
5 | +import org.apache.rocketmq.spring.core.RocketMQTemplate; | |
6 | +import org.springframework.beans.factory.annotation.Autowired; | |
7 | +import org.springframework.stereotype.Component; | |
8 | +import org.springframework.web.bind.annotation.RequestMapping; | |
9 | + | |
10 | +/** | |
11 | + * @author kurisu | |
12 | + */ | |
13 | +@Slf4j | |
14 | +@Component | |
15 | +public class SendMsgProducer { | |
16 | + @Autowired | |
17 | + private RocketMQTemplate rocketMQTemplate; | |
18 | + | |
19 | + @RequestMapping(value = "send") | |
20 | + public void send(MessageSendMq messageSendMq) { | |
21 | + try { | |
22 | + log.info("模板消息发送成功mq: body:[{}]", messageSendMq); | |
23 | + rocketMQTemplate.syncSend(MessageSendMq.TOPIC + ":*", messageSendMq); | |
24 | + } catch (Exception e) { | |
25 | + e.printStackTrace(); | |
26 | + } | |
27 | + } | |
28 | +} | |
0 | 29 | \ No newline at end of file | ... | ... |
fw-hestia-service/src/main/java/cn/fw/hestia/service/buz/MessageCenterBizService.java
0 → 100644
1 | +package cn.fw.hestia.service.buz; | |
2 | + | |
3 | +import cn.fw.common.data.mybatis.pagination.PageData; | |
4 | +import cn.fw.common.page.AppPage; | |
5 | +import cn.fw.hestia.common.constant.MessageStr; | |
6 | +import cn.fw.hestia.common.utils.DateUtil; | |
7 | +import cn.fw.hestia.common.utils.StringUtils; | |
8 | +import cn.fw.hestia.component.SendMsgProducer; | |
9 | +import cn.fw.hestia.domain.db.MessageHistory; | |
10 | +import cn.fw.hestia.domain.db.SendLog; | |
11 | +import cn.fw.hestia.domain.enums.MessageStateEnum; | |
12 | +import cn.fw.hestia.domain.vo.HistoryQuery; | |
13 | +import cn.fw.hestia.domain.vo.MessageHistoryVO; | |
14 | +import cn.fw.hestia.rpc.passport.TemplateMessageService; | |
15 | +import cn.fw.hestia.rpc.passport.dto.TMParam; | |
16 | +import cn.fw.hestia.sdk.params.TemplateMessageParam; | |
17 | +import cn.fw.hestia.sdk.result.MessageSendMq; | |
18 | +import cn.fw.hestia.service.data.MessageHistoryService; | |
19 | +import cn.fw.hestia.service.data.SendLogService; | |
20 | +import cn.fw.passport.sdk.api.param.WxMpTempMessageData; | |
21 | +import com.alibaba.fastjson.JSON; | |
22 | +import com.alibaba.fastjson.JSONArray; | |
23 | +import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |
24 | +import lombok.Getter; | |
25 | +import lombok.RequiredArgsConstructor; | |
26 | +import lombok.extern.slf4j.Slf4j; | |
27 | +import org.springframework.stereotype.Service; | |
28 | +import org.springframework.transaction.annotation.Transactional; | |
29 | +import org.springframework.util.CollectionUtils; | |
30 | + | |
31 | +import java.util.*; | |
32 | +import java.util.stream.Collectors; | |
33 | + | |
34 | +import static cn.fw.common.businessvalidator.Validator.BV; | |
35 | + | |
36 | +/** | |
37 | + * @author : kurisu | |
38 | + * @className : MessageCenterBizService | |
39 | + * @description : 消息中心处理类 | |
40 | + * @date: 2021-09-24 17:10 | |
41 | + */ | |
42 | +@Service | |
43 | +@RequiredArgsConstructor | |
44 | +@Slf4j | |
45 | +public class MessageCenterBizService { | |
46 | + private final MessageHistoryService messageHistoryService; | |
47 | + private final SendLogService sendLogService; | |
48 | + private final TemplateMessageService templateMessageService; | |
49 | + private final SendMsgProducer sendMsgProducer; | |
50 | + | |
51 | + /** | |
52 | + * 消息模板Code | |
53 | + */ | |
54 | + @Getter | |
55 | + private final String templateCode = "OPENTM412432053"; | |
56 | + | |
57 | + /** | |
58 | + * 发送 | |
59 | + * | |
60 | + * @param templateMessageParam | |
61 | + * @return token | |
62 | + */ | |
63 | + @Transactional(rollbackFor = Exception.class) | |
64 | + public Long saveMessage(TemplateMessageParam templateMessageParam) { | |
65 | + MessageHistory messageHistory = createBean(templateMessageParam); | |
66 | + messageHistoryService.save(messageHistory); | |
67 | + return messageHistory.getId(); | |
68 | + } | |
69 | + | |
70 | + | |
71 | + /** | |
72 | + * 发送模板消息 | |
73 | + * | |
74 | + * @param history | |
75 | + */ | |
76 | + @Transactional(rollbackFor = Exception.class) | |
77 | + public void sendMessage(MessageHistory history) { | |
78 | + TMParam tmParam = createTmParam(history); | |
79 | + String result = templateMessageService.sendTemplateMessage(tmParam); | |
80 | + boolean succeed = MessageStr.SUCCEED_STR.equals(result); | |
81 | + final int frequency = history.getFrequency() + 1; | |
82 | + history.setFrequency(frequency); | |
83 | + if (succeed) { | |
84 | + history.setState(MessageStateEnum.SUMI); | |
85 | + //发送成功发送mq | |
86 | + sendMsgProducer.send(new MessageSendMq(history.getId(), new Date())); | |
87 | + } else { | |
88 | + history.setSendTime(DateUtil.getExpired(history.getSendTime(), 1 << frequency, Calendar.MINUTE)); | |
89 | + } | |
90 | + messageHistoryService.updateById(history); | |
91 | + SendLog sendLog = new SendLog(); | |
92 | + sendLog.setMessageId(history.getId()); | |
93 | + sendLog.setSendTime(new Date()); | |
94 | + sendLog.setSucceed(succeed); | |
95 | + sendLog.setResult(result); | |
96 | + sendLogService.save(sendLog); | |
97 | + } | |
98 | + | |
99 | + /** | |
100 | + * 撤回消息 | |
101 | + * | |
102 | + * @param sceneToken | |
103 | + * @return | |
104 | + */ | |
105 | + @Transactional(rollbackFor = Exception.class) | |
106 | + public Boolean revokeMessage(Long sceneToken) { | |
107 | + MessageHistory history = messageHistoryService.getById(sceneToken); | |
108 | + if (Objects.isNull(history)) { | |
109 | + return Boolean.TRUE; | |
110 | + } | |
111 | + history.setYn(Boolean.FALSE); | |
112 | + return messageHistoryService.updateById(history); | |
113 | + } | |
114 | + | |
115 | + /** | |
116 | + * 查询未读数 | |
117 | + * | |
118 | + * @param memberId | |
119 | + * @return | |
120 | + */ | |
121 | + public int unreadCount(Long memberId) { | |
122 | + return messageHistoryService.count(Wrappers.<MessageHistory>lambdaQuery() | |
123 | + .eq(MessageHistory::getMemberId, memberId) | |
124 | + .eq(MessageHistory::getReadz, Boolean.FALSE) | |
125 | + .eq(MessageHistory::getYn, Boolean.TRUE) | |
126 | + ); | |
127 | + } | |
128 | + | |
129 | + /** | |
130 | + * 查询页面所需参数 | |
131 | + * | |
132 | + * @param sceneToken | |
133 | + * @return | |
134 | + */ | |
135 | + public Map<String, String> queryPageParams(Long sceneToken) { | |
136 | + MessageHistory history = messageHistoryService.getById(sceneToken); | |
137 | + BV.notNull(history, () -> "消息不存在或者已经被撤销"); | |
138 | + readMessage(history); | |
139 | + String pageParams = history.getPageParams(); | |
140 | + if (StringUtils.isEmpty(pageParams)) { | |
141 | + return new HashMap<>(0); | |
142 | + } | |
143 | + return JSON.<HashMap<String, String>>parseObject(pageParams, HashMap.class); | |
144 | + } | |
145 | + | |
146 | + /** | |
147 | + * 查询历史消息记录 | |
148 | + * @param query | |
149 | + * @return | |
150 | + */ | |
151 | + public AppPage<MessageHistoryVO> queryHistory(HistoryQuery query) { | |
152 | + PageData<MessageHistory> pageData = messageHistoryService.page(new PageData<>(query), Wrappers.<MessageHistory>lambdaQuery() | |
153 | + .eq(MessageHistory::getMemberId, query.getMemberId()) | |
154 | + .eq(MessageHistory::getYn, Boolean.TRUE) | |
155 | + .orderByDesc(MessageHistory::getCreateTime) | |
156 | + ); | |
157 | + AppPage<MessageHistoryVO> page = AppPage.empty(query); | |
158 | + page.setCurrent((int) pageData.getCurrent()); | |
159 | + page.setPageSize((int) pageData.getSize()); | |
160 | + page.setTotal(pageData.getTotal()); | |
161 | + page.setData(new ArrayList<>()); | |
162 | + if (!CollectionUtils.isEmpty(pageData.getRecords())) { | |
163 | + List<MessageHistoryVO> voList = pageData.getRecords().stream().map(MessageHistoryVO::with).collect(Collectors.toList()); | |
164 | + page.setData(voList); | |
165 | + } | |
166 | + return page; | |
167 | + } | |
168 | + | |
169 | + @Transactional(rollbackFor = Exception.class) | |
170 | + protected void readMessage(MessageHistory history) { | |
171 | + if (Boolean.FALSE.equals(history.getReadz())) { | |
172 | + history.setReadz(Boolean.TRUE); | |
173 | + messageHistoryService.updateById(history); | |
174 | + } | |
175 | + } | |
176 | + | |
177 | + private MessageHistory createBean(TemplateMessageParam param) { | |
178 | + MessageHistory messageHistory = new MessageHistory(); | |
179 | + messageHistory.setMemberId(param.getMemberId()); | |
180 | + messageHistory.setTemplateCode(getTemplateCode()); | |
181 | + messageHistory.setTitle(param.getTitle()); | |
182 | + messageHistory.setRemark(param.getRemark()); | |
183 | + messageHistory.setPagePath(param.getPath()); | |
184 | + messageHistory.setReadz(Boolean.FALSE); | |
185 | + messageHistory.setFrequency(0); | |
186 | + messageHistory.setYn(Boolean.TRUE); | |
187 | + messageHistory.setSendTime(new Date()); | |
188 | + messageHistory.setState(MessageStateEnum.MADA); | |
189 | + List<WxMpTempMessageData> keywords = Arrays.asList( | |
190 | + new WxMpTempMessageData(param.getChangeType()), | |
191 | + new WxMpTempMessageData(param.getChangeResult()) | |
192 | + ); | |
193 | + messageHistory.setKeywords(JSONArray.toJSONString(keywords)); | |
194 | + if (!CollectionUtils.isEmpty(param.getParamMap())) { | |
195 | + messageHistory.setPageParams(JSON.toJSONString(param.getParamMap())); | |
196 | + } | |
197 | + return messageHistory; | |
198 | + } | |
199 | + | |
200 | + private TMParam createTmParam(MessageHistory history) { | |
201 | + TMParam tmParam = new TMParam(); | |
202 | + tmParam.setSceneToken(history.getId()); | |
203 | + tmParam.setTitle(history.getTitle()); | |
204 | + tmParam.setRemark(history.getRemark()); | |
205 | + tmParam.setPath(history.getPagePath()); | |
206 | + tmParam.setTemplateCode(history.getTemplateCode()); | |
207 | + tmParam.setMemberId(history.getMemberId()); | |
208 | + tmParam.setKeywords(history.getKeywords()); | |
209 | + return tmParam; | |
210 | + } | |
211 | +} | ... | ... |
fw-hestia-service/src/main/java/cn/fw/hestia/service/MessageHistoryService.java renamed to fw-hestia-service/src/main/java/cn/fw/hestia/service/data/MessageHistoryService.java
fw-hestia-service/src/main/java/cn/fw/hestia/service/SendLogService.java renamed to fw-hestia-service/src/main/java/cn/fw/hestia/service/data/SendLogService.java
fw-hestia-service/src/main/java/cn/fw/hestia/service/impl/MessageHistoryServiceImpl.java renamed to fw-hestia-service/src/main/java/cn/fw/hestia/service/data/impl/MessageHistoryServiceImpl.java
1 | -package cn.fw.hestia.service.impl; | |
1 | +package cn.fw.hestia.service.data.impl; | |
2 | 2 | |
3 | 3 | import cn.fw.hestia.dao.MessageHistoryDao; |
4 | 4 | import cn.fw.hestia.domain.db.MessageHistory; |
5 | -import cn.fw.hestia.service.MessageHistoryService; | |
5 | +import cn.fw.hestia.service.data.MessageHistoryService; | |
6 | 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
7 | 7 | import org.springframework.stereotype.Service; |
8 | 8 | ... | ... |
fw-hestia-service/src/main/java/cn/fw/hestia/service/impl/SendLogServiceImpl.java renamed to fw-hestia-service/src/main/java/cn/fw/hestia/service/data/impl/SendLogServiceImpl.java
1 | -package cn.fw.hestia.service.impl; | |
1 | +package cn.fw.hestia.service.data.impl; | |
2 | 2 | |
3 | 3 | import cn.fw.hestia.dao.SendLogDao; |
4 | 4 | import cn.fw.hestia.domain.db.SendLog; |
5 | -import cn.fw.hestia.service.SendLogService; | |
5 | +import cn.fw.hestia.service.data.SendLogService; | |
6 | 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
7 | 7 | import org.springframework.stereotype.Service; |
8 | 8 | ... | ... |