All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mxixm.fastboot.weixin.module.message.WxMessage Maven / Gradle / Ivy

The newest version!
package com.mxixm.fastboot.weixin.module.message;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mxixm.fastboot.weixin.module.Wx;
import com.mxixm.fastboot.weixin.module.message.adapters.WxXmlAdapters;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * 所有消息都是通过Msg推送的
 * 坑啊,主动发消息竟然是json格式
 * 真是尴尬,不仅格式不同,结构也不同,坑爹。。。
 * 特别是text消息,json的在text结构下,xml在顶级
 *
 * 注解@JsonUnwrapped @XmlElementWrapper这两个对于XML和JSON完全相反的功能,两个都只提供了一个。。。
 * https://stackoverflow.com/questions/16202583/xmlelementwrapper-for-unwrapped-collections
 * https://github.com/FasterXML/jackson-databind/issues/512
 * FastBootWeixin  WxMessage
 * 

* 加入WxMessageTemplate用于发送消息 * WxMessageConverter用于转换消息(把文件转换为media_id等) * @author Guangshan * @summary FastBootWeixin WxMessage * @Copyright (c) 2017, Guangshan Group All Rights Reserved * @since 2017/8/2 23:21 */ @XmlRootElement(name = "xml") @XmlAccessorType(XmlAccessType.NONE) @NoArgsConstructor @Getter public class WxMessage { private static final Log logger = LogFactory.getLog(MethodHandles.lookup().lookupClass()); /** * 标记是发送的消息还是接收的消息,没有想到一个合适的单词,就先用Intent吧 */ public enum Intent { SEND, RECEIVE, ALL } public enum Type { /** * 收到Button事件和普通事件 */ @JsonProperty("event") EVENT(Intent.RECEIVE, Wx.Category.EVENT, Wx.Category.BUTTON), /** * 文本消息 */ @JsonProperty("text") TEXT(Intent.ALL, Wx.Category.MESSAGE), /** * 图片消息 */ @JsonProperty("image") IMAGE(Intent.ALL, Wx.Category.MESSAGE), /** * 语音消息 */ @JsonProperty("voice") VOICE(Intent.ALL, Wx.Category.MESSAGE), /** * 视频消息 */ @JsonProperty("video") VIDEO(Intent.ALL, Wx.Category.MESSAGE), /** * 小视频消息 */ @JsonProperty("short_video") SHORT_VIDEO(Intent.RECEIVE, Wx.Category.MESSAGE), /** * 地理位置消息 */ @JsonProperty("location") LOCATION(Intent.RECEIVE, Wx.Category.MESSAGE), /** * 链接消息 */ @JsonProperty("link") LINK(Intent.RECEIVE, Wx.Category.MESSAGE), /** * 发送音乐消息 */ @JsonProperty("music") MUSIC(Intent.SEND, Wx.Category.MESSAGE), /** * 发送图文消息 */ @JsonProperty("news") NEWS(Intent.SEND, Wx.Category.MESSAGE), /** * 发送图文消息(点击跳转到图文消息页面) */ @JsonProperty("mpnews") MPNEWS(Intent.SEND, Wx.Category.MESSAGE), /** * 发送卡券 */ @JsonProperty("wxcard") WXCARD(Intent.SEND, Wx.Category.MESSAGE); private Intent intent; private Wx.Category[] categories; Type(Intent intent, Wx.Category... categories) { this.intent = intent; this.categories = categories; } public Intent getIntent() { return intent; } public Wx.Category[] getCategories() { return categories; } } /** * 消息的基础字段 * 开发者微信号 */ @XmlElement(name = "ToUserName", required = true) @JsonProperty("touser") protected String toUserName; /** * 消息的基础字段 * 发送方帐号(一个OpenID) */ @XmlElement(name = "FromUserName", required = true) @JsonIgnore protected String fromUserName; /** * 消息的基础字段 * 消息创建时间 (整型) */ @XmlJavaTypeAdapter(WxXmlAdapters.CreateTimeAdaptor.class) @XmlElement(name = "CreateTime", required = true) @JsonIgnore protected Date createTime; /** * 消息的基础字段 * 消息类型,event */ @XmlJavaTypeAdapter(WxXmlAdapters.MsgTypeAdaptor.class) @XmlElement(name = "MsgType", required = true) @JsonProperty("msgtype") protected Type messageType; WxMessage(String toUserName, String fromUserName, Date createTime, Type messageType) { this.toUserName = toUserName; this.fromUserName = fromUserName; this.createTime = createTime != null ? createTime : new Date(); this.messageType = messageType; } public void setFromUserName(String fromUserName) { this.fromUserName = fromUserName; } public void setToUserName(String toUserName) { this.toUserName = toUserName; } public static Builder builder() { return new Builder(); } public static class Builder { protected String toUserName; protected String fromUserName; protected Date createTime; protected Type messageType; Builder() { } public T toUserName(String toUserName) { this.toUserName = toUserName; return (T) this; } public T fromUserName(String fromUserName) { this.fromUserName = fromUserName; return (T) this; } public T createTime(Date createTime) { this.createTime = createTime; return (T) this; } protected T msgType(Type msgType) { this.messageType = msgType; return (T) this; } public WxMessage build() { return new WxMessage(toUserName, fromUserName, createTime, messageType); } public String toString() { return "com.example.myproject.module.message.WxMessage.Builder(toUserName=" + this.toUserName + ", fromUserName=" + this.fromUserName + ", createTime=" + this.createTime + ", messageType=" + this.messageType + ")"; } } @XmlRootElement(name = "xml") @XmlAccessorType(XmlAccessType.FIELD) @NoArgsConstructor @Getter public static class Text extends WxMessage { @XmlElement(name = "Content") @XmlJavaTypeAdapter(Body.TextBodyAdaptor.class) @JsonProperty("text") protected Body body; Text(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.body = body; } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.TEXT); return builder; } @XmlAccessorType(XmlAccessType.NONE) @AllArgsConstructor @NoArgsConstructor public static class Body { @JsonProperty("content") protected String content; public static class TextBodyAdaptor extends XmlAdapter { @Override public Body unmarshal(String v) throws Exception { return new Body(v); } @Override public String marshal(Body v) throws Exception { return v.content; } } } public static class Builder extends WxMessage.Builder { private String content; Builder() { } // 父类如何返回? // 使用泛型搞定了 public Builder content(String content) { this.content = content; return this; } public Text build() { return new Text(toUserName, fromUserName, createTime, messageType, new Body(content)); } public String toString() { return "com.example.myproject.module.message.WxMessage.Text.Builder(content=" + this.content + ")"; } } } @NoArgsConstructor @AllArgsConstructor @Data public static class MediaBody { @XmlElement(name = "MediaId", required = true) @JsonProperty("media_id") protected String mediaId; @JsonIgnore protected String mediaPath; @JsonIgnore protected String mediaUrl; } public static class MediaBuilder extends Builder { protected String mediaId; protected String mediaPath; protected String mediaUrl; MediaBuilder() { } public T mediaId(String mediaId) { this.mediaId = mediaId; return (T) this; } public T mediaPath(String mediaPath) { this.mediaPath = mediaPath; return (T) this; } public T mediaUrl(String mediaUrl) { this.mediaUrl = mediaUrl; return (T) this; } } @XmlRootElement(name = "xml") @NoArgsConstructor @Getter public static class Image extends WxMessage { @XmlElement(name = "Image", required = true) @JsonProperty("image") protected Body body; Image(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.body = body; } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.IMAGE); return builder; } @XmlAccessorType(XmlAccessType.NONE) @Data public static class Body extends MediaBody { public Body(String mediaId, String mediaPath, String mediaUrl) { super(mediaId, mediaPath, mediaUrl); } } public static class Builder extends WxMessage.MediaBuilder { Builder() { } public Image build() { return new Image(toUserName, fromUserName, createTime, messageType, new Body(mediaId, mediaPath, mediaUrl)); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(mediaId=" + this.mediaId + ")"; } } } @XmlRootElement(name = "xml") @NoArgsConstructor @Getter public static class Voice extends WxMessage { @XmlElement(name = "Voice", required = true) @JsonProperty("voice") protected Body body; Voice(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.body = body; } @XmlAccessorType(XmlAccessType.NONE) @NoArgsConstructor @Data public static class Body extends MediaBody { public Body(String mediaId, String mediaPath, String mediaUrl) { super(mediaId, mediaPath, mediaUrl); } } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.VOICE); return builder; } public static class Builder extends WxMessage.MediaBuilder { Builder() { } public Voice build() { return new Voice(toUserName, fromUserName, createTime, messageType, new Body(mediaId, mediaPath, mediaUrl)); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(mediaId=" + this.mediaId + ")"; } } } @XmlRootElement(name = "xml") @NoArgsConstructor @Getter public static class Video extends WxMessage { @XmlElement(name = "Video") @JsonProperty("video") protected Body body; Video(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.body = body; } @XmlAccessorType(XmlAccessType.NONE) @AllArgsConstructor @NoArgsConstructor @Data public static class Body extends MediaBody { @XmlElement(name = "ThumbMediaId") @JsonProperty("thumb_media_id") protected String thumbMediaId; @XmlElement(name = "Title") @JsonProperty("title") protected String title; @XmlElement(name = "Description") @JsonProperty("description") protected String description; @JsonIgnore protected String thumbMediaPath; @JsonIgnore protected String thumbMediaUrl; } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.VIDEO); return builder; } /** * 上面的body和下面的body风格不一致。。。算了,什么时候强迫症犯了再改好了 * 加了几个参数之后发现还是下面这种方式好啊。。。 */ public static class Builder extends WxMessage.MediaBuilder { protected Body body; Builder() { body = new Body(); } public Builder body(String mediaId, String thumbMediaId, String title, String description) { this.body.mediaId = mediaId; this.body.thumbMediaId = thumbMediaId; this.body.title = title; this.body.description = description; return this; } public Builder thumbMediaPath(String thumbMediaPath) { this.body.thumbMediaPath = thumbMediaPath; return this; } public Builder thumbMediaUrl(String thumbMediaUrl) { this.body.thumbMediaUrl = thumbMediaUrl; return this; } public Builder title(String title) { this.body.title = title; return this; } public Builder description(String description) { this.body.description = description; return this; } public Video build() { return new Video(toUserName, fromUserName, createTime, messageType, body); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(body=" + this.body.toString() + ")"; } } } @XmlRootElement(name = "xml") @NoArgsConstructor @Getter public static class Music extends WxMessage { @XmlElement(name = "Music") @JsonProperty("music") protected Body body; Music(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.body = body; } /** * 其实可以再抽象一个thumbMediaBody的。。。我懒 */ @XmlAccessorType(XmlAccessType.NONE) @AllArgsConstructor @NoArgsConstructor @Data public static class Body extends MediaBody { @XmlElement(name = "ThumbMediaId", required = true) @JsonProperty("thumb_media_id") protected String thumbMediaId; @XmlElement(name = "Title") @JsonProperty("title") protected String title; @XmlElement(name = "Description") @JsonProperty("description") protected String description; @XmlElement(name = "MusicUrl") @JsonProperty("musicurl") protected String musicUrl; @XmlElement(name = "HQMusicUrl") @JsonProperty("hqmusicurl") protected String hqMusicUrl; /** * 懒省事,做个简单的替换 * @param thumbMediaId */ public void setMediaId(String thumbMediaId) { this.thumbMediaId = thumbMediaId; } public String getMediaId() { return this.thumbMediaId; } } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.MUSIC); return builder; } public static class Builder extends WxMessage.MediaBuilder { protected Body body; Builder() { body = new Body(); } public Builder body(String thumbMediaId, String title, String description, String musicUrl, String hqMusicUrl) { this.body.thumbMediaId = thumbMediaId; this.body.title = title; this.body.description = description; this.body.musicUrl = musicUrl; this.body.hqMusicUrl = hqMusicUrl; return this; } public Builder thumbMediaId(String thumbMediaId) { this.body.thumbMediaId = thumbMediaId; return this; } public Builder thumbMediaPath(String thumbMediaPath) { this.body.mediaPath = thumbMediaPath; return this; } public Builder thumbMediaUrl(String thumbMediaUrl) { this.body.mediaUrl = thumbMediaUrl; return this; } public Builder title(String title) { this.body.title = title; return this; } public Builder description(String description) { this.body.description = description; return this; } public Builder musicUrl(String musicUrl) { this.body.musicUrl = musicUrl; return this; } public Builder hqMusicUrl(String hqMusicUrl) { this.body.hqMusicUrl = hqMusicUrl; return this; } public Music build() { return new Music(toUserName, fromUserName, createTime, messageType, body); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(body=" + this.body.toString() + ")"; } } } /** * 图文消息(点击跳转到外链) */ @XmlRootElement(name = "xml") @NoArgsConstructor @Getter public static class News extends WxMessage { /** * 图文消息个数,限制为8条以内 */ @XmlElement(name = "ArticleCount", required = true) protected Integer articleCount; @XmlElement(name = "Articles", required = true) @JsonProperty("news") protected Body body; News(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.articleCount = body.getArticles().size(); this.body = body; } @XmlAccessorType(XmlAccessType.NONE) @AllArgsConstructor @NoArgsConstructor @Getter public static class Body { @XmlElements(@XmlElement(name = "item", type = Item.class)) @JsonProperty("articles") protected List articles; } /** * 突然想省个事,虽然这里确实是用builder更好一点,但是我就是不用 * 写builder了,但是刚才还有个事情忘记了,不知道是啥了。 */ @XmlAccessorType(XmlAccessType.NONE) @AllArgsConstructor @NoArgsConstructor public static class Item { @XmlElement(name = "Title", required = true) @JsonProperty("title") protected String title; @XmlElement(name = "Description", required = true) @JsonProperty("description") protected String description; @XmlElement(name = "PicUrl", required = true) @JsonProperty("picurl") protected String picUrl; @XmlElement(name = "Url", required = true) @JsonProperty("url") protected String url; public String getPicUrl() { return picUrl; } public void setPicUrl(String picUrl) { this.picUrl = picUrl; } public void setUrl(String url) { this.url = url; } public String getUrl() { return url; } public static Builder builder() { return new Builder(); } public static class Builder { private String title; private String description; private String picUrl; private String url; Builder() { } public Builder title(String title) { this.title = title; return this; } public Builder description(String description) { this.description = description; return this; } public Builder picUrl(String picUrl) { this.picUrl = picUrl; return this; } public Builder url(String url) { this.url = url; return this; } public Item build() { return new Item(title, description, picUrl, url); } public String toString() { return "com.example.myproject.module.message.WxMessage.News.Item.ItemBuilder(title=" + this.title + ", description=" + this.description + ", picUrl=" + this.picUrl + ", host=" + this.url + ")"; } } } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.NEWS); return builder; } public static class Builder extends WxMessage.Builder { // 是叫items呢还是articles呢 protected LinkedList items; protected Item lastItem; Builder() { items = new LinkedList<>(); } /** * 添加主article,就是最上面那个大图 * * @param title * @param description * @param picUrl * @param url * @return dummy */ public Builder firstItem(String title, String description, String picUrl, String url) { this.items.addFirst(new Item(title, description, picUrl, url)); return this; } public Builder firstItem(Item item) { this.items.addFirst(item); return this; } public Builder addItem(String title, String description, String picUrl, String url) { this.items.addLast(new Item(title, description, picUrl, url)); return this; } public Builder addItem(Item item) { this.items.addLast(item); return this; } public Builder addItems(Collection item) { this.items.addAll(item); return this; } public Builder lastItem(Item item) { this.lastItem = item; return this; } // 这里关于最后项目的判断应该能优化一下,今天太累了,明天改2017年8月7日00:18:52 public News build() { // 这里可能不是一个好的代码习惯,可能会造成items变量名混乱。 List items = this.items; if (this.items.size() > 7) { if (this.lastItem != null) { logger.warn("图文消息至多只能有八条,最后的图文消息将被忽略"); items = this.items.subList(0, 7); items.add(this.lastItem); } else if (this.items.size() > 8) { logger.warn("图文消息至多只能有八条,最后的图文消息将被忽略"); items = this.items.subList(0, 8); } } else if (this.lastItem != null) { items.add(this.lastItem); } return new News(toUserName, fromUserName, createTime, messageType, new Body(items)); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(body=" + this.items.toString() + ")"; } } } /** * 发送图文消息(点击跳转到图文消息页面) */ @XmlRootElement(name = "xml") @NoArgsConstructor @Getter public static class MpNews extends WxMessage { @XmlElement(name = "Mpnews", required = true) @JsonProperty("mpnews") protected Body body; MpNews(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.body = body; } @XmlAccessorType(XmlAccessType.NONE) @AllArgsConstructor @NoArgsConstructor public static class Body { @XmlElement(name = "MediaId", required = true) @JsonProperty("media_id") protected String mediaId; } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.MPNEWS); return builder; } public static class Builder extends WxMessage.Builder { protected String mediaId; Builder() { } public Builder mediaId(String mediaId) { this.mediaId = mediaId; return this; } public MpNews build() { return new MpNews(toUserName, fromUserName, createTime, messageType, new Body(mediaId)); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(mediaId=" + this.mediaId + ")"; } } } /** * 发送卡券 */ @XmlRootElement(name = "xml") @NoArgsConstructor @Getter public static class WxCard extends WxMessage { @XmlElement(name = "WxCard", required = true) @JsonProperty("wxcard") protected Body body; WxCard(String toUserName, String fromUserName, Date createTime, Type messageType, Body body) { super(toUserName, fromUserName, createTime, messageType); this.body = body; } @XmlAccessorType(XmlAccessType.NONE) @AllArgsConstructor @NoArgsConstructor public static class Body { @XmlElement(name = "CardId", required = true) @JsonProperty("card_id") protected String cardId; } public static Builder builder() { Builder builder = new Builder(); builder.msgType(Type.WXCARD); return builder; } public static class Builder extends WxMessage.Builder { protected String cardId; Builder() { } public Builder cardId(String cardId) { this.cardId = cardId; return this; } public WxCard build() { return new WxCard(toUserName, fromUserName, createTime, messageType, new Body(cardId)); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(mediaId=" + this.cardId + ")"; } } } @AllArgsConstructor public static class Status extends WxMessage { @JsonIgnore protected Type messageType; @JsonProperty("command") protected Command command; Status(String toUserName, String fromUserName, Date createTime, Type messageType, boolean isTyping) { super(toUserName, fromUserName, createTime, messageType); this.command = isTyping ? Command.TYPING : Command.CANCEL_TYPING; } private enum Command { @JsonProperty("Typing") TYPING, @JsonProperty("CancelTyping") CANCEL_TYPING } public static Builder builder() { Builder builder = new Builder(); return builder; } public static class Builder extends WxMessage.Builder { protected boolean isTyping; Builder() { } public Builder isTyping(boolean isTyping) { this.isTyping = isTyping; return this; } public Status build() { return new Status(toUserName, fromUserName, createTime, messageType, isTyping); } public String toString() { return "com.example.myproject.module.message.WxMessage.Image.Builder(mediaId=" + this.isTyping + ")"; } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy