Merge pull request #172 from sglmsn/sgssxln

Sgssxln
This commit is contained in:
ttttupup 2023-06-06 17:12:55 +08:00 committed by GitHub
commit 8229a15089
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 174 additions and 39 deletions

View File

@ -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)

View File

@ -17,6 +17,8 @@ public enum WxMsgType {
表情(47), 表情(47),
转账和收款(49), 转账和收款(49),
收到转账之后或者文件助手等信息(51), 收到转账之后或者文件助手等信息(51),
入群(10000),
/** /**
* 扫码触发,会触发2次, 有一次有编号,一次没有,还有登陆之后也有,很多情况都会调用这个 * 扫码触发,会触发2次, 有一次有编号,一次没有,还有登陆之后也有,很多情况都会调用这个
*/ */

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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()));
}
}

View File

@ -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
} }

View File

@ -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) {

View File

@ -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>&lt;![CDATA[]]&gt;</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();
}
} }

View File

@ -32,6 +32,10 @@ class HttpSendUtilTest {
void 开启hook() { void 开启hook() {
} }
@Test
void 关闭ook() {
HttpSendUtil.关闭hook();
}
@Test @Test
void 获取群成员() { void 获取群成员() {