From 83e9411bcd61f386a019c270df06040f88d32393 Mon Sep 17 00:00:00 2001 From: hotlcc Date: Wed, 25 Jul 2018 11:03:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/hotlcc/wechat4j/Wechat.java | 173 ++++++++++++++++- .../com/hotlcc/wechat4j/api/WebWeixinApi.java | 16 +- .../hotlcc/wechat4j/enums/RetcodeEnum.java | 29 +++ .../hotlcc/wechat4j/enums/SelectorEnum.java | 30 +++ .../wechat4j/handler/ExitEventHandler.java | 8 +- .../wechat4j/handler/ReceivedMsgHandler.java | 17 ++ .../com/hotlcc/wechat4j/model/AppInfo.java | 24 +++ .../hotlcc/wechat4j/model/ReceivedMsg.java | 179 ++++++++++++++++++ .../hotlcc/wechat4j/model/RecommendInfo.java | 96 ++++++++++ src/test/java/TestClass.java | 35 ---- 10 files changed, 550 insertions(+), 57 deletions(-) create mode 100644 src/main/java/com/hotlcc/wechat4j/enums/RetcodeEnum.java create mode 100644 src/main/java/com/hotlcc/wechat4j/enums/SelectorEnum.java create mode 100644 src/main/java/com/hotlcc/wechat4j/handler/ReceivedMsgHandler.java create mode 100644 src/main/java/com/hotlcc/wechat4j/model/AppInfo.java create mode 100644 src/main/java/com/hotlcc/wechat4j/model/ReceivedMsg.java create mode 100644 src/main/java/com/hotlcc/wechat4j/model/RecommendInfo.java delete mode 100644 src/test/java/TestClass.java diff --git a/src/main/java/com/hotlcc/wechat4j/Wechat.java b/src/main/java/com/hotlcc/wechat4j/Wechat.java index 974744a..d75a870 100644 --- a/src/main/java/com/hotlcc/wechat4j/Wechat.java +++ b/src/main/java/com/hotlcc/wechat4j/Wechat.java @@ -5,7 +5,11 @@ import com.alibaba.fastjson.JSONObject; import com.hotlcc.wechat4j.api.WebWeixinApi; import com.hotlcc.wechat4j.enums.ExitTypeEnum; import com.hotlcc.wechat4j.enums.LoginTipEnum; +import com.hotlcc.wechat4j.enums.RetcodeEnum; +import com.hotlcc.wechat4j.enums.SelectorEnum; import com.hotlcc.wechat4j.handler.ExitEventHandler; +import com.hotlcc.wechat4j.handler.ReceivedMsgHandler; +import com.hotlcc.wechat4j.model.ReceivedMsg; import com.hotlcc.wechat4j.util.CommonUtil; import com.hotlcc.wechat4j.util.PropertiesUtil; import com.hotlcc.wechat4j.util.QRCodeUtil; @@ -67,6 +71,8 @@ public class Wechat { //退出事件处理器 private List exitEventHandlers; + //接收消息处理器 + private List receivedMsgHandlers; public Wechat(CookieStore cookieStore) { this.cookieStore = cookieStore; @@ -82,6 +88,9 @@ public class Wechat { } public void addExitEventHandler(ExitEventHandler handler) { + if (handler == null) { + return; + } if (exitEventHandlers == null) { exitEventHandlers = new ArrayList<>(); } @@ -90,10 +99,37 @@ public class Wechat { } public void addExitEventHandler(Collection handlers) { + if (handlers == null || handlers.isEmpty()) { + return; + } if (exitEventHandlers == null) { exitEventHandlers = new ArrayList<>(); } - exitEventHandlers.addAll(handlers); + for (ExitEventHandler handler : handlers) { + addExitEventHandler(handler); + } + } + + public void addReceivedMsgHandler(ReceivedMsgHandler handler) { + if (handler == null) { + return; + } + if (receivedMsgHandlers == null) { + receivedMsgHandlers = new ArrayList<>(); + } + receivedMsgHandlers.add(handler); + } + + public void addReceivedMsgHandler(Collection handlers) { + if (handlers == null || handlers.isEmpty()) { + return; + } + if (receivedMsgHandlers == null) { + receivedMsgHandlers = new ArrayList<>(); + } + for (ReceivedMsgHandler handler : handlers) { + addReceivedMsgHandler(handler); + } } private HttpClient buildHttpClient(CookieStore cookieStore) { @@ -103,7 +139,7 @@ public class Wechat { long keepAlive = super.getKeepAliveDuration(response, context); if (keepAlive == -1) { //如果服务器没有设置keep-alive这个参数,我们就把它设置成1分钟 - keepAlive = 5000; + keepAlive = 60000; } return keepAlive; } @@ -561,7 +597,7 @@ public class Wechat { //人为退出 int retcode = result.getIntValue("retcode"); - if (retcode != 0) { + if (retcode != RetcodeEnum.RECODE_0.getCode()) { logger.info("微信退出或从其它设备登录"); logout(); processExitEvent(ExitTypeEnum.REMOTE_EXIT, null); @@ -622,25 +658,25 @@ public class Wechat { try { switch (type) { case ERROR_EXIT: - handler.forError(wechat); + handler.handleErrorExitEvent(wechat); break; case REMOTE_EXIT: - handler.forRemote(wechat); + handler.handleRemoteExitEvent(wechat); break; case LOCAL_EXIT: - handler.forLocal(wechat); + handler.handleLocalExitEvent(wechat); break; default: break; } } catch (Exception e) { - logger.error("Exit event \"" + type.name() + "\" process error.", e); + logger.error("Exit event process error.", e); } try { - handler.forAll(wechat, type, t); + handler.handleAllType(wechat, type, t); } catch (Exception e) { - logger.error("ForAll Exit event process error.", e); + logger.error("Exit event process error.", e); } } @@ -650,7 +686,124 @@ public class Wechat { * @param selector */ private void processSelector(int selector) { - System.out.println(selector); + try { + SelectorEnum e = SelectorEnum.valueOf(selector); + if (e == null) { + logger.warn("Cannot process selector for error selector {}", selector); + return; + } + + switch (e) { + case SELECTOR_0: + break; + case SELECTOR_2: + webWxSync(); + break; + case SELECTOR_4: + break; + case SELECTOR_7: + break; + default: + break; + } + } catch (Exception e) { + logger.error("Execute processSelector error.", e); + } + } + + /** + * 同步数据 + * + * @return + */ + private void webWxSync() { + try { + JSONObject result = webWeixinApi.webWxSync(httpClient, passTicket, wxsid, skey, wxuin, SyncKey); + if (result == null) { + logger.error("从服务端同步新数据异常"); + return; + } + + JSONObject BaseResponse = result.getJSONObject("BaseResponse"); + if (BaseResponse == null) { + logger.warn("同步接口返回数据格式错误"); + return; + } + + int Ret = BaseResponse.getIntValue("Ret"); + if (Ret != RetcodeEnum.RECODE_0.getCode()) { + logger.warn("同步接口返回错误代码:{}", Ret); + return; + } + + //新消息处理 + JSONArray AddMsgList = result.getJSONArray("AddMsgList"); + processNewMsg(AddMsgList); + + //更新SyncKey + try { + SyncKeyLock.lock(); + SyncKey = result.getJSONObject("SyncKey"); + } finally { + SyncKeyLock.unlock(); + } + } catch (Exception e) { + logger.error("Execute webWxSync error.", e); + } + } + + /** + * 处理新消息 + * + * @param AddMsgList + */ + private void processNewMsg(JSONArray AddMsgList) { + try { + if (AddMsgList != null && !AddMsgList.isEmpty()) { + int len = AddMsgList.size(); + logger.debug("收到{}条新消息", len); + for (int i = 0; i < len; i++) { + JSONObject AddMsg = AddMsgList.getJSONObject(i); + processNewMsg(AddMsg); + } + } + } catch (Exception e) { + logger.error("Execute processNewMsg error.", e); + } + } + + private void processNewMsg(JSONObject AddMsg) { + try { + ReceivedMsg msg = new ReceivedMsg(AddMsg); + processNewMsg(msg); + } catch (Exception e) { + logger.error("Execute processNewMsg error.", e); + } + } + + private void processNewMsg(ReceivedMsg msg) { + try { + if (receivedMsgHandlers == null) { + return; + } + for (ReceivedMsgHandler handler : receivedMsgHandlers) { + if (handler != null) { + processNewMsg(msg, handler); + } + } + } catch (Exception e) { + logger.error("Execute processNewMsg error.", e); + } + } + + private void processNewMsg(ReceivedMsg msg, ReceivedMsgHandler handler) { + try { + if (handler != null) { + handler.handleAllType(wechat, msg); + } + } catch (Exception e) { + + } } } diff --git a/src/main/java/com/hotlcc/wechat4j/api/WebWeixinApi.java b/src/main/java/com/hotlcc/wechat4j/api/WebWeixinApi.java index cdd9ee7..eda2cd7 100644 --- a/src/main/java/com/hotlcc/wechat4j/api/WebWeixinApi.java +++ b/src/main/java/com/hotlcc/wechat4j/api/WebWeixinApi.java @@ -490,14 +490,14 @@ public class WebWeixinApi { } /** - * 从服务端拉取新消息 + * 从服务端同步新数据 */ - public JSONObject pullNewMsg(HttpClient httpClient, - String passticket, - String wxsid, - String skey, - String wxuin, - JSONObject SyncKey) { + public JSONObject webWxSync(HttpClient httpClient, + String passticket, + String wxsid, + String skey, + String wxuin, + JSONObject SyncKey) { try { String url = new ST(PropertiesUtil.getProperty("webwx-url.webwxsync_url")) .add("skey", skey) @@ -525,7 +525,7 @@ public class WebWeixinApi { return JSONObject.parseObject(res); } catch (Exception e) { - logger.error("从服务端拉取新消息异常", e); + logger.error("从服务端同步新数据异常", e); return null; } } diff --git a/src/main/java/com/hotlcc/wechat4j/enums/RetcodeEnum.java b/src/main/java/com/hotlcc/wechat4j/enums/RetcodeEnum.java new file mode 100644 index 0000000..5d70bfe --- /dev/null +++ b/src/main/java/com/hotlcc/wechat4j/enums/RetcodeEnum.java @@ -0,0 +1,29 @@ +package com.hotlcc.wechat4j.enums; + +public enum RetcodeEnum { + RECODE_0(0, "正常"), + RECODE_1100(1100, "失败/登出微信"), + RECODE_1101(1101, "从其它设备登录微信"); + + private int code; + private String desc; + + RetcodeEnum(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public int getCode() { + return code; + } + + public static RetcodeEnum valueOf(int code) { + RetcodeEnum[] es = values(); + for (RetcodeEnum e : es) { + if (e.code == code) { + return e; + } + } + return null; + } +} diff --git a/src/main/java/com/hotlcc/wechat4j/enums/SelectorEnum.java b/src/main/java/com/hotlcc/wechat4j/enums/SelectorEnum.java new file mode 100644 index 0000000..d994def --- /dev/null +++ b/src/main/java/com/hotlcc/wechat4j/enums/SelectorEnum.java @@ -0,0 +1,30 @@ +package com.hotlcc.wechat4j.enums; + +public enum SelectorEnum { + SELECTOR_0(0, "正常"), + SELECTOR_2(2, "有新消息"), + SELECTOR_4(4, "目前发现修改了联系人备注会出现"), + SELECTOR_7(7, "手机操作了微信"); + + private int code; + private String desc; + + SelectorEnum(int code, String desc) { + this.code = code; + this.desc = desc; + } + + public int getCode() { + return code; + } + + public static SelectorEnum valueOf(int code) { + SelectorEnum[] es = values(); + for (SelectorEnum e : es) { + if (e.code == code) { + return e; + } + } + return null; + } +} diff --git a/src/main/java/com/hotlcc/wechat4j/handler/ExitEventHandler.java b/src/main/java/com/hotlcc/wechat4j/handler/ExitEventHandler.java index 17a75a1..6c971f6 100644 --- a/src/main/java/com/hotlcc/wechat4j/handler/ExitEventHandler.java +++ b/src/main/java/com/hotlcc/wechat4j/handler/ExitEventHandler.java @@ -14,26 +14,26 @@ public interface ExitEventHandler { * @param type * @param t */ - void forAll(Wechat wechat, ExitTypeEnum type, Throwable t); + void handleAllType(Wechat wechat, ExitTypeEnum type, Throwable t); /** * 针对错误导致的退出事件 * * @param wechat */ - void forError(Wechat wechat); + void handleErrorExitEvent(Wechat wechat); /** * 针对远程人为导致的退出事件 * * @param wechat */ - void forRemote(Wechat wechat); + void handleRemoteExitEvent(Wechat wechat); /** * 针对本地任务导致的退出事件 * * @param wechat */ - void forLocal(Wechat wechat); + void handleLocalExitEvent(Wechat wechat); } diff --git a/src/main/java/com/hotlcc/wechat4j/handler/ReceivedMsgHandler.java b/src/main/java/com/hotlcc/wechat4j/handler/ReceivedMsgHandler.java new file mode 100644 index 0000000..abb6a33 --- /dev/null +++ b/src/main/java/com/hotlcc/wechat4j/handler/ReceivedMsgHandler.java @@ -0,0 +1,17 @@ +package com.hotlcc.wechat4j.handler; + +import com.hotlcc.wechat4j.Wechat; +import com.hotlcc.wechat4j.model.ReceivedMsg; + +/** + * 接收消息处理器 + */ +public interface ReceivedMsgHandler { + /** + * 处理所有类型的消息 + * + * @param wechat + * @param msg + */ + void handleAllType(Wechat wechat, ReceivedMsg msg); +} diff --git a/src/main/java/com/hotlcc/wechat4j/model/AppInfo.java b/src/main/java/com/hotlcc/wechat4j/model/AppInfo.java new file mode 100644 index 0000000..0f3d325 --- /dev/null +++ b/src/main/java/com/hotlcc/wechat4j/model/AppInfo.java @@ -0,0 +1,24 @@ +package com.hotlcc.wechat4j.model; + +import com.alibaba.fastjson.JSONObject; + +public final class AppInfo { + private Integer Type; + private String AppID; + + public AppInfo(JSONObject info) { + if (info == null) { + return; + } + this.Type = info.getInteger("Type"); + this.AppID = info.getString("AppID"); + } + + public Integer getType() { + return Type; + } + + public String getAppID() { + return AppID; + } +} diff --git a/src/main/java/com/hotlcc/wechat4j/model/ReceivedMsg.java b/src/main/java/com/hotlcc/wechat4j/model/ReceivedMsg.java new file mode 100644 index 0000000..21c921c --- /dev/null +++ b/src/main/java/com/hotlcc/wechat4j/model/ReceivedMsg.java @@ -0,0 +1,179 @@ +package com.hotlcc.wechat4j.model; + +import com.alibaba.fastjson.JSONObject; + +public final class ReceivedMsg { + public ReceivedMsg(JSONObject msg) { + if (msg == null) { + return; + } + this.SubMsgType = msg.getInteger("SubMsgType"); + this.VoiceLength = msg.getLong("VoiceLength"); + this.FileName = msg.getString("FileName"); + this.ImgHeight = msg.getLong("ImgHeight"); + this.ToUserName = msg.getString("ToUserName"); + this.HasProductId = msg.getLong("HasProductId"); + this.ImgStatus = msg.getInteger("ImgStatus"); + this.Url = msg.getString("Url"); + this.ImgWidth = msg.getInteger("ImgWidth"); + this.ForwardFlag = msg.getInteger("ForwardFlag"); + this.Status = msg.getInteger("Status"); + this.Ticket = msg.getString("Ticket"); + this.RecommendInfo = new RecommendInfo(msg.getJSONObject("RecommendInfo")); + this.CreateTime = msg.getLong("CreateTime"); + this.NewMsgId = msg.getLong("NewMsgId"); + this.MsgType = msg.getInteger("MsgType"); + this.EncryFileName = msg.getString("EncryFileName"); + this.MsgId = msg.getString("MsgId"); + this.StatusNotifyCode = msg.getInteger("StatusNotifyCode"); + this.AppInfo = new AppInfo(msg.getJSONObject("AppInfo")); + this.PlayLength = msg.getLong("PlayLength"); + this.MediaId = msg.getString("MediaId"); + this.Content = msg.getString("Content"); + this.StatusNotifyUserName = msg.getString("StatusNotifyUserName"); + this.FromUserName = msg.getString("FromUserName"); + this.OriContent = msg.getString("OriContent"); + this.FileSize = msg.getString("FileSize"); + } + + private Integer SubMsgType; + private Long VoiceLength; + private String FileName; + private Long ImgHeight; + private String ToUserName; + private Long HasProductId; + private Integer ImgStatus; + private String Url; + private Integer ImgWidth; + private Integer ForwardFlag; + private Integer Status; + private String Ticket; + private RecommendInfo RecommendInfo; + private Long CreateTime; + private Long NewMsgId; + private Integer MsgType; + private String EncryFileName; + private String MsgId; + private Integer StatusNotifyCode; + private AppInfo AppInfo; + private Integer AppMsgType; + private Long PlayLength; + private String MediaId; + private String Content; + private String StatusNotifyUserName; + private String FromUserName; + private String OriContent; + private String FileSize; + + public Integer getSubMsgType() { + return SubMsgType; + } + + public Long getVoiceLength() { + return VoiceLength; + } + + public String getFileName() { + return FileName; + } + + public Long getImgHeight() { + return ImgHeight; + } + + public String getToUserName() { + return ToUserName; + } + + public Long getHasProductId() { + return HasProductId; + } + + public Integer getImgStatus() { + return ImgStatus; + } + + public String getUrl() { + return Url; + } + + public Integer getImgWidth() { + return ImgWidth; + } + + public Integer getForwardFlag() { + return ForwardFlag; + } + + public Integer getStatus() { + return Status; + } + + public String getTicket() { + return Ticket; + } + + public com.hotlcc.wechat4j.model.RecommendInfo getRecommendInfo() { + return RecommendInfo; + } + + public Long getCreateTime() { + return CreateTime; + } + + public Long getNewMsgId() { + return NewMsgId; + } + + public Integer getMsgType() { + return MsgType; + } + + public String getEncryFileName() { + return EncryFileName; + } + + public String getMsgId() { + return MsgId; + } + + public Integer getStatusNotifyCode() { + return StatusNotifyCode; + } + + public com.hotlcc.wechat4j.model.AppInfo getAppInfo() { + return AppInfo; + } + + public Integer getAppMsgType() { + return AppMsgType; + } + + public Long getPlayLength() { + return PlayLength; + } + + public String getMediaId() { + return MediaId; + } + + public String getContent() { + return Content; + } + + public String getStatusNotifyUserName() { + return StatusNotifyUserName; + } + + public String getFromUserName() { + return FromUserName; + } + + public String getOriContent() { + return OriContent; + } + + public String getFileSize() { + return FileSize; + } +} diff --git a/src/main/java/com/hotlcc/wechat4j/model/RecommendInfo.java b/src/main/java/com/hotlcc/wechat4j/model/RecommendInfo.java new file mode 100644 index 0000000..dfc7884 --- /dev/null +++ b/src/main/java/com/hotlcc/wechat4j/model/RecommendInfo.java @@ -0,0 +1,96 @@ +package com.hotlcc.wechat4j.model; + +import com.alibaba.fastjson.JSONObject; + +public final class RecommendInfo { + public RecommendInfo(JSONObject info) { + if (info == null) { + return; + } + this.Ticket = info.getString("Ticket"); + this.UserName = info.getString("UserName"); + this.Sex = info.getInteger("Sex"); + this.AttrStatus = info.getInteger("AttrStatus"); + this.City = info.getString("City"); + this.NickName = info.getString("NickName"); + this.Scene = info.getInteger("Scene"); + this.Province = info.getString("Province"); + this.Content = info.getString("Content"); + this.Alias = info.getString("Alias"); + this.Signature = info.getString("Signature"); + this.OpCode = info.getInteger("OpCode"); + this.QQNum = info.getLong("QQNum"); + this.VerifyFlag = info.getInteger("VerifyFlag"); + } + + private String Ticket; + private String UserName; + private Integer Sex; + private Integer AttrStatus; + private String City; + private String NickName; + private Integer Scene; + private String Province; + private String Content; + private String Alias; + private String Signature; + private Integer OpCode; + private Long QQNum; + private Integer VerifyFlag; + + public String getTicket() { + return Ticket; + } + + public String getUserName() { + return UserName; + } + + public Integer getSex() { + return Sex; + } + + public Integer getAttrStatus() { + return AttrStatus; + } + + public String getCity() { + return City; + } + + public String getNickName() { + return NickName; + } + + public Integer getScene() { + return Scene; + } + + public String getProvince() { + return Province; + } + + public String getContent() { + return Content; + } + + public String getAlias() { + return Alias; + } + + public String getSignature() { + return Signature; + } + + public Integer getOpCode() { + return OpCode; + } + + public Long getQQNum() { + return QQNum; + } + + public Integer getVerifyFlag() { + return VerifyFlag; + } +} diff --git a/src/test/java/TestClass.java b/src/test/java/TestClass.java deleted file mode 100644 index 783719e..0000000 --- a/src/test/java/TestClass.java +++ /dev/null @@ -1,35 +0,0 @@ -import com.hotlcc.wechat4j.Wechat; -import com.hotlcc.wechat4j.api.WebWeixinApi; -import com.hotlcc.wechat4j.util.QRCodeUtil; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.FileInputStream; -import java.io.IOException; - -public class TestClass { - private static Logger logger = LoggerFactory.getLogger(TestClass.class); - - public void test03() throws IOException { - BufferedImage image = ImageIO.read(new FileInputStream("D:/2.jpg")); - System.out.println(QRCodeUtil.toCharMatrix(image)); - } - - public void test04() { - WebWeixinApi api = new WebWeixinApi(); - Wechat wechat = new Wechat(); - wechat.setWebWeixinApi(api); - wechat.test(); - } - - @Test - public void test05() { - WebWeixinApi api = new WebWeixinApi(); - Wechat wechat = new Wechat(); - wechat.setWebWeixinApi(api); - System.out.println(wechat.autoLogin()); - } -}