Merge pull request #303 from PathfinderAx/develop
feat(0): [java]-[mvn]-功能更新及缺陷修复 Close #300
This commit is contained in:
commit
e218167307
138
clients/java/wechat-ferry-mvn/CHANGELOG.md
vendored
138
clients/java/wechat-ferry-mvn/CHANGELOG.md
vendored
@ -1,31 +1,81 @@
|
||||
## v39.3.3
|
||||
|
||||
### 版本列表
|
||||
|
||||
下载地址:[v39.3.3](https://github.com/lich0821/WeChatFerry/releases/tag/v39.3.3)
|
||||
|
||||
| 名称 | 版本 | 文件名 |
|
||||
|-----------------|-----------|---------------------------|
|
||||
| 微信客户端 | 3.9.11.25 | WeChatSetup-3.9.11.25.exe |
|
||||
| WeChatFerry-SDK | 39.3.3 | v39.3.3.zip |
|
||||
|
||||
### 功能列表
|
||||
|
||||
| 接口名 | 地址 | 是否支持 | 备注 |
|
||||
|----------------|-------------------|------|-------------------|
|
||||
| 查询登录状态 | /loginStatus | √ | 已测试 |
|
||||
| 获取登录微信内部识别号UID | /loginWeChatUid | √ | 已测试 |
|
||||
| 获取登录微信信息 | /loginWeChatInfo | √ | 已测试 |
|
||||
| 获取消息类型列表 | /list/msgType | √ | 已测试 |
|
||||
| 获取联系人列表 | /list/contacts | √ | 已测试 |
|
||||
| 获取数据库表名称列表 | /list/dbTableName | √ | 已测试 |
|
||||
| 获取指定数据库中的表列表 | /list/dbTable | √ | 已测试 |
|
||||
| 执行数据库查询SQL | /exec/dbQuerySql | √ | 已测试 |
|
||||
| 查询群成员 | /list/groupMember | √ | 已测试 |
|
||||
| 发送消息汇总入口 | /send/msgMaster | x | 预留 |
|
||||
| 发送文本消息 | /send/textMsg | x | 该版本不支持 |
|
||||
| 发送富文本消息 | /send/richTextMsg | x | 缩略图参数需要为空,否则会发送失败 |
|
||||
| 发送XML消息 | /send/xmlMsg | ? | 待测试 |
|
||||
| 发送图片消息 | /send/imageMsg | √ | 已测试 |
|
||||
| 发送表情消息 | /send/emojiMsg | x | 该版本不支持 |
|
||||
| 发送文件消息 | /send/fileMsg | x | 该版本不支持 |
|
||||
| 拍一拍群友 | /patOnePat | √ | 已测试 |
|
||||
| 接口名 | 地址 | 是否支持 | 备注 |
|
||||
|----------------|------------------------|------|-------------------|
|
||||
| 查询登录状态 | /loginStatus | ✔️ | 已测试 |
|
||||
| 获取登录微信内部识别号UID | /loginWeChatUid | ✔️ | 已测试 |
|
||||
| 获取登录微信信息 | /loginWeChatInfo | ✔️ | 已测试 |
|
||||
| 获取消息类型列表 | /list/msgType | ✔️ | 已测试 |
|
||||
| 获取联系人列表 | /list/contacts | ✔️ | 已测试 |
|
||||
| 获取数据库表名称列表 | /list/dbTableName | ✔️ | 已测试 |
|
||||
| 获取指定数据库中的表列表 | /list/dbTable | ✔️ | 已测试 |
|
||||
| 执行数据库查询SQL | /exec/dbQuerySql | ✔️ | 已测试 |
|
||||
| 发送消息汇总入口 | /send/msgMaster | ❌ | 预留 |
|
||||
| 发送文本消息 | /send/textMsg | ✔️ | 已测试 |
|
||||
| 发送富文本消息 | /send/richTextMsg | ❌ | 缩略图参数需要为空,否则会发送失败 |
|
||||
| 发送XML消息 | /send/xmlMsg | ❌ | 该版本不支持 |
|
||||
| 发送图片消息 | /send/imageMsg | ✔️ | 已测试 |
|
||||
| 发送表情消息 | /send/emojiMsg | ❌ | 该版本不支持 |
|
||||
| 发送文件消息 | /send/fileMsg | ❌ | 该版本不支持 |
|
||||
| 拍一拍群友 | /patOnePat | ✔️ | 已测试 |
|
||||
| 撤回消息 | /revokeMsg | ❌ | 该版本不支持 |
|
||||
| 通过好友申请 | /passFriendApply | ❌ | 该版本不支持 |
|
||||
| 添加群成员为微信好友 | /addFriend/groupMember | ❔ | 待测试 |
|
||||
| 查询群成员 | /groupMember/list | ✔️ | 已测试 |
|
||||
| 邀请群成员 | /groupMember/invite | ❔ | 待测试 |
|
||||
| 删除群成员 | /groupMember/delete | ❔ | 待测试 |
|
||||
| 查询朋友圈 | /friendCircle | ❔ | 待测试 |
|
||||
| 接收转账 | /receiveTransfer | ❌ | 该版本不支持 |
|
||||
|
||||
### 已知BUG
|
||||
|
||||
- 1.发送表情微信客户端闪退 - `待修复`
|
||||
- 2.发送富文本包含thumbnailUrl参数会导致消息发送不出去 - `待修复`
|
||||
- 3.发送文件成功之后客户端崩溃 - `待修复`
|
||||
|
||||
### 2025-01-04
|
||||
|
||||
#### ⛰️ Features
|
||||
|
||||
- 退群监测功能关闭,待完善,目前未开启
|
||||
- 说明文档更新
|
||||
|
||||
#### 🐛 Bug fixes
|
||||
- 微信端退出之后,调用接口返回客户端状态异常提示
|
||||
|
||||
### 2024-12-27
|
||||
|
||||
#### ⛰️ Features
|
||||
|
||||
- 查询群成员返回类新增字段
|
||||
- 新增退群监测功能
|
||||
- 说明文档更新
|
||||
|
||||
### 2024-12-25
|
||||
|
||||
#### ⛰️ Features
|
||||
|
||||
- 新增通过好友申请接口
|
||||
- 新增添加群成员为微信好友接口
|
||||
- 新增邀请群成员接口
|
||||
- 新增删除群成员接口
|
||||
- 新增刷新朋友圈接口
|
||||
- 新增撤回消息接口
|
||||
- 接收转账
|
||||
- 查询群成员请求地址变更
|
||||
- 消息回调配置文件参数名称修改
|
||||
- 封装接收到消息之后的业务操作类
|
||||
|
||||
### 2024-12-24
|
||||
|
||||
@ -45,3 +95,53 @@
|
||||
- 适配SDK39.3.3版本
|
||||
- wcf.proto文件部分字段类型修改
|
||||
- 消息转发适配多种消息类型
|
||||
|
||||
<br/>
|
||||
|
||||
___
|
||||
|
||||
<br/><br/>
|
||||
|
||||
## v39.2.4 - 推荐✨
|
||||
|
||||
### 版本列表
|
||||
|
||||
下载地址:[v39.2.4](https://github.com/lich0821/WeChatFerry/releases/tag/v39.2.4)
|
||||
|
||||
| 名称 | 版本 | 文件名 |
|
||||
|-----------------|-----------|---------------------------|
|
||||
| 微信客户端 | 3.9.10.27 | WeChatSetup-3.9.10.27.exe |
|
||||
| WeChatFerry-SDK | 39.2.4 | v39.2.4.zip |
|
||||
|
||||
### 功能列表
|
||||
|
||||
| 接口名 | 地址 | 是否支持 | 备注 |
|
||||
|----------------|------------------------|------|--------|
|
||||
| 查询登录状态 | /loginStatus | ✔️ | 已测试 |
|
||||
| 获取登录微信内部识别号UID | /loginWeChatUid | ✔️ | 已测试 |
|
||||
| 获取登录微信信息 | /loginWeChatInfo | ✔️ | 已测试 |
|
||||
| 获取消息类型列表 | /list/msgType | ✔️ | 已测试 |
|
||||
| 获取联系人列表 | /list/contacts | ✔️ | 已测试 |
|
||||
| 获取数据库表名称列表 | /list/dbTableName | ✔️ | 已测试 |
|
||||
| 获取指定数据库中的表列表 | /list/dbTable | ✔️ | 已测试 |
|
||||
| 执行数据库查询SQL | /exec/dbQuerySql | ✔️ | 已测试 |
|
||||
| 发送消息汇总入口 | /send/msgMaster | ❌ | 预留 |
|
||||
| 发送文本消息 | /send/textMsg | ✔️ | 已测试 |
|
||||
| 发送富文本消息 | /send/richTextMsg | ✔️ | 已测试 |
|
||||
| 发送XML消息 | /send/xmlMsg | ❌ | 该版本不支持 |
|
||||
| 发送图片消息 | /send/imageMsg | ✔️ | 已测试 |
|
||||
| 发送表情消息 | /send/emojiMsg | ✔️ | 已测试 |
|
||||
| 发送文件消息 | /send/fileMsg | ✔️ | 已测试 |
|
||||
| 拍一拍群友 | /patOnePat | ✔️ | 已测试 |
|
||||
| 撤回消息 | /revokeMsg | ❌ | 该版本不支持 |
|
||||
| 通过好友申请 | /passFriendApply | ❌ | 该版本不支持 |
|
||||
| 添加群成员为微信好友 | /addFriend/groupMember | ❔ | 待测试 |
|
||||
| 查询群成员 | /groupMember/list | ✔️ | 已测试 |
|
||||
| 邀请群成员 | /groupMember/invite | ❔ | 待测试 |
|
||||
| 删除群成员 | /groupMember/delete | ❔ | 待测试 |
|
||||
| 查询朋友圈 | /friendCircle | ❔ | 待测试 |
|
||||
| 接收转账 | /receiveTransfer | ❌ | 该版本不支持 |
|
||||
|
||||
<br/>
|
||||
|
||||
___
|
41
clients/java/wechat-ferry-mvn/README.MD
vendored
41
clients/java/wechat-ferry-mvn/README.MD
vendored
@ -13,7 +13,7 @@
|
||||
|-----------------|-----------|----|
|
||||
| JDK | 1.8+ | √ |
|
||||
| Maven | 3.8+ | √ |
|
||||
| 微信 | 3.9.11.25 | √ |
|
||||
| 微信客户端 | 3.9.11.25 | √ |
|
||||
| WeChatFerry-SDK | 39.3.3 | √ |
|
||||
| MySQL | 8.0+ | 备用 |
|
||||
|
||||
@ -35,6 +35,15 @@
|
||||
|
||||
把刚下载的最新发布文件解压到本项目中的 dll 文件目录下,直接替换原因文件即可
|
||||
|
||||
替换 `clients/java/wechat-ferry-mvn/dll` 目录下(也可以在配置文件中改为自定义的目录)
|
||||
|
||||
- sdk.dll
|
||||
- spy.dll
|
||||
- spy_debug.dll
|
||||
|
||||
> 如果之前已经使用本项目启动过微信,此时替换发现替换不了,是因为正则运行的微信客户端正在使用该文件,
|
||||
> 请退出并关闭微信客户端之后再进行替换
|
||||
|
||||
### 修改配置文件
|
||||
|
||||
配置文件:src/main/resources/application.yml
|
||||
@ -71,15 +80,17 @@ swagger地址:http://localhost:9201/swagger-ui/index.html
|
||||
|
||||
### 核心依赖
|
||||
|
||||
| 依赖 | 版本 | 说明 |
|
||||
|---------------|--------|----------|
|
||||
| Spring Boot | 2.7.18 | 基础框架 |
|
||||
| protobuf-java | 3.22.2 | rpc |
|
||||
| jna | 5.6.0 | 态访问系统本地库 |
|
||||
| nng-java | 1.4.0 | 本地包 |
|
||||
| fastjson2 | 2.0.52 | 序列化 |
|
||||
| dom4j | 2.1.3 | XML解析包 |
|
||||
| httpclient | 4.5.13 | 客户端请求 |
|
||||
| 依赖 | 版本 | 说明 |
|
||||
|---------------|-------------|----------|
|
||||
| Spring Boot | 2.7.18 | 基础框架 |
|
||||
| protobuf-java | 3.22.2 | rpc |
|
||||
| jna | 5.6.0 | 态访问系统本地库 |
|
||||
| nng-java | 1.4.0 | 本地包 |
|
||||
| fastjson2 | 2.0.52 | 序列化 |
|
||||
| dom4j | 2.1.3 | XML解析包 |
|
||||
| httpclient | 4.5.13 | 客户端请求 |
|
||||
| validation | 2.0.1.Final | 参数校验 |
|
||||
| springfox | 3.0.0 | swagger3 |
|
||||
|
||||
### 模块结构
|
||||
|
||||
@ -93,16 +104,22 @@ wechat-ferry-mvn
|
||||
│ ├─main 重启命令
|
||||
│ │ ├─java(com.wechat.ferry) java代码目录
|
||||
│ │ │ ├─config 配置
|
||||
│ │ │ ├─constant 常量
|
||||
│ │ │ ├─controller 控制层(API接口)
|
||||
│ │ │ ├─entity 聚合模型
|
||||
│ │ │ │ ├─dto DTO模型
|
||||
│ │ │ │ ├─po 数据库实体(与表结构一一对应,否则请使用DTO)
|
||||
│ │ │ │ ├─proto PB实体
|
||||
│ │ │ │ └─vo 视图层返回体目录
|
||||
│ │ │ ├─enums 枚举
|
||||
│ │ │ ├─exception 异常封装
|
||||
│ │ │ ├─handle 处理层
|
||||
│ │ │ ├─service 业务接口
|
||||
│ │ │ ├─service 业务层
|
||||
│ │ │ │ └─impl 业务实现类
|
||||
│ │ │ ├─utils 工具类
|
||||
│ │ │ ├─strategy 策略层
|
||||
│ │ │ │ └─impl 策略实现类(如接收到消息之后的事件处理可以放在这里)
|
||||
│ │ │ ├─task 定时任务
|
||||
│ │ │ ├─utils 工具层
|
||||
│ │ │ └─WcferryApplication.java 启动类
|
||||
│ │ │
|
||||
│ │ │resources 资源目录
|
||||
|
3
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/aggregation/.gitkeep
vendored
Normal file
3
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/aggregation/.gitkeep
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file !.gitkeep
|
15
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/aggregation/facade/ChatRoomDo.java
vendored
Normal file
15
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/aggregation/facade/ChatRoomDo.java
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package com.wechat.ferry.aggregation.facade;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 聚合模型类-联系人
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2023-06-08 22:39:53
|
||||
*/
|
||||
@Slf4j
|
||||
@Data
|
||||
public class ChatRoomDo {
|
||||
}
|
190
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/aggregation/facade/ContactDo.java
vendored
Normal file
190
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/aggregation/facade/ContactDo.java
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
package com.wechat.ferry.aggregation.facade;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.wechat.ferry.config.WeChatFerryProperties;
|
||||
import com.wechat.ferry.entity.po.wcf.Contact;
|
||||
import com.wechat.ferry.entity.proto.Wcf;
|
||||
import com.wechat.ferry.enums.DatabaseNameEnum;
|
||||
import com.wechat.ferry.enums.WxContactsMixedEnum;
|
||||
import com.wechat.ferry.enums.WxContactsOfficialEnum;
|
||||
import com.wechat.ferry.enums.WxContactsTypeEnum;
|
||||
import com.wechat.ferry.handle.WeChatSocketClient;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 聚合模型类-联系人
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2023-06-08 22:39:53
|
||||
*/
|
||||
@Slf4j
|
||||
@Data
|
||||
public class ContactDo extends Contact {
|
||||
|
||||
/**
|
||||
* 微信内部识别号UID
|
||||
*/
|
||||
@ApiModelProperty(value = "微信内部识别号UID")
|
||||
private String weChatUid;
|
||||
|
||||
/**
|
||||
* 联系人类型
|
||||
*/
|
||||
@ApiModelProperty(value = "联系人类型")
|
||||
private String contactType;
|
||||
|
||||
/**
|
||||
* 展示名称
|
||||
* 有备注优先展示备注
|
||||
*/
|
||||
@ApiModelProperty(value = "展示名称")
|
||||
private String showName;
|
||||
|
||||
/**
|
||||
* 根据自定义SQL查询联系人列表
|
||||
*
|
||||
* @param wechatSocketClient 通信客户端
|
||||
* @param weChatFerryProperties 配置文件
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-27 16:06
|
||||
*/
|
||||
public List<ContactDo> queryContactListBySql(WeChatSocketClient wechatSocketClient, WeChatFerryProperties weChatFerryProperties) {
|
||||
List<ContactDo> list = new ArrayList<>();
|
||||
// 查询联系人
|
||||
List<Wcf.DbRow> dbContactList = wechatSocketClient.querySql(DatabaseNameEnum.MICRO_MSG.getCode(),
|
||||
"SELECT UserName, Alias, DelFlag, Type, VerifyFlag, Remark, NickName, LabelIDList, DomainList, ChatRoomType, PYInitial, QuanPin, RemarkPYInitial, RemarkQuanPin, ChatRoomNotify FROM Contact;");
|
||||
if (!CollectionUtils.isEmpty(dbContactList)) {
|
||||
for (Wcf.DbRow dbRow : dbContactList) {
|
||||
List<Wcf.DbField> dbFieldList = dbRow.getFieldsList();
|
||||
if (!ObjectUtils.isEmpty(dbFieldList)) {
|
||||
ContactDo po = new ContactDo();
|
||||
for (Wcf.DbField dbField : dbFieldList) {
|
||||
String content = (String)wechatSocketClient.convertSqlVal(dbField.getType(), dbField.getContent());
|
||||
// 用户名
|
||||
if ("UserName".equals(dbField.getColumn())) {
|
||||
po.setUserName(content);
|
||||
po.setWeChatUid(content);
|
||||
// 设置类型
|
||||
String type = convertContactType(content, weChatFerryProperties);
|
||||
po.setContactType(type);
|
||||
}
|
||||
// 用户名
|
||||
if ("Alias".equals(dbField.getColumn())) {
|
||||
po.setAlias(content);
|
||||
}
|
||||
// 昵称
|
||||
if ("NickName".equals(dbField.getColumn())) {
|
||||
po.setNickname(content);
|
||||
}
|
||||
// 删除标志
|
||||
if ("DelFlag".equals(dbField.getColumn())) {
|
||||
po.setDelFlag(Integer.valueOf(content));
|
||||
}
|
||||
//
|
||||
if ("VerifyFlag".equals(dbField.getColumn())) {
|
||||
po.setVerifyFlag(Integer.valueOf(content));
|
||||
}
|
||||
//
|
||||
if ("Remark".equals(dbField.getColumn())) {
|
||||
po.setRemark(content);
|
||||
}
|
||||
//
|
||||
if ("LabelIDList".equals(dbField.getColumn())) {
|
||||
po.setLabelIdList(content);
|
||||
}
|
||||
//
|
||||
if ("DomainList".equals(dbField.getColumn())) {
|
||||
po.setDomainList(content);
|
||||
}
|
||||
//
|
||||
if ("ChatRoomType".equals(dbField.getColumn())) {
|
||||
po.setChatRoomType(Integer.valueOf(content));
|
||||
}
|
||||
}
|
||||
list.add(po);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换联系人类型
|
||||
* 类型判断,存在优先级的,官方杂号优先级高于微信公众号(如果定义重复了,常规禁止重复,手机端和电脑端分类不同)
|
||||
*
|
||||
* @param weChatUid 微信识别号
|
||||
* @param weChatFerryProperties 配置文件
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-27 15:56
|
||||
*/
|
||||
public static String convertContactType(String weChatUid, WeChatFerryProperties weChatFerryProperties) {
|
||||
String type = "";
|
||||
// 官方杂号集合
|
||||
Map<String, String> mixedNoMap = WxContactsMixedEnum.toCodeNameMap();
|
||||
mixedNoMap.putAll(convertContactsTypeProperties(weChatFerryProperties.getContactsTypeMixed()));
|
||||
// 公众号
|
||||
Map<String, String> officialMap = WxContactsOfficialEnum.toCodeNameMap();
|
||||
officialMap.putAll(convertContactsTypeProperties(weChatFerryProperties.getContactsTypeOfficial()));
|
||||
|
||||
// 类型判断,存在优先级的,官方杂号优先级高于微信公众号(如果定义重复了,常规禁止重复,手机端和电脑端分类不同)
|
||||
if (weChatUid.endsWith(WxContactsTypeEnum.WORK.getAffix())) {
|
||||
// 企微
|
||||
type = WxContactsTypeEnum.WORK.getCode();
|
||||
} else if (weChatUid.endsWith(WxContactsTypeEnum.GROUP.getAffix()) || weChatUid.endsWith("@im.chatroom")) {
|
||||
// 群聊 @im.chatroom 这种是很早之前的格式,单独例举
|
||||
type = WxContactsTypeEnum.GROUP.getCode();
|
||||
} else if (mixedNoMap.containsKey(weChatUid)) {
|
||||
// 官方杂号
|
||||
type = WxContactsTypeEnum.OFFICIAL_MIXED_NO.getCode();
|
||||
} else if (weChatUid.startsWith(WxContactsTypeEnum.OFFICIAL_ACCOUNT.getAffix())) {
|
||||
// 微信公众号
|
||||
type = WxContactsTypeEnum.OFFICIAL_ACCOUNT.getCode();
|
||||
} else if (officialMap.containsKey(weChatUid)) {
|
||||
type = WxContactsTypeEnum.OFFICIAL_ACCOUNT.getCode();
|
||||
} else {
|
||||
// 个微
|
||||
type = WxContactsTypeEnum.PERSON.getCode();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换联系人类型配置
|
||||
*
|
||||
* @param list 配置参数
|
||||
* @return map key:code val:name
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-24 16:55
|
||||
*/
|
||||
public static Map<String, String> convertContactsTypeProperties(List<String> list) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
for (String str : list) {
|
||||
String key = str;
|
||||
String val = str;
|
||||
// 存在名称则分割
|
||||
if (str.contains("|")) {
|
||||
int index = str.indexOf("|");
|
||||
key = str.substring(0, index);
|
||||
val = str.substring(index + 1);
|
||||
}
|
||||
map.put(key, val);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
@ -81,7 +81,7 @@ public class WeChatConfiguration {
|
||||
// 只打印
|
||||
// wechatSocketClient.printWxMsg(wechatSocketClient.getMsg());
|
||||
// 转发到boot项目进行消息处理
|
||||
wechatSocketClient.forwardMsg(wechatSocketClient.getMsg(), url);
|
||||
wechatSocketClient.localCallbackAnalyzeMsg(wechatSocketClient.getMsg(), url);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -47,24 +47,24 @@ public class WeChatFerryProperties {
|
||||
private List<String> openMsgGroups;
|
||||
|
||||
/**
|
||||
* 接收消息转发开关
|
||||
* 接收消息回调开关
|
||||
*/
|
||||
private Boolean receiveMsgFwdSwitch = false;
|
||||
private Boolean receiveMsgCallbackSwitch = false;
|
||||
|
||||
/**
|
||||
* 接收消息转发URL
|
||||
* 接收消息回调地址
|
||||
*/
|
||||
private List<String> receiveMsgFwdUrls;
|
||||
private List<String> receiveMsgCallbackUrls;
|
||||
|
||||
/**
|
||||
* 发送消息转发标识 1-关闭 2-全转发 3-发送成功才转发
|
||||
* 发送消息回调标识 1-关闭 2-全部回调 3-发送成功才回调
|
||||
*/
|
||||
private String sendMsgFwdFlag = "1";
|
||||
private String sendMsgCallbackFlag = "1";
|
||||
|
||||
/**
|
||||
* 发送消息转发URL
|
||||
* 发送消息回调地址
|
||||
*/
|
||||
private List<String> sendMsgFwdUrls;
|
||||
private List<String> sendMsgCallbackUrls;
|
||||
|
||||
/**
|
||||
* 调用第三方服务客户端成功状态码
|
||||
|
@ -10,10 +10,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.wechat.ferry.entity.TResponse;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfAddFriendGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDatabaseSqlReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDatabaseTableReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDeleteGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfInviteGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfPassFriendApplyReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfPatOnePatMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfReceiveTransferReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfRevokeMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendEmojiMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendFileMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendImageMsgReq;
|
||||
@ -115,13 +121,6 @@ public class WeChatDllController {
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询群成员", notes = "queryGroupMember")
|
||||
@PostMapping(value = "/list/groupMember")
|
||||
public TResponse<List<WxPpWcfGroupMemberResp>> queryGroupMember(@Validated @RequestBody WxPpWcfGroupMemberReq request) {
|
||||
List<WxPpWcfGroupMemberResp> list = weChatDllService.queryGroupMember(request);
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "发送消息汇总入口", notes = "sendMsgMaster")
|
||||
@PostMapping(value = "/send/msgMaster")
|
||||
public TResponse<WxPpWcfSendTextMsgResp> sendMsgMaster(@Validated @RequestBody String jsonString) {
|
||||
@ -184,12 +183,12 @@ public class WeChatDllController {
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
// }
|
||||
|
||||
// @ApiOperation(value = "撤回消息", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
// }
|
||||
//
|
||||
@ApiOperation(value = "撤回消息", notes = "revokeMsg")
|
||||
@PostMapping(value = "/revokeMsg")
|
||||
public TResponse<Object> revokeMsg(@Validated @RequestBody WxPpWcfRevokeMsgReq request) {
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
// @ApiOperation(value = "转发消息", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
@ -209,19 +208,55 @@ public class WeChatDllController {
|
||||
// }
|
||||
//
|
||||
|
||||
// @ApiOperation(value = "通过好友申请", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<WxPpSendPatOnePatMsgResp> friendApply(@Validated @RequestBody WxPpPatOnePatMsgReq request) {
|
||||
// // WxPpSendPatOnePatMsgResp resp = weChatDllService.patOnePat(request);
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, resp);
|
||||
// }
|
||||
@ApiOperation(value = "通过好友申请", notes = "passFriendApply")
|
||||
@PostMapping(value = "/passFriendApply")
|
||||
public TResponse<Object> passFriendApply(@Validated @RequestBody WxPpWcfPassFriendApplyReq request) {
|
||||
weChatDllService.passFriendApply(request);
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "添加群成员为微信好友", notes = "addFriendGroupMember")
|
||||
@PostMapping(value = "/addFriend/groupMember")
|
||||
public TResponse<Object> addFriendGroupMember(@Validated @RequestBody WxPpWcfAddFriendGroupMemberReq request) {
|
||||
weChatDllService.addFriendGroupMember(request);
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询群成员列表", notes = "queryGroupMemberList")
|
||||
@PostMapping(value = "/groupMember/list")
|
||||
public TResponse<List<WxPpWcfGroupMemberResp>> queryGroupMemberList(@Validated @RequestBody WxPpWcfGroupMemberReq request) {
|
||||
List<WxPpWcfGroupMemberResp> list = weChatDllService.queryGroupMemberList(request);
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "邀请群成员", notes = "inviteGroupMember")
|
||||
@PostMapping(value = "/groupMember/invite")
|
||||
public TResponse<Object> inviteGroupMember(@Validated @RequestBody WxPpWcfInviteGroupMemberReq request) {
|
||||
weChatDllService.inviteGroupMember(request);
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除群成员", notes = "deleteGroupMember")
|
||||
@PostMapping(value = "/groupMember/delete")
|
||||
public TResponse<Object> deleteGroupMember(@Validated @RequestBody WxPpWcfDeleteGroupMemberReq request) {
|
||||
weChatDllService.deleteGroupMember(request);
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询朋友圈", notes = "queryFriendCircle")
|
||||
@PostMapping(value = "/friendCircle")
|
||||
public TResponse<Object> queryFriendCircle() {
|
||||
weChatDllService.queryFriendCircle();
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "接收转账", notes = "receiveTransfer")
|
||||
@PostMapping(value = "/receiveTransfer")
|
||||
public TResponse<Object> receiveTransfer(@Validated @RequestBody WxPpWcfReceiveTransferReq request) {
|
||||
weChatDllService.receiveTransfer(request);
|
||||
return TResponse.ok(ResponseCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
// @ApiOperation(value = "获取朋友圈消息", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
// }
|
||||
//
|
||||
// @ApiOperation(value = "下载图片、视频、文件", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
@ -233,23 +268,5 @@ public class WeChatDllController {
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
// }
|
||||
//
|
||||
// @ApiOperation(value = "添加群成员", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
// }
|
||||
//
|
||||
// @ApiOperation(value = "删除群成员", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
// }
|
||||
//
|
||||
// @ApiOperation(value = "邀请群成员", notes = "queryMsgTypeList")
|
||||
// @PostMapping(value = "/list/msgType")
|
||||
// public TResponse<Object> queryMsgTypeList() {
|
||||
// return TResponse.ok(ResponseCodeEnum.SUCCESS, list);
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* DTO-ge微信消息
|
||||
* DTO-个微信消息
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-09-26 19:56
|
||||
|
35
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/ChatRoom.java
vendored
Normal file
35
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/ChatRoom.java
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package com.wechat.ferry.entity.po.wcf;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 实体类-群信息表
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-27 10:01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "ChatRoom", description = "群信息表")
|
||||
public class ChatRoom {
|
||||
|
||||
/**
|
||||
* 群名称
|
||||
*/
|
||||
@ApiModelProperty(value = "群名称")
|
||||
private String chatRoomName;
|
||||
|
||||
/**
|
||||
* 用户名称列表
|
||||
*/
|
||||
@ApiModelProperty(value = "用户名称列表")
|
||||
private String userNameList;
|
||||
|
||||
/**
|
||||
* 显示名称列表
|
||||
*/
|
||||
@ApiModelProperty(value = "显示名称列表")
|
||||
private String displayNameList;
|
||||
|
||||
}
|
47
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/ChatRoomInfo.java
vendored
Normal file
47
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/ChatRoomInfo.java
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
package com.wechat.ferry.entity.po.wcf;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 实体类-群详细信息表
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-27 10:03
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "ChatRoomInfo", description = "群详细信息表")
|
||||
public class ChatRoomInfo {
|
||||
|
||||
/**
|
||||
* 群名称
|
||||
*/
|
||||
@ApiModelProperty(value = "群名称")
|
||||
private String chatRoomName;
|
||||
|
||||
/**
|
||||
* 群公告
|
||||
*/
|
||||
@ApiModelProperty(value = "群公告")
|
||||
private String announcement;
|
||||
|
||||
/**
|
||||
* 公告编辑者
|
||||
*/
|
||||
@ApiModelProperty(value = "公告编辑者")
|
||||
private String announcementEditor;
|
||||
|
||||
/**
|
||||
* 公告发布时间
|
||||
*/
|
||||
@ApiModelProperty(value = "公告发布时间")
|
||||
private String announcementPublishTime;
|
||||
|
||||
/**
|
||||
* 群状态
|
||||
*/
|
||||
@ApiModelProperty(value = "群状态")
|
||||
private Integer chatRoomStatus;
|
||||
|
||||
}
|
71
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/Contact.java
vendored
Normal file
71
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/Contact.java
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
package com.wechat.ferry.entity.po.wcf;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 实体类-联系人表
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-27 09:47
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "Contact对象", description = "联系人表")
|
||||
public class Contact {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@ApiModelProperty(value = "用户名")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 别名
|
||||
*/
|
||||
@ApiModelProperty(value = "别名")
|
||||
private String alias;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@ApiModelProperty(value = "昵称")
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 删除标志
|
||||
*/
|
||||
@ApiModelProperty(value = "删除标志")
|
||||
private Integer delFlag;
|
||||
|
||||
/**
|
||||
* 验证标志
|
||||
*/
|
||||
@ApiModelProperty(value = "验证标志")
|
||||
private Integer verifyFlag;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ApiModelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 标签ID列表
|
||||
*/
|
||||
@ApiModelProperty(value = "标签ID列表")
|
||||
private String labelIdList;
|
||||
|
||||
/**
|
||||
* 域名列表
|
||||
*/
|
||||
@ApiModelProperty(value = "域名列表")
|
||||
private String domainList;
|
||||
|
||||
/**
|
||||
* 群类型
|
||||
*/
|
||||
@ApiModelProperty(value = "群类型")
|
||||
private Integer chatRoomType;
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.wechat.ferry.entity.po.wcf;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 实体类-联系人头像信息表
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-27 09:59
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "ContactHeadImgUrl对象", description = "联系人头像信息表")
|
||||
public class ContactHeadImgUrl {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@ApiModelProperty(value = "用户名")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 小头像URL
|
||||
*/
|
||||
@ApiModelProperty(value = "小头像URL")
|
||||
private String smallHeadIngUrl;
|
||||
|
||||
/**
|
||||
* 大头像URL
|
||||
*/
|
||||
@ApiModelProperty(value = "大头像URL")
|
||||
private String bigHeadIngUrl;
|
||||
|
||||
}
|
35
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/RevokeMsgStorage.java
vendored
Normal file
35
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/entity/po/wcf/RevokeMsgStorage.java
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package com.wechat.ferry.entity.po.wcf;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 实体类-撤回消息存储表
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-27 10:08
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "RevokeMsgStorage对象", description = "撤回消息存储表")
|
||||
public class RevokeMsgStorage {
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private Integer createTime;
|
||||
|
||||
/**
|
||||
* 消息服务ID
|
||||
*/
|
||||
@ApiModelProperty(value = "消息服务ID")
|
||||
private Integer msgSvrId;
|
||||
|
||||
/**
|
||||
* 撤回服务ID
|
||||
*/
|
||||
@ApiModelProperty(value = "撤回服务ID")
|
||||
private Integer revokeSvrId;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.wechat.ferry.entity.vo.request;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 请求入参-添加群成员为好友
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 09:53
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "wxPpWcfAddFriendGroupMemberReq", description = "个微WCF添加群成员为好友请求入参")
|
||||
public class WxPpWcfAddFriendGroupMemberReq {
|
||||
|
||||
/**
|
||||
* 群编号
|
||||
*/
|
||||
@NotBlank(message = "群编号不能为空")
|
||||
@ApiModelProperty(value = "群编号")
|
||||
private String groupNo;
|
||||
|
||||
/**
|
||||
* 待添加的群成员列表
|
||||
*/
|
||||
@ApiModelProperty(value = "待添加的群成员列表")
|
||||
private List<String> groupMembers;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.wechat.ferry.entity.vo.request;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 请求入参-个微WCF删除群成员
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 10:01
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "wxPpWcfDeleteGroupMemberReq", description = "个微WCF删除群成员请求入参")
|
||||
public class WxPpWcfDeleteGroupMemberReq {
|
||||
|
||||
/**
|
||||
* 群编号
|
||||
*/
|
||||
@NotBlank(message = "群编号不能为空")
|
||||
@ApiModelProperty(value = "群编号")
|
||||
private String groupNo;
|
||||
|
||||
/**
|
||||
* 待删除的群成员列表
|
||||
*/
|
||||
@ApiModelProperty(value = "待删除的群成员列表")
|
||||
private List<String> groupMembers;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.wechat.ferry.entity.vo.request;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 请求入参-个微WCF邀请群成员
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 09:51
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "wxPpWcfInviteGroupMemberReq", description = "个微WCF邀请群成员请求入参")
|
||||
public class WxPpWcfInviteGroupMemberReq {
|
||||
|
||||
/**
|
||||
* 群编号
|
||||
*/
|
||||
@NotBlank(message = "群编号不能为空")
|
||||
@ApiModelProperty(value = "群编号")
|
||||
private String groupNo;
|
||||
|
||||
/**
|
||||
* 待邀请的群成员列表
|
||||
*/
|
||||
@ApiModelProperty(value = "待邀请的群成员列表")
|
||||
private List<String> groupMembers;
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.wechat.ferry.entity.vo.request;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 请求入参-通过好友申请
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 09:30
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "wxPpWcfPassFriendApplyReq", description = "个微WCF通过好友申请请求入参")
|
||||
public class WxPpWcfPassFriendApplyReq {
|
||||
|
||||
/**
|
||||
* 申请人
|
||||
* v3 xml.attrib["encryptusername"]
|
||||
* 加密用户名 (好友申请消息里 v3 开头的字符串)
|
||||
*/
|
||||
@NotBlank(message = "申请人不能为空")
|
||||
@ApiModelProperty(value = "申请人")
|
||||
private String applicant;
|
||||
|
||||
/**
|
||||
* 审核人
|
||||
* v4 xml.attrib["ticket"]
|
||||
* Ticket (好友申请消息里 v4 开头的字符串)
|
||||
* 一般指自己,别人申请添加,自己审核是否通过
|
||||
*/
|
||||
@NotBlank(message = "审核人不能为空")
|
||||
@ApiModelProperty(value = "审核人")
|
||||
private String reviewer;
|
||||
|
||||
/**
|
||||
* 场景
|
||||
* 申请方式 (好友申请消息里的 scene); 为了兼容旧接口,默认为扫码添加 (30)
|
||||
*/
|
||||
@ApiModelProperty(value = "场景")
|
||||
private String scene;
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.wechat.ferry.entity.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 请求入参-个微WCF接收转账
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 13:46
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "wxPpWcfReceiveTransferReq", description = "个微WCF接收转账请求入参")
|
||||
public class WxPpWcfReceiveTransferReq {
|
||||
|
||||
/**
|
||||
* 转账人
|
||||
*/
|
||||
@ApiModelProperty(value = "转账人")
|
||||
private String weChatUid;
|
||||
|
||||
/**
|
||||
* 转账编号 transferId
|
||||
*/
|
||||
@ApiModelProperty(value = "转账编号")
|
||||
private String transferId;
|
||||
|
||||
/**
|
||||
* 交易编号 Transaction id
|
||||
*/
|
||||
@ApiModelProperty(value = "交易编号")
|
||||
private String transactionId;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.wechat.ferry.entity.vo.request;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 请求入参-撤回消息
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 12:00
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "wxPpWcfRevokeMsgReq", description = "个微WCF撤回消息请求入参")
|
||||
public class WxPpWcfRevokeMsgReq {
|
||||
|
||||
/**
|
||||
* 消息编号
|
||||
*/
|
||||
@ApiModelProperty(value = "场景")
|
||||
private String msgId;
|
||||
|
||||
}
|
@ -33,4 +33,16 @@ public class WxPpWcfGroupMemberResp {
|
||||
@ApiModelProperty(value = "状态")
|
||||
private String state;
|
||||
|
||||
/**
|
||||
* 是否自己
|
||||
*/
|
||||
@ApiModelProperty(value = "是否自己")
|
||||
private Boolean whetherSelf;
|
||||
|
||||
/**
|
||||
* 是否企微
|
||||
*/
|
||||
@ApiModelProperty(value = "是否企微")
|
||||
private Boolean whetherWork;
|
||||
|
||||
}
|
||||
|
@ -8,15 +8,15 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 枚举-消息转发开关
|
||||
* 1-关闭 2-全转发 3-发送成功才转发
|
||||
* 枚举-消息回调开关
|
||||
* 1-关闭 2-全部回调 3-发送成功才回调
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024/10/01 15:42
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MsgFwdTypeEnum {
|
||||
public enum MsgCallbackTypeEnum {
|
||||
|
||||
/**
|
||||
* 1-关闭
|
||||
@ -24,14 +24,14 @@ public enum MsgFwdTypeEnum {
|
||||
CLOSE("1", "关闭"),
|
||||
|
||||
/**
|
||||
* 2-全转发
|
||||
* 2-全部回调
|
||||
*/
|
||||
ALL("2", "全转发"),
|
||||
ALL("2", "全部回调"),
|
||||
|
||||
/**
|
||||
* 3-发送成功才转发
|
||||
* 3-发送成功才回调
|
||||
*/
|
||||
SUCCESS("3", "发送成功才转发"),
|
||||
SUCCESS("3", "发送成功才回调"),
|
||||
|
||||
/**
|
||||
* 未匹配上
|
||||
@ -47,12 +47,13 @@ public enum MsgFwdTypeEnum {
|
||||
/**
|
||||
* map集合 key:code val:枚举
|
||||
*/
|
||||
public static final Map<String, MsgFwdTypeEnum> codeMap = Arrays.stream(values()).collect(Collectors.toMap(MsgFwdTypeEnum::getCode, v -> v));
|
||||
public static final Map<String, MsgCallbackTypeEnum> codeMap =
|
||||
Arrays.stream(values()).collect(Collectors.toMap(MsgCallbackTypeEnum::getCode, v -> v));
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static MsgFwdTypeEnum getCodeMap(String code) {
|
||||
public static MsgCallbackTypeEnum getCodeMap(String code) {
|
||||
return codeMap.getOrDefault(code, UN_MATCH);
|
||||
}
|
||||
|
48
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/enums/MsgEventTypeEnum.java
vendored
Normal file
48
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/enums/MsgEventTypeEnum.java
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package com.wechat.ferry.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 枚举-消息事件类型
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024/12/27 18:09
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MsgEventTypeEnum {
|
||||
|
||||
/**
|
||||
* 1-注入成功
|
||||
*/
|
||||
INJECT("1", "注入成功"),
|
||||
|
||||
/**
|
||||
* 未匹配上
|
||||
*/
|
||||
UN_MATCH("", null),
|
||||
|
||||
// 结束
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* map集合 key:code val:枚举
|
||||
*/
|
||||
public static final Map<String, MsgEventTypeEnum> codeMap = Arrays.stream(values()).collect(Collectors.toMap(MsgEventTypeEnum::getCode, v -> v));
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static MsgEventTypeEnum getCodeMap(String code) {
|
||||
return codeMap.getOrDefault(code, UN_MATCH);
|
||||
}
|
||||
|
||||
}
|
49
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/enums/ReceiveMsgChannelEnum.java
vendored
Normal file
49
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/enums/ReceiveMsgChannelEnum.java
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package com.wechat.ferry.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 枚举-接收消息处理渠道
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024/12/25 14:15
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ReceiveMsgChannelEnum {
|
||||
|
||||
/**
|
||||
* 1-签到
|
||||
*/
|
||||
SIGN_IN("1", "签到"),
|
||||
|
||||
/**
|
||||
* 未匹配上
|
||||
*/
|
||||
UN_MATCH("", null),
|
||||
|
||||
// 结束
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* map集合 key:code val:枚举
|
||||
*/
|
||||
public static final Map<String, ReceiveMsgChannelEnum> codeMap =
|
||||
Arrays.stream(values()).collect(Collectors.toMap(ReceiveMsgChannelEnum::getCode, v -> v));
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static ReceiveMsgChannelEnum getCodeMap(String code) {
|
||||
return codeMap.getOrDefault(code, UN_MATCH);
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +1,29 @@
|
||||
package com.wechat.ferry.handle;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.sun.jna.Native;
|
||||
import com.wechat.ferry.entity.dto.WxPpMsgDTO;
|
||||
import com.wechat.ferry.entity.proto.Wcf.DbQuery;
|
||||
import com.wechat.ferry.entity.proto.Wcf.DbRow;
|
||||
import com.wechat.ferry.entity.proto.Wcf.DecPath;
|
||||
import com.wechat.ferry.entity.proto.Wcf.Functions;
|
||||
import com.wechat.ferry.entity.proto.Wcf.MemberMgmt;
|
||||
import com.wechat.ferry.entity.proto.Wcf.Request;
|
||||
import com.wechat.ferry.entity.proto.Wcf.Response;
|
||||
import com.wechat.ferry.entity.proto.Wcf.Verification;
|
||||
import com.wechat.ferry.entity.proto.Wcf.WxMsg;
|
||||
import com.wechat.ferry.exception.BizException;
|
||||
import com.wechat.ferry.service.SDK;
|
||||
import com.wechat.ferry.utils.HttpClientUtil;
|
||||
import com.wechat.ferry.utils.XmlJsonConvertUtil;
|
||||
@ -117,14 +121,21 @@ public class WeChatSocketClient {
|
||||
|
||||
public Response sendCmd(Request req) {
|
||||
try {
|
||||
// 设置超时时间 20s
|
||||
cmdSocket.setSendTimeout(20000);
|
||||
ByteBuffer bb = ByteBuffer.wrap(req.toByteArray());
|
||||
cmdSocket.send(bb);
|
||||
ByteBuffer ret = ByteBuffer.allocate(BUFFER_SIZE);
|
||||
long size = cmdSocket.receive(ret, true);
|
||||
return Response.parseFrom(Arrays.copyOfRange(ret.array(), 0, (int)size));
|
||||
} catch (Exception e) {
|
||||
log.error("命令调用失败: ", e);
|
||||
return null;
|
||||
if ("Timed out".equals(e.getMessage())) {
|
||||
log.error("请求超时: ", e);
|
||||
throw new BizException("请求超时:1.接口耗时太长,2.服务与客户端失去联系,请重启本服务!详细异常信息:" + e.getMessage());
|
||||
} else {
|
||||
log.error("命令调用失败: ", e);
|
||||
throw new BizException("命令调用失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,42 +170,6 @@ public class WeChatSocketClient {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收好友请求
|
||||
*
|
||||
* @param v3 xml.attrib["encryptusername"]
|
||||
* @param v4 xml.attrib["ticket"]
|
||||
* @return 结果状态码
|
||||
*/
|
||||
public int acceptNewFriend(String v3, String v4) {
|
||||
int ret = -1;
|
||||
Verification verification = Verification.newBuilder().setV3(v3).setV4(v4).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_ACCEPT_FRIEND_VALUE).setV(verification).build();
|
||||
Response rsp = sendCmd(req);
|
||||
if (rsp != null) {
|
||||
ret = rsp.getStatus();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加群成员为微信好友
|
||||
*
|
||||
* @param roomID 群ID
|
||||
* @param wxIds 要加群的人列表,逗号分隔
|
||||
* @return 1 为成功,其他失败
|
||||
*/
|
||||
public int addChatroomMembers(String roomID, String wxIds) {
|
||||
int ret = -1;
|
||||
MemberMgmt memberMgmt = MemberMgmt.newBuilder().setRoomid(roomID).setWxids(wxIds).build();
|
||||
Request req = Request.newBuilder().setFuncValue(Functions.FUNC_ADD_ROOM_MEMBERS_VALUE).setM(memberMgmt).build();
|
||||
Response rsp = sendCmd(req);
|
||||
if (rsp != null) {
|
||||
ret = rsp.getStatus();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密图片
|
||||
*
|
||||
@ -348,7 +323,16 @@ public class WeChatSocketClient {
|
||||
}
|
||||
}
|
||||
|
||||
public void forwardMsg(WxMsg msg, String url) {
|
||||
/**
|
||||
* 本机回调解析消息
|
||||
*
|
||||
* @param msg 消息内容
|
||||
* @param url 回调地址
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-05 12:50
|
||||
*/
|
||||
public void localCallbackAnalyzeMsg(WxMsg msg, String url) {
|
||||
String xml = msg.getXml();
|
||||
xml = xml.replaceAll(">[\\s\\p{Zs}]*<", "><");
|
||||
String content = msg.getContent();
|
||||
@ -396,10 +380,50 @@ public class WeChatSocketClient {
|
||||
try {
|
||||
String responseStr = HttpClientUtil.doPostJson(url, jsonString);
|
||||
if (!JSONObject.parseObject(responseStr).getString("code").equals("200")) {
|
||||
log.error("本机消息转发失败!-URL:{}", url);
|
||||
log.error("本机消息回调失败!-URL:{}", url);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("转发接口报错:", e);
|
||||
log.error("本机消息回调接口报错:", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SQL类型
|
||||
*
|
||||
* @param type 转换类型
|
||||
* @return 函数
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-05 12:54
|
||||
*/
|
||||
public Function<byte[], Object> getSqlType(int type) {
|
||||
Map<Integer, Function<byte[], Object>> sqlTypeMap = new HashMap<>();
|
||||
// 初始化SQL_TYPES 根据类型执行不同的Func
|
||||
sqlTypeMap.put(1, bytes -> new String(bytes, StandardCharsets.UTF_8));
|
||||
sqlTypeMap.put(2, bytes -> ByteBuffer.wrap(bytes).getFloat());
|
||||
sqlTypeMap.put(3, bytes -> new String(bytes, StandardCharsets.UTF_8));
|
||||
sqlTypeMap.put(4, bytes -> bytes);
|
||||
sqlTypeMap.put(5, bytes -> null);
|
||||
return sqlTypeMap.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL转换类型
|
||||
*
|
||||
* @param type 转换类型
|
||||
* @param content 待转换内容
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-05 12:54
|
||||
*/
|
||||
public Object convertSqlVal(int type, ByteString content) {
|
||||
// 根据每一列的类型转换
|
||||
Function<byte[], Object> converter = getSqlType(type);
|
||||
if (converter != null) {
|
||||
return converter.apply(content.toByteArray());
|
||||
} else {
|
||||
log.warn("[SQL转换类型]-未知的SQL类型: {}", type);
|
||||
return content.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,16 @@ package com.wechat.ferry.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfAddFriendGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDatabaseSqlReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDatabaseTableReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDeleteGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfInviteGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfPassFriendApplyReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfPatOnePatMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfReceiveTransferReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfRevokeMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendEmojiMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendFileMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendImageMsgReq;
|
||||
@ -117,17 +123,6 @@ public interface WeChatDllService {
|
||||
*/
|
||||
List<WxPpWcfDatabaseRowResp> execDbQuerySql(WxPpWcfDatabaseSqlReq request);
|
||||
|
||||
/**
|
||||
* 查询群成员
|
||||
*
|
||||
* @param request 请求入参
|
||||
* @return 数据库记录
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-02 20:59
|
||||
*/
|
||||
List<WxPpWcfGroupMemberResp> queryGroupMember(WxPpWcfGroupMemberReq request);
|
||||
|
||||
/**
|
||||
* 发送文本消息(可 @)
|
||||
*
|
||||
@ -207,4 +202,90 @@ public interface WeChatDllService {
|
||||
*/
|
||||
WxPpWcfSendPatOnePatMsgResp patOnePat(WxPpWcfPatOnePatMsgReq request);
|
||||
|
||||
/**
|
||||
* 撤回消息
|
||||
*
|
||||
* @return 结果状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 11:59
|
||||
*/
|
||||
String revokeMsg(WxPpWcfRevokeMsgReq request);
|
||||
|
||||
/**
|
||||
* 通过好友申请
|
||||
*
|
||||
* @param request 请求入参
|
||||
* @return 结果状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 09:38
|
||||
*/
|
||||
String passFriendApply(WxPpWcfPassFriendApplyReq request);
|
||||
|
||||
/**
|
||||
* 添加群成员为微信好友
|
||||
*
|
||||
* @param request 请求入参
|
||||
* @return 结果状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 09:38
|
||||
*/
|
||||
String addFriendGroupMember(WxPpWcfAddFriendGroupMemberReq request);
|
||||
|
||||
/**
|
||||
* 查询群成员列表
|
||||
*
|
||||
* @param request 请求入参
|
||||
* @return 数据库记录
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-02 20:59
|
||||
*/
|
||||
List<WxPpWcfGroupMemberResp> queryGroupMemberList(WxPpWcfGroupMemberReq request);
|
||||
|
||||
/**
|
||||
* 邀请群成员
|
||||
*
|
||||
* @param request 请求入参
|
||||
* @return 结果状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 10:02
|
||||
*/
|
||||
String inviteGroupMember(WxPpWcfInviteGroupMemberReq request);
|
||||
|
||||
/**
|
||||
* 删除群成员
|
||||
*
|
||||
* @param request 请求入参
|
||||
* @return 结果状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 10:03
|
||||
*/
|
||||
String deleteGroupMember(WxPpWcfDeleteGroupMemberReq request);
|
||||
|
||||
/**
|
||||
* 查询朋友圈
|
||||
*
|
||||
* @return 结果状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 11:11
|
||||
*/
|
||||
String queryFriendCircle();
|
||||
|
||||
/**
|
||||
* 接收转账
|
||||
*
|
||||
* @param request 请求入参
|
||||
* @return 结果状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 13:48
|
||||
*/
|
||||
String receiveTransfer(WxPpWcfReceiveTransferReq request);
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
package com.wechat.ferry.service.impl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ -17,14 +14,20 @@ import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.wechat.ferry.aggregation.facade.ContactDo;
|
||||
import com.wechat.ferry.config.WeChatFerryProperties;
|
||||
import com.wechat.ferry.entity.proto.Wcf;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfAddFriendGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDatabaseSqlReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDatabaseTableReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfDeleteGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfInviteGroupMemberReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfPassFriendApplyReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfPatOnePatMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfReceiveTransferReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfRevokeMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendEmojiMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendFileMsgReq;
|
||||
import com.wechat.ferry.entity.vo.request.WxPpWcfSendImageMsgReq;
|
||||
@ -46,11 +49,10 @@ import com.wechat.ferry.entity.vo.response.WxPpWcfSendRichTextMsgResp;
|
||||
import com.wechat.ferry.entity.vo.response.WxPpWcfSendTextMsgResp;
|
||||
import com.wechat.ferry.entity.vo.response.WxPpWcfSendXmlMsgResp;
|
||||
import com.wechat.ferry.enums.DatabaseNameEnum;
|
||||
import com.wechat.ferry.enums.MsgFwdTypeEnum;
|
||||
import com.wechat.ferry.enums.MsgCallbackTypeEnum;
|
||||
import com.wechat.ferry.enums.SexEnum;
|
||||
import com.wechat.ferry.enums.WxContactsMixedEnum;
|
||||
import com.wechat.ferry.enums.WxContactsOfficialEnum;
|
||||
import com.wechat.ferry.enums.WxContactsTypeEnum;
|
||||
import com.wechat.ferry.exception.BizException;
|
||||
import com.wechat.ferry.handle.WeChatSocketClient;
|
||||
import com.wechat.ferry.service.WeChatDllService;
|
||||
import com.wechat.ferry.utils.HttpClientUtil;
|
||||
@ -80,6 +82,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public Boolean loginStatus() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
Boolean status = wechatSocketClient.isLogin();
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[查询]-[登录状态]-耗时:{}ms,status:{}", (endTime - startTime), status);
|
||||
@ -89,6 +93,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public String queryLoginWeChatUid() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
String weChatUid = "";
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_GET_SELF_WXID_VALUE).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
@ -103,6 +109,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public WxPpWcfLoginInfoResp queryLoginWeChatInfo() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
WxPpWcfLoginInfoResp resp = new WxPpWcfLoginInfoResp();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_GET_USER_INFO_VALUE).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
@ -121,6 +129,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public List<WxPpWcfMsgTypeResp> queryMsgTypeList() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
List<WxPpWcfMsgTypeResp> list = new ArrayList<>();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_GET_MSG_TYPES_VALUE).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
@ -142,6 +152,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public List<WxPpWcfContactsResp> queryContactsList() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
List<WxPpWcfContactsResp> list = new ArrayList<>();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_GET_CONTACTS_VALUE).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
@ -174,38 +186,9 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
}
|
||||
// 微信类型
|
||||
if (!ObjectUtils.isEmpty(rpcContact.getWxid())) {
|
||||
// 官方杂号集合
|
||||
Map<String, String> mixedNoMap = WxContactsMixedEnum.toCodeNameMap();
|
||||
mixedNoMap.putAll(convertContactsTypeProperties(weChatFerryProperties.getContactsTypeMixed()));
|
||||
// 公众号
|
||||
Map<String, String> officialMap = WxContactsOfficialEnum.toCodeNameMap();
|
||||
officialMap.putAll(convertContactsTypeProperties(weChatFerryProperties.getContactsTypeOfficial()));
|
||||
|
||||
// 类型判断,存在优先级的,官方杂号优先级高于微信公众号(如果定义重复了,常规禁止重复,手机端和电脑端分类不同)
|
||||
if (rpcContact.getWxid().endsWith(WxContactsTypeEnum.WORK.getAffix())) {
|
||||
// 企微
|
||||
vo.setType(WxContactsTypeEnum.WORK.getCode());
|
||||
vo.setTypeLabel(WxContactsTypeEnum.WORK.getName());
|
||||
} else if (rpcContact.getWxid().endsWith(WxContactsTypeEnum.GROUP.getAffix()) || rpcContact.getWxid().endsWith("@im.chatroom")) {
|
||||
// 群聊 @im.chatroom 这种是很早之前的格式,单独例举
|
||||
vo.setType(WxContactsTypeEnum.GROUP.getCode());
|
||||
vo.setTypeLabel(WxContactsTypeEnum.GROUP.getName());
|
||||
} else if (mixedNoMap.containsKey(rpcContact.getWxid())) {
|
||||
// 官方杂号
|
||||
vo.setType(WxContactsTypeEnum.OFFICIAL_MIXED_NO.getCode());
|
||||
vo.setTypeLabel(WxContactsTypeEnum.OFFICIAL_MIXED_NO.getName());
|
||||
} else if (rpcContact.getWxid().startsWith(WxContactsTypeEnum.OFFICIAL_ACCOUNT.getAffix())) {
|
||||
// 微信公众号
|
||||
vo.setType(WxContactsTypeEnum.OFFICIAL_ACCOUNT.getCode());
|
||||
vo.setTypeLabel(WxContactsTypeEnum.OFFICIAL_ACCOUNT.getName());
|
||||
} else if (officialMap.containsKey(rpcContact.getWxid())) {
|
||||
vo.setType(WxContactsTypeEnum.OFFICIAL_ACCOUNT.getCode());
|
||||
vo.setTypeLabel(WxContactsTypeEnum.OFFICIAL_ACCOUNT.getName());
|
||||
} else {
|
||||
// 个微
|
||||
vo.setType(WxContactsTypeEnum.PERSON.getCode());
|
||||
vo.setTypeLabel(WxContactsTypeEnum.PERSON.getName());
|
||||
}
|
||||
String type = ContactDo.convertContactType(rpcContact.getWxid(), weChatFerryProperties);
|
||||
vo.setType(type);
|
||||
vo.setTypeLabel(WxContactsTypeEnum.getCodeMap(rpcContact.getWxid()).getName());
|
||||
}
|
||||
list.add(vo);
|
||||
}
|
||||
@ -218,6 +201,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public List<String> queryDbTableNameList() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
List<String> list = new ArrayList<>();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_GET_DB_NAMES_VALUE).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
@ -232,6 +217,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public List<WxPpWcfDatabaseTableResp> queryDbTableList(WxPpWcfDatabaseTableReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[查询]-[数据库表列表]-request:{}", request);
|
||||
List<WxPpWcfDatabaseTableResp> list = new ArrayList<>();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_GET_DB_TABLES_VALUE).setStr(request.getDatabaseName()).build();
|
||||
@ -253,6 +240,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
@Override
|
||||
public List<WxPpWcfDatabaseRowResp> execDbQuerySql(WxPpWcfDatabaseSqlReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
List<WxPpWcfDatabaseRowResp> list = new ArrayList<>();
|
||||
List<Wcf.DbRow> wcfList = wechatSocketClient.querySql(request.getDatabaseName(), request.getSqlText());
|
||||
if (!CollectionUtils.isEmpty(wcfList)) {
|
||||
@ -266,7 +255,7 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
log.warn("未知的SQL类型: {}", dbField.getType());
|
||||
value = dbField.getContent().toByteArray();
|
||||
} else {
|
||||
value = convertSqlVal(dbField.getType(), dbField.getContent());
|
||||
value = wechatSocketClient.convertSqlVal(dbField.getType(), dbField.getContent());
|
||||
}
|
||||
fieldVo.setType(String.valueOf(dbField.getType()));
|
||||
fieldVo.setColumn(dbField.getColumn());
|
||||
@ -283,9 +272,219 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxPpWcfGroupMemberResp> queryGroupMember(WxPpWcfGroupMemberReq request) {
|
||||
public WxPpWcfSendTextMsgResp sendTextMsg(WxPpWcfSendTextMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[发送消息]-[文本消息]-入参打印:{}", request);
|
||||
String atUser = "";
|
||||
if (request.getIsAtAll()) {
|
||||
// 艾特全体,仅管理员有效
|
||||
atUser = "@all";
|
||||
} else {
|
||||
// 处理艾特的人员
|
||||
if (!CollectionUtils.isEmpty(request.getAtUsers())) {
|
||||
atUser = String.join(",", request.getAtUsers());
|
||||
}
|
||||
}
|
||||
Wcf.TextMsg textMsg = Wcf.TextMsg.newBuilder().setMsg(request.getMsgText()).setReceiver(request.getRecipient()).setAters(atUser).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_TXT_VALUE).setTxt(textMsg).build();
|
||||
log.debug("sendText: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
// 0 为成功,其他失败
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[文本消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendRichTextMsgResp sendRichTextMsg(WxPpWcfSendRichTextMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[发送消息]-[富文本消息]-入参打印:{}", request);
|
||||
Wcf.RichText richTextMsg = Wcf.RichText.newBuilder().setName(request.getName()).setAccount(request.getAccount()).setTitle(request.getTitle())
|
||||
.setDigest(request.getDigest()).setUrl(request.getJumpUrl()).setThumburl(request.getThumbnailUrl()).setReceiver(request.getRecipient())
|
||||
.build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_RICH_TXT_VALUE).setRt(richTextMsg).build();
|
||||
log.debug("sendRichText: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[富文本消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendXmlMsgResp sendXmlMsg(WxPpWcfSendXmlMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[发送消息]-[XML消息]-入参打印:{}", request);
|
||||
int xmlType = 0x21;
|
||||
if ("21".equals(request.getXmlType())) {
|
||||
// 小程序
|
||||
xmlType = 0x21;
|
||||
} else {
|
||||
xmlType = Integer.parseInt(request.getXmlType());
|
||||
}
|
||||
Wcf.XmlMsg xmlMsg = Wcf.XmlMsg.newBuilder().setContent(request.getXmlContent()).setReceiver(request.getRecipient())
|
||||
.setPath(request.getResourcePath()).setType(xmlType).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_XML_VALUE).setXml(xmlMsg).build();
|
||||
log.debug("sendXml: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[XML消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendImageMsgResp sendImageMsg(WxPpWcfSendImageMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[发送消息]-[图片消息]-入参打印:{}", request);
|
||||
WxPpWcfSendImageMsgResp resp = new WxPpWcfSendImageMsgResp();
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(request.getResourcePath()).setReceiver(request.getRecipient()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_IMG_VALUE).setFile(pathMsg).build();
|
||||
log.debug("sendImage: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[图片消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendEmojiMsgResp sendEmojiMsg(WxPpWcfSendEmojiMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[发送消息]-[表情消息]-入参打印:{}", request);
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(request.getResourcePath()).setReceiver(request.getRecipient()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_EMOTION_VALUE).setFile(pathMsg).build();
|
||||
log.debug("sendEmotion: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[表情消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendFileMsgResp sendFileMsg(WxPpWcfSendFileMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[发送消息]-[文件消息]-入参打印:{}", request);
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(request.getResourcePath()).setReceiver(request.getRecipient()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_FILE_VALUE).setFile(pathMsg).build();
|
||||
log.debug("sendFile: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[文件消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendPatOnePatMsgResp patOnePat(WxPpWcfPatOnePatMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[发送消息]-[拍一拍消息]-入参打印:{}", request);
|
||||
Wcf.PatMsg patMsg = Wcf.PatMsg.newBuilder().setRoomid(request.getRecipient()).setWxid(request.getPatUser()).build();
|
||||
Wcf.Request wcfReq = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_PAT_MSG_VALUE).setPm(patMsg).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(wcfReq);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[拍一拍消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String revokeMsg(WxPpWcfRevokeMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[撤回消息]-[消息撤回]-入参打印:{}", request);
|
||||
long msgId = Long.parseLong(request.getMsgId());
|
||||
Wcf.Request wcfReq = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_REVOKE_MSG_VALUE).setUi64(msgId).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(wcfReq);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
// 回调处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgCallback(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[撤回消息]-[消息撤回]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String passFriendApply(WxPpWcfPassFriendApplyReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[好友申请]-[通过好友申请]-入参打印:{}", request);
|
||||
Wcf.Verification verification = Wcf.Verification.newBuilder().setV3(request.getApplicant()).setV4(request.getReviewer()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_ACCEPT_FRIEND_VALUE).setV(verification).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[好友申请]-[通过好友申请]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addFriendGroupMember(WxPpWcfAddFriendGroupMemberReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[添加好友]-[添加群成员为好友]-入参打印:{}", request);
|
||||
if (CollectionUtils.isEmpty(request.getGroupMembers())) {
|
||||
log.error("[添加好友]-[添加群成员为好友]-待添加人员为空,本次操作取消");
|
||||
return "";
|
||||
}
|
||||
String groupMembersStr = String.join(",", request.getGroupMembers());
|
||||
Wcf.MemberMgmt memberMgmt = Wcf.MemberMgmt.newBuilder().setRoomid(request.getGroupNo()).setWxids(groupMembersStr).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_ADD_ROOM_MEMBERS_VALUE).setM(memberMgmt).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[添加好友]-[添加群成员为好友]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxPpWcfGroupMemberResp> queryGroupMemberList(WxPpWcfGroupMemberReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
List<WxPpWcfGroupMemberResp> list = new ArrayList<>();
|
||||
String weChatUid = queryLoginWeChatUid();
|
||||
// 查询群成员
|
||||
List<Wcf.DbRow> wcfList = new ArrayList<>();
|
||||
if (!ObjectUtils.isEmpty(request.getGroupNo())) {
|
||||
@ -303,11 +502,11 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
for (Wcf.DbField dbField : dbFieldList) {
|
||||
if ("UserName".equals(dbField.getColumn())) {
|
||||
vo = new WxPpWcfGroupMemberResp();
|
||||
String content = (String)convertSqlVal(dbField.getType(), dbField.getContent());
|
||||
String content = (String)wechatSocketClient.convertSqlVal(dbField.getType(), dbField.getContent());
|
||||
vo.setWeChatUid(content);
|
||||
}
|
||||
if ("NickName".equals(dbField.getColumn())) {
|
||||
String content = (String)convertSqlVal(dbField.getType(), dbField.getContent());
|
||||
String content = (String)wechatSocketClient.convertSqlVal(dbField.getType(), dbField.getContent());
|
||||
vo.setGroupNickName(content);
|
||||
dbMap.put(vo.getWeChatUid(), vo.getGroupNickName());
|
||||
}
|
||||
@ -330,6 +529,10 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
for (Wcf.RoomData.RoomMember member : roomData.getMembersList()) {
|
||||
vo = new WxPpWcfGroupMemberResp();
|
||||
vo.setWeChatUid(member.getWxid());
|
||||
// 是否为自己微信
|
||||
vo.setWhetherSelf(weChatUid.equals(member.getWxid()));
|
||||
// 是否为企微
|
||||
vo.setWhetherWork(member.getWxid().endsWith(WxContactsTypeEnum.WORK.getAffix()));
|
||||
String nickName = member.getName();
|
||||
if (ObjectUtils.isEmpty(nickName)) {
|
||||
// 如果没有设置群昵称则默认为微信名称
|
||||
@ -353,207 +556,78 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendTextMsgResp sendTextMsg(WxPpWcfSendTextMsgReq request) {
|
||||
public String inviteGroupMember(WxPpWcfInviteGroupMemberReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[文本消息]-入参打印:{}", request);
|
||||
String atUser = "";
|
||||
if (request.getIsAtAll()) {
|
||||
// 艾特全体,仅管理员有效
|
||||
atUser = "@all";
|
||||
} else {
|
||||
// 处理艾特的人员
|
||||
if (!CollectionUtils.isEmpty(request.getAtUsers())) {
|
||||
atUser = String.join(",", request.getAtUsers());
|
||||
}
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[群成员]-[邀请群成员加入]-入参打印:{}", request);
|
||||
if (CollectionUtils.isEmpty(request.getGroupMembers())) {
|
||||
log.error("[群成员]-[邀请群成员加入]-待邀请进群的人员为空,本次操作取消");
|
||||
return "";
|
||||
}
|
||||
Wcf.TextMsg textMsg = Wcf.TextMsg.newBuilder().setMsg(request.getMsgText()).setReceiver(request.getRecipient()).setAters(atUser).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_TXT_VALUE).setTxt(textMsg).build();
|
||||
log.debug("sendText: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
String groupMembersStr = String.join(",", request.getGroupMembers());
|
||||
Wcf.MemberMgmt memberMgmt = Wcf.MemberMgmt.newBuilder().setRoomid(request.getGroupNo()).setWxids(groupMembersStr).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_INV_ROOM_MEMBERS_VALUE).setM(memberMgmt).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
// 0 为成功,其他失败
|
||||
int state = judgeSendMsgState(rsp);
|
||||
// 转发处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgForward(stringJson, state);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[文本消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
log.info("[群成员]-[邀请群成员加入]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendRichTextMsgResp sendRichTextMsg(WxPpWcfSendRichTextMsgReq request) {
|
||||
public String deleteGroupMember(WxPpWcfDeleteGroupMemberReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[富文本消息]-入参打印:{}", request);
|
||||
Wcf.RichText richTextMsg = Wcf.RichText.newBuilder().setName(request.getName()).setAccount(request.getAccount()).setTitle(request.getTitle())
|
||||
.setDigest(request.getDigest()).setUrl(request.getJumpUrl()).setThumburl(request.getThumbnailUrl()).setReceiver(request.getRecipient())
|
||||
.build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_RICH_TXT_VALUE).setRt(richTextMsg).build();
|
||||
log.debug("sendRichText: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeSendMsgState(rsp);
|
||||
// 转发处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgForward(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[富文本消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendXmlMsgResp sendXmlMsg(WxPpWcfSendXmlMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[XML消息]-入参打印:{}", request);
|
||||
int xmlType = 0x21;
|
||||
if ("21".equals(request.getXmlType())) {
|
||||
// 小程序
|
||||
xmlType = 0x21;
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[群成员]-[删除群成员]-入参打印:{}", request);
|
||||
if (CollectionUtils.isEmpty(request.getGroupMembers())) {
|
||||
log.error("[群成员]-[删除群成员]-待删除的人员为空,本次操作取消");
|
||||
return "";
|
||||
}
|
||||
Wcf.XmlMsg xmlMsg = Wcf.XmlMsg.newBuilder().setContent(request.getXmlContent()).setReceiver(request.getRecipient())
|
||||
.setPath(request.getResourcePath()).setType(xmlType).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_XML_VALUE).setXml(xmlMsg).build();
|
||||
log.debug("sendXml: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
String groupMembersStr = String.join(",", request.getGroupMembers());
|
||||
Wcf.MemberMgmt memberMgmt = Wcf.MemberMgmt.newBuilder().setRoomid(request.getGroupNo()).setWxids(groupMembersStr).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_DEL_ROOM_MEMBERS_VALUE).setM(memberMgmt).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeSendMsgState(rsp);
|
||||
// 转发处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgForward(stringJson, state);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[XML消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
log.info("[群成员]-[删除群成员]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendImageMsgResp sendImageMsg(WxPpWcfSendImageMsgReq request) {
|
||||
public String queryFriendCircle() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[图片消息]-入参打印:{}", request);
|
||||
WxPpWcfSendImageMsgResp resp = new WxPpWcfSendImageMsgResp();
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(request.getResourcePath()).setReceiver(request.getRecipient()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_IMG_VALUE).setFile(pathMsg).build();
|
||||
log.debug("sendImage: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[查询]-[刷新朋友圈]-开始");
|
||||
// id 开始 id,0 为最新页 (string based uint64)
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_REFRESH_PYQ_VALUE).setUi64(0).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeSendMsgState(rsp);
|
||||
// 转发处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgForward(stringJson, state);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[图片消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public WxPpWcfSendEmojiMsgResp sendEmojiMsg(WxPpWcfSendEmojiMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[表情消息]-入参打印:{}", request);
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(request.getResourcePath()).setReceiver(request.getRecipient()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_EMOTION_VALUE).setFile(pathMsg).build();
|
||||
log.debug("sendEmotion: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeSendMsgState(rsp);
|
||||
// 转发处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgForward(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[表情消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
log.info("[查询]-[刷新朋友圈]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendFileMsgResp sendFileMsg(WxPpWcfSendFileMsgReq request) {
|
||||
public String receiveTransfer(WxPpWcfReceiveTransferReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[文件消息]-入参打印:{}", request);
|
||||
Wcf.PathMsg pathMsg = Wcf.PathMsg.newBuilder().setPath(request.getResourcePath()).setReceiver(request.getRecipient()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_FILE_VALUE).setFile(pathMsg).build();
|
||||
log.debug("sendFile: {}", wechatSocketClient.bytesToHex(req.toByteArray()));
|
||||
// 公共校验
|
||||
checkClientStatus();
|
||||
log.info("[转账]-[接收转账]-开始");
|
||||
Wcf.Transfer transfer =
|
||||
Wcf.Transfer.newBuilder().setWxid(request.getWeChatUid()).setTfid(request.getTransferId()).setTaid(request.getTransferId()).build();
|
||||
Wcf.Request req = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_RECV_TRANSFER_VALUE).setTf(transfer).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(req);
|
||||
int state = judgeSendMsgState(rsp);
|
||||
// 转发处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgForward(stringJson, state);
|
||||
int state = judgeWcfCmdState(rsp);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[文件消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPpWcfSendPatOnePatMsgResp patOnePat(WxPpWcfPatOnePatMsgReq request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[拍一拍消息]-入参打印:{}", request);
|
||||
Wcf.PatMsg patMsg = Wcf.PatMsg.newBuilder().setRoomid(request.getRecipient()).setWxid(request.getPatUser()).build();
|
||||
Wcf.Request wcfReq = Wcf.Request.newBuilder().setFuncValue(Wcf.Functions.FUNC_SEND_PAT_MSG_VALUE).setPm(patMsg).build();
|
||||
Wcf.Response rsp = wechatSocketClient.sendCmd(wcfReq);
|
||||
int state = judgeSendMsgState(rsp);
|
||||
// 转发处理
|
||||
String stringJson = JSON.toJSONString(request);
|
||||
sendMsgForward(stringJson, state);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("[发送消息]-[拍一拍消息]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return null;
|
||||
log.info("[转账]-[接收转账]-处理结束,耗时:{}ms", (endTime - startTime));
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SQL类型
|
||||
*
|
||||
* @param type 转换类型
|
||||
* @return 函数
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-05 12:54
|
||||
*/
|
||||
public Function<byte[], Object> getSqlType(int type) {
|
||||
Map<Integer, Function<byte[], Object>> sqlTypeMap = new HashMap<>();
|
||||
// 初始化SQL_TYPES 根据类型执行不同的Func
|
||||
sqlTypeMap.put(1, bytes -> ByteBuffer.wrap(bytes).getInt());
|
||||
sqlTypeMap.put(2, bytes -> ByteBuffer.wrap(bytes).getFloat());
|
||||
sqlTypeMap.put(3, bytes -> new String(bytes, StandardCharsets.UTF_8));
|
||||
sqlTypeMap.put(4, bytes -> bytes);
|
||||
sqlTypeMap.put(5, bytes -> null);
|
||||
return sqlTypeMap.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL转换类型
|
||||
*
|
||||
* @param type 转换类型
|
||||
* @param content 待转换内容
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-05 12:54
|
||||
*/
|
||||
public Object convertSqlVal(int type, ByteString content) {
|
||||
// 根据每一列的类型转换
|
||||
Function<byte[], Object> converter = getSqlType(type);
|
||||
if (converter != null) {
|
||||
return converter.apply(content.toByteArray());
|
||||
} else {
|
||||
log.warn("未知的SQL类型: {}", type);
|
||||
return content.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换艾特用户
|
||||
*
|
||||
* @param groupNo 群组编号
|
||||
* @param atUsers 艾特的用户(名称/微信编号)
|
||||
* @return 组装后的艾特用户
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-10-03 11:35
|
||||
*/
|
||||
public String dealAtUser(String groupNo, List<String> atUsers) {
|
||||
String atUserStr = "";
|
||||
if (!CollectionUtils.isEmpty(atUsers)) {
|
||||
// 取出要艾特的用户
|
||||
for (String atUser : atUsers) {
|
||||
|
||||
}
|
||||
}
|
||||
return atUserStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息转发
|
||||
* 消息回调
|
||||
*
|
||||
* @param jsonString json数据
|
||||
* @param state cmd调用状态
|
||||
@ -561,27 +635,27 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
* @author chandler
|
||||
* @date 2024-10-10 23:10
|
||||
*/
|
||||
private void sendMsgForward(String jsonString, Integer state) {
|
||||
// 根据配置文件决定是否转发
|
||||
if (MsgFwdTypeEnum.CLOSE.getCode().equals(weChatFerryProperties.getSendMsgFwdFlag())
|
||||
|| (MsgFwdTypeEnum.SUCCESS.getCode().equals(weChatFerryProperties.getSendMsgFwdFlag()) && 0 != state)) {
|
||||
// 如果是关闭 或者 配置为成功才转发但发送状态为失败 的情况则取消发送
|
||||
private void sendMsgCallback(String jsonString, Integer state) {
|
||||
// 根据配置文件决定是否回调
|
||||
if (MsgCallbackTypeEnum.CLOSE.getCode().equals(weChatFerryProperties.getSendMsgCallbackFlag())
|
||||
|| (MsgCallbackTypeEnum.SUCCESS.getCode().equals(weChatFerryProperties.getSendMsgCallbackFlag()) && 0 != state)) {
|
||||
// 如果是关闭 或者 配置为成功才回调但发送状态为失败 的情况则取消发送
|
||||
return;
|
||||
}
|
||||
// 开启转发,且转发地址不为空
|
||||
if (!CollectionUtils.isEmpty(weChatFerryProperties.getSendMsgFwdUrls())) {
|
||||
for (String receiveMsgFwdUrl : weChatFerryProperties.getSendMsgFwdUrls()) {
|
||||
// 开启回调,且回调地址不为空
|
||||
if (!CollectionUtils.isEmpty(weChatFerryProperties.getSendMsgCallbackUrls())) {
|
||||
for (String receiveMsgFwdUrl : weChatFerryProperties.getSendMsgCallbackUrls()) {
|
||||
if (!receiveMsgFwdUrl.startsWith("http")) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String responseStr = HttpClientUtil.doPostJson(receiveMsgFwdUrl, jsonString);
|
||||
if (judgeSuccess(responseStr)) {
|
||||
log.error("[发送消息]-消息转发外部接口,获取响应状态失败!-URL:{}", receiveMsgFwdUrl);
|
||||
log.error("[发送消息]-消息回调至外部接口,获取响应状态失败!-URL:{}", receiveMsgFwdUrl);
|
||||
}
|
||||
log.debug("[发送消息]-[转发接收到的消息]-转发消息至:{}", receiveMsgFwdUrl);
|
||||
log.debug("[发送消息]-[回调接收到的消息]-回调消息至:{}", receiveMsgFwdUrl);
|
||||
} catch (Exception e) {
|
||||
log.error("[发送消息]-消息转发接口[{}]服务异常:", receiveMsgFwdUrl, e);
|
||||
log.error("[发送消息]-消息回调接口[{}]服务异常:", receiveMsgFwdUrl, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -615,8 +689,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断发送消息状态
|
||||
* 0 为成功,其他失败
|
||||
* 判断WCF的CMD调用状态
|
||||
* 有值 为成功,其他失败
|
||||
*
|
||||
* @param rsp 响应参数
|
||||
* @return 状态
|
||||
@ -624,8 +698,8 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
* @author chandler
|
||||
* @date 2024-12-23 21:53
|
||||
*/
|
||||
private int judgeSendMsgState(Wcf.Response rsp) {
|
||||
// 0 为成功,其他失败
|
||||
private int judgeWcfCmdState(Wcf.Response rsp) {
|
||||
// 有值 为成功,其他失败
|
||||
int state = -1;
|
||||
if (rsp != null) {
|
||||
state = rsp.getStatus();
|
||||
@ -660,4 +734,16 @@ public class WeChatDllServiceImpl implements WeChatDllService {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求前检测客户端状态
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2025-01-04 18:34
|
||||
*/
|
||||
private void checkClientStatus() {
|
||||
if (!wechatSocketClient.isLogin()) {
|
||||
throw new BizException("微信客户端未登录或状态异常,请人工关闭本服务之后,退出微信客户端在重启本服务!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@ -14,6 +13,8 @@ import com.alibaba.fastjson2.JSONObject;
|
||||
import com.wechat.ferry.config.WeChatFerryProperties;
|
||||
import com.wechat.ferry.entity.dto.WxPpMsgDTO;
|
||||
import com.wechat.ferry.service.WeChatMsgService;
|
||||
import com.wechat.ferry.strategy.msg.receive.ReceiveMsgFactory;
|
||||
import com.wechat.ferry.strategy.msg.receive.ReceiveMsgStrategy;
|
||||
import com.wechat.ferry.utils.HttpClientUtil;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -34,34 +35,46 @@ public class WeChatMsgServiceImpl implements WeChatMsgService {
|
||||
@Override
|
||||
public void receiveMsg(String jsonString) {
|
||||
// 转发接口处理
|
||||
receiveMsgForward(jsonString);
|
||||
receiveMsgCallback(jsonString);
|
||||
// 转为JSON对象
|
||||
WxPpMsgDTO dto = JSON.parseObject(jsonString, WxPpMsgDTO.class);
|
||||
// 有开启的群聊配置
|
||||
if (!CollectionUtils.isEmpty(weChatFerryProperties.getOpenMsgGroups())) {
|
||||
// 指定处理的群聊
|
||||
if (weChatFerryProperties.getOpenMsgGroups().contains(dto.getRoomId())) {
|
||||
// TODO 这里可以拓展自己需要的功能
|
||||
if (weChatFerryProperties.getOpenMsgGroups().contains(dto.getRoomId()) || weChatFerryProperties.getOpenMsgGroups().contains("ALL")) {
|
||||
// TODO 模式有多种 1-根据消息类型单独调用某一个 2-全部调用,各业务类中自己决定是否继续
|
||||
if (true) {
|
||||
// 因为一种消息允许进行多种处理,这里采用执行所有策略,请自行在各策略中判断是否需要执行
|
||||
for (ReceiveMsgStrategy value : ReceiveMsgFactory.getAllStrategyContainers().values()) {
|
||||
value.doHandle(dto);
|
||||
}
|
||||
} else {
|
||||
// 单独调用某一种
|
||||
// 这里自己把消息类型转为自己的枚举类型
|
||||
String handleType = "1";
|
||||
ReceiveMsgStrategy receiveMsgStrategy = ReceiveMsgFactory.getStrategy(handleType);
|
||||
receiveMsgStrategy.doHandle(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug("[收到消息]-[消息内容]-打印:{}", dto);
|
||||
}
|
||||
|
||||
private void receiveMsgForward(String jsonString) {
|
||||
// 开启转发,且转发地址不为空
|
||||
if (weChatFerryProperties.getReceiveMsgFwdSwitch() && !CollectionUtils.isEmpty(weChatFerryProperties.getReceiveMsgFwdUrls())) {
|
||||
for (String receiveMsgFwdUrl : weChatFerryProperties.getReceiveMsgFwdUrls()) {
|
||||
private void receiveMsgCallback(String jsonString) {
|
||||
// 开启回调,且回调地址不为空
|
||||
if (weChatFerryProperties.getReceiveMsgCallbackSwitch() && !CollectionUtils.isEmpty(weChatFerryProperties.getReceiveMsgCallbackUrls())) {
|
||||
for (String receiveMsgFwdUrl : weChatFerryProperties.getReceiveMsgCallbackUrls()) {
|
||||
if (!receiveMsgFwdUrl.startsWith("http")) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String responseStr = HttpClientUtil.doPostJson(receiveMsgFwdUrl, jsonString);
|
||||
if (judgeSuccess(responseStr)) {
|
||||
log.error("[接收消息]-消息转发外部接口,获取响应状态失败!-URL:{}", receiveMsgFwdUrl);
|
||||
log.error("[接收消息]-消息回调至外部接口,获取响应状态失败!-URL:{}", receiveMsgFwdUrl);
|
||||
}
|
||||
log.debug("[接收消息]-[转发接收到的消息]-转发消息至:{}", receiveMsgFwdUrl);
|
||||
log.debug("[接收消息]-[回调接收到的消息]-回调消息至:{}", receiveMsgFwdUrl);
|
||||
} catch (Exception e) {
|
||||
log.error("[接收消息]-消息转发接口[{}]服务异常:", receiveMsgFwdUrl, e);
|
||||
log.error("[接收消息]-消息回调接口[{}]服务异常:", receiveMsgFwdUrl, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/strategy/.gitkeep
vendored
Normal file
3
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/strategy/.gitkeep
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file !.gitkeep
|
@ -0,0 +1,84 @@
|
||||
package com.wechat.ferry.strategy.msg.receive;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.wechat.ferry.enums.ReceiveMsgChannelEnum;
|
||||
import com.wechat.ferry.exception.BizException;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 策略Context-消息处理-接收消息
|
||||
* 可以切换策略的Context(这里实际是Factory)类
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 14:08
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ReceiveMsgFactory implements InitializingBean {
|
||||
|
||||
private static final Map<String, ReceiveMsgStrategy> strategyContainerMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* spring的上下文
|
||||
*/
|
||||
@Resource
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* 实现InitializingBean的方法会在启动的时候执行afterPropertiesSet()方法
|
||||
* 将Strategy的类都按照定义好的规则(fetchKey),放入Map中
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
// 初始化时把所有的策略bean放进ioc,用于使用的时候获取
|
||||
Map<String, ReceiveMsgStrategy> strategyMap = applicationContext.getBeansOfType(ReceiveMsgStrategy.class);
|
||||
strategyMap.forEach((k, v) -> {
|
||||
String type = v.getStrategyType();
|
||||
log.debug("[策略Context]-[MessageNoticeSendFactory]-策略类型加载:{}", type);
|
||||
strategyContainerMap.putIfAbsent(type, v);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据策略类型获取不同处理策略类
|
||||
*
|
||||
* @param strategyType 策略类型
|
||||
* @return 策略类
|
||||
*/
|
||||
public static ReceiveMsgStrategy getStrategy(String strategyType) {
|
||||
log.debug("[策略Context]-[ReceiveMsgStrategy]-当前策略类型:{}", strategyType);
|
||||
// 策略类对应的枚举
|
||||
if (!ReceiveMsgChannelEnum.codeMap.containsKey(strategyType)) {
|
||||
// 当前的渠道类型未匹配到
|
||||
log.error("入参中的策略类型:{}不在枚举(ReceiveMsgChannelEnum)定义范围内,请检查数据合法性!", strategyType);
|
||||
// TODO 正常所有的策略都应该在枚举中定义,但考虑到有些人是把项目集成到自己系统中,部分自己的策略类未在枚举中定义,所以这里不抛异常,但是我们建议开启
|
||||
// throw new BizException("当前策略未在枚举中定义,请先在枚举中指定");
|
||||
}
|
||||
ReceiveMsgStrategy handler = strategyContainerMap.get(strategyType);
|
||||
if (handler == null) {
|
||||
log.error("[策略Context]-[MessageNoticeSendFactory]-策略类型:{}-未找到合适的处理器!", strategyType);
|
||||
throw new BizException("未找到合适的处理器!");
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部策略
|
||||
* 用于需要全部执行的情况
|
||||
*
|
||||
* @return 所有的策略类
|
||||
*/
|
||||
public static Map<String, ReceiveMsgStrategy> getAllStrategyContainers() {
|
||||
return strategyContainerMap;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.wechat.ferry.strategy.msg.receive;
|
||||
|
||||
import com.wechat.ferry.entity.dto.WxPpMsgDTO;
|
||||
|
||||
/**
|
||||
* 策略接口-消息处理-接收消息处理
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 14:07
|
||||
*/
|
||||
public interface ReceiveMsgStrategy {
|
||||
|
||||
/**
|
||||
* 获取策略的类型
|
||||
*
|
||||
* @return 返回代表策略类型的字符串
|
||||
*/
|
||||
String getStrategyType();
|
||||
|
||||
/**
|
||||
* 具体的处理
|
||||
*
|
||||
* @return 如果是多字段,可以转为JSON字符串返回,已适配不同的返回数据
|
||||
*/
|
||||
String doHandle(WxPpMsgDTO dto);
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.wechat.ferry.strategy.msg.receive.impl;
|
||||
|
||||
import com.wechat.ferry.entity.dto.WxPpMsgDTO;
|
||||
import com.wechat.ferry.enums.ReceiveMsgChannelEnum;
|
||||
import com.wechat.ferry.strategy.msg.receive.ReceiveMsgStrategy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 策略实现类-接收消息-签到处理
|
||||
*
|
||||
* @author chandler
|
||||
* @date 2024-12-25 14:19
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SignInMsgStrategyImpl implements ReceiveMsgStrategy {
|
||||
|
||||
@Override
|
||||
public String getStrategyType() {
|
||||
log.debug("[接收消息]-[签到处理]-匹配到:{}-{}-策略", ReceiveMsgChannelEnum.SIGN_IN.getCode(), ReceiveMsgChannelEnum.SIGN_IN.getName());
|
||||
return ReceiveMsgChannelEnum.SIGN_IN.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doHandle(WxPpMsgDTO dto) {
|
||||
// TODO 这里写具体的操作
|
||||
// 当前是使用的所有策略类全部执行 所以这里需要控制哪种类型才处理
|
||||
log.info("签到处理");
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
3
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/task/.gitkeep
vendored
Normal file
3
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/task/.gitkeep
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file !.gitkeep
|
193
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/task/ContactGroupMonitorTask.java
vendored
Normal file
193
clients/java/wechat-ferry-mvn/src/main/java/com/wechat/ferry/task/ContactGroupMonitorTask.java
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
package com.wechat.ferry.task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.wechat.ferry.aggregation.facade.ContactDo;
|
||||
import com.wechat.ferry.config.WeChatFerryProperties;
|
||||
import com.wechat.ferry.enums.WxContactsTypeEnum;
|
||||
import com.wechat.ferry.handle.WeChatSocketClient;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ContactGroupMonitorTask {
|
||||
|
||||
private WeChatSocketClient wechatSocketClient;
|
||||
|
||||
@Autowired
|
||||
public void setWechatSocketClient(WeChatSocketClient wechatSocketClient) {
|
||||
this.wechatSocketClient = wechatSocketClient;
|
||||
}
|
||||
|
||||
@Resource
|
||||
private WeChatFerryProperties weChatFerryProperties;
|
||||
|
||||
/**
|
||||
* 全部联系人信息集合 key:微信标识-weChatUid val:联系人信息
|
||||
*/
|
||||
private final Map<String, ContactDo> allContactDoMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 个微联系人信息集合 key:微信标识-weChatUid val:联系人信息
|
||||
*/
|
||||
private final Map<String, String> ppContactDoMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 企微联系人信息集合 key:微信标识-weChatUid val:联系人信息
|
||||
*/
|
||||
private final Map<String, String> cpContactDoMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 群组信息集合 key:群ID val:群名称
|
||||
*/
|
||||
private final Map<String, String> groupMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 群成员信息集合 key:群ID val:微信标识-weChatUid
|
||||
*/
|
||||
private final Map<String, Map<String, String>> groupMemberMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 初始化状态
|
||||
*/
|
||||
private Boolean initStatus = false;
|
||||
|
||||
@Scheduled(cron = "0 0 0 * * ?")
|
||||
public void scheduled() {
|
||||
if (true) {
|
||||
// 目前查询的所有的联系人,未判断群组是否已退出等状态,故该功能暂不启用,仅提供一个小样例
|
||||
return;
|
||||
}
|
||||
ContactDo contactDo = new ContactDo();
|
||||
// 查询联系人
|
||||
List<ContactDo> contactList = contactDo.queryContactListBySql(wechatSocketClient, weChatFerryProperties);
|
||||
log.info("[定时任务]-[联系人群组监控]-{}", contactList.size());
|
||||
// 调用联系人监控处理
|
||||
contactMonitor(contactList);
|
||||
log.info("[定时任务]-[联系人群组监控]-结束");
|
||||
}
|
||||
|
||||
// 联系人监控
|
||||
private void contactMonitor(List<ContactDo> contactList) {
|
||||
// 新增个微联系人
|
||||
List<String> addPpContactList = new ArrayList<>();
|
||||
// 删除个微联系人
|
||||
List<String> deletePpContactList = new ArrayList<>();
|
||||
// 新增企微联系人
|
||||
List<String> addCpContactList = new ArrayList<>();
|
||||
// 删除企微联系人
|
||||
List<String> deleteCpContactList = new ArrayList<>();
|
||||
// 新增群组
|
||||
List<String> addGroupList = new ArrayList<>();
|
||||
// 退出群组
|
||||
List<String> deleteGroupList = new ArrayList<>();
|
||||
// 本次个微联系人标识列表
|
||||
List<String> nowPpContactIdList = new ArrayList<>();
|
||||
// 本次企微联系人标识列表
|
||||
List<String> nowCpContactIdList = new ArrayList<>();
|
||||
// 本次群组标识列表
|
||||
List<String> nowGroupIdList = new ArrayList<>();
|
||||
|
||||
// 开始匹配
|
||||
if (!CollectionUtils.isEmpty(contactList)) {
|
||||
// 判断全部联系人是否为空
|
||||
if (allContactDoMap.isEmpty()) {
|
||||
for (ContactDo contactDo : contactList) {
|
||||
// 首次初始化
|
||||
allContactDoMap.put(contactDo.getWeChatUid(), contactDo);
|
||||
if (WxContactsTypeEnum.PERSON.getCode().equals(contactDo.getContactType())) {
|
||||
// 个微-初始化
|
||||
ppContactDoMap.put(contactDo.getWeChatUid(), contactDo.getNickname());
|
||||
} else if (WxContactsTypeEnum.WORK.getCode().equals(contactDo.getContactType())) {
|
||||
// 企业微信-初始化
|
||||
cpContactDoMap.put(contactDo.getWeChatUid(), contactDo.getNickname());
|
||||
} else if (WxContactsTypeEnum.GROUP.getCode().equals(contactDo.getContactType())) {
|
||||
// 群组-初始化
|
||||
groupMap.put(contactDo.getWeChatUid(), contactDo.getNickname());
|
||||
}
|
||||
}
|
||||
log.info("[定时任务]-[联系人监控]-首次初始化成功");
|
||||
} else {
|
||||
// 检测新增联系人
|
||||
for (ContactDo contactDo : contactList) {
|
||||
if (WxContactsTypeEnum.PERSON.getCode().equals(contactDo.getContactType())) {
|
||||
// 个微
|
||||
nowPpContactIdList.add(contactDo.getWeChatUid());
|
||||
if (!ppContactDoMap.containsKey(contactDo.getWeChatUid())) {
|
||||
// 个微-新增
|
||||
addPpContactList.add(contactDo.getWeChatUid());
|
||||
ppContactDoMap.put(contactDo.getWeChatUid(), contactDo.getNickname());
|
||||
}
|
||||
} else if (WxContactsTypeEnum.WORK.getCode().equals(contactDo.getContactType())) {
|
||||
// 企业微信
|
||||
nowCpContactIdList.add(contactDo.getWeChatUid());
|
||||
if (!cpContactDoMap.containsKey(contactDo.getWeChatUid())) {
|
||||
// 企业微信-新增
|
||||
addCpContactList.add(contactDo.getWeChatUid());
|
||||
cpContactDoMap.put(contactDo.getWeChatUid(), contactDo.getNickname());
|
||||
}
|
||||
} else if (WxContactsTypeEnum.GROUP.getCode().equals(contactDo.getContactType())) {
|
||||
// 群组
|
||||
nowGroupIdList.add(contactDo.getWeChatUid());
|
||||
if (!groupMap.containsKey(contactDo.getWeChatUid())) {
|
||||
// 群组-新增
|
||||
addGroupList.add(contactDo.getWeChatUid());
|
||||
groupMap.put(contactDo.getWeChatUid(), contactDo.getNickname());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化完成
|
||||
if (initStatus) {
|
||||
// 个微
|
||||
for (Map.Entry<String, String> entry : ppContactDoMap.entrySet()) {
|
||||
if (!nowPpContactIdList.contains(entry.getKey())) {
|
||||
// 个微-删除
|
||||
deletePpContactList.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
// 企微
|
||||
for (Map.Entry<String, String> entry : cpContactDoMap.entrySet()) {
|
||||
if (!nowCpContactIdList.contains(entry.getKey())) {
|
||||
// 企微-删除
|
||||
deleteCpContactList.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
// 群组
|
||||
for (Map.Entry<String, String> entry : groupMap.entrySet()) {
|
||||
if (!nowGroupIdList.contains(entry.getKey())) {
|
||||
// 群组-删除
|
||||
deleteGroupList.add(entry.getKey());
|
||||
log.info("\"{}\"离开了群聊");
|
||||
}
|
||||
}
|
||||
log.info("[定时任务]-[联系人监控]-个微新增:{},个微删除:{},企微新增:{},企微删除:{},群组新增:{},群组删除:{}", addPpContactList, deletePpContactList, addCpContactList,
|
||||
deleteCpContactList, addGroupList, deleteGroupList);
|
||||
}
|
||||
}
|
||||
initStatus = true;
|
||||
}
|
||||
|
||||
// 监控群成员
|
||||
private void groupMemberMonitor() {
|
||||
if (!groupMap.isEmpty()) {
|
||||
List<String> groupIdList = new ArrayList<>(groupMap.keySet());
|
||||
for (String groupId : groupIdList) {
|
||||
// 查询
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -35,15 +35,15 @@ wechat:
|
||||
# 需要开启消息处理的群
|
||||
open-msg-groups:
|
||||
- 53257911728@chatroom
|
||||
# 接收消息转发开关
|
||||
receive-msg-fwd-switch: false
|
||||
# 接收消息转发URL
|
||||
receive-msg-fwd-urls:
|
||||
# 接收消息回调开关
|
||||
receive-msg-callback-switch: false
|
||||
# 接收消息回调地址
|
||||
receive-msg-callback-urls:
|
||||
- http://localhost:9001/msg
|
||||
# 发送消息转发标识 1-关闭 2-全转发 3-发送成功才转发
|
||||
send-msg-fwd-flag: '1'
|
||||
# 发送消息转发URL
|
||||
send-msg-fwd-urls:
|
||||
# 发送消息回调标识 1-关闭 2-全部回调 3-发送成功才回调
|
||||
send-msg-callback-flag: '1'
|
||||
# 发送消息回调地址
|
||||
send-msg-callback-urls:
|
||||
- http://localhost:9001/msg
|
||||
# 调用第三方服务客户端成功状态码
|
||||
third-party-ok-codes:
|
||||
|
Loading…
Reference in New Issue
Block a user