2026-06-25 a26b31cc9f3ee9b21b1a754e80fa7359e8a7a8f8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package cn.iocoder.yudao.module.mp.framework.mp.core.util;
 
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
 
import jakarta.validation.Validator;
 
/**
 * 公众号工具类
 *
 * @author 芋道源码
 */
@Slf4j
public class MpUtils {
 
    /**
     * 校验消息的格式是否符合要求
     *
     * @param type 类型
     * @param message 消息
     */
    public static void validateMessage(Validator validator, String type, Object message) {
        // 获得对应的校验 group
        Class<?> group;
        switch (type) {
            case WxConsts.XmlMsgType.TEXT:
                group = TextMessageGroup.class;
                break;
            case WxConsts.XmlMsgType.IMAGE:
                group = ImageMessageGroup.class;
                break;
            case WxConsts.XmlMsgType.VOICE:
                group = VoiceMessageGroup.class;
                break;
            case WxConsts.XmlMsgType.VIDEO:
                group = VideoMessageGroup.class;
                break;
            case WxConsts.XmlMsgType.NEWS:
                group = NewsMessageGroup.class;
                break;
            case WxConsts.XmlMsgType.MUSIC:
                group = MusicMessageGroup.class;
                break;
            default:
                log.error("[validateMessage][未知的消息类型({})]", message);
                throw new IllegalArgumentException("不支持的消息类型:" + type);
        }
        // 执行校验
        ValidationUtils.validate(validator, message, group);
    }
 
    public static void validateButton(Validator validator, String type, String messageType, Object button) {
        if (StrUtil.isBlank(type)) {
            return;
        }
        // 获得对应的校验 group
        Class<?> group;
        switch (type) {
            case WxConsts.MenuButtonType.CLICK:
                group = ClickButtonGroup.class;
                validateMessage(validator, messageType, button); // 需要额外校验回复的消息格式
                break;
            case WxConsts.MenuButtonType.VIEW:
                group = ViewButtonGroup.class;
                break;
            case WxConsts.MenuButtonType.MINIPROGRAM:
                group = MiniProgramButtonGroup.class;
                break;
            case WxConsts.MenuButtonType.SCANCODE_WAITMSG:
                group = ScanCodeWaitMsgButtonGroup.class;
                validateMessage(validator, messageType, button); // 需要额外校验回复的消息格式
                break;
            case "article_" + WxConsts.MenuButtonType.VIEW_LIMITED:
                group = ViewLimitedButtonGroup.class;
                break;
            case WxConsts.MenuButtonType.SCANCODE_PUSH: // 不用校验,直接 return 即可
            case WxConsts.MenuButtonType.PIC_SYSPHOTO:
            case WxConsts.MenuButtonType.PIC_PHOTO_OR_ALBUM:
            case WxConsts.MenuButtonType.PIC_WEIXIN:
            case WxConsts.MenuButtonType.LOCATION_SELECT:
                return;
            default:
                log.error("[validateButton][未知的按钮({})]", button);
                throw new IllegalArgumentException("不支持的按钮类型:" + type);
        }
        // 执行校验
        ValidationUtils.validate(validator, button, group);
    }
 
    /**
     * 根据消息类型,获得对应的媒体文件类型
     *
     * 注意,不会返回 WxConsts.MediaFileType.THUMB,因为该类型会有明确标注
     *
     * @param messageType 消息类型 {@link  WxConsts.XmlMsgType}
     * @return 媒体文件类型 {@link WxConsts.MediaFileType}
     */
    public static String getMediaFileType(String messageType) {
        switch (messageType) {
            case WxConsts.XmlMsgType.IMAGE:
                return WxConsts.MediaFileType.IMAGE;
            case WxConsts.XmlMsgType.VOICE:
                return WxConsts.MediaFileType.VOICE;
            case WxConsts.XmlMsgType.VIDEO:
                return WxConsts.MediaFileType.VIDEO;
            default:
                return WxConsts.MediaFileType.FILE;
        }
    }
 
    /**
     * Text 类型的消息,参数校验 Group
     */
    public interface TextMessageGroup {}
 
    /**
     * Image 类型的消息,参数校验 Group
     */
    public interface ImageMessageGroup {}
 
    /**
     * Voice 类型的消息,参数校验 Group
     */
    public interface VoiceMessageGroup {}
 
    /**
     * Video 类型的消息,参数校验 Group
     */
    public interface VideoMessageGroup {}
 
    /**
     * News 类型的消息,参数校验 Group
     */
    public interface NewsMessageGroup {}
 
    /**
     * Music 类型的消息,参数校验 Group
     */
    public interface MusicMessageGroup {}
 
    /**
     * Click 类型的按钮,参数校验 Group
     */
    public interface ClickButtonGroup {}
 
    /**
     * View 类型的按钮,参数校验 Group
     */
    public interface ViewButtonGroup {}
 
    /**
     * MiniProgram 类型的按钮,参数校验 Group
     */
    public interface MiniProgramButtonGroup {}
 
    /**
     * SCANCODE_WAITMSG 类型的按钮,参数校验 Group
     */
    public interface ScanCodeWaitMsgButtonGroup {}
 
    /**
     * VIEW_LIMITED 类型的按钮,参数校验 Group
     */
    public interface ViewLimitedButtonGroup {}
}