Skip to content

Commit ebb9ccd

Browse files
authored
🎨 #3376 【小程序】完善事件消息推送对json数据格式的支持
1 parent 76c7e99 commit ebb9ccd

File tree

9 files changed

+218
-23
lines changed

9 files changed

+218
-23
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package cn.binarywang.wx.miniapp.message;
2+
3+
import cn.binarywang.wx.miniapp.config.WxMaConfig;
4+
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
5+
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
6+
import lombok.AllArgsConstructor;
7+
import lombok.Builder;
8+
import lombok.Data;
9+
import lombok.NoArgsConstructor;
10+
import lombok.experimental.Accessors;
11+
12+
import java.io.Serializable;
13+
14+
/**
15+
* 微信小程序输出给微信服务器的JSON格式消息.
16+
*
17+
* @author <a href="https://github.com/binarywang">Binary Wang</a>
18+
*/
19+
@Data
20+
@Accessors(chain = true)
21+
@Builder
22+
@AllArgsConstructor
23+
@NoArgsConstructor
24+
public class WxMaJsonOutMessage implements WxMaOutMessage {
25+
private static final long serialVersionUID = 4241135225946919154L;
26+
27+
protected String toUserName;
28+
protected String fromUserName;
29+
protected Long createTime;
30+
protected String msgType;
31+
32+
/**
33+
* 转换成JSON格式.
34+
*/
35+
@Override
36+
public String toJson() {
37+
return WxMaGsonBuilder.create().toJson(this);
38+
}
39+
40+
/**
41+
* 转换成XML格式(对于JSON消息类型,返回JSON格式).
42+
*/
43+
@Override
44+
public String toXml() {
45+
// JSON消息类型默认返回JSON格式
46+
return toJson();
47+
}
48+
49+
/**
50+
* 转换成加密的JSON格式.
51+
*/
52+
@Override
53+
public String toEncryptedJson(WxMaConfig config) {
54+
String plainJson = toJson();
55+
WxMaCryptUtils pc = new WxMaCryptUtils(config);
56+
return pc.encrypt(plainJson);
57+
}
58+
59+
/**
60+
* 转换成加密的XML格式(对于JSON消息类型,返回加密的JSON格式).
61+
*/
62+
@Override
63+
public String toEncryptedXml(WxMaConfig config) {
64+
// JSON消息类型默认返回加密的JSON格式
65+
return toEncryptedJson(config);
66+
}
67+
}

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageHandler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ public interface WxMaMessageHandler {
2020
* @param context 上下文
2121
* @param service 服务类
2222
* @param sessionManager session管理器
23-
* @return 输出消息
23+
* @return 输出消息,可以是XML格式或JSON格式
2424
* @throws WxErrorException 异常
2525
*/
26-
WxMaXmlOutMessage handle(WxMaMessage message, Map<String, Object> context,
27-
WxMaService service, WxSessionManager sessionManager) throws WxErrorException;
26+
WxMaOutMessage handle(WxMaMessage message, Map<String, Object> context,
27+
WxMaService service, WxSessionManager sessionManager) throws WxErrorException;
2828

2929
}

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouter.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public WxMaMessageRouterRule rule() {
107107
/**
108108
* 处理微信消息.
109109
*/
110-
public WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map<String, Object> context) {
110+
public WxMaOutMessage route(final WxMaMessage wxMessage, final Map<String, Object> context) {
111111
if (isMsgDuplicated(wxMessage)) {
112112
// 如果是重复消息,那么就不做处理
113113
return null;
@@ -129,7 +129,7 @@ public WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map<String, Ob
129129
}
130130

131131
final List<Future<?>> futures = new ArrayList<>();
132-
WxMaXmlOutMessage result = null;
132+
WxMaOutMessage result = null;
133133
for (final WxMaMessageRouterRule rule : matchRules) {
134134
// 返回最后一个非异步的rule的执行结果
135135
if (rule.isAsync()) {
@@ -168,7 +168,7 @@ public WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map<String, Ob
168168
return result;
169169
}
170170

171-
public WxMaXmlOutMessage route(final WxMaMessage wxMessage) {
171+
public WxMaOutMessage route(final WxMaMessage wxMessage) {
172172
return this.route(wxMessage, new HashMap<>(2));
173173
}
174174

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageRouterRule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ protected boolean test(WxMaMessage wxMessage) {
201201
/**
202202
* 处理微信推送过来的消息.
203203
*/
204-
protected WxMaXmlOutMessage service(WxMaMessage wxMessage,
204+
protected WxMaOutMessage service(WxMaMessage wxMessage,
205205
Map<String, Object> context,
206206
WxMaService wxMaService,
207207
WxSessionManager sessionManager,
@@ -210,7 +210,7 @@ protected WxMaXmlOutMessage service(WxMaMessage wxMessage,
210210
context = new HashMap<>(16);
211211
}
212212

213-
WxMaXmlOutMessage outMessage = null;
213+
WxMaOutMessage outMessage = null;
214214
try {
215215
// 如果拦截器不通过
216216
for (WxMaMessageInterceptor interceptor : this.interceptors) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package cn.binarywang.wx.miniapp.message;
2+
3+
import cn.binarywang.wx.miniapp.config.WxMaConfig;
4+
5+
import java.io.Serializable;
6+
7+
/**
8+
* 微信小程序输出消息的通用接口,支持XML和JSON两种格式.
9+
*
10+
* @author <a href="https://github.com/binarywang">Binary Wang</a>
11+
*/
12+
public interface WxMaOutMessage extends Serializable {
13+
14+
/**
15+
* 转换成XML格式.
16+
*
17+
* @return XML格式的消息
18+
*/
19+
String toXml();
20+
21+
/**
22+
* 转换成JSON格式.
23+
*
24+
* @return JSON格式的消息
25+
*/
26+
String toJson();
27+
28+
/**
29+
* 转换成加密的XML格式.
30+
*
31+
* @param config 配置对象
32+
* @return 加密后的XML格式消息
33+
*/
34+
String toEncryptedXml(WxMaConfig config);
35+
36+
/**
37+
* 转换成加密的JSON格式.
38+
*
39+
* @param config 配置对象
40+
* @return 加密后的JSON格式消息
41+
*/
42+
String toEncryptedJson(WxMaConfig config);
43+
}

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaXmlOutMessage.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
@Builder
2727
@AllArgsConstructor
2828
@NoArgsConstructor
29-
public class WxMaXmlOutMessage implements Serializable {
29+
public class WxMaXmlOutMessage implements WxMaOutMessage {
3030
private static final long serialVersionUID = 4241135225946919153L;
3131

3232
@XStreamAlias("ToUserName")
@@ -45,16 +45,36 @@ public class WxMaXmlOutMessage implements Serializable {
4545
protected String msgType;
4646

4747
@SuppressWarnings("unchecked")
48+
@Override
4849
public String toXml() {
4950
return XStreamTransformer.toXml((Class<WxMaXmlOutMessage>) this.getClass(), this);
5051
}
5152

53+
/**
54+
* 转换成JSON格式(对于XML消息类型,返回XML格式).
55+
*/
56+
@Override
57+
public String toJson() {
58+
// XML消息类型默认返回XML格式
59+
return toXml();
60+
}
61+
5262
/**
5363
* 转换成加密的xml格式.
5464
*/
65+
@Override
5566
public String toEncryptedXml(WxMaConfig config) {
5667
String plainXml = toXml();
5768
WxMaCryptUtils pc = new WxMaCryptUtils(config);
5869
return pc.encrypt(plainXml);
5970
}
71+
72+
/**
73+
* 转换成加密的JSON格式(对于XML消息类型,返回加密的XML格式).
74+
*/
75+
@Override
76+
public String toEncryptedJson(WxMaConfig config) {
77+
// XML消息类型默认返回加密的XML格式
78+
return toEncryptedXml(config);
79+
}
6080
}

weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/demo/WxMaDemoServer.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
99
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
1010
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
11+
import cn.binarywang.wx.miniapp.message.WxMaOutMessage;
1112
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage;
1213
import cn.binarywang.wx.miniapp.test.TestConfig;
1314
import me.chanjar.weixin.common.api.WxConsts;
@@ -32,8 +33,8 @@ public class WxMaDemoServer {
3233

3334
private static final WxMaMessageHandler logHandler = new WxMaMessageHandler() {
3435
@Override
35-
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
36-
WxMaService service, WxSessionManager sessionManager) throws WxErrorException {
36+
public WxMaOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
37+
WxMaService service, WxSessionManager sessionManager) throws WxErrorException {
3738
System.out.println("收到消息:" + wxMessage.toString());
3839
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
3940
.toUser(wxMessage.getFromUser()).build());
@@ -43,8 +44,8 @@ public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> conte
4344

4445
private static final WxMaMessageHandler textHandler = new WxMaMessageHandler() {
4546
@Override
46-
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
47-
WxMaService service, WxSessionManager sessionManager)
47+
public WxMaOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
48+
WxMaService service, WxSessionManager sessionManager)
4849
throws WxErrorException {
4950
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
5051
.toUser(wxMessage.getFromUser()).build());
@@ -55,8 +56,8 @@ public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> conte
5556

5657
private static final WxMaMessageHandler picHandler = new WxMaMessageHandler() {
5758
@Override
58-
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
59-
WxMaService service, WxSessionManager sessionManager) throws WxErrorException {
59+
public WxMaOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
60+
WxMaService service, WxSessionManager sessionManager) throws WxErrorException {
6061
try {
6162
WxMediaUploadResult uploadResult = service.getMediaService()
6263
.uploadMedia(WxMaConstants.MediaType.IMAGE, "png",
@@ -76,8 +77,8 @@ public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> conte
7677

7778
private static final WxMaMessageHandler qrcodeHandler = new WxMaMessageHandler() {
7879
@Override
79-
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
80-
WxMaService service, WxSessionManager sessionManager) throws WxErrorException {
80+
public WxMaOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context,
81+
WxMaService service, WxSessionManager sessionManager) throws WxErrorException {
8182
try {
8283
final File file = service.getQrcodeService().createQrcode("123", 430);
8384
WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia(WxMaConstants.MediaType.IMAGE, file);
@@ -96,7 +97,7 @@ public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> conte
9697

9798
private static final WxMaMessageHandler customerServiceMessageHandler = new WxMaMessageHandler() {
9899
@Override
99-
public WxMaXmlOutMessage handle(WxMaMessage message, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) {
100+
public WxMaOutMessage handle(WxMaMessage message, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) {
100101
return new WxMaXmlOutMessage()
101102
.setMsgType(WxConsts.XmlMsgType.TRANSFER_CUSTOMER_SERVICE)
102103
.setFromUserName(message.getToUser())

weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/demo/WxMaPortalServlet.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import cn.binarywang.wx.miniapp.config.WxMaConfig;
66
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
77
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
8-
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage;
8+
import cn.binarywang.wx.miniapp.message.WxMaOutMessage;
99
import lombok.AllArgsConstructor;
1010
import org.apache.commons.io.IOUtils;
1111
import org.apache.commons.lang3.StringUtils;
@@ -62,9 +62,13 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
6262
inMessage = WxMaMessage.fromXml(request.getInputStream());
6363
}
6464

65-
final WxMaXmlOutMessage outMessage = this.messageRouter.route(inMessage);
65+
final WxMaOutMessage outMessage = this.messageRouter.route(inMessage);
6666
if (outMessage != null) {
67-
response.getWriter().write(outMessage.toXml());
67+
if (isJson) {
68+
response.getWriter().write(outMessage.toJson());
69+
} else {
70+
response.getWriter().write(outMessage.toXml());
71+
}
6872
return;
6973
}
7074

@@ -82,9 +86,13 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
8286
inMessage = WxMaMessage.fromEncryptedXml(request.getInputStream(), this.config, timestamp, nonce, msgSignature);
8387
}
8488

85-
final WxMaXmlOutMessage outMessage = this.messageRouter.route(inMessage);
89+
final WxMaOutMessage outMessage = this.messageRouter.route(inMessage);
8690
if (outMessage != null) {
87-
response.getWriter().write(outMessage.toEncryptedXml(this.config));
91+
if (isJson) {
92+
response.getWriter().write(outMessage.toEncryptedJson(this.config));
93+
} else {
94+
response.getWriter().write(outMessage.toEncryptedXml(this.config));
95+
}
8896
return;
8997
}
9098
response.getWriter().write("success");
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package cn.binarywang.wx.miniapp.message;
2+
3+
import me.chanjar.weixin.common.api.WxConsts;
4+
import org.testng.annotations.Test;
5+
6+
import static org.assertj.core.api.Assertions.assertThat;
7+
8+
public class WxMaJsonOutMessageTest {
9+
10+
@Test
11+
public void testToJson() {
12+
WxMaJsonOutMessage message = WxMaJsonOutMessage.builder()
13+
.fromUserName("test_from_user")
14+
.toUserName("test_to_user")
15+
.msgType(WxConsts.XmlMsgType.TRANSFER_CUSTOMER_SERVICE)
16+
.createTime(System.currentTimeMillis() / 1000)
17+
.build();
18+
19+
String jsonResult = message.toJson();
20+
assertThat(jsonResult).isNotEmpty();
21+
assertThat(jsonResult).contains("test_from_user");
22+
assertThat(jsonResult).contains("test_to_user");
23+
assertThat(jsonResult).contains(WxConsts.XmlMsgType.TRANSFER_CUSTOMER_SERVICE);
24+
25+
System.out.println("JSON Output:");
26+
System.out.println(jsonResult);
27+
}
28+
29+
@Test
30+
public void testEmptyMessage() {
31+
WxMaJsonOutMessage message = new WxMaJsonOutMessage();
32+
String jsonResult = message.toJson();
33+
assertThat(jsonResult).isNotEmpty();
34+
System.out.println("Empty message JSON:");
35+
System.out.println(jsonResult);
36+
}
37+
38+
@Test
39+
public void testImplementsInterface() {
40+
WxMaJsonOutMessage message = WxMaJsonOutMessage.builder()
41+
.fromUserName("test_from_user")
42+
.toUserName("test_to_user")
43+
.msgType(WxConsts.XmlMsgType.TEXT)
44+
.createTime(System.currentTimeMillis() / 1000)
45+
.build();
46+
47+
// Test that it implements WxMaOutMessage interface
48+
WxMaOutMessage outMessage = message;
49+
assertThat(outMessage).isNotNull();
50+
51+
// Test both toJson and toXml methods (for JSON messages, both return JSON format)
52+
assertThat(outMessage.toJson()).isNotEmpty();
53+
assertThat(outMessage.toXml()).isNotEmpty();
54+
assertThat(outMessage.toJson()).isEqualTo(outMessage.toXml());
55+
}
56+
}

0 commit comments

Comments
 (0)