@@ -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> | ||||
@@ -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; | |||||
private String thumbMediaId; | |||||
private String title; | |||||
private String description; | |||||
@SerializedName("text") | |||||
private KfText text; | |||||
@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); | |||||
} | } | ||||
} | } |
@@ -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(); | ||||
} | |||||
} | |||||
} | } |
@@ -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; | ||||
} | } | ||||
} | } |
@@ -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; | |||||
} | |||||
} |
@@ -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; | ||||
} | } | ||||
} | } |
@@ -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; | ||||
} | } | ||||
@@ -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()); | ||||
} | } | ||||
@@ -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; | |||||
} | |||||
} |
@@ -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.Test; | |||||
import org.testng.annotations.*; | |||||
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; | |||||
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); | |||||
} | |||||
private WxMaService wxService; | |||||
public void testSendKefuMessage() throws WxErrorException { | public void testSendKefuMessage() throws WxErrorException { | ||||
TestConfig config = (TestConfig) this.wxService | |||||
.getWxMaConfig(); | |||||
WxMaKefuMessage message = new WxMaKefuMessage(); | |||||
message.setMsgType(WxConsts.KefuMsgType.TEXT); | |||||
message.setToUser(config.getOpenid()); | |||||
message.setContent( | |||||
"欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>"); | |||||
TestConfig config = (TestConfig) this.wxService.getWxMaConfig(); | |||||
WxMaKefuMessage message = WxMaKefuMessage.newTextBuilder() | |||||
.toUser(config.getOpenid()) | |||||
.content("欢迎欢迎,热烈欢迎\n换行测试\n超链接:<a href=\"http://www.baidu.com\">Hello World</a>") | |||||
.build(); | |||||
this.wxService.getMsgService().sendKefuMsg(message); | this.wxService.getMsgService().sendKefuMsg(message); | ||||
} | } | ||||
@@ -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.Assert; | |||||
import org.testng.annotations.Test; | |||||
import org.testng.annotations.*; | |||||
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() { | |||||
WxMaKefuMessage reply = new WxMaKefuMessage(); | |||||
reply.setToUser("OPENID"); | |||||
reply.setMsgType(WxConsts.KefuMsgType.TEXT); | |||||
reply.setContent("sfsfdsdf"); | |||||
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); | |||||
} | |||||
public void testTextBuild() { | |||||
WxMaKefuMessage reply = WxMaKefuMessage.newTextBuilder().toUser("OPENID").content("sfsfdsdf").build(); | |||||
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); | |||||
public void testTextBuilder() { | |||||
WxMaKefuMessage reply = WxMaKefuMessage.newTextBuilder() | |||||
.toUser("OPENID") | |||||
.content("sfsfdsdf") | |||||
.build(); | |||||
assertThat(reply.toJson()) | |||||
.isEqualTo("{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); | |||||
} | } | ||||
public void testImageReply() { | |||||
WxMaKefuMessage reply = new WxMaKefuMessage(); | |||||
reply.setToUser("OPENID"); | |||||
reply.setMsgType(WxConsts.KefuMsgType.IMAGE); | |||||
reply.setMediaId("MEDIA_ID"); | |||||
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); | |||||
public void testImageBuilder() { | |||||
WxMaKefuMessage reply = WxMaKefuMessage.newImageBuilder() | |||||
.toUser("OPENID") | |||||
. mediaId("MEDIA_ID") | |||||
.build(); | |||||
assertThat(reply.toJson()) | |||||
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); | |||||
} | } | ||||
public void testImageBuild() { | |||||
WxMaKefuMessage reply = WxMaKefuMessage.newImageBuilder().toUser("OPENID").mediaId("MEDIA_ID").build(); | |||||
Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); | |||||
public void testLinkBuilder() { | |||||
WxMaKefuMessage reply = WxMaKefuMessage.newLinkBuilder() | |||||
.toUser("OPENID") | |||||
.url("url") | |||||
.description("description") | |||||
.title("title") | |||||
.thumbUrl("thumbUrl") | |||||
.build(); | |||||
assertThat(reply.toJson()) | |||||
.isEqualTo( "{\"touser\":\"OPENID\",\"msgtype\":\"image\"," + | |||||
"\"link\":{\"title\":\"title\",\"description\":\"description\",\"url\":\"url\",\"thumb_url\":\"thumbUrl\"}}"); | |||||
} | } | ||||