From 2c0a44d9cb8b03af7a3577f7a9abad9b01a46c78 Mon Sep 17 00:00:00 2001 From: zhangyl Date: Mon, 8 Jun 2026 15:37:16 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B0=8F=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E8=AE=A2=E9=98=85=E6=B6=88=E6=81=AF=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 简单处理长度和格式,覆盖常见场景 --- .../wx/miniapp/bean/WxMaSubscribeMessage.java | 104 +++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java index 984e9573db..1b020ed396 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java @@ -4,10 +4,12 @@ import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; import lombok.*; import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; /** * 订阅消息 @@ -24,6 +26,18 @@ public class WxMaSubscribeMessage implements Serializable { private static final long serialVersionUID = 6846729898251286686L; + /** + * 预编译正则,避免每次调用 resetValue 时重复编译 + */ + private static final Pattern NUMBER_PATTERN = Pattern.compile("[^0-9.\\-]"); + private static final Pattern NUMBER_VALID_PATTERN = Pattern.compile("-?\\d+\\.?\\d*|-?\\.\\d+"); + private static final Pattern LETTER_PATTERN = Pattern.compile("[^a-zA-Z]"); + private static final Pattern SYMBOL_PATTERN = Pattern.compile("[a-zA-Z0-9\\u4e00-\\u9fa5]"); + private static final Pattern PHONE_PATTERN = Pattern.compile("[^0-9+\\-]"); + private static final Pattern NAME_PATTERN = Pattern.compile("[^\\u4e00-\\u9fa5a-zA-Z0-9 \\u00b7.\\u3001\\uff0c\\u3002\\-]"); + private static final Pattern CHINESE_PATTERN = Pattern.compile("[\\u4e00-\\u9fa5]"); + private static final Pattern PHRASE_PATTERN = Pattern.compile("[^\\u4e00-\\u9fa5]"); + /** * 接收者(用户)的 openid. *
@@ -79,11 +93,99 @@ public WxMaSubscribeMessage addData(MsgData datum) {
       this.data = new ArrayList<>();
     }
 
-    this.data.add(datum);
+    this.data.add(resetValue(datum));
 
     return this;
   }
 
+  /**
+   * 处理订阅消息字符串长度及格式问题
+   *
+   * @link 发送订阅消息
+   */
+  private MsgData resetValue(MsgData datum) {
+    String name = datum.getName();
+    String value = datum.getValue();
+
+    if (StringUtils.isBlank(value)) {
+      // 空值会发送失败,改为-
+      datum.setValue("-");
+      return datum;
+    }
+
+    if (StringUtils.startsWith(name, "thing") && value.length() > 20) {
+      // thing.DATA: 20个以内字符,可汉字、数字、字母或符号组合
+      value = StringUtils.substring(value, 0, 17) + "...";
+    } else if (StringUtils.startsWith(name, "number")) {
+      // number.DATA: 32位以内数字,只能数字,可带小数
+      value = NUMBER_PATTERN.matcher(value).replaceAll("");
+      if (!NUMBER_VALID_PATTERN.matcher(value).matches()) {
+        value = "-";
+      }
+      if (value.length() > 32) {
+        value = StringUtils.substring(value, 0, 32);
+      }
+    } else if (StringUtils.startsWith(name, "letter")) {
+      // letter.DATA: 32位以内字母,只能字母
+      value = LETTER_PATTERN.matcher(value).replaceAll("");
+      if (value.length() > 32) {
+        value = StringUtils.substring(value, 0, 32);
+      }
+    } else if (StringUtils.startsWith(name, "symbol")) {
+      // symbol.DATA: 5位以内符号,只能符号(除中文、英文、数字外的常见符号)
+      value = SYMBOL_PATTERN.matcher(value).replaceAll("");
+      if (value.length() > 5) {
+        value = StringUtils.substring(value, 0, 5);
+      }
+    } else if (StringUtils.startsWith(name, "character_string") && value.length() > 32) {
+      // character_string.DATA: 32位以内,可数字、字母或符号组合
+      value = StringUtils.substring(value, 0, 29) + "...";
+    } else if (StringUtils.startsWith(name, "phone_number")) {
+      // phone_number.DATA: 17位以内,数字、符号
+      value = PHONE_PATTERN.matcher(value).replaceAll("");
+      // 只允许一个前导+号
+      int firstPlus = value.indexOf('+');
+      if (firstPlus >= 0) {
+        value = value.substring(0, firstPlus + 1) + value.substring(firstPlus + 1).replace("+", "");
+      }
+      if (value.length() > 17) {
+        value = StringUtils.substring(value, 0, 14) + "...";
+      }
+    } else if (StringUtils.startsWith(name, "car_number") && value.length() > 8) {
+      value = StringUtils.substring(value, 0, 5) + "...";
+    } else if (StringUtils.startsWith(name, "name")) {
+      // name.DATA: 10个以内纯汉字或20个以内纯字母或符号,中文和字母混合按中文名算10个字内
+      // 用预编译正则过滤非法字符,\\s 替换为字面空格避免保留 \n \t \r
+      value = NAME_PATTERN.matcher(value).replaceAll("");
+      boolean containsChinese = CHINESE_PATTERN.matcher(value).find();
+      if (containsChinese) {
+        // 含中文,按中文名算,10个字内
+        if (value.length() > 10) {
+          value = StringUtils.substring(value, 0, 7) + "...";
+        }
+      } else {
+        // 纯字母或符号,20个以内
+        if (value.length() > 20) {
+          value = StringUtils.substring(value, 0, 17) + "...";
+        }
+      }
+    } else if (StringUtils.startsWith(name, "phrase")) {
+      // phrase.DATA: 5个以内纯汉字
+      value = PHRASE_PATTERN.matcher(value).replaceAll("");
+      if (value.length() > 5) {
+        value = StringUtils.substring(value, 0, 5);
+      }
+    }
+
+    // 过滤后兜底检查,防止正则过滤产生空字符串
+    if (StringUtils.isEmpty(value)) {
+      value = "-";
+    }
+
+    datum.setValue(value);
+    return datum;
+  }
+
   public String toJson() {
     return WxMaGsonBuilder.create().toJson(this);
   }

From 6baa9924216c4955d5ae8976abdcbd4ffea8c7e9 Mon Sep 17 00:00:00 2001
From: zhangyl 
Date: Mon, 8 Jun 2026 16:28:46 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B0=8F=E7=A8=8B?=
 =?UTF-8?q?=E5=BA=8F=E8=AE=A2=E9=98=85=E6=B6=88=E6=81=AF=E5=8F=82=E6=95=B0?=
 =?UTF-8?q?=E5=80=BC=E5=A4=84=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../wx/miniapp/bean/WxMaSubscribeMessage.java | 60 +++++++++++++------
 1 file changed, 42 insertions(+), 18 deletions(-)

diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java
index 1b020ed396..e372f27039 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaSubscribeMessage.java
@@ -34,7 +34,8 @@ public class WxMaSubscribeMessage implements Serializable {
   private static final Pattern LETTER_PATTERN = Pattern.compile("[^a-zA-Z]");
   private static final Pattern SYMBOL_PATTERN = Pattern.compile("[a-zA-Z0-9\\u4e00-\\u9fa5]");
   private static final Pattern PHONE_PATTERN = Pattern.compile("[^0-9+\\-]");
-  private static final Pattern NAME_PATTERN = Pattern.compile("[^\\u4e00-\\u9fa5a-zA-Z0-9 \\u00b7.\\u3001\\uff0c\\u3002\\-]");
+  private static final Pattern NAME_PATTERN = Pattern.compile("[^\\u4e00-\\u9fa5a-zA-Z \\u00b7.\\u3001\\uff0c\\u3002\\-]");
+  private static final Pattern CHARACTER_STRING_PATTERN = Pattern.compile("[\\u4e00-\\u9fa5]");
   private static final Pattern CHINESE_PATTERN = Pattern.compile("[\\u4e00-\\u9fa5]");
   private static final Pattern PHRASE_PATTERN = Pattern.compile("[^\\u4e00-\\u9fa5]");
 
@@ -89,6 +90,9 @@ public class WxMaSubscribeMessage implements Serializable {
   private String lang = WxMaConstants.MiniProgramLang.ZH_CN;
 
   public WxMaSubscribeMessage addData(MsgData datum) {
+    if (datum == null) {
+      return this;
+    }
     if (this.data == null) {
       this.data = new ArrayList<>();
     }
@@ -120,7 +124,7 @@ private MsgData resetValue(MsgData datum) {
       // number.DATA: 32位以内数字,只能数字,可带小数
       value = NUMBER_PATTERN.matcher(value).replaceAll("");
       if (!NUMBER_VALID_PATTERN.matcher(value).matches()) {
-        value = "-";
+        value = "0";
       }
       if (value.length() > 32) {
         value = StringUtils.substring(value, 0, 32);
@@ -128,35 +132,57 @@ private MsgData resetValue(MsgData datum) {
     } else if (StringUtils.startsWith(name, "letter")) {
       // letter.DATA: 32位以内字母,只能字母
       value = LETTER_PATTERN.matcher(value).replaceAll("");
+      if (value.isEmpty()) {
+        value = "A";
+      }
       if (value.length() > 32) {
         value = StringUtils.substring(value, 0, 32);
       }
     } else if (StringUtils.startsWith(name, "symbol")) {
       // symbol.DATA: 5位以内符号,只能符号(除中文、英文、数字外的常见符号)
       value = SYMBOL_PATTERN.matcher(value).replaceAll("");
+      if (value.isEmpty()) {
+        value = "-";
+      }
       if (value.length() > 5) {
         value = StringUtils.substring(value, 0, 5);
       }
-    } else if (StringUtils.startsWith(name, "character_string") && value.length() > 32) {
-      // character_string.DATA: 32位以内,可数字、字母或符号组合
-      value = StringUtils.substring(value, 0, 29) + "...";
+    } else if (StringUtils.startsWith(name, "character_string")) {
+      // character_string.DATA: 32位以内,可数字、字母或符号组合(不含中文)
+      value = CHARACTER_STRING_PATTERN.matcher(value).replaceAll("");
+      if (value.isEmpty()) {
+        value = "0";
+      }
+      if (value.length() > 32) {
+        value = StringUtils.substring(value, 0, 32);
+      }
     } else if (StringUtils.startsWith(name, "phone_number")) {
       // phone_number.DATA: 17位以内,数字、符号
       value = PHONE_PATTERN.matcher(value).replaceAll("");
-      // 只允许一个前导+号
-      int firstPlus = value.indexOf('+');
-      if (firstPlus >= 0) {
-        value = value.substring(0, firstPlus + 1) + value.substring(firstPlus + 1).replace("+", "");
+      // 只允许一个前导+号,且必须在开头
+      if (value.startsWith("+")) {
+        value = "+" + value.substring(1).replace("+", "");
+      } else {
+        value = value.replace("+", "");
+      }
+      if (value.isEmpty()) {
+        value = "0";
       }
       if (value.length() > 17) {
-        value = StringUtils.substring(value, 0, 14) + "...";
+        value = StringUtils.substring(value, 0, 17);
+      }
+    } else if (StringUtils.startsWith(name, "car_number")) {
+      // car_number.DATA: 8位以内,第一位与最后一位可为汉字,其余为字母或数字
+      if (value.length() > 8) {
+        value = StringUtils.substring(value, 0, 8);
       }
-    } else if (StringUtils.startsWith(name, "car_number") && value.length() > 8) {
-      value = StringUtils.substring(value, 0, 5) + "...";
     } else if (StringUtils.startsWith(name, "name")) {
       // name.DATA: 10个以内纯汉字或20个以内纯字母或符号,中文和字母混合按中文名算10个字内
-      // 用预编译正则过滤非法字符,\\s 替换为字面空格避免保留 \n \t \r
+      // 过滤非法字符,不保留数字(name 类型不允许数字)
       value = NAME_PATTERN.matcher(value).replaceAll("");
+      if (value.isEmpty()) {
+        value = "-";
+      }
       boolean containsChinese = CHINESE_PATTERN.matcher(value).find();
       if (containsChinese) {
         // 含中文,按中文名算,10个字内
@@ -172,16 +198,14 @@ private MsgData resetValue(MsgData datum) {
     } else if (StringUtils.startsWith(name, "phrase")) {
       // phrase.DATA: 5个以内纯汉字
       value = PHRASE_PATTERN.matcher(value).replaceAll("");
+      if (value.isEmpty()) {
+        value = "好";
+      }
       if (value.length() > 5) {
         value = StringUtils.substring(value, 0, 5);
       }
     }
 
-    // 过滤后兜底检查,防止正则过滤产生空字符串
-    if (StringUtils.isEmpty(value)) {
-      value = "-";
-    }
-
     datum.setValue(value);
     return datum;
   }