Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package cn.binarywang.wx.miniapp.message;

import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
* 微信小程序输出给微信服务器的JSON格式消息.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class WxMaJsonOutMessage implements WxMaOutMessage {
private static final long serialVersionUID = 4241135225946919154L;

protected String toUserName;
protected String fromUserName;
protected Long createTime;
protected String msgType;

/**
* 转换成JSON格式.
*/
@Override
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
}

/**
* 转换成XML格式(对于JSON消息类型,返回JSON格式).
*/
@Override
public String toXml() {
// JSON消息类型默认返回JSON格式
return toJson();
}

/**
* 转换成加密的JSON格式.
*/
@Override
public String toEncryptedJson(WxMaConfig config) {
String plainJson = toJson();
WxMaCryptUtils pc = new WxMaCryptUtils(config);
return pc.encrypt(plainJson);
}

/**
* 转换成加密的XML格式(对于JSON消息类型,返回加密的JSON格式).
*/
@Override
public String toEncryptedXml(WxMaConfig config) {
// JSON消息类型默认返回加密的JSON格式
return toEncryptedJson(config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ public interface WxMaMessageHandler {
* @param context 上下文
* @param service 服务类
* @param sessionManager session管理器
* @return 输出消息
* @return 输出消息,可以是XML格式或JSON格式
* @throws WxErrorException 异常
*/
WxMaXmlOutMessage handle(WxMaMessage message, Map<String, Object> context,
WxMaService service, WxSessionManager sessionManager) throws WxErrorException;
WxMaOutMessage handle(WxMaMessage message, Map<String, Object> context,
WxMaService service, WxSessionManager sessionManager) throws WxErrorException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public WxMaMessageRouterRule rule() {
/**
* 处理微信消息.
*/
public WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map<String, Object> context) {
public WxMaOutMessage route(final WxMaMessage wxMessage, final Map<String, Object> context) {
if (isMsgDuplicated(wxMessage)) {
// 如果是重复消息,那么就不做处理
return null;
Expand All @@ -129,7 +129,7 @@ public WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map<String, Ob
}

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

public WxMaXmlOutMessage route(final WxMaMessage wxMessage) {
public WxMaOutMessage route(final WxMaMessage wxMessage) {
return this.route(wxMessage, new HashMap<>(2));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ protected boolean test(WxMaMessage wxMessage) {
/**
* 处理微信推送过来的消息.
*/
protected WxMaXmlOutMessage service(WxMaMessage wxMessage,
protected WxMaOutMessage service(WxMaMessage wxMessage,
Map<String, Object> context,
WxMaService wxMaService,
WxSessionManager sessionManager,
Expand All @@ -210,7 +210,7 @@ protected WxMaXmlOutMessage service(WxMaMessage wxMessage,
context = new HashMap<>(16);
}

WxMaXmlOutMessage outMessage = null;
WxMaOutMessage outMessage = null;
try {
// 如果拦截器不通过
for (WxMaMessageInterceptor interceptor : this.interceptors) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cn.binarywang.wx.miniapp.message;

import cn.binarywang.wx.miniapp.config.WxMaConfig;

import java.io.Serializable;

/**
* 微信小程序输出消息的通用接口,支持XML和JSON两种格式.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public interface WxMaOutMessage extends Serializable {

/**
* 转换成XML格式.
*
* @return XML格式的消息
*/
String toXml();

/**
* 转换成JSON格式.
*
* @return JSON格式的消息
*/
String toJson();

/**
* 转换成加密的XML格式.
*
* @param config 配置对象
* @return 加密后的XML格式消息
*/
String toEncryptedXml(WxMaConfig config);

/**
* 转换成加密的JSON格式.
*
* @param config 配置对象
* @return 加密后的JSON格式消息
*/
String toEncryptedJson(WxMaConfig config);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class WxMaXmlOutMessage implements Serializable {
public class WxMaXmlOutMessage implements WxMaOutMessage {
private static final long serialVersionUID = 4241135225946919153L;

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

@SuppressWarnings("unchecked")
@Override
public String toXml() {
return XStreamTransformer.toXml((Class<WxMaXmlOutMessage>) this.getClass(), this);
}

/**
* 转换成JSON格式(对于XML消息类型,返回XML格式).
*/
@Override
public String toJson() {
// XML消息类型默认返回XML格式
return toXml();
}

/**
* 转换成加密的xml格式.
*/
@Override
public String toEncryptedXml(WxMaConfig config) {
String plainXml = toXml();
WxMaCryptUtils pc = new WxMaCryptUtils(config);
return pc.encrypt(plainXml);
}

/**
* 转换成加密的JSON格式(对于XML消息类型,返回加密的XML格式).
*/
@Override
public String toEncryptedJson(WxMaConfig config) {
// XML消息类型默认返回加密的XML格式
return toEncryptedXml(config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
import cn.binarywang.wx.miniapp.message.WxMaOutMessage;
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage;
import cn.binarywang.wx.miniapp.test.TestConfig;
import me.chanjar.weixin.common.api.WxConsts;
Expand All @@ -32,8 +33,8 @@ public class WxMaDemoServer {

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

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

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

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

private static final WxMaMessageHandler customerServiceMessageHandler = new WxMaMessageHandler() {
@Override
public WxMaXmlOutMessage handle(WxMaMessage message, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) {
public WxMaOutMessage handle(WxMaMessage message, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) {
return new WxMaXmlOutMessage()
.setMsgType(WxConsts.XmlMsgType.TRANSFER_CUSTOMER_SERVICE)
.setFromUserName(message.getToUser())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage;
import cn.binarywang.wx.miniapp.message.WxMaOutMessage;
import lombok.AllArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -62,9 +62,13 @@ protected void service(HttpServletRequest request, HttpServletResponse response)
inMessage = WxMaMessage.fromXml(request.getInputStream());
}

final WxMaXmlOutMessage outMessage = this.messageRouter.route(inMessage);
final WxMaOutMessage outMessage = this.messageRouter.route(inMessage);
if (outMessage != null) {
response.getWriter().write(outMessage.toXml());
if (isJson) {
response.getWriter().write(outMessage.toJson());
} else {
response.getWriter().write(outMessage.toXml());
}
return;
}

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

final WxMaXmlOutMessage outMessage = this.messageRouter.route(inMessage);
final WxMaOutMessage outMessage = this.messageRouter.route(inMessage);
if (outMessage != null) {
response.getWriter().write(outMessage.toEncryptedXml(this.config));
if (isJson) {
response.getWriter().write(outMessage.toEncryptedJson(this.config));
} else {
response.getWriter().write(outMessage.toEncryptedXml(this.config));
}
return;
}
response.getWriter().write("success");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package cn.binarywang.wx.miniapp.message;

import me.chanjar.weixin.common.api.WxConsts;
import org.testng.annotations.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class WxMaJsonOutMessageTest {

@Test
public void testToJson() {
WxMaJsonOutMessage message = WxMaJsonOutMessage.builder()
.fromUserName("test_from_user")
.toUserName("test_to_user")
.msgType(WxConsts.XmlMsgType.TRANSFER_CUSTOMER_SERVICE)
.createTime(System.currentTimeMillis() / 1000)
.build();

String jsonResult = message.toJson();
assertThat(jsonResult).isNotEmpty();
assertThat(jsonResult).contains("test_from_user");
assertThat(jsonResult).contains("test_to_user");
assertThat(jsonResult).contains(WxConsts.XmlMsgType.TRANSFER_CUSTOMER_SERVICE);

System.out.println("JSON Output:");
System.out.println(jsonResult);
}

@Test
public void testEmptyMessage() {
WxMaJsonOutMessage message = new WxMaJsonOutMessage();
String jsonResult = message.toJson();
assertThat(jsonResult).isNotEmpty();
System.out.println("Empty message JSON:");
System.out.println(jsonResult);
}

@Test
public void testImplementsInterface() {
WxMaJsonOutMessage message = WxMaJsonOutMessage.builder()
.fromUserName("test_from_user")
.toUserName("test_to_user")
.msgType(WxConsts.XmlMsgType.TEXT)
.createTime(System.currentTimeMillis() / 1000)
.build();

// Test that it implements WxMaOutMessage interface
WxMaOutMessage outMessage = message;
assertThat(outMessage).isNotNull();

// Test both toJson and toXml methods (for JSON messages, both return JSON format)
assertThat(outMessage.toJson()).isNotEmpty();
assertThat(outMessage.toXml()).isNotEmpty();
assertThat(outMessage.toJson()).isEqualTo(outMessage.toXml());
}
}