diff --git a/java_client/README.md b/java_client/README.md index 9c712ab..d41a462 100644 --- a/java_client/README.md +++ b/java_client/README.md @@ -1,5 +1,6 @@ 环境为jdk17 执行之后会在当前项目所处磁盘根路径生成一个exec文件夹,然后会把src/main/resources/exec下的文件放在那避免因为路径问题出错 +java_client/src/main/resources/exec/c.exe 为注入器,只不过把名字改短了,更新的话换成最新版,改个名字就行, wxhelper.dll同理 项目启动之后,会生成一个tcp服务端,用来接受hook信息,然后把接收的信息放在队列中,之后用一个线程去循环处理消息. 具体实现可以看 diff --git a/java_client/src/main/java/com/example/wxhk/constant/WxMsgType.java b/java_client/src/main/java/com/example/wxhk/constant/WxMsgType.java index 59b9570..d46ffde 100644 --- a/java_client/src/main/java/com/example/wxhk/constant/WxMsgType.java +++ b/java_client/src/main/java/com/example/wxhk/constant/WxMsgType.java @@ -16,7 +16,7 @@ public enum WxMsgType { 收到名片(42), 表情(47), 转账和收款(49), - 收到转账之后(51), + 收到转账之后或者文件助手等信息(51), /** * 扫码触发,会触发2次, 有一次有编号,一次没有,还有登陆之后也有,很多情况都会调用这个 */ @@ -25,11 +25,11 @@ public enum WxMsgType { ; Integer type; - public Integer getType() { - return type; - } - WxMsgType(Integer type) { this.type = type; } + + public Integer getType() { + return type; + } } diff --git a/java_client/src/main/java/com/example/wxhk/controller/WxMsgController.java b/java_client/src/main/java/com/example/wxhk/controller/WxMsgController.java index 05e4ede..78b2e5d 100644 --- a/java_client/src/main/java/com/example/wxhk/controller/WxMsgController.java +++ b/java_client/src/main/java/com/example/wxhk/controller/WxMsgController.java @@ -5,10 +5,10 @@ import org.dromara.hutool.log.Log; public class WxMsgController { - protected static final Log log = Log.get(); + protected static final Log log = Log.get(); - void init(){ + void init() { } } diff --git a/java_client/src/main/java/com/example/wxhk/infe/Resp.java b/java_client/src/main/java/com/example/wxhk/infe/Resp.java new file mode 100644 index 0000000..1c3fd04 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/infe/Resp.java @@ -0,0 +1,11 @@ +package com.example.wxhk.infe; + +/** + * http 响应 + * @author wt + * @date 2023/06/01 + */ +public interface Resp extends java.io.Serializable{ + + +} diff --git a/java_client/src/main/java/com/example/wxhk/infe/SendMsg.java b/java_client/src/main/java/com/example/wxhk/infe/SendMsg.java new file mode 100644 index 0000000..4050bd6 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/infe/SendMsg.java @@ -0,0 +1,17 @@ +package com.example.wxhk.infe; + +import io.vertx.core.json.JsonObject; + +/** + * http接口请求的基础接口 + * + * @author wt + * @date 2023/06/01 + */ +public interface SendMsg extends java.io.Serializable{ + + default JsonObject toJson(){ + return JsonObject.mapFrom(this); + } + +} diff --git a/java_client/src/main/java/com/example/wxhk/model/PrivateChatMsg.java b/java_client/src/main/java/com/example/wxhk/model/PrivateChatMsg.java index ceb6da0..25424b7 100644 --- a/java_client/src/main/java/com/example/wxhk/model/PrivateChatMsg.java +++ b/java_client/src/main/java/com/example/wxhk/model/PrivateChatMsg.java @@ -17,6 +17,7 @@ import java.io.Serializable; @JsonIgnoreProperties(ignoreUnknown = true) public class PrivateChatMsg implements Serializable { + String path; /** * 内容 */ @@ -41,8 +42,6 @@ public class PrivateChatMsg implements Serializable { private String signature; private String time; private Integer timestamp; - - String path; /** * 类型 */ diff --git a/java_client/src/main/java/com/example/wxhk/model/request/AddFriends.java b/java_client/src/main/java/com/example/wxhk/model/request/AddFriends.java new file mode 100644 index 0000000..42178aa --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/AddFriends.java @@ -0,0 +1,20 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 添加wxid 好友 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class AddFriends implements SendMsg { + String wxid; + /** + * 验证信息 + */ + String msg; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/ConfirmThePayment.java b/java_client/src/main/java/com/example/wxhk/model/request/ConfirmThePayment.java new file mode 100644 index 0000000..d17d7ff --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/ConfirmThePayment.java @@ -0,0 +1,27 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 确认收款 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class ConfirmThePayment implements SendMsg { + /** + * 转账人微信id,从hook的消息中获取 + */ + String wxid; + /** + * 从hook的消息中获取对应的字段内容 + */ + String transcationId; + /** + * 从hook的消息中获取对应的字段内容。 + */ + String transferId; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/FindWeChat.java b/java_client/src/main/java/com/example/wxhk/model/request/FindWeChat.java new file mode 100644 index 0000000..68a80a9 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/FindWeChat.java @@ -0,0 +1,19 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 通过手机或者qq查找微信 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class FindWeChat implements SendMsg { + /** + * 通过 手机或qq查询信息 + */ + String keyword; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/ForwardMessages.java b/java_client/src/main/java/com/example/wxhk/model/request/ForwardMessages.java new file mode 100644 index 0000000..fed4d28 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/ForwardMessages.java @@ -0,0 +1,23 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 转发消息 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class ForwardMessages implements SendMsg { + /** + * 消息接收人wxid + */ + String wxid; + /** + * 消息id + */ + String msgid; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/GetGroupMembers.java b/java_client/src/main/java/com/example/wxhk/model/request/GetGroupMembers.java new file mode 100644 index 0000000..036fa9d --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/GetGroupMembers.java @@ -0,0 +1,16 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 获取群成员 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class GetGroupMembers implements SendMsg { + String chatRoomId; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/GetsTheNicknameOfAGroupMember.java b/java_client/src/main/java/com/example/wxhk/model/request/GetsTheNicknameOfAGroupMember.java new file mode 100644 index 0000000..5d68590 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/GetsTheNicknameOfAGroupMember.java @@ -0,0 +1,23 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 获取群成员昵称 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class GetsTheNicknameOfAGroupMember implements SendMsg { + /** + * 聊天室id + */ + String chatRoomId; + /** + * 成员id + */ + String memberId; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/IncreaseGroupMembership.java b/java_client/src/main/java/com/example/wxhk/model/request/IncreaseGroupMembership.java new file mode 100644 index 0000000..a80cee2 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/IncreaseGroupMembership.java @@ -0,0 +1,23 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 增加群成员 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class IncreaseGroupMembership implements SendMsg { + /** + * 聊天室id + */ + String chatRoomId; + /** + * 成员id,以,分割 + */ + String memberIds; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/OpenHook.java b/java_client/src/main/java/com/example/wxhk/model/request/OpenHook.java new file mode 100644 index 0000000..12929d0 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/OpenHook.java @@ -0,0 +1,18 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 开启hook + * + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class OpenHook implements SendMsg { + String port; + String ip; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/SendAtText.java b/java_client/src/main/java/com/example/wxhk/model/request/SendAtText.java new file mode 100644 index 0000000..d158bc3 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/SendAtText.java @@ -0,0 +1,25 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 发送at文本 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class SendAtText implements SendMsg { + /** + * 聊天室id,群聊用 + */ + String chatRoomId; + /** + * 群聊的时候用at多个用逗号隔开,@所有人则是notify@all + */ + String wxids; + + String msg; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/SendFile.java b/java_client/src/main/java/com/example/wxhk/model/request/SendFile.java new file mode 100644 index 0000000..54fcfb9 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/SendFile.java @@ -0,0 +1,22 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 发送文件 + * + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class SendFile implements SendMsg { + String wxid; + /** + * 发送文件路径 + * "filePath": "C:/Users/123.txt" + */ + String filePath; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/SendImg.java b/java_client/src/main/java/com/example/wxhk/model/request/SendImg.java new file mode 100644 index 0000000..cd62977 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/SendImg.java @@ -0,0 +1,22 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 发送图片 + * + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class SendImg implements SendMsg { + String wxid; + /** + * 发送图片接口 + * "imagePath": "C:/Users/123.png" + */ + String imagePath; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/SendMsg.java b/java_client/src/main/java/com/example/wxhk/model/request/SendMsg.java new file mode 100644 index 0000000..e86b213 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/SendMsg.java @@ -0,0 +1,52 @@ +package com.example.wxhk.model.request; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * http请求参数 + * + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class SendMsg { + /** + * wxid + */ + String wxid; + /** + * 消息内容 + */ + String msg; + + /** + * 聊天室id,群聊用 + */ + String chatRoomId; + /** + * 成员id + */ + String memberId; + + /** + * 群聊的时候用at多个用逗号隔开,@所有人则是notify@all + */ + String wxids; + /** + * 发送图片接口 + * "imagePath": "C:/Users/123.png" + */ + String imagePath; + /** + * 发送文件路径 + * "filePath": "C:/Users/123.txt" + */ + String filePath; + /** + * 通过 手机或qq查询信息 + */ + String keyword; + +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/SendText.java b/java_client/src/main/java/com/example/wxhk/model/request/SendText.java new file mode 100644 index 0000000..a749c3d --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/SendText.java @@ -0,0 +1,18 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 发送文本 + * + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class SendText implements SendMsg { + String wxid; + String msg; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/request/ThroughFriends.java b/java_client/src/main/java/com/example/wxhk/model/request/ThroughFriends.java new file mode 100644 index 0000000..4e68332 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/request/ThroughFriends.java @@ -0,0 +1,27 @@ +package com.example.wxhk.model.request; + +import com.example.wxhk.infe.SendMsg; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 通过好友请求 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +public class ThroughFriends implements SendMsg { + /** + * 添加好友消息内容里的encryptusername + */ + String v3; + /** + * 添加好友消息内容里的ticket + */ + String v4; + /** + * 好友权限,0是无限制,1是不让他看我,2是不看他,3是1+2 + */ + String permission; +} diff --git a/java_client/src/main/java/com/example/wxhk/model/response/ContactList.java b/java_client/src/main/java/com/example/wxhk/model/response/ContactList.java new file mode 100644 index 0000000..fcd1770 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/response/ContactList.java @@ -0,0 +1,50 @@ +package com.example.wxhk.model.response; + +import com.example.wxhk.infe.Resp; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * 联系人列表 + * @author wt + * @date 2023/06/01 + */ +@Data +@Accessors(chain = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ContactList implements Resp { + + /** + * code : 1 + * data : [{"customAccount":"","delFlag":0,"type":1,"userName":"朋友推荐消息","verifyFlag":0,"wxid":"fmessage"},{"customAccount":"tencent_cloud","delFlag":0,"type":3,"userName":"腾讯云助手","verifyFlag":24,"wxid":"gh_a73e2407e0f8"},{"customAccount":"","delFlag":0,"type":1,"userName":"语音记事本","verifyFlag":0,"wxid":"medianote"},{"customAccount":"","delFlag":0,"type":1,"userName":"漂流瓶","verifyFlag":0,"wxid":"floatbottle"},{"customAccount":"jys-wt","delFlag":0,"type":8651011,"userName":"时光似水戏流年","verifyFlag":0,"wxid":"wxid_gf1fogt5a0pq22"},{"customAccount":"wxzhifu","delFlag":0,"type":3,"userName":"微信支付","verifyFlag":24,"wxid":"gh_3dfda90e39d6"},{"customAccount":"dhkzfr","delFlag":0,"type":3,"userName":"阿芙(代发)","verifyFlag":0,"wxid":"wxid_kh16lri40gzj22"},{"customAccount":"","delFlag":0,"type":3,"userName":"文件传输助手","verifyFlag":0,"wxid":"filehelper"},{"customAccount":"","delFlag":0,"type":3,"userName":"fff","verifyFlag":0,"wxid":"24964676359@chatroom"},{"customAccount":"","delFlag":0,"type":2,"userName":"最美阿芙","verifyFlag":0,"wxid":"23793178249@chatroom"},{"customAccount":"afu943344","delFlag":0,"type":2,"userName":"A-阿芙4号-LOL永劫云顶出租-代发","verifyFlag":0,"wxid":"wxid_1gxthknqbmwv22"},{"customAccount":"","delFlag":0,"type":3,"userName":"微信收款助手","verifyFlag":24,"wxid":"gh_f0a92aa7146c"},{"customAccount":"","delFlag":0,"type":0,"userName":"","verifyFlag":0,"wxid":"25984984710827869@openim"}] + * result : OK + */ + + private Integer code; + private String result; + private List data; + + @Data + @Accessors(chain = true) + public static class DataBean implements Serializable { + /** + * customAccount : + * delFlag : 0 + * type : 1 + * userName : 朋友推荐消息 + * verifyFlag : 0 + * wxid : fmessage + */ + + private String customAccount; + private Integer delFlag; + private Integer type; + private String userName; + private Integer verifyFlag; + private String wxid; + } +} diff --git a/java_client/src/main/java/com/example/wxhk/model/response/GroupMembers.java b/java_client/src/main/java/com/example/wxhk/model/response/GroupMembers.java new file mode 100644 index 0000000..f13cf09 --- /dev/null +++ b/java_client/src/main/java/com/example/wxhk/model/response/GroupMembers.java @@ -0,0 +1,37 @@ +package com.example.wxhk.model.response; + +import com.example.wxhk.infe.Resp; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@Accessors(chain = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class GroupMembers implements Resp { + + /** + * code : 1 + * data : {"admin":"wxid_gf1fogt5a0pq22","chatRoomId":"24964676359@chatroom","members":"wxid_gf1fogt5a0pq22^Gwxid_4yr8erik0uho22"} + * result : OK + */ + + private Integer code; + private DataBean data; + private String result; + + @Data + public static class DataBean implements Serializable { + /** + * admin : wxid_gf1fogt5a0pq22 + * chatRoomId : 24964676359@chatroom + * members : wxid_gf1fogt5a0pq22^Gwxid_4yr8erik0uho22 + */ + + private String admin; + private String chatRoomId; + private String members; + } +} diff --git a/java_client/src/main/java/com/example/wxhk/msg/WxMsgHandle.java b/java_client/src/main/java/com/example/wxhk/msg/WxMsgHandle.java index a31fec0..0f99519 100644 --- a/java_client/src/main/java/com/example/wxhk/msg/WxMsgHandle.java +++ b/java_client/src/main/java/com/example/wxhk/msg/WxMsgHandle.java @@ -18,42 +18,49 @@ import org.w3c.dom.NodeList; import java.math.BigDecimal; import java.util.Iterator; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @Component public class WxMsgHandle { - public static final ConcurrentHashMap map = new ConcurrentHashMap<>(32); - + public static final ConcurrentHashMap map = new ConcurrentHashMap<>(32); + protected static final Log log = Log.get(); public static ConcurrentHashMap cache = new ConcurrentHashMap<>(); - protected static final Log log=Log.get(); - - public WxMsgHandle() { add(chatMsg -> { + if(Objects.equals(chatMsg.getIsSendMsg(), 1) && Objects.equals(chatMsg.getIsSendByPhone(), 1)){ + log.info("手机端对:{}发出:{}",chatMsg.getFromUser(),chatMsg.getContent()); + return 1; + } return 1; - },WxMsgType.私聊信息);// 好友请求 + }, WxMsgType.私聊信息); + add(chatMsg -> { + if("filehelper".equals(chatMsg.getFromUser())){ + log.info("文件助手:{},",chatMsg.getContent()); + } + return 1; + }, WxMsgType.收到转账之后或者文件助手等信息); add(chatMsg -> { HttpSendUtil.通过好友请求(chatMsg); return 1; - },WxMsgType.好友请求);// 好友请求 + }, WxMsgType.好友请求);// 好友请求 add(chatMsg -> { boolean f = 解析扫码支付第二段(chatMsg); - if(f){ - f=解析收款信息1段(chatMsg); - if(f){ + if (f) { + f = 解析收款信息1段(chatMsg); + if (f) { 解析收款信息2段(chatMsg); } } return null; - },WxMsgType.转账和收款); + }, WxMsgType.转账和收款); add(chatMsg -> { boolean f = 解析扫码支付第一段(chatMsg); return null; - },WxMsgType.扫码触发); - + }, WxMsgType.扫码触发); } @@ -69,14 +76,14 @@ public class WxMsgHandle { Document document = XmlUtil.parseXml(chatMsg.getContent()); Element documentElement = document.getDocumentElement(); String localName = documentElement.getLocalName(); - if("sysmsg".equals(localName)){ + if ("sysmsg".equals(localName)) { String type = documentElement.getAttribute("type"); - if("paymsg".equals(type)){ + if ("paymsg".equals(type)) { NodeList outtradeno = documentElement.getElementsByTagName("outtradeno"); - if (outtradeno.getLength()>0) { + if (outtradeno.getLength() > 0) { String textContent = outtradeno.item(0).getTextContent(); String textContent1 = documentElement.getElementsByTagName("username").item(0).getTextContent(); - cache.put(textContent,textContent1); + cache.put(textContent, textContent1); return false; } } @@ -99,23 +106,23 @@ public class WxMsgHandle { Document document = XmlUtil.parseXml(chatMsg.getContent()); Element documentElement = document.getDocumentElement(); String localName = documentElement.getLocalName(); - if("msg".equals(localName)){ + if ("msg".equals(localName)) { NodeList outtradeno = documentElement.getElementsByTagName("weapp_path"); - if(outtradeno.getLength()>1){ + if (outtradeno.getLength() > 1) { String textContent = outtradeno.item(1).getTextContent(); Set> entries = cache.entrySet(); Iterator> iterator = entries.iterator(); - while (iterator.hasNext()){ + while (iterator.hasNext()) { Map.Entry next = iterator.next(); if (textContent.contains(next.getKey())) { // 得到了交易信息 NodeList word = documentElement.getElementsByTagName("word"); String monery = word.item(1).getTextContent(); String remark = word.item(3).getTextContent(); - if(monery.startsWith("¥")){ + if (monery.startsWith("¥")) { String substring = monery.substring(1); BigDecimal decimal = new BigDecimal(substring); - log.info("扫码收款:{},付款人:{},付款备注:{}",decimal.stripTrailingZeros().toPlainString(),next.getValue(),remark); + log.info("扫码收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), next.getValue(), remark); iterator.remove(); return false; } @@ -130,25 +137,26 @@ public class WxMsgHandle { } return true; } + public static boolean 解析收款信息2段(PrivateChatMsg chatMsg) { try { Document document = XmlUtil.parseXml(chatMsg.getContent()); Element documentElement = document.getDocumentElement(); String localName = documentElement.getLocalName(); - if("msg".equals(localName)){ - if (documentElement.getElementsByTagName("transcationid").getLength()>0) { + if ("msg".equals(localName)) { + if (documentElement.getElementsByTagName("transcationid").getLength() > 0) { String remark = documentElement.getElementsByTagName("pay_memo").item(0).getTextContent(); String monery = documentElement.getElementsByTagName("feedesc").item(0).getTextContent(); String receiver_username = documentElement.getElementsByTagName("receiver_username").item(0).getTextContent(); - if(InitWeChat.WXID_MAP.contains(receiver_username)){ + if (InitWeChat.WXID_MAP.contains(receiver_username)) { // 如果是自己转出去的,则不需要解析了 return false; } - if(monery.startsWith("¥")){ + if (monery.startsWith("¥")) { String substring = monery.substring(1); BigDecimal decimal = new BigDecimal(substring); - log.info("收款:{},付款人:{},付款备注:{}",decimal.stripTrailingZeros().toPlainString(),receiver_username,remark); + log.info("收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), receiver_username, remark); return false; } } @@ -163,52 +171,50 @@ public class WxMsgHandle { /** * 解析收款信息1段 * 会自动进行收款 + * * @param chatMsg * @return boolean true则 继续解析,false则不需要解析了 */ - public static boolean 解析收款信息1段(PrivateChatMsg chatMsg){ + public static boolean 解析收款信息1段(PrivateChatMsg chatMsg) { try { String content = chatMsg.getContent(); Document document = XmlUtil.parseXml(content); Node paysubtype = document.getElementsByTagName("paysubtype").item(0); - if("1".equals(paysubtype.getTextContent().trim())){ + if ("1".equals(paysubtype.getTextContent().trim())) { // 手机发出去的 String textContent = document.getElementsByTagName("receiver_username").item(0).getTextContent(); - if(!InitWeChat.WXID_MAP.contains(textContent)){ + if (!InitWeChat.WXID_MAP.contains(textContent)) { // 如果不是机器人收款,则认为不需要解析了,大概率是机器人自己发出去的 return false; } Node transcationid = document.getDocumentElement().getElementsByTagName("transcationid").item(0); Node transferid = document.getDocumentElement().getElementsByTagName("transferid").item(0); - HttpSyncUtil.exec(HttpAsyncUtil.Type.确认收款, new JsonObject().put("wxid",chatMsg.getFromUser()) - .put("transcationId",transcationid.getTextContent()) - .put("transferId",transferid.getTextContent())); + HttpSyncUtil.exec(HttpAsyncUtil.Type.确认收款, new JsonObject().put("wxid", chatMsg.getFromUser()) + .put("transcationId", transcationid.getTextContent()) + .put("transferId", transferid.getTextContent())); return false; } - } catch (Exception e) { - log.error(e); + } catch (Exception e) { + log.error(e); } return true; } - - public interface Handle{ - Object handle(PrivateChatMsg chatMsg); + public static void exec(PrivateChatMsg chatMsg) { + Handle handle = map.get(chatMsg.getType()); + if (handle != null) { + handle.handle(chatMsg); + } } - - - public void add(Handle handle, WxMsgType...type){ + public void add(Handle handle, WxMsgType... type) { for (WxMsgType integer : type) { map.put(integer.getType(), handle); } } - public static void exec(PrivateChatMsg chatMsg){ - Handle handle = map.get(chatMsg.getType()); - if (handle != null) { - handle.handle(chatMsg); - } + public interface Handle { + Object handle(PrivateChatMsg chatMsg); } } diff --git a/java_client/src/main/java/com/example/wxhk/tcp/vertx/ArrHandle.java b/java_client/src/main/java/com/example/wxhk/tcp/vertx/ArrHandle.java index 39add74..d9fa2f6 100644 --- a/java_client/src/main/java/com/example/wxhk/tcp/vertx/ArrHandle.java +++ b/java_client/src/main/java/com/example/wxhk/tcp/vertx/ArrHandle.java @@ -15,40 +15,51 @@ import java.util.concurrent.TimeUnit; /** * 消息处理 + * * @author wt * @date 2023/05/31 */ @Component public class ArrHandle { - protected static final Log log = Log.get(); - public static final ThreadPoolExecutor sub = new ThreadPoolExecutor(1, 10, 30, TimeUnit.MINUTES, new LinkedBlockingQueue<>(), new NamedThreadFactory("sub", false)); + public static final ThreadPoolExecutor sub = new ThreadPoolExecutor(1, 10, 30, TimeUnit.MINUTES, new LinkedBlockingQueue<>(), new NamedThreadFactory("sub", false)); + public static final ThreadLocal chatMsgThreadLocal = new InheritableThreadLocal<>(); + protected static final Log log = Log.get(); + /** + * 得到当前正在处理的消息 + * + * @return {@link PrivateChatMsg} + */ + public static PrivateChatMsg getPriMsg() { + return chatMsgThreadLocal.get(); + } - @PostConstruct - public void exec(){ - for (int i = 0; i < sub.getCorePoolSize(); i++) { - sub.submit(() -> { - while (!Thread.currentThread().isInterrupted()){ - try { - JsonObject take = VertxTcp.LINKED_BLOCKING_QUEUE.take(); - log.info("{}",take.encode()); - - PrivateChatMsg privateChatMsg = take.mapTo(PrivateChatMsg.class); - if("weixin".equals(privateChatMsg.getFromUser())){ - String s = HttpSendUtil.获取当前登陆微信id(); - InitWeChat.WXID_MAP.add(s); - continue; - } - WxMsgHandle.exec(privateChatMsg); - } catch (Exception e) { - log.error(e); + @PostConstruct + public void exec() { + for (int i = 0; i < sub.getCorePoolSize(); i++) { + sub.submit(() -> { + while (!Thread.currentThread().isInterrupted()) { + try { + JsonObject take = VertxTcp.LINKED_BLOCKING_QUEUE.take(); + log.info("{}", take.encode()); + PrivateChatMsg privateChatMsg = take.mapTo(PrivateChatMsg.class); + chatMsgThreadLocal.set(privateChatMsg); + if ("weixin".equals(privateChatMsg.getFromUser())) { + String s = HttpSendUtil.获取当前登陆微信id(); + InitWeChat.WXID_MAP.add(s); + continue; } + WxMsgHandle.exec(privateChatMsg); + chatMsgThreadLocal.remove(); + } catch (Exception e) { + log.error(e); } - log.error("退出线程了"); - }); - } - + } + log.error("退出线程了"); + }); } + } + } diff --git a/java_client/src/main/java/com/example/wxhk/tcp/vertx/InitWeChat.java b/java_client/src/main/java/com/example/wxhk/tcp/vertx/InitWeChat.java index 649eaf3..9c5eab5 100644 --- a/java_client/src/main/java/com/example/wxhk/tcp/vertx/InitWeChat.java +++ b/java_client/src/main/java/com/example/wxhk/tcp/vertx/InitWeChat.java @@ -31,9 +31,8 @@ import java.io.IOException; public class InitWeChat implements CommandLineRunner { public final static Log log = Log.get(); - + public static final ConcurrentHashSet WXID_MAP = new ConcurrentHashSet<>(); public static String wxPath; - public static Integer wxPort; public static Integer vertxPort; /** @@ -41,9 +40,6 @@ public class InitWeChat implements CommandLineRunner { */ public static File DLL_PATH; - public static final ConcurrentHashSet WXID_MAP=new ConcurrentHashSet<>(); - - public static void 注入dll(String wxPid) throws IOException { String format = StrUtil.format("cmd /C c.exe -I {} -p {}\\wxhelper.dll -m {}", wxPid, DLL_PATH.getAbsolutePath(), wxPid); Process exec = Runtime.getRuntime().exec(format, null, DLL_PATH); @@ -138,15 +134,15 @@ public class InitWeChat implements CommandLineRunner { 注入dll(wxPid); } ThreadUtil.execute(() -> { - while (!Thread.currentThread().isInterrupted()){ + while (!Thread.currentThread().isInterrupted()) { JsonObject exec = HttpSyncUtil.exec(HttpAsyncUtil.Type.检查微信登陆, new JsonObject()); - if(exec.getInteger("code").equals(1)){ + if (exec.getInteger("code").equals(1)) { JsonObject dl = HttpSyncUtil.exec(HttpAsyncUtil.Type.获取登录信息, new JsonObject()); JsonObject jsonObject = dl.getJsonObject("data"); String wx = jsonObject.getString("wxid"); WXID_MAP.add(wx); if (log.isDebugEnabled()) { - log.debug("检测到微信登陆:{}",wx); + log.debug("检测到微信登陆:{}", wx); } break; } diff --git a/java_client/src/main/java/com/example/wxhk/tcp/vertx/VertxTcp.java b/java_client/src/main/java/com/example/wxhk/tcp/vertx/VertxTcp.java index aad3656..4a9bd8b 100644 --- a/java_client/src/main/java/com/example/wxhk/tcp/vertx/VertxTcp.java +++ b/java_client/src/main/java/com/example/wxhk/tcp/vertx/VertxTcp.java @@ -19,21 +19,20 @@ import java.util.concurrent.LinkedBlockingQueue; /** * 接受微信hook信息 + * * @author wt * @date 2023/05/26 */ @Component @Order() public class VertxTcp extends AbstractVerticle implements CommandLineRunner { - protected static final Log log = Log.get(); - NetServer netServer; public final static LinkedBlockingQueue LINKED_BLOCKING_QUEUE = new LinkedBlockingQueue<>(); - - + protected static final Log log = Log.get(); + NetServer netServer; @Override public void start(Promise startPromise) throws Exception { - netServer = vertx.createNetServer(new NetServerOptions() + netServer = vertx.createNetServer(new NetServerOptions() .setPort(InitWeChat.getVertxPort()) .setIdleTimeout(0) .setLogActivity(false) @@ -63,9 +62,9 @@ public class VertxTcp extends AbstractVerticle implements CommandLineRunner { listen.onComplete(event -> { boolean succeeded = event.succeeded(); if (succeeded) { - HttpAsyncUtil.exec(HttpAsyncUtil.Type.开启hook, new JsonObject().put("port", "8080").put("ip", "127.0.0.1")); + HttpAsyncUtil.exec(HttpAsyncUtil.Type.开启hook, new JsonObject().put("port", InitWeChat.getVertxPort().toString()).put("ip", "127.0.0.1")); startPromise.complete(); - }else{ + } else { startPromise.fail(event.cause()); } @@ -74,6 +73,6 @@ public class VertxTcp extends AbstractVerticle implements CommandLineRunner { @Override public void run(String... args) throws Exception { - WxhkApplication.vertx.deployVerticle(this,new DeploymentOptions().setWorkerPoolSize(6)); + WxhkApplication.vertx.deployVerticle(this, new DeploymentOptions().setWorkerPoolSize(6)); } } diff --git a/java_client/src/main/java/com/example/wxhk/util/HttpAsyncUtil.java b/java_client/src/main/java/com/example/wxhk/util/HttpAsyncUtil.java index 49d9015..db408bf 100644 --- a/java_client/src/main/java/com/example/wxhk/util/HttpAsyncUtil.java +++ b/java_client/src/main/java/com/example/wxhk/util/HttpAsyncUtil.java @@ -19,9 +19,9 @@ import org.dromara.hutool.log.Log; * @date 2023/05/25 */ public class HttpAsyncUtil { - protected static final Log log = Log.get(); - public static final WebClient client = WebClient.create(WxhkApplication.vertx,new WebClientOptions().setDefaultHost("localhost").setDefaultPort(InitWeChat.wxPort) + public static final WebClient client = WebClient.create(WxhkApplication.vertx, new WebClientOptions().setDefaultHost("localhost").setDefaultPort(InitWeChat.wxPort) .setConnectTimeout(10000).setMaxPoolSize(10).setPoolEventLoopSize(10)); + protected static final Log log = Log.get(); public static Future> exec(Type type, JsonObject object) { return client.post(InitWeChat.wxPort, "localhost", "/api/?type=" + type.getType()) @@ -29,7 +29,7 @@ public class HttpAsyncUtil { .onSuccess(event -> { if (log.isDebugEnabled()) { - log.debug("type:{},{}",type.getType(), event.bodyAsJsonObject()); + log.debug("type:{},{}", type.getType(), event.bodyAsJsonObject()); } } ); @@ -53,6 +53,7 @@ public class HttpAsyncUtil { 发送文件("6"), 开启hook("9"), 关闭hook("10"), + 添加好友("20"), 通过好友申请("23"), 获取群成员("25"), 获取群成员昵称("26"), @@ -65,12 +66,12 @@ public class HttpAsyncUtil { ; String type; - public String getType() { - return type; - } - Type(String type) { this.type = type; } + + public String getType() { + return type; + } } } diff --git a/java_client/src/main/java/com/example/wxhk/util/HttpSendUtil.java b/java_client/src/main/java/com/example/wxhk/util/HttpSendUtil.java index 8a815ea..d1eb918 100644 --- a/java_client/src/main/java/com/example/wxhk/util/HttpSendUtil.java +++ b/java_client/src/main/java/com/example/wxhk/util/HttpSendUtil.java @@ -1,6 +1,10 @@ package com.example.wxhk.util; import com.example.wxhk.model.PrivateChatMsg; +import com.example.wxhk.model.request.*; +import com.example.wxhk.model.response.ContactList; +import com.example.wxhk.model.response.GroupMembers; +import com.example.wxhk.tcp.vertx.ArrHandle; import com.example.wxhk.tcp.vertx.InitWeChat; import io.vertx.core.json.JsonObject; import org.dromara.hutool.core.util.XmlUtil; @@ -10,48 +14,133 @@ import org.w3c.dom.Node; /** * 常见方法 + * * @author wt * @date 2023/05/29 */ public class HttpSendUtil { - protected static final Log log = Log.get(); - public static JsonObject 通过好友请求(PrivateChatMsg msg){ + protected static final Log log = Log.get(); + + public static JsonObject 通过好友请求(PrivateChatMsg msg) { Document document = XmlUtil.parseXml(msg.getContent()); String encryptusername = document.getDocumentElement().getAttribute("encryptusername"); String ticket = document.getDocumentElement().getAttribute("ticket"); return HttpSyncUtil.exec(HttpAsyncUtil.Type.通过好友申请, new JsonObject().put("v3", encryptusername).put("v4", ticket).put("permission", "0")); } - public static JsonObject 确认收款(PrivateChatMsg msg){ + + public static JsonObject 确认收款(PrivateChatMsg msg) { try { String content = msg.getContent(); Document document = XmlUtil.parseXml(content); Node paysubtype = document.getElementsByTagName("paysubtype").item(0); - if("1".equals(paysubtype.getTextContent().trim())){ + if ("1".equals(paysubtype.getTextContent().trim())) { // 手机发出去的 String textContent = document.getElementsByTagName("receiver_username").item(0).getTextContent(); - if(!InitWeChat.WXID_MAP.contains(textContent)){ - return new JsonObject().put("spick",true); + if (!InitWeChat.WXID_MAP.contains(textContent)) { + return new JsonObject().put("spick", true); } Node transcationid = document.getDocumentElement().getElementsByTagName("transcationid").item(0); Node transferid = document.getDocumentElement().getElementsByTagName("transferid").item(0); - return HttpSyncUtil.exec(HttpAsyncUtil.Type.确认收款, new JsonObject().put("wxid",msg.getFromUser()) - .put("transcationId",transcationid.getTextContent()) - .put("transferId",transferid.getTextContent())); + return HttpSyncUtil.exec(HttpAsyncUtil.Type.确认收款, new JsonObject().put("wxid", msg.getFromUser()) + .put("transcationId", transcationid.getTextContent()) + .put("transferId", transferid.getTextContent())); } // 如果是确认接受收款,则跳过 return new JsonObject(); - } catch (Exception e) { + } catch (Exception e) { throw new RuntimeException(e); } } - public static String 获取当前登陆微信id(){ + public static JsonObject 发送文本(String wxid, String msg) { + return HttpSyncUtil.exec(HttpAsyncUtil.Type.发送文本, JsonObject.mapFrom(new SendMsg().setMsg(msg).setWxid(wxid))); + } + + public static JsonObject 发送文本(String msg) { + return 发送文本(ArrHandle.getPriMsg().getFromUser(), msg); + } + + public static JsonObject 发送at文本(String chatRoomId, String wxids, String msg) { + return HttpSyncUtil.exec(HttpAsyncUtil.Type.发送at文本, JsonObject.mapFrom(new SendMsg().setMsg(msg).setWxids(wxids).setChatRoomId(chatRoomId))); + } + + public static JsonObject 发送at文本(String wxids, String msg) { + return 发送at文本(ArrHandle.getPriMsg().getFromGroup(), wxids, msg); + } + + public static JsonObject 发送图片(String wxid, String msg) { + return HttpSyncUtil.exec(HttpAsyncUtil.Type.发送图片, JsonObject.mapFrom(new SendMsg().setImagePath(msg).setWxid(wxid))); + } + + public static JsonObject 发送图片(String msg) { + return 发送图片(ArrHandle.getPriMsg().getFromUser(), msg); + } + + public static JsonObject 发送文件(String wxid, String msg) { + return HttpSyncUtil.exec(HttpAsyncUtil.Type.发送文件, JsonObject.mapFrom(new SendMsg().setFilePath(msg).setWxid(wxid))); + } + + public static JsonObject 发送文件(String msg) { + return 发送文件(ArrHandle.getPriMsg().getFromUser(), msg); + } + + public static JsonObject 添加好友(AddFriends p) { + return HttpSyncUtil.exec(HttpAsyncUtil.Type.添加好友, p.toJson()); + } + + + public static String 获取当前登陆微信id() { JsonObject exec = HttpSyncUtil.exec(HttpAsyncUtil.Type.获取登录信息, new JsonObject()); return exec.getJsonObject("data").getString("wxid"); } + public static ContactList 联系人列表(){ + JsonObject exec = HttpSyncUtil.exec(HttpAsyncUtil.Type.联系人列表, new JsonObject()); + return exec.mapTo(ContactList.class); + } + public static JsonObject 开启hook(OpenHook hook){ + JsonObject exec = HttpSyncUtil.exec(HttpAsyncUtil.Type.开启hook,hook.toJson()); + return exec; + } + public static JsonObject 关闭hook(){ + JsonObject exec = HttpSyncUtil.exec(HttpAsyncUtil.Type.关闭hook,new JsonObject()); + return exec; + } + + public static GroupMembers 获取群成员(GetGroupMembers p){ + return HttpSyncUtil.exec(HttpAsyncUtil.Type.获取群成员, p.toJson()).mapTo(GroupMembers.class); + + } + + + @Deprecated + public static com.example.wxhk.infe.SendMsg of(HttpAsyncUtil.Type type) { + switch (type) { + + case 检查微信登陆 -> { + + } + case 获取登录信息 -> { + } + case 发送文本 -> { + return new SendText(); + } + case 发送at文本 -> { + return new SendAtText(); + } + case 发送图片 -> { + return new SendImg(); + } + case 发送文件 -> { + return new SendFile(); + } + + } + return new SendText(); + } + } diff --git a/java_client/src/main/java/com/example/wxhk/util/HttpSyncUtil.java b/java_client/src/main/java/com/example/wxhk/util/HttpSyncUtil.java index d5a2a63..21686ac 100644 --- a/java_client/src/main/java/com/example/wxhk/util/HttpSyncUtil.java +++ b/java_client/src/main/java/com/example/wxhk/util/HttpSyncUtil.java @@ -16,18 +16,20 @@ import org.dromara.hutool.log.Log; * @date 2023/05/25 */ public class HttpSyncUtil { + protected static final Log log = Log.get(); static final ClientEngine engine; - protected static final Log log = Log.get(); + static { ClientConfig clientConfig = ClientConfig.of() .setTimeout(30 * 1000); engine = ClientEngineFactory.createEngine(clientConfig); } - public static JsonObject exec(HttpAsyncUtil.Type type,JsonObject obj){ + + public static JsonObject exec(HttpAsyncUtil.Type type, JsonObject obj) { String post = engine.send(Request.of("http://localhost:" + InitWeChat.wxPort + "/api/?type=" + type.getType()).method(Method.POST).body(obj.encode())).bodyStr(); if (log.isDebugEnabled()) { - log.debug("type:{},{}",type.getType(),post); + log.debug("type:{},{}", type.getType(), post); } return new JsonObject(post); } diff --git a/java_client/src/test/java/com/example/wxhk/tcp/HttpAsyncUtilTest.java b/java_client/src/test/java/com/example/wxhk/tcp/HttpAsyncUtilTest.java index 6bf1ddf..23d1ba4 100644 --- a/java_client/src/test/java/com/example/wxhk/tcp/HttpAsyncUtilTest.java +++ b/java_client/src/test/java/com/example/wxhk/tcp/HttpAsyncUtilTest.java @@ -41,4 +41,8 @@ class HttpAsyncUtilTest { ThreadUtil.sync(this); } + @Test + void exec2() { + + } } \ No newline at end of file diff --git a/java_client/src/test/java/com/example/wxhk/util/HttpSendUtilTest.java b/java_client/src/test/java/com/example/wxhk/util/HttpSendUtilTest.java new file mode 100644 index 0000000..1b384e0 --- /dev/null +++ b/java_client/src/test/java/com/example/wxhk/util/HttpSendUtilTest.java @@ -0,0 +1,41 @@ +package com.example.wxhk.util; + +import com.example.wxhk.model.request.GetGroupMembers; +import com.example.wxhk.model.response.ContactList; +import com.example.wxhk.model.response.GroupMembers; +import org.dromara.hutool.core.lang.Console; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; + +@SpringBootTest +class HttpSendUtilTest { + + + @Test + void 获取当前登陆微信id() { + String s = HttpSendUtil.获取当前登陆微信id(); + } + + @Test + void 联系人列表() { + ContactList contactList = HttpSendUtil.联系人列表(); + + List data = contactList.getData(); + for (ContactList.DataBean datum : data) { + Console.log(datum.getWxid(),datum.getUserName()); + } + Console.log(contactList); + } + @Test + void 开启hook() { + + } + + @Test + void 获取群成员() { + GroupMembers 获取群成员 = HttpSendUtil.获取群成员(new GetGroupMembers().setChatRoomId("24964676359@chatroom")); + Console.log(获取群成员); + } +} \ No newline at end of file