Skip to content

Commit 3233384

Browse files
authored
🎨 #3880 【企业微信】修复MemChangeList群成员变更ID解析为空字符串的问题
1 parent 5ff4114 commit 3233384

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package me.chanjar.weixin.common.util.xml;
2+
3+
import com.thoughtworks.xstream.converters.Converter;
4+
import com.thoughtworks.xstream.converters.MarshallingContext;
5+
import com.thoughtworks.xstream.converters.UnmarshallingContext;
6+
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
7+
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
8+
9+
/**
10+
* 兼容两种格式的字符串列表转换器:
11+
* <ul>
12+
* <li>旧格式(4.8.0之前):&lt;MemChangeList&gt;&lt;![CDATA[id1,id2]]&gt;&lt;/MemChangeList&gt;</li>
13+
* <li>新格式(4.8.0起):&lt;MemChangeList&gt;&lt;Item&gt;&lt;![CDATA[id1]]&gt;&lt;/Item&gt;&lt;/MemChangeList&gt;</li>
14+
* </ul>
15+
* 解析结果统一为逗号分隔的字符串。
16+
*/
17+
public class XStreamCDataListConverter implements Converter {
18+
19+
@Override
20+
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
21+
if (source != null) {
22+
writer.setValue("<![CDATA[" + source + "]]>");
23+
}
24+
}
25+
26+
@Override
27+
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
28+
if (reader.hasMoreChildren()) {
29+
// 新格式:含有 <Item> 子元素
30+
StringBuilder sb = new StringBuilder();
31+
while (reader.hasMoreChildren()) {
32+
reader.moveDown();
33+
String value = reader.getValue();
34+
if (value != null && !value.isEmpty()) {
35+
if (sb.length() > 0) {
36+
sb.append(",");
37+
}
38+
sb.append(value);
39+
}
40+
reader.moveUp();
41+
}
42+
return sb.length() > 0 ? sb.toString() : null;
43+
} else {
44+
// 旧格式:直接 CDATA 文本
45+
String value = reader.getValue();
46+
return (value != null && !value.isEmpty()) ? value : null;
47+
}
48+
}
49+
50+
@Override
51+
public boolean canConvert(Class type) {
52+
return type == String.class;
53+
}
54+
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import me.chanjar.weixin.common.util.xml.IntegerArrayConverter;
1212
import me.chanjar.weixin.common.util.xml.LongArrayConverter;
1313
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
14+
import me.chanjar.weixin.common.util.xml.XStreamCDataListConverter;
1415
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
1516
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
1617
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
@@ -156,7 +157,7 @@ public class WxCpXmlMessage implements Serializable {
156157
private String memChangeCnt;
157158

158159
@XStreamAlias("MemChangeList")
159-
@XStreamConverter(value = XStreamCDataConverter.class)
160+
@XStreamConverter(value = XStreamCDataListConverter.class)
160161
private String memChangeList;
161162

162163
@XStreamAlias("LastMemVer")

weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessageTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,5 +570,53 @@ public void testExternalChatChangeEvent() {
570570
assertEquals(wxMessage3.getUpdateDetail(), "change_name");
571571
// 当XML中没有MemChangeList元素时,字段应该为null而不是空字符串
572572
assertThat(wxMessage3.getMemChangeList()).isNull();
573+
574+
// 测试企业微信4.8.0新格式:MemChangeList使用<Item>子元素(加群场景)
575+
String xmlNewFormatAddMember = "<xml>"
576+
+ "<ToUserName><![CDATA[c2e112dad808119117371bbcd6]]></ToUserName>"
577+
+ "<FromUserName><![CDATA[sys]]></FromUserName>"
578+
+ "<CreateTime>9811170016713</CreateTime>"
579+
+ "<MsgType><![CDATA[event]]></MsgType>"
580+
+ "<Event><![CDATA[change_external_chat]]></Event>"
581+
+ "<ChatId><![CDATA[wrxUBwDQAAa44T11Ziaed811rhUr8-3Igmug]]></ChatId>"
582+
+ "<ChangeType><![CDATA[update]]></ChangeType>"
583+
+ "<UpdateDetail><![CDATA[add_member]]></UpdateDetail>"
584+
+ "<JoinScene>3</JoinScene>"
585+
+ "<MemChangeCnt>1</MemChangeCnt>"
586+
+ "<MemChangeList><Item><![CDATA[wmxUBwDQAAO-Hn5_wFJz4wvo5TxLFibw]]></Item></MemChangeList>"
587+
+ "<LastMemVer><![CDATA[5807afd2ab75771d5e8ac623f534ac0b]]></LastMemVer>"
588+
+ "<CurMemVer><![CDATA[ea36e8b6062b803cda0ee45e9418d637]]></CurMemVer>"
589+
+ "</xml>";
590+
WxCpXmlMessage wxMessage4 = WxCpXmlMessage.fromXml(xmlNewFormatAddMember);
591+
assertEquals(wxMessage4.getEvent(), WxCpConsts.EventType.CHANGE_EXTERNAL_CHAT);
592+
assertEquals(wxMessage4.getChangeType(), "update");
593+
assertEquals(wxMessage4.getUpdateDetail(), "add_member");
594+
assertEquals(wxMessage4.getJoinScene(), "3");
595+
assertEquals(wxMessage4.getMemChangeCnt(), "1");
596+
// 新格式:<Item>子元素中的成员ID应被正确解析
597+
assertEquals(wxMessage4.getMemChangeList(), "wmxUBwDQAAO-Hn5_wFJz4wvo5TxLFibw");
598+
599+
// 测试企业微信4.8.0新格式:多个<Item>子元素(多成员变更)
600+
String xmlNewFormatMultiMember = "<xml>"
601+
+ "<ToUserName><![CDATA[toUser]]></ToUserName>"
602+
+ "<FromUserName><![CDATA[sys]]></FromUserName>"
603+
+ "<CreateTime>1403610513</CreateTime>"
604+
+ "<MsgType><![CDATA[event]]></MsgType>"
605+
+ "<Event><![CDATA[change_external_chat]]></Event>"
606+
+ "<ChangeType><![CDATA[update]]></ChangeType>"
607+
+ "<ChatId><![CDATA[wrOgQhDgAAMYQiS5ol9G7gK9JVAAAA]]></ChatId>"
608+
+ "<UpdateDetail><![CDATA[del_member]]></UpdateDetail>"
609+
+ "<QuitScene>1</QuitScene>"
610+
+ "<MemChangeCnt>2</MemChangeCnt>"
611+
+ "<MemChangeList>"
612+
+ "<Item><![CDATA[wmEJiCwAAA9KG2qlSq6rKwASSgAAAA]]></Item>"
613+
+ "<Item><![CDATA[wmEJiCwAAA9KG2qlSq6rKwBBBBBBB]]></Item>"
614+
+ "</MemChangeList>"
615+
+ "</xml>";
616+
WxCpXmlMessage wxMessage5 = WxCpXmlMessage.fromXml(xmlNewFormatMultiMember);
617+
assertEquals(wxMessage5.getUpdateDetail(), "del_member");
618+
assertEquals(wxMessage5.getMemChangeCnt(), "2");
619+
// 多个<Item>元素应被解析为逗号分隔字符串
620+
assertEquals(wxMessage5.getMemChangeList(), "wmEJiCwAAA9KG2qlSq6rKwASSgAAAA,wmEJiCwAAA9KG2qlSq6rKwBBBBBBB");
573621
}
574622
}

0 commit comments

Comments
 (0)