Skip to content

Commit 1037dfd

Browse files
authored
🎨 #4049 【小程序】优化订阅消息字符串处理
1 parent fab9862 commit 1037dfd

1 file changed

Lines changed: 127 additions & 1 deletion

File tree

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
55
import lombok.*;
66
import lombok.experimental.Accessors;
7+
import org.apache.commons.lang3.StringUtils;
78

89
import java.io.Serializable;
910
import java.util.ArrayList;
1011
import java.util.List;
12+
import java.util.regex.Pattern;
1113

1214
/**
1315
* 订阅消息
@@ -24,6 +26,19 @@
2426
public class WxMaSubscribeMessage implements Serializable {
2527
private static final long serialVersionUID = 6846729898251286686L;
2628

29+
/**
30+
* 预编译正则,避免每次调用 resetValue 时重复编译
31+
*/
32+
private static final Pattern NUMBER_PATTERN = Pattern.compile("[^0-9.\\-]");
33+
private static final Pattern NUMBER_VALID_PATTERN = Pattern.compile("-?\\d+\\.?\\d*|-?\\.\\d+");
34+
private static final Pattern LETTER_PATTERN = Pattern.compile("[^a-zA-Z]");
35+
private static final Pattern SYMBOL_PATTERN = Pattern.compile("[a-zA-Z0-9\\u4e00-\\u9fa5]");
36+
private static final Pattern PHONE_PATTERN = Pattern.compile("[^0-9+\\-]");
37+
private static final Pattern NAME_PATTERN = Pattern.compile("[^\\u4e00-\\u9fa5a-zA-Z \\u00b7.\\u3001\\uff0c\\u3002\\-]");
38+
private static final Pattern CHARACTER_STRING_PATTERN = Pattern.compile("[\\u4e00-\\u9fa5]");
39+
private static final Pattern CHINESE_PATTERN = Pattern.compile("[\\u4e00-\\u9fa5]");
40+
private static final Pattern PHRASE_PATTERN = Pattern.compile("[^\\u4e00-\\u9fa5]");
41+
2742
/**
2843
* 接收者(用户)的 openid.
2944
* <pre>
@@ -75,15 +90,126 @@ public class WxMaSubscribeMessage implements Serializable {
7590
private String lang = WxMaConstants.MiniProgramLang.ZH_CN;
7691

7792
public WxMaSubscribeMessage addData(MsgData datum) {
93+
if (datum == null) {
94+
return this;
95+
}
7896
if (this.data == null) {
7997
this.data = new ArrayList<>();
8098
}
8199

82-
this.data.add(datum);
100+
this.data.add(resetValue(datum));
83101

84102
return this;
85103
}
86104

105+
/**
106+
* 处理订阅消息字符串长度及格式问题
107+
*
108+
* @link <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/mp-message-management/subscribe-message/api_sendmessage.html">发送订阅消息</a>
109+
*/
110+
private MsgData resetValue(MsgData datum) {
111+
String name = datum.getName();
112+
String value = datum.getValue();
113+
114+
if (StringUtils.isBlank(value)) {
115+
// 空值会发送失败,改为-
116+
datum.setValue("-");
117+
return datum;
118+
}
119+
120+
if (StringUtils.startsWith(name, "thing") && value.length() > 20) {
121+
// thing.DATA: 20个以内字符,可汉字、数字、字母或符号组合
122+
value = StringUtils.substring(value, 0, 17) + "...";
123+
} else if (StringUtils.startsWith(name, "number")) {
124+
// number.DATA: 32位以内数字,只能数字,可带小数
125+
value = NUMBER_PATTERN.matcher(value).replaceAll("");
126+
if (!NUMBER_VALID_PATTERN.matcher(value).matches()) {
127+
value = "0";
128+
}
129+
if (value.length() > 32) {
130+
value = StringUtils.substring(value, 0, 32);
131+
}
132+
} else if (StringUtils.startsWith(name, "letter")) {
133+
// letter.DATA: 32位以内字母,只能字母
134+
value = LETTER_PATTERN.matcher(value).replaceAll("");
135+
if (value.isEmpty()) {
136+
value = "A";
137+
}
138+
if (value.length() > 32) {
139+
value = StringUtils.substring(value, 0, 32);
140+
}
141+
} else if (StringUtils.startsWith(name, "symbol")) {
142+
// symbol.DATA: 5位以内符号,只能符号(除中文、英文、数字外的常见符号)
143+
value = SYMBOL_PATTERN.matcher(value).replaceAll("");
144+
if (value.isEmpty()) {
145+
value = "-";
146+
}
147+
if (value.length() > 5) {
148+
value = StringUtils.substring(value, 0, 5);
149+
}
150+
} else if (StringUtils.startsWith(name, "character_string")) {
151+
// character_string.DATA: 32位以内,可数字、字母或符号组合(不含中文)
152+
value = CHARACTER_STRING_PATTERN.matcher(value).replaceAll("");
153+
if (value.isEmpty()) {
154+
value = "0";
155+
}
156+
if (value.length() > 32) {
157+
value = StringUtils.substring(value, 0, 32);
158+
}
159+
} else if (StringUtils.startsWith(name, "phone_number")) {
160+
// phone_number.DATA: 17位以内,数字、符号
161+
value = PHONE_PATTERN.matcher(value).replaceAll("");
162+
// 只允许一个前导+号,且必须在开头
163+
if (value.startsWith("+")) {
164+
value = "+" + value.substring(1).replace("+", "");
165+
} else {
166+
value = value.replace("+", "");
167+
}
168+
if (value.isEmpty()) {
169+
value = "0";
170+
}
171+
if (value.length() > 17) {
172+
value = StringUtils.substring(value, 0, 17);
173+
}
174+
} else if (StringUtils.startsWith(name, "car_number")) {
175+
// car_number.DATA: 8位以内,第一位与最后一位可为汉字,其余为字母或数字
176+
if (value.length() > 8) {
177+
value = StringUtils.substring(value, 0, 8);
178+
}
179+
} else if (StringUtils.startsWith(name, "name")) {
180+
// name.DATA: 10个以内纯汉字或20个以内纯字母或符号,中文和字母混合按中文名算10个字内
181+
// 过滤非法字符,不保留数字(name 类型不允许数字)
182+
value = NAME_PATTERN.matcher(value).replaceAll("");
183+
if (value.isEmpty()) {
184+
value = "-";
185+
}
186+
boolean containsChinese = CHINESE_PATTERN.matcher(value).find();
187+
if (containsChinese) {
188+
// 含中文,按中文名算,10个字内
189+
if (value.length() > 10) {
190+
value = StringUtils.substring(value, 0, 7) + "...";
191+
}
192+
} else {
193+
// 纯字母或符号,20个以内
194+
if (value.length() > 20) {
195+
value = StringUtils.substring(value, 0, 17) + "...";
196+
}
197+
}
198+
} else if (StringUtils.startsWith(name, "phrase")) {
199+
// phrase.DATA: 5个以内纯汉字
200+
value = PHRASE_PATTERN.matcher(value).replaceAll("");
201+
if (value.isEmpty()) {
202+
value = "好";
203+
}
204+
if (value.length() > 5) {
205+
value = StringUtils.substring(value, 0, 5);
206+
}
207+
}
208+
209+
datum.setValue(value);
210+
return datum;
211+
}
212+
87213
public String toJson() {
88214
return WxMaGsonBuilder.create().toJson(this);
89215
}

0 commit comments

Comments
 (0)