訂閱號消息API XML對象封裝

前言

這篇文章介紹微信訂閱號消息接口中,XML對象的封裝和解析。希望能給大家帶來幫助,微信開發這塊也不是很熟悉,只限跑通簡單示例,懂行大佬輕拍。下面會詳細介紹包括哪些內容。

介紹

對象主要包括兩類,普通消息和推送消息。以及一個通用的轉換工具類,類似fastjson的工具類。 為簡單起見這裡把語音,文本,圖片等各自特有的字段都整合到一個對象裡,方便使用,缺點是字段顯得多些。要補充的是,代碼只限跑通例子,對於性能,規範等方面沒有做過多的考慮。其中推送消息類有問題,無法使用,普通消息解析是正常的,可以用以下對應的單測例子debug校驗。

代碼

接口對象

<code>//消息對象類
@Data //lombok 註解
@XmlAccessorType(XmlAccessType.FIELD) //必須
@XmlRootElement(name = "xml")
public class WxMsg {
@XmlElement(name = "ToUserName")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String toUserName; //接收方微信號

@XmlElement(name = "FromUserName")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String fromUserName;//發送方微信號,若為普通用戶,則是一個OpenID

@XmlElement(name = "CreateTime")
private Long createTime;//消息創建時間 (整型)

@XmlElement(name = "MsgType")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String msgType;//video voice text image location link

@XmlElement(name = "PicUrl")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String picUrl; // 圖片鏈接(由系統生成)

@XmlElement(name = "Content")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String content; //文本消息內容

@XmlElement(name = "MediaId")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String mediaId;//視頻消息媒體id,可以調用獲取臨時素材接口拉取數據。

@XmlElement(name = "Format")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String format; //語音格式:amr speex等

@XmlElement(name = "Recognition")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String recognition; // 語音識別結果,UTF8編碼

@XmlElement(name = "ThumbMediaId")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String thumbMediaId;//視頻消息縮略圖的媒體id,可以調用多媒體文件下載接口拉取數據。

@XmlElement(name = "Title")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String title; //鏈接消息標題

@XmlElement(name = "Description")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String description; //鏈接消息描述

@XmlElement(name = "Url")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String url; //鏈接消息link

@XmlElement(name = "Location_X")
private String locationX; //地理位置緯度

@XmlElement(name = "Location_Y")

private String locationY; //地理位置經度

@XmlElement(name = "Scale")
private Integer scale; //地理精度

@XmlElement(name = "Label")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String label; //地理位置詳情

@XmlElement(name = "ArticleCount")
private Integer articleCount; //圖文消息文章數量

@XmlElement(name = "MsgId")
private Long msgId; //消息id,64位整型

/**
* 附加類型
**/
@XmlElement(name = "Music")
private WxMusic music;

@XmlElement(name = "Voice")
private WxVoice wxVoice;

@XmlElement(name = "Video")
private WxVideo wxVideo;

@XmlElement(name = "Image")
private WxImage wxImage;

@XmlElement(name = "Articles")
private WxNews articles;


@Getter
@AllArgsConstructor
public enum MsgType {
UnKnow(-1, "unknow", "未知類型"),
Text(1, "text", "文本"),
Voice(2, "voice", "語音"),
Image(3, "image", "圖像"),
Location(4, "location", "位置"),
Link(5, "link", "鏈接"),
Event(6, "event", "推送"),
Video(7, "video", "視頻"),

Music(8, "music", "音樂"),
News(9, "news", "圖文");

private int code;
private String key;
private String desc;

public static MsgType fromKey(String key) {
return Arrays.stream(MsgType.values()).filter(e -> e.key.equals(key)).findFirst().orElse(MsgType.UnKnow);
}
}
}

/<code>
<code>//推送消息類
@EqualsAndHashCode(callSuper = true)
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "xml")
public class WxEventMsg extends WxMsg {

@XmlElement(name = "Event")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String event; //事件類型,subscribe(訂閱)、unsubscribe(取消訂閱) 事件類型,LOCATION 菜單 CLICK 跳轉 VIEW

@XmlElement(name = "EventKey")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String eventKey; //未關注:事件KEY值,qrscene_為前綴,後面為二維碼的參數值 , 已關注:事件KEY值,是一個32位無符號整數,即創建二維碼時的二維碼scene_id 菜單:事件KEY值,與自定義菜單接口中KEY值對應 ; 跳轉: 配置的url

@XmlElement(name = "Ticket")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String ticket; //二維碼的ticket,可用來換取二維碼圖片

@XmlElement(name = "Latitude")
private String latitude; //地理位置緯度

@XmlElement(name = "Longitude")

private String longitude; //地理位置經度

@XmlElement(name = "Precision")
private String precision; //地理位置精度 浮點

@XmlElement(name = "ScanCodeInfo")
private WxScan scanCodeInfo;

@XmlElement(name = "MenuId")
private String menuId; //菜單ID,如果是個性化菜單,則可以通過這個字段,知道是哪個規則的菜單被點擊了


@Getter
@AllArgsConstructor
public enum EventType {
UnKnow(-1, "unkown", "未知類型"),
Subscribe(1, "subscribe", "加入訂閱"),
Unsubscribe(2, "unsubscribe", "取消訂閱"),
Location(3, "LOCATION", "位置"),
MenuClick(4, "CLICK", "菜單點擊"),
ViewClick(5, "VIEW", "鏈接點擊"),
ScanPush(6, "scancode_push", "掃碼"),
ScanWaitMsg(7, "scancode_waitmsg", "掃碼推事件且彈出“消息接收中”提示框的事件推送"),
PicSysPhoto(8, "pic_sysphoto", "系統拍照"),
ViewMiniProgram(9, "view_miniprogram", "點擊菜單跳轉小程序的事件推送"),
PicWeixin(10, "pic_weixin", "彈出微信相冊發圖器的事件推送"),
;

private int code;
private String key;
private String desc;
}
}
/<code>
<code>//幾個擴展消息

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class WxImage {

@XmlElement(name = "MediaId")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String mediaId;

}

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMusic {

@XmlElement(name = "Title")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String title; //音樂標題

@XmlElement(name = "Description")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String description; //音樂描述

@XmlElement(name = "MusicUrl")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String musicUrl; //音樂鏈接

@XmlElement(name = "HQMusicUrl")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String hqMusicUrl; //高質量音樂鏈接,WIFI環境優先使用該鏈接播放音樂

@XmlElement(name = "ThumbMediaId")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String thumbMediaId; //縮略圖的媒體id,通過素材管理中的接口上傳多媒體文件,得到的id
}

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class WxNews {

@XmlElement(name = "item")
List<item> item;


@Data

@XmlAccessorType(XmlAccessType.FIELD)
public static class Item {
@XmlElement(name = "Title")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String title; //圖文消息標題

@XmlElement(name = "Description")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String description; //圖文消息描述

@XmlElement(name = "PicUrl")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String picUrl; //圖片鏈接,支持JPG、PNG格式,較好的效果為大圖360*200,小圖200*200

@XmlElement(name = "Url")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String url; //點擊圖文消息跳轉鏈接
}
}

@Data
public class WxScan {
@XmlElement(name = "ScanType")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String scanType; //掃描結果,即二維碼對應的字符串信息

@XmlElement(name = "ScanResult")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String scanResult; //掃描結果,即二維碼對應的字符串信息
}

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class WxVideo {
@XmlElement(name = "MediaId")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String mediaId; //通過素材管理中的接口上傳多媒體文件,得到的id

@XmlElement(name = "Title")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String title; //視頻消息的標題


@XmlElement(name = "Description")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String description; //視頻消息的描述
}

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class WxVoice {
@XmlElement(name = "MediaId")
@XmlJavaTypeAdapter(XmlUtil.CDATAAdapter.class)
private String mediaId;
}

/<item>/<code>


訂閱號消息API XML對象封裝


封裝XML解析類

<code>
public class XmlUtil {

public static T parseXml(String input, Class tClass) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(tClass);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(input);
T obj = (T) unmarshaller.unmarshal(reader);
return obj;
} catch (Exception ignore) {
return null;
}
}

//核心都是使用的jdk自帶 rt.jar
public static String toXml(T obj) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
Marshaller malshaller = jaxbContext.createMarshaller();
StringWriter writer = new StringWriter();
malshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
malshaller.setProperty("com.sun.xml.internal.bind.characterEscapeHandler",
(CharacterEscapeHandler) (ch, start, length, isAttVal, writer1) -> writer1.write(ch, start, length)); //不轉義內容 如amp;, 可以取消這個參數試試
malshaller.setProperty("com.sun.xml.internal.bind.xmlDeclaration", false);//去除 頭
malshaller.marshal(obj, writer);
return writer.toString();
} catch (Exception ignore) {
return null;
}
}

//CDATA 格式內容的處理
public static class CDATAAdapter extends XmlAdapter<string> {

@Override
public String marshal(String v) throws Exception {
return "";
}

@Override
public String unmarshal(String v) throws Exception {
return v;
}
}
}

/<string>
/<code>

測試例子

<code>    @Test
public void xmlTest() {
String data = "\\n"
+ " <tousername>\\n"
+ " <fromusername>\\n"
+ " <createtime>1348831860/<createtime>\\n"
+ " <msgtype>\\n"
+ " <picurl>\\n"
+ " <mediaid>\\n"
+ " <msgid>1234567890123456/<msgid>\\n"
+ "
\\n"
+ "\\n";
WxMsg msg = XmlUtil.parseXml(data, WxMsg.class);
System.out.println(msg);
}

@Test
public void xmlStringTest() {
WxMsg msg = new WxMsg();
msg.setCreateTime(222244L);
msg.setPicUrl("hsdgfsdgsdgsdg");
System.out.println(XmlUtil.toXml(msg));
}

@Test
public void wxNewsTest() {
String news = "\\n"
+ " <tousername>\\n"

+ " <fromusername>\\n"
+ " <createtime>12345678/<createtime>\\n"
+ " <msgtype>\\n"
+ " <articlecount>1/<articlecount>\\n"
+ " <articles>\\n"
+ " <item>\\n"
+ " <title>\\n"
+ " <description>\\n"
+ " <picurl>\\n"
+ " \\n"
+ " /<item>\\n"
+ " <item>\\n"
+ " <title>\\n"
+ " <description>\\n"
+ " <picurl>\\n"
+ " \\n"
+ " /<item>\\n"
+ " /<articles>\\n"
+ "
";
WxMsg msg = XmlUtil.parseXml(news, WxMsg.class);
System.out.println(msg);

WxNews.Item news1 = new WxNews.Item();
WxNews wxNews = new WxNews();
news1.setDescription("fsdfsdgsdgsdg");
news1.setTitle("sdgsdngaosdng");
news1.setUrl("sdnobvnsdiong");
news1.setPicUrl("sdnongsd");
msg.setArticles(wxNews);
wxNews.setItem(Lists.newArrayList(news1,news1));
System.out.println(XmlUtil.toXml(msg));
}
/<code>

結語

至此結束。再次補充下,代碼只限跑通例子,對於性能,規範等方面沒有做過多的考慮,有類似需求的可以加以修改優化;如果使用maven打包,報找不到rt.jar問題,按如下補充pom.xml配置:

<code>            <plugin>
<groupid>org.apache.maven.plugins/<groupid>

<artifactid>maven-compiler-plugin/<artifactid>
<configuration>
<source>1.8/<source>
<target>1.8/<target>
<encoding>UTF-8/<encoding>
<compilerargs>
-XDignore.symbol.file
/<compilerargs>
<fork>true/<fork>
/<configuration>
/<plugin>
/<code>

謝謝。


分享到:


相關文章: