mirror of
https://github.com/ttttupup/wxhelper.git
synced 2024-11-16 23:39:25 +08:00
commit
8229a15089
@ -11,6 +11,9 @@ com.example.wxhk.tcp.vertx.VertxTcp 这个是tcp服务端,接受信息
|
|||||||
com.example.wxhk.tcp.vertx.InitWeChat 微信环境初始化
|
com.example.wxhk.tcp.vertx.InitWeChat 微信环境初始化
|
||||||
|
|
||||||
com.example.wxhk.tcp.vertx.ArrHandle 循环消息处理
|
com.example.wxhk.tcp.vertx.ArrHandle 循环消息处理
|
||||||
|
|
||||||
|
com.example.wxhk.server.WxSmgServer 为消息处理接口,实现其中的方法即可
|
||||||
|
|
||||||
![image](https://github.com/sglmsn/wxhelper/assets/36943585/59d49401-a492-46a9-8ed9-dab7fb1822b4)
|
![image](https://github.com/sglmsn/wxhelper/assets/36943585/59d49401-a492-46a9-8ed9-dab7fb1822b4)
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ public enum WxMsgType {
|
|||||||
表情(47),
|
表情(47),
|
||||||
转账和收款(49),
|
转账和收款(49),
|
||||||
收到转账之后或者文件助手等信息(51),
|
收到转账之后或者文件助手等信息(51),
|
||||||
|
|
||||||
|
入群(10000),
|
||||||
/**
|
/**
|
||||||
* 扫码触发,会触发2次, 有一次有编号,一次没有,还有登陆之后也有,很多情况都会调用这个
|
* 扫码触发,会触发2次, 有一次有编号,一次没有,还有登陆之后也有,很多情况都会调用这个
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.example.wxhk.model.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付信息
|
||||||
|
*
|
||||||
|
* @author wt
|
||||||
|
* @param receiverUsername 付款人
|
||||||
|
* @param decimal 收款金额
|
||||||
|
* @param remark 备注
|
||||||
|
* @param transcationid
|
||||||
|
* @param transferid
|
||||||
|
* @date 2023/06/06
|
||||||
|
*/
|
||||||
|
public record PayoutInformation(String receiverUsername, BigDecimal decimal, String remark,String transcationid,String transferid) implements java.io.Serializable {
|
||||||
|
|
||||||
|
public PayoutInformation(String receiverUsername, BigDecimal decimal, String remark) {
|
||||||
|
this(receiverUsername, decimal, remark, null, null);
|
||||||
|
}
|
||||||
|
}
|
@ -2,15 +2,13 @@ package com.example.wxhk.msg;
|
|||||||
|
|
||||||
import com.example.wxhk.constant.WxMsgType;
|
import com.example.wxhk.constant.WxMsgType;
|
||||||
import com.example.wxhk.model.PrivateChatMsg;
|
import com.example.wxhk.model.PrivateChatMsg;
|
||||||
|
import com.example.wxhk.model.dto.PayoutInformation;
|
||||||
|
import com.example.wxhk.server.WxSmgServer;
|
||||||
import com.example.wxhk.tcp.vertx.InitWeChat;
|
import com.example.wxhk.tcp.vertx.InitWeChat;
|
||||||
import com.example.wxhk.util.HttpAsyncUtil;
|
|
||||||
import com.example.wxhk.util.HttpSendUtil;
|
|
||||||
import com.example.wxhk.util.HttpSyncUtil;
|
|
||||||
import io.vertx.core.json.JsonObject;
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import org.dromara.hutool.core.text.StrUtil;
|
|
||||||
import org.dromara.hutool.core.util.XmlUtil;
|
import org.dromara.hutool.core.util.XmlUtil;
|
||||||
import org.dromara.hutool.log.Log;
|
import org.dromara.hutool.log.Log;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@ -20,7 +18,6 @@ import org.w3c.dom.NodeList;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
@ -38,40 +35,36 @@ public class WxMsgHandle {
|
|||||||
*/
|
*/
|
||||||
public static ConcurrentHashMap<String, String> collection_code_caching = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<String, String> collection_code_caching = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
public static WxSmgServer wxSmgServer;
|
||||||
/**
|
/**
|
||||||
* 看
|
* 看
|
||||||
*/
|
*/
|
||||||
public static final ReentrantReadWriteLock LOOK = new ReentrantReadWriteLock();
|
public static final ReentrantReadWriteLock LOOK = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void setWxSmgServer(WxSmgServer wxSmgServer) {
|
||||||
|
WxMsgHandle.wxSmgServer = wxSmgServer;
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
add(chatMsg -> {
|
add(chatMsg -> {
|
||||||
if (Objects.equals(chatMsg.getIsSendMsg(), 1) && Objects.equals(chatMsg.getIsSendByPhone(), 1)) {
|
wxSmgServer.私聊(chatMsg);
|
||||||
log.info("手机端对:{}发出:{}", chatMsg.getFromUser(), chatMsg.getContent());
|
return null;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}, WxMsgType.私聊信息);
|
}, WxMsgType.私聊信息);
|
||||||
add(chatMsg -> {
|
add(chatMsg -> {
|
||||||
if (FILEHELPER.equals(chatMsg.getFromUser())) {
|
if (FILEHELPER.equals(chatMsg.getFromUser())) {
|
||||||
log.info("文件助手:{},", chatMsg.getContent());
|
wxSmgServer.文件助手(chatMsg);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}, WxMsgType.收到转账之后或者文件助手等信息);
|
}, WxMsgType.收到转账之后或者文件助手等信息);
|
||||||
add(chatMsg -> {
|
add(chatMsg -> {
|
||||||
if (FILEHELPER.equals(chatMsg.getFromUser())) {
|
wxSmgServer.收到名片(chatMsg);
|
||||||
Document document = XmlUtil.parseXml(chatMsg.getContent());
|
|
||||||
Element documentElement = document.getDocumentElement();
|
|
||||||
String username = documentElement.getAttribute("username");
|
|
||||||
if (StrUtil.isNotBlank(username)) {
|
|
||||||
HttpSendUtil.发送文本(username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}, WxMsgType.收到名片);
|
}, WxMsgType.收到名片);
|
||||||
add(chatMsg -> {
|
add(chatMsg -> {
|
||||||
HttpSendUtil.通过好友请求(chatMsg);
|
wxSmgServer.收到好友请求(chatMsg);
|
||||||
return 1;
|
return 1;
|
||||||
}, WxMsgType.好友请求);// 好友请求
|
}, WxMsgType.好友请求);// 好友请求
|
||||||
add(chatMsg -> {
|
add(chatMsg -> {
|
||||||
@ -148,7 +141,7 @@ public class WxMsgHandle {
|
|||||||
String substring = monery.substring(1);
|
String substring = monery.substring(1);
|
||||||
BigDecimal decimal = new BigDecimal(substring);
|
BigDecimal decimal = new BigDecimal(substring);
|
||||||
log.info("扫码收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), next.getValue(), remark);
|
log.info("扫码收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), next.getValue(), remark);
|
||||||
HttpSendUtil.发送文本(next.getValue(), StrUtil.format("扫码收款:{},备注:{}", decimal.stripTrailingZeros().toPlainString(), remark));
|
wxSmgServer.扫码收款(new PayoutInformation(next.getValue(),decimal,remark));
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -174,18 +167,18 @@ public class WxMsgHandle {
|
|||||||
String remark = documentElement.getElementsByTagName("pay_memo").item(0).getTextContent();
|
String remark = documentElement.getElementsByTagName("pay_memo").item(0).getTextContent();
|
||||||
String monery = documentElement.getElementsByTagName("feedesc").item(0).getTextContent();
|
String monery = documentElement.getElementsByTagName("feedesc").item(0).getTextContent();
|
||||||
String receiver_username = documentElement.getElementsByTagName("receiver_username").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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monery.startsWith("¥")) {
|
if (monery.startsWith("¥")) {
|
||||||
String substring = monery.substring(1);
|
String substring = monery.substring(1);
|
||||||
BigDecimal decimal = new BigDecimal(substring);
|
BigDecimal decimal = new BigDecimal(substring);
|
||||||
log.info("收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), receiver_username, remark);
|
log.info("收款:{},付款人:{},付款备注:{}", decimal.stripTrailingZeros().toPlainString(), chatMsg.getFromUser(), remark);
|
||||||
HttpSendUtil.发送文本(receiver_username, StrUtil.format("收到款项:{},备注:{}", decimal.stripTrailingZeros().toPlainString(), remark));
|
wxSmgServer.收款之后(new PayoutInformation(chatMsg.getFromUser(), decimal, remark));
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -207,7 +200,7 @@ public class WxMsgHandle {
|
|||||||
String content = chatMsg.getContent();
|
String content = chatMsg.getContent();
|
||||||
Document document = XmlUtil.parseXml(content);
|
Document document = XmlUtil.parseXml(content);
|
||||||
NodeList paysubtype1 = document.getElementsByTagName("paysubtype");
|
NodeList paysubtype1 = document.getElementsByTagName("paysubtype");
|
||||||
if(paysubtype1.getLength()==0){
|
if (paysubtype1.getLength() == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Node paysubtype = paysubtype1.item(0);
|
Node paysubtype = paysubtype1.item(0);
|
||||||
@ -218,12 +211,18 @@ public class WxMsgHandle {
|
|||||||
// 如果不是机器人收款,则认为不需要解析了,大概率是机器人自己发出去的
|
// 如果不是机器人收款,则认为不需要解析了,大概率是机器人自己发出去的
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Node transcationid = document.getDocumentElement().getElementsByTagName("transcationid").item(0);
|
|
||||||
Node transferid = document.getDocumentElement().getElementsByTagName("transferid").item(0);
|
String remark = document.getElementsByTagName("pay_memo").item(0).getTextContent();
|
||||||
HttpSyncUtil.exec(HttpAsyncUtil.Type.确认收款, new JsonObject().put("wxid", chatMsg.getFromUser())
|
String monery = document.getElementsByTagName("feedesc").item(0).getTextContent();
|
||||||
.put("transcationId", transcationid.getTextContent())
|
String receiver_username = document.getElementsByTagName("receiver_username").item(0).getTextContent();
|
||||||
.put("transferId", transferid.getTextContent()));
|
if (monery.startsWith("¥")) {
|
||||||
return false;
|
String substring = monery.substring(1);
|
||||||
|
BigDecimal decimal = new BigDecimal(substring);
|
||||||
|
Node transcationid = document.getDocumentElement().getElementsByTagName("transcationid").item(0);
|
||||||
|
Node transferid = document.getDocumentElement().getElementsByTagName("transferid").item(0);
|
||||||
|
wxSmgServer.接到收款(new PayoutInformation(chatMsg.getFromUser(), decimal, remark, transcationid.getTextContent(), transferid.getTextContent()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.example.wxhk.server;
|
||||||
|
|
||||||
|
import com.example.wxhk.model.PrivateChatMsg;
|
||||||
|
import com.example.wxhk.model.dto.PayoutInformation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信消息处理提取
|
||||||
|
* @author wt
|
||||||
|
* @date 2023/06/06
|
||||||
|
*/
|
||||||
|
public interface WxSmgServer {
|
||||||
|
/**
|
||||||
|
* 接到收款
|
||||||
|
*
|
||||||
|
* @param payoutInformation 支付信息
|
||||||
|
*/
|
||||||
|
void 接到收款(PayoutInformation payoutInformation);
|
||||||
|
|
||||||
|
void 收款之后(PayoutInformation pay);
|
||||||
|
|
||||||
|
void 私聊(PrivateChatMsg chatMsg);
|
||||||
|
|
||||||
|
void 文件助手(PrivateChatMsg chatMsg);
|
||||||
|
|
||||||
|
void 收到名片(PrivateChatMsg chatMsg);
|
||||||
|
|
||||||
|
void 收到好友请求(PrivateChatMsg chatMsg);
|
||||||
|
|
||||||
|
void 扫码收款(PayoutInformation payoutInformation);
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.example.wxhk.server.impl;
|
||||||
|
|
||||||
|
import com.example.wxhk.model.PrivateChatMsg;
|
||||||
|
import com.example.wxhk.model.dto.PayoutInformation;
|
||||||
|
import com.example.wxhk.model.request.ConfirmThePayment;
|
||||||
|
import com.example.wxhk.util.HttpSendUtil;
|
||||||
|
import org.dromara.hutool.core.text.StrUtil;
|
||||||
|
import org.dromara.hutool.core.util.XmlUtil;
|
||||||
|
import org.dromara.hutool.log.Log;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class WxSmgServerImpl implements com.example.wxhk.server.WxSmgServer {
|
||||||
|
|
||||||
|
protected static final Log log=Log.get();
|
||||||
|
|
||||||
|
public static final String FILEHELPER = "filehelper";
|
||||||
|
@Override
|
||||||
|
public void 接到收款(PayoutInformation payoutInformation) {
|
||||||
|
HttpSendUtil.确认收款(new ConfirmThePayment().setWxid(payoutInformation.receiverUsername()).setTranscationId(payoutInformation.transcationid()).setTransferId(payoutInformation.transferid()));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void 收款之后(PayoutInformation pay) {
|
||||||
|
HttpSendUtil.发送文本(pay.receiverUsername(), StrUtil.format("收到款项:{},备注:{}", pay.decimal().stripTrailingZeros().toPlainString(), pay.remark()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void 私聊(PrivateChatMsg chatMsg) {
|
||||||
|
if (Objects.equals(chatMsg.getIsSendMsg(), 1) && Objects.equals(chatMsg.getIsSendByPhone(), 1)) {
|
||||||
|
log.info("手机端对:{}发出:{}", chatMsg.getFromUser(), chatMsg.getContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void 文件助手(PrivateChatMsg chatMsg) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void 收到名片(PrivateChatMsg chatMsg) {
|
||||||
|
if (FILEHELPER.equals(chatMsg.getFromUser())) {
|
||||||
|
Document document = XmlUtil.parseXml(chatMsg.getContent());
|
||||||
|
Element documentElement = document.getDocumentElement();
|
||||||
|
String username = documentElement.getAttribute("username");
|
||||||
|
if (StrUtil.isNotBlank(username)) {
|
||||||
|
HttpSendUtil.发送文本(username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void 收到好友请求(PrivateChatMsg chatMsg) {
|
||||||
|
HttpSendUtil.通过好友请求(chatMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void 扫码收款(PayoutInformation payoutInformation) {
|
||||||
|
HttpSendUtil.发送文本(payoutInformation.receiverUsername(), StrUtil.format("扫码收款:{},备注:{}", payoutInformation.decimal().stripTrailingZeros().toPlainString(), payoutInformation.remark()));
|
||||||
|
}
|
||||||
|
}
|
@ -150,9 +150,8 @@ public class InitWeChat implements CommandLineRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
// FIXME: 2023/6/2 程序结束后关闭hook会偶尔出现微信闪退情况,暂时禁用
|
||||||
HttpSyncUtil.exec(HttpAsyncUtil.Type.关闭hook, new JsonObject());
|
// Runtime.getRuntime().addShutdownHook(new Thread(HttpSendUtil::关闭hook));
|
||||||
}));
|
|
||||||
//netstat -aon|findstr "端口号"
|
//netstat -aon|findstr "端口号"
|
||||||
// c.exe -I 4568 -p D:\exec\wxhelper.dll -m 4568
|
// c.exe -I 4568 -p D:\exec\wxhelper.dll -m 4568
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,11 @@ public class HttpSendUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static JsonObject 确认收款(ConfirmThePayment payment){
|
||||||
|
return HttpSyncUtil.exec(HttpAsyncUtil.Type.确认收款, payment.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static com.example.wxhk.infe.SendMsg of(HttpAsyncUtil.Type type) {
|
public static com.example.wxhk.infe.SendMsg of(HttpAsyncUtil.Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -81,4 +81,12 @@ public class XmlTest {
|
|||||||
String alias = documentElement.getAttribute("alias");
|
String alias = documentElement.getAttribute("alias");
|
||||||
Console.log(alias,username);
|
Console.log(alias,username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 公众号(){
|
||||||
|
String con = "{\"content\":\"请问您指的是账单的什么问题呢?请回复数字选择:\\n1.如何导出微信账单记录\\n2.如何查看已删除账单\\n3.怎么删除交易记录\",\"fromGroup\":\"gh_3dfda90e39d6\",\"fromUser\":\"gh_3dfda90e39d6\",\"isSendMsg\":0,\"msgId\":9025889923001869810,\"pid\":9920,\"sign\":\"0a66d3dab6b64ca646f512cd278d5f3d\",\"signature\":\"<msgsource>\\n\\t<tips>3</tips>\\n\\t<bizmsg>\\n\\t\\t<bizmsgshowtype>3</bizmsgshowtype>\\n\\t\\t<bizmsgfromuser><![CDATA[gh_3dfda90e39d6]]></bizmsgfromuser>\\n\\t</bizmsg>\\n\\t<msg_cluster_type>1</msg_cluster_type>\\n\\t<service_type>1</service_type>\\n\\t<scene>13</scene>\\n\\t<signature>v1_iJNyfNLb</signature>\\n\\t<tmp_node>\\n\\t\\t<publisher-id><![CDATA[]]></publisher-id>\\n\\t</tmp_node>\\n</msgsource>\\n\",\"time\":\"2023-06-05 11:32:17\",\"timestamp\":1685935937,\"type\":1}";
|
||||||
|
PrivateChatMsg privateChatMsg = new JsonObject(con).mapTo(PrivateChatMsg.class);
|
||||||
|
Document document = XmlUtil.parseXml(privateChatMsg.getSignature());
|
||||||
|
Element documentElement = document.getDocumentElement();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,10 @@ class HttpSendUtilTest {
|
|||||||
void 开启hook() {
|
void 开启hook() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
void 关闭ook() {
|
||||||
|
HttpSendUtil.关闭hook();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void 获取群成员() {
|
void 获取群成员() {
|
||||||
|
Loading…
Reference in New Issue
Block a user