#425 小程序客服消息新增图文链接消息支持

This commit is contained in:
Binary Wang
2018-01-27 17:58:39 +08:00
parent b44f9b315f
commit a687d00d4a
11 changed files with 185 additions and 107 deletions

View File

@@ -61,6 +61,11 @@
<artifactId>joda-time</artifactId> <artifactId>joda-time</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-guava</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>redis.clients</groupId> <groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <artifactId>jedis</artifactId>

View File

@@ -1,8 +1,12 @@
package cn.binarywang.wx.miniapp.bean; package cn.binarywang.wx.miniapp.bean;
import cn.binarywang.wx.miniapp.builder.ImageBuilder; import cn.binarywang.wx.miniapp.builder.ImageBuilder;
import cn.binarywang.wx.miniapp.builder.LinkBuilder;
import cn.binarywang.wx.miniapp.builder.TextBuilder; import cn.binarywang.wx.miniapp.builder.TextBuilder;
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
@@ -16,13 +20,59 @@ import java.io.Serializable;
public class WxMaKefuMessage implements Serializable { public class WxMaKefuMessage implements Serializable {
private static final long serialVersionUID = -9196732086954365246L; private static final long serialVersionUID = -9196732086954365246L;
@SerializedName("touser")
private String toUser; private String toUser;
@SerializedName("msgtype")
private String msgType; private String msgType;
private String content;
private String mediaId; @SerializedName("text")
private String thumbMediaId; private KfText text;
private String title;
private String description; @SerializedName("image")
private KfImage image;
@SerializedName("link")
private KfLink link;
@SerializedName("miniprogrampage")
private KfMaPage maPage;
@Data
@AllArgsConstructor
public static class KfText {
private String content;
}
@Data
@AllArgsConstructor
public static class KfImage {
@SerializedName("media_id")
private String mediaId;
}
@Data
@Builder
public static class KfLink {
private String title;
private String description;
private String url;
@SerializedName("thumb_url")
private String thumbUrl;
}
@Data
@Builder
public static class KfMaPage {
private String title;
@SerializedName("pagepath")
private String pagePath;
@SerializedName("thumb_media_id")
private String thumbMediaId;
}
/** /**
* 获得文本消息builder. * 获得文本消息builder.
@@ -38,8 +88,15 @@ public class WxMaKefuMessage implements Serializable {
return new ImageBuilder(); return new ImageBuilder();
} }
/**
* 获得图文链接消息builder.
*/
public static LinkBuilder newLinkBuilder() {
return new LinkBuilder();
}
public String toJson() { public String toJson() {
return WxMaGsonBuilder.create().toJson(this); return new GsonBuilder().create().toJson(this);
} }
} }

View File

@@ -31,8 +31,9 @@ public class WxMaWxcodeLimit extends AbstractWxMaQrcodeWrapper implements Serial
return WxMaGsonBuilder.create().fromJson(json, WxMaWxcodeLimit.class); return WxMaGsonBuilder.create().fromJson(json, WxMaWxcodeLimit.class);
} }
@Override
public String toString() { public String toString() {
return super.toString(); return super.toString();
} }
} }

View File

@@ -4,6 +4,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.constant.WxMaConstants; import cn.binarywang.wx.miniapp.constant.WxMaConstants;
/** /**
* 图片消息builder.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a> * @author <a href="https://github.com/binarywang">Binary Wang</a>
*/ */
public final class ImageBuilder extends BaseBuilder<ImageBuilder> { public final class ImageBuilder extends BaseBuilder<ImageBuilder> {
@@ -21,7 +23,7 @@ public final class ImageBuilder extends BaseBuilder<ImageBuilder> {
@Override @Override
public WxMaKefuMessage build() { public WxMaKefuMessage build() {
WxMaKefuMessage m = super.build(); WxMaKefuMessage m = super.build();
m.setMediaId(this.mediaId); m.setImage(new WxMaKefuMessage.KfImage(this.mediaId));
return m; return m;
} }
} }

View File

@@ -0,0 +1,52 @@
package cn.binarywang.wx.miniapp.builder;
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
/**
* 图文链接builder
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class LinkBuilder extends BaseBuilder<LinkBuilder> {
private String title;
private String description;
private String url;
private String thumbUrl;
public LinkBuilder() {
this.msgType = WxMaConstants.KefuMsgType.IMAGE;
}
public LinkBuilder title(String title) {
this.title = title;
return this;
}
public LinkBuilder description(String description) {
this.description = description;
return this;
}
public LinkBuilder url(String url) {
this.url = url;
return this;
}
public LinkBuilder thumbUrl(String thumbUrl) {
this.thumbUrl = thumbUrl;
return this;
}
@Override
public WxMaKefuMessage build() {
WxMaKefuMessage m = super.build();
m.setLink(WxMaKefuMessage.KfLink.builder().title(this.title)
.description(this.description)
.url(this.url)
.thumbUrl(this.thumbUrl)
.build()
);
return m;
}
}

View File

@@ -4,6 +4,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.constant.WxMaConstants; import cn.binarywang.wx.miniapp.constant.WxMaConstants;
/** /**
* 文本消息builder.
*
* @author <a href="https://github.com/binarywang">Binary Wang</a> * @author <a href="https://github.com/binarywang">Binary Wang</a>
*/ */
public final class TextBuilder extends BaseBuilder<TextBuilder> { public final class TextBuilder extends BaseBuilder<TextBuilder> {
@@ -21,7 +23,7 @@ public final class TextBuilder extends BaseBuilder<TextBuilder> {
@Override @Override
public WxMaKefuMessage build() { public WxMaKefuMessage build() {
WxMaKefuMessage m = super.build(); WxMaKefuMessage m = super.build();
m.setContent(this.content); m.setText(new WxMaKefuMessage.KfText(this.content));
return m; return m;
} }
} }

View File

@@ -2,29 +2,29 @@ package cn.binarywang.wx.miniapp.constant;
/** /**
* <pre> * <pre>
* 小程序常量 * 小程序常量.
* </pre> * </pre>
* *
* @author <a href="https://github.com/binarywang">Binary Wang</a> * @author <a href="https://github.com/binarywang">Binary Wang</a>
*/ */
public class WxMaConstants { public class WxMaConstants {
/** /**
* 微信接口返回的参数errcode * 微信接口返回的参数errcode.
*/ */
public static final String ERRCODE = "errcode"; public static final String ERRCODE = "errcode";
/** /**
* 素材类型 * 素材类型.
*/ */
public static class MediaType { public static class MediaType {
/** /**
* 图片 * 图片.
*/ */
public static final String IMAGE = "image"; public static final String IMAGE = "image";
} }
/** /**
* 消息格式 * 消息格式.
*/ */
public static class MsgDataFormat { public static class MsgDataFormat {
public static final String XML = "XML"; public static final String XML = "XML";
@@ -32,32 +32,40 @@ public class WxMaConstants {
} }
/** /**
* 客服消息的消息类型 * 客服消息的消息类型.
*/ */
public static class KefuMsgType { public static class KefuMsgType {
/** /**
* 文本消息 * 文本消息.
*/ */
public static final String TEXT = "text"; public static final String TEXT = "text";
/** /**
* 图片消息 * 图片消息.
*/ */
public static final String IMAGE = "image"; public static final String IMAGE = "image";
/**
* 图文链接.
*/
public static final String LINK = "link";
/**
* 小程序卡片消息.
*/
public static final String MA_PAGE = "miniprogrampage";
} }
public static final class ErrorCode { public static final class ErrorCode {
/** /**
* 40001 获取access_token时AppSecret错误或者access_token无效 * 40001 获取access_token时AppSecret错误或者access_token无效.
*/ */
public static final int ERR_40001 = 40001; public static final int ERR_40001 = 40001;
/** /**
* 42001 access_token超时 * 42001 access_token超时.
*/ */
public static final int ERR_42001 = 42001; public static final int ERR_42001 = 42001;
/** /**
* 40014 不合法的access_token请开发者认真比对access_token的有效性如是否过期 * 40014 不合法的access_token请开发者认真比对access_token的有效性如是否过期.
*/ */
public static final int ERR_40014 = 40014; public static final int ERR_40014 = 40014;
} }

View File

@@ -1,6 +1,5 @@
package cn.binarywang.wx.miniapp.util.json; package cn.binarywang.wx.miniapp.util.json;
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@@ -13,7 +12,6 @@ public class WxMaGsonBuilder {
static { static {
INSTANCE.disableHtmlEscaping(); INSTANCE.disableHtmlEscaping();
INSTANCE.registerTypeAdapter(WxMaKefuMessage.class, new WxMaKefuMessageGsonAdapter());
INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter()); INSTANCE.registerTypeAdapter(WxMaTemplateMessage.class, new WxMaTemplateMessageGsonAdapter());
} }

View File

@@ -1,38 +0,0 @@
package cn.binarywang.wx.miniapp.util.json;
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxMaKefuMessageGsonAdapter implements JsonSerializer<WxMaKefuMessage> {
@Override
public JsonElement serialize(WxMaKefuMessage message, Type typeOfSrc, JsonSerializationContext context) {
JsonObject messageJson = new JsonObject();
messageJson.addProperty("touser", message.getToUser());
messageJson.addProperty("msgtype", message.getMsgType());
if (WxMaConstants.KefuMsgType.TEXT.equals(message.getMsgType())) {
JsonObject text = new JsonObject();
text.addProperty("content", message.getContent());
messageJson.add("text", text);
}
if (WxMaConstants.KefuMsgType.IMAGE.equals(message.getMsgType())) {
JsonObject image = new JsonObject();
image.addProperty("media_id", message.getMediaId());
messageJson.add("image", image);
}
return messageJson;
}
}

View File

@@ -7,16 +7,14 @@ import cn.binarywang.wx.miniapp.test.ApiTestModule;
import cn.binarywang.wx.miniapp.test.TestConfig; import cn.binarywang.wx.miniapp.test.TestConfig;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.annotations.Guice; import org.testng.annotations.*;
import org.testng.annotations.Test;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
/** /**
* 测试客服相关接口 * 测试消息相关接口
* *
* @author <a href="https://github.com/binarywang">Binary Wang</a> * @author <a href="https://github.com/binarywang">Binary Wang</a>
*/ */
@@ -25,26 +23,14 @@ import java.util.Date;
public class WxMaMsgServiceImplTest { public class WxMaMsgServiceImplTest {
@Inject @Inject
protected WxMaService wxService; private WxMaService wxService;
public void testSendKefuMpNewsMessage() throws WxErrorException {
TestConfig configStorage = (TestConfig) this.wxService
.getWxMaConfig();
WxMaKefuMessage message = new WxMaKefuMessage();
message.setMsgType(WxConsts.KefuMsgType.MPNEWS);
message.setToUser(configStorage.getOpenid());
this.wxService.getMsgService().sendKefuMsg(message);
}
public void testSendKefuMessage() throws WxErrorException { public void testSendKefuMessage() throws WxErrorException {
TestConfig config = (TestConfig) this.wxService TestConfig config = (TestConfig) this.wxService.getWxMaConfig();
.getWxMaConfig(); WxMaKefuMessage message = WxMaKefuMessage.newTextBuilder()
WxMaKefuMessage message = new WxMaKefuMessage(); .toUser(config.getOpenid())
message.setMsgType(WxConsts.KefuMsgType.TEXT); .content("欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>")
message.setToUser(config.getOpenid()); .build();
message.setContent(
"欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>");
this.wxService.getMsgService().sendKefuMsg(message); this.wxService.getMsgService().sendKefuMsg(message);
} }

View File

@@ -1,8 +1,8 @@
package cn.binarywang.wx.miniapp.bean; package cn.binarywang.wx.miniapp.bean;
import me.chanjar.weixin.common.api.WxConsts; import org.testng.annotations.*;
import org.testng.Assert;
import org.testng.annotations.Test; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* @author <a href="https://github.com/binarywang">Binary Wang</a> * @author <a href="https://github.com/binarywang">Binary Wang</a>
@@ -10,30 +10,35 @@ import org.testng.annotations.Test;
@Test @Test
public class WxMaKefuMessageTest { public class WxMaKefuMessageTest {
public void testTextReply() { public void testTextBuilder() {
WxMaKefuMessage reply = new WxMaKefuMessage(); WxMaKefuMessage reply = WxMaKefuMessage.newTextBuilder()
reply.setToUser("OPENID"); .toUser("OPENID")
reply.setMsgType(WxConsts.KefuMsgType.TEXT); .content("sfsfdsdf")
reply.setContent("sfsfdsdf"); .build();
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); assertThat(reply.toJson())
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}");
} }
public void testTextBuild() { public void testImageBuilder() {
WxMaKefuMessage reply = WxMaKefuMessage.newTextBuilder().toUser("OPENID").content("sfsfdsdf").build(); WxMaKefuMessage reply = WxMaKefuMessage.newImageBuilder()
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); .toUser("OPENID")
. mediaId("MEDIA_ID")
.build();
assertThat(reply.toJson())
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}");
} }
public void testImageReply() { public void testLinkBuilder() {
WxMaKefuMessage reply = new WxMaKefuMessage(); WxMaKefuMessage reply = WxMaKefuMessage.newLinkBuilder()
reply.setToUser("OPENID"); .toUser("OPENID")
reply.setMsgType(WxConsts.KefuMsgType.IMAGE); .url("url")
reply.setMediaId("MEDIA_ID"); .description("description")
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); .title("title")
} .thumbUrl("thumbUrl")
.build();
public void testImageBuild() { assertThat(reply.toJson())
WxMaKefuMessage reply = WxMaKefuMessage.newImageBuilder().toUser("OPENID").mediaId("MEDIA_ID").build(); .isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"image\"," +
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); "\"link\":{\"title\":\"title\",\"description\":\"description\",\"url\":\"url\",\"thumb_url\":\"thumbUrl\"}}");
} }