feat(知识库): 增加知识库模块

This commit is contained in:
ageer
2025-03-02 11:19:29 +08:00
parent 04f579d033
commit 1385b165c9
1421 changed files with 166583 additions and 64636 deletions

View File

@@ -1,29 +0,0 @@
package com.xmzs.common.wechat;
import com.xmzs.common.wechat.core.MsgCenter;
import com.xmzs.common.wechat.face.IMsgHandlerFace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Wechat {
private static final Logger LOG = LoggerFactory.getLogger(Wechat.class);
private IMsgHandlerFace msgHandler;
public Wechat(IMsgHandlerFace msgHandler) {
System.setProperty("jsse.enableSNIExtension", "false"); // 防止SSL错误
this.msgHandler = msgHandler;
}
public void start() {
LOG.info("+++++++++++++++++++开始消息处理+++++++++++++++++++++");
new Thread(new Runnable() {
@Override
public void run() {
MsgCenter.handleMsg(msgHandler);
}
}).start();
}
}

View File

@@ -1,43 +0,0 @@
package com.xmzs.common.wechat.api;
import java.io.File;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* 辅助工具类,该类暂时未用,请忽略
*
* @author https://github.com/yaphone
* @date 创建时间2017年5月22日 下午10:34:46
* @version 1.0
*
*/
public class AssistTools {
private static OkHttpClient client = new OkHttpClient();
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
public static boolean sendQrPicToServer(String username, String password, String uploadUrl, String localPath)
throws IOException {
File file = new File(localPath);
RequestBody requestBody = new MultipartBody.Builder().addFormDataPart("username", username)
.addFormDataPart("password", password)
.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file)).build();
Request request = new Request.Builder().url(uploadUrl).post(requestBody).build();
Call call = client.newCall(request);
try {
Response response = call.execute();
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
}

View File

@@ -1,215 +0,0 @@
package com.xmzs.common.wechat.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xmzs.common.wechat.core.Core;
import com.xmzs.common.wechat.utils.enums.StorageLoginInfoEnum;
import com.xmzs.common.wechat.utils.enums.URLEnum;
/**
* 微信小工具,如获好友列表等
*
* @author https://github.com/yaphone
* @date 创建时间2017年5月4日 下午10:49:16
* @version 1.0
*
*/
public class WechatTools {
private static Logger LOG = LoggerFactory.getLogger(WechatTools.class);
private static Core core = Core.getInstance();
/**
* 根据用户名发送文本消息
*
* @author https://github.com/yaphone
* @date 2017年5月4日 下午10:43:14
* @param msg
* @param toUserName
*/
public static void sendMsgByUserName(String msg, String toUserName) {
MessageTools.sendMsgById(msg, toUserName);
}
/**
* <p>
* 通过RealName获取本次UserName
* </p>
* <p>
* 如NickName为"yaphone"则获取UserName=
* "@1212d3356aea8285e5bbe7b91229936bc183780a8ffa469f2d638bf0d2e4fc63"
* 可通过UserName发送消息
* </p>
*
* @author https://github.com/yaphone
* @date 2017年5月4日 下午10:56:31
* @param name
* @return
*/
public static String getUserNameByNickName(String nickName) {
for (JSONObject o : core.getContactList()) {
if (o.getString("NickName").equals(nickName)) {
return o.getString("UserName");
}
}
return null;
}
/**
* 返回好友昵称列表
*
* @author https://github.com/yaphone
* @date 2017年5月4日 下午11:37:20
* @return
*/
public static List<String> getContactNickNameList() {
List<String> contactNickNameList = new ArrayList<String>();
for (JSONObject o : core.getContactList()) {
contactNickNameList.add(o.getString("NickName"));
}
return contactNickNameList;
}
/**
* 返回好友完整信息列表
*
* @date 2017年6月26日 下午9:45:39
* @return
*/
public static List<JSONObject> getContactList() {
return core.getContactList();
}
/**
* 返回群列表
*
* @author https://github.com/yaphone
* @date 2017年5月5日 下午9:55:21
* @return
*/
public static List<JSONObject> getGroupList() {
return core.getGroupList();
}
/**
* 获取群ID列表
*
* @date 2017年6月21日 下午11:42:56
* @return
*/
public static List<String> getGroupIdList() {
return core.getGroupIdList();
}
/**
* 获取群NickName列表
*
* @date 2017年6月21日 下午11:43:38
* @return
*/
public static List<String> getGroupNickNameList() {
return core.getGroupNickNameList();
}
/**
* 根据groupIdList返回群成员列表
*
* @date 2017年6月13日 下午11:12:31
* @param groupId
* @return
*/
public static JSONArray getMemberListByGroupId(String groupId) {
return core.getGroupMemeberMap().get(groupId);
}
/**
* 退出微信
*
* @author https://github.com/yaphone
* @date 2017年5月18日 下午11:56:54
*/
public static void logout() {
webWxLogout();
}
private static boolean webWxLogout() {
String url = String.format(URLEnum.WEB_WX_LOGOUT.getUrl(),
core.getLoginInfo().get(StorageLoginInfoEnum.url.getKey()));
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
params.add(new BasicNameValuePair("redirect", "1"));
params.add(new BasicNameValuePair("type", "1"));
params.add(
new BasicNameValuePair("skey", (String) core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey())));
try {
HttpEntity entity = core.getMyHttpClient().doGet(url, params, false, null);
String text = EntityUtils.toString(entity, Consts.UTF_8); // 无消息
return true;
} catch (Exception e) {
LOG.debug(e.getMessage());
}
return false;
}
public static void setUserInfo() {
for (JSONObject o : core.getContactList()) {
core.getUserInfoMap().put(o.getString("NickName"), o);
core.getUserInfoMap().put(o.getString("UserName"), o);
}
}
/**
*
* 根据用户昵称设置备注名称
*
* @date 2017年5月27日 上午12:21:40
* @param userName
* @param remName
*/
public static void remarkNameByNickName(String nickName, String remName) {
String url = String.format(URLEnum.WEB_WX_REMARKNAME.getUrl(), core.getLoginInfo().get("url"),
core.getLoginInfo().get(StorageLoginInfoEnum.pass_ticket.getKey()));
Map<String, Object> msgMap = new HashMap<String, Object>();
Map<String, Object> msgMap_BaseRequest = new HashMap<String, Object>();
msgMap.put("CmdId", 2);
msgMap.put("RemarkName", remName);
msgMap.put("UserName", core.getUserInfoMap().get(nickName).get("UserName"));
msgMap_BaseRequest.put("Uin", core.getLoginInfo().get(StorageLoginInfoEnum.wxuin.getKey()));
msgMap_BaseRequest.put("Sid", core.getLoginInfo().get(StorageLoginInfoEnum.wxsid.getKey()));
msgMap_BaseRequest.put("Skey", core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey()));
msgMap_BaseRequest.put("DeviceID", core.getLoginInfo().get(StorageLoginInfoEnum.deviceid.getKey()));
msgMap.put("BaseRequest", msgMap_BaseRequest);
try {
String paramStr = JSON.toJSONString(msgMap);
HttpEntity entity = core.getMyHttpClient().doPost(url, paramStr);
// String result = EntityUtils.toString(entity, Consts.UTF_8);
LOG.info("修改备注" + remName);
} catch (Exception e) {
LOG.error("remarkNameByUserName", e);
}
}
/**
* 获取微信在线状态
*
* @date 2017年6月16日 上午12:47:46
* @return
*/
public static boolean getWechatStatus() {
return core.isAlive();
}
}

View File

@@ -1,89 +0,0 @@
package com.xmzs.common.wechat.controller;
import com.xmzs.common.core.exception.base.BaseException;
import com.xmzs.common.wechat.utils.SleepUtils;
import com.xmzs.common.wechat.utils.enums.URLEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xmzs.common.wechat.api.WechatTools;
import com.xmzs.common.wechat.core.Core;
import com.xmzs.common.wechat.service.ILoginService;
import com.xmzs.common.wechat.service.impl.LoginServiceImpl;
import com.xmzs.common.wechat.thread.CheckLoginStatusThread;
import com.xmzs.common.wechat.utils.tools.CommonTools;
/**
* 登陆控制器
*
* @author https://github.com/yaphone
* @version 1.0
* @date 创建时间2017年5月13日 下午12:56:07
*/
public class LoginController {
private static Logger LOG = LoggerFactory.getLogger(LoginController.class);
private ILoginService loginService = new LoginServiceImpl();
private static Core core = Core.getInstance();
/**
* 获取二维码地址
* 风险:已登录账号不可调用该接口,会移除当前core信息
* @return
*/
public String login_1() {
if (core.isAlive()) {
LOG.warn("微信已登陆");
throw new BaseException("微信已登陆");
}
LOG.info("1.获取微信UUID");
while (loginService.getUuid() == null) {
LOG.warn("1.1. 获取微信UUID失败一秒后重新获取");
SleepUtils.sleep(1000);
}
LOG.info("2. 获取登陆二维码图片");
return URLEnum.QRCODE_URL.getUrl() + core.getUuid();
}
public void login_2() {
LOG.info("3. 请扫描二维码图片,并在手机上确认");
if (!core.isAlive()) {
loginService.login();
core.setAlive(true);
LOG.info(("登陆成功"));
}
LOG.info("4. 登陆超时,请重新扫描二维码图片");
LOG.info("5. 登陆成功,微信初始化");
if (!loginService.webWxInit()) {
LOG.info("6. 微信初始化异常");
System.exit(0);
}
LOG.info("6. 开启微信状态通知");
loginService.wxStatusNotify();
LOG.info("7. 清除。。。。");
CommonTools.clearScreen();
LOG.info(String.format("欢迎回来, %s", core.getNickName()));
LOG.info("8. 开始接收消息");
loginService.startReceiving();
LOG.info("9. 获取联系人信息");
loginService.webWxGetContact();
LOG.info("10. 获取群好友及群好友列表");
loginService.WebWxBatchGetContact();
LOG.info("11. 缓存本次登陆好友相关消息");
WechatTools.setUserInfo(); // 登陆成功后缓存本次登陆好友相关消息NickName, UserName
LOG.info("12.开启微信状态检测线程");
new Thread(new CheckLoginStatusThread()).start();
}
}

View File

@@ -1,276 +0,0 @@
package com.xmzs.common.wechat.core;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xmzs.common.wechat.beans.BaseMsg;
import com.xmzs.common.wechat.utils.MyHttpClient;
import com.xmzs.common.wechat.utils.enums.parameters.BaseParaEnum;
/**
* 核心存储类,全局只保存一份,单例模式
*
* @author https://github.com/yaphone
* @date 创建时间2017年4月23日 下午2:33:56
* @version 1.0
*
*/
public class Core {
private static Core instance;
private Core() {
}
public static Core getInstance() {
if (instance == null) {
synchronized (Core.class) {
instance = new Core();
}
}
return instance;
}
boolean alive = false;
private int memberCount = 0;
private String indexUrl;
private String userName;
private String nickName;
private List<BaseMsg> msgList = new ArrayList<BaseMsg>();
private JSONObject userSelf; // 登陆账号自身信息
private List<JSONObject> memberList = new ArrayList<JSONObject>(); // 好友+群聊+公众号+特殊账号
private List<JSONObject> contactList = new ArrayList<JSONObject>();// 好友
private List<JSONObject> groupList = new ArrayList<JSONObject>();; // 群
private Map<String, JSONArray> groupMemeberMap = new HashMap<String, JSONArray>(); // 群聊成员字典
private List<JSONObject> publicUsersList = new ArrayList<JSONObject>();;// 公众号/服务号
private List<JSONObject> specialUsersList = new ArrayList<JSONObject>();;// 特殊账号
private List<String> groupIdList = new ArrayList<String>(); // 群ID列表
private List<String> groupNickNameList = new ArrayList<String>(); // 群NickName列表
private Map<String, JSONObject> userInfoMap = new HashMap<String, JSONObject>();
Map<String, Object> loginInfo = new HashMap<String, Object>();
// CloseableHttpClient httpClient = HttpClients.createDefault();
MyHttpClient myHttpClient = MyHttpClient.getInstance();
String uuid = null;
boolean useHotReload = false;
String hotReloadDir = "itchat.pkl";
int receivingRetryCount = 5;
private long lastNormalRetcodeTime; // 最后一次收到正常retcode的时间秒为单位
/**
* 请求参数
*/
public Map<String, Object> getParamMap() {
return new HashMap<String, Object>(1) {
/**
*
*/
private static final long serialVersionUID = 1L;
{
Map<String, String> map = new HashMap<String, String>();
for (BaseParaEnum baseRequest : BaseParaEnum.values()) {
map.put(baseRequest.para(), getLoginInfo().get(baseRequest.value()).toString());
}
put("BaseRequest", map);
}
};
}
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
}
public List<JSONObject> getMemberList() {
return memberList;
}
public void setMemberList(List<JSONObject> memberList) {
this.memberList = memberList;
}
public Map<String, Object> getLoginInfo() {
return loginInfo;
}
public void setLoginInfo(Map<String, Object> loginInfo) {
this.loginInfo = loginInfo;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public int getMemberCount() {
return memberCount;
}
public void setMemberCount(int memberCount) {
this.memberCount = memberCount;
}
public boolean isUseHotReload() {
return useHotReload;
}
public void setUseHotReload(boolean useHotReload) {
this.useHotReload = useHotReload;
}
public String getHotReloadDir() {
return hotReloadDir;
}
public void setHotReloadDir(String hotReloadDir) {
this.hotReloadDir = hotReloadDir;
}
public int getReceivingRetryCount() {
return receivingRetryCount;
}
public void setReceivingRetryCount(int receivingRetryCount) {
this.receivingRetryCount = receivingRetryCount;
}
public MyHttpClient getMyHttpClient() {
return myHttpClient;
}
public List<BaseMsg> getMsgList() {
return msgList;
}
public void setMsgList(List<BaseMsg> msgList) {
this.msgList = msgList;
}
public void setMyHttpClient(MyHttpClient myHttpClient) {
this.myHttpClient = myHttpClient;
}
public List<String> getGroupIdList() {
return groupIdList;
}
public void setGroupIdList(List<String> groupIdList) {
this.groupIdList = groupIdList;
}
public List<JSONObject> getContactList() {
return contactList;
}
public void setContactList(List<JSONObject> contactList) {
this.contactList = contactList;
}
public List<JSONObject> getGroupList() {
return groupList;
}
public void setGroupList(List<JSONObject> groupList) {
this.groupList = groupList;
}
public List<JSONObject> getPublicUsersList() {
return publicUsersList;
}
public void setPublicUsersList(List<JSONObject> publicUsersList) {
this.publicUsersList = publicUsersList;
}
public List<JSONObject> getSpecialUsersList() {
return specialUsersList;
}
public void setSpecialUsersList(List<JSONObject> specialUsersList) {
this.specialUsersList = specialUsersList;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public JSONObject getUserSelf() {
return userSelf;
}
public void setUserSelf(JSONObject userSelf) {
this.userSelf = userSelf;
}
public Map<String, JSONObject> getUserInfoMap() {
return userInfoMap;
}
public void setUserInfoMap(Map<String, JSONObject> userInfoMap) {
this.userInfoMap = userInfoMap;
}
public synchronized long getLastNormalRetcodeTime() {
return lastNormalRetcodeTime;
}
public synchronized void setLastNormalRetcodeTime(long lastNormalRetcodeTime) {
this.lastNormalRetcodeTime = lastNormalRetcodeTime;
}
public List<String> getGroupNickNameList() {
return groupNickNameList;
}
public void setGroupNickNameList(List<String> groupNickNameList) {
this.groupNickNameList = groupNickNameList;
}
public Map<String, JSONArray> getGroupMemeberMap() {
return groupMemeberMap;
}
public void setGroupMemeberMap(Map<String, JSONArray> groupMemeberMap) {
this.groupMemeberMap = groupMemeberMap;
}
public String getIndexUrl() {
return indexUrl;
}
public void setIndexUrl(String indexUrl) {
this.indexUrl = indexUrl;
}
}

View File

@@ -1,171 +0,0 @@
package com.xmzs.common.wechat.core;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import com.xmzs.common.wechat.utils.enums.MsgCodeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xmzs.common.wechat.api.MessageTools;
import com.xmzs.common.wechat.beans.BaseMsg;
import com.xmzs.common.wechat.face.IMsgHandlerFace;
import com.xmzs.common.wechat.utils.enums.MsgTypeEnum;
import com.xmzs.common.wechat.utils.tools.CommonTools;
/**
* 消息处理中心
*
* @author https://github.com/yaphone
* @date 创建时间2017年5月14日 下午12:47:50
* @version 1.0
*
*/
public class MsgCenter {
private static Logger LOG = LoggerFactory.getLogger(MsgCenter.class);
private static Core core = Core.getInstance();
/**
* 接收消息,放入队列
*
* @author https://github.com/yaphone
* @date 2017年4月23日 下午2:30:48
* @param msgList
* @return
*/
public static JSONArray produceMsg(JSONArray msgList) {
JSONArray result = new JSONArray();
for (int i = 0; i < msgList.size(); i++) {
JSONObject msg = new JSONObject();
JSONObject m = msgList.getJSONObject(i);
m.put("groupMsg", false);// 是否是群消息
if (m.getString("FromUserName").contains("@@") || m.getString("ToUserName").contains("@@")) { // 群聊消息
if (m.getString("FromUserName").contains("@@")
&& !core.getGroupIdList().contains(m.getString("FromUserName"))) {
core.getGroupIdList().add((m.getString("FromUserName")));
} else if (m.getString("ToUserName").contains("@@")
&& !core.getGroupIdList().contains(m.getString("ToUserName"))) {
core.getGroupIdList().add((m.getString("ToUserName")));
}
// 群消息与普通消息不同的是在其消息体Content中会包含发送者id及":<br/>"消息,这里需要处理一下,去掉多余信息,只保留消息内容
if (m.getString("Content").contains("<br/>")) {
String content = m.getString("Content").substring(m.getString("Content").indexOf("<br/>") + 5);
m.put("Content", content);
m.put("groupMsg", true);
}
} else {
CommonTools.msgFormatter(m, "Content");
}
if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_TEXT.getCode())) { // words
// 文本消息
if (m.getString("Url").length() != 0) {
String regEx = "(.+?\\(.+?\\))";
Matcher matcher = CommonTools.getMatcher(regEx, m.getString("Content"));
String data = "Map";
if (matcher.find()) {
data = matcher.group(1);
}
msg.put("Type", "Map");
msg.put("Text", data);
} else {
msg.put("Type", MsgTypeEnum.TEXT.getType());
msg.put("Text", m.getString("Content"));
}
m.put("Type", msg.getString("Type"));
m.put("Text", msg.getString("Text"));
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_IMAGE.getCode())
|| m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_EMOTICON.getCode())) { // 图片消息
m.put("Type", MsgTypeEnum.PIC.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VOICE.getCode())) { // 语音消息
m.put("Type", MsgTypeEnum.VOICE.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VERIFYMSG.getCode())) {// friends
// 好友确认消息
// MessageTools.addFriend(core, userName, 3, ticket); // 确认添加好友
m.put("Type", MsgTypeEnum.VERIFYMSG.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_SHARECARD.getCode())) { // 共享名片
m.put("Type", MsgTypeEnum.NAMECARD.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VIDEO.getCode())
|| m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_MICROVIDEO.getCode())) {// viedo
m.put("Type", MsgTypeEnum.VIEDO.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_MEDIA.getCode())) { // 多媒体消息
m.put("Type", MsgTypeEnum.MEDIA.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_STATUSNOTIFY.getCode())) {// phone
// init
// 微信初始化消息
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_SYS.getCode())) {// 系统消息
m.put("Type", MsgTypeEnum.SYS.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_RECALLED.getCode())) { // 撤回消息
} else {
LOG.info("Useless msg");
}
LOG.info("收到消息一条,来自: " + m.getString("FromUserName"));
result.add(m);
}
return result;
}
/**
* 消息处理
*
* @author https://github.com/yaphone
* @date 2017年5月14日 上午10:52:34
* @param msgHandler
*/
public static void handleMsg(IMsgHandlerFace msgHandler) {
while (true) {
if (core.getMsgList().size() > 0 && core.getMsgList().get(0).getContent() != null) {
if (core.getMsgList().get(0).getContent().length() > 0) {
BaseMsg msg = core.getMsgList().get(0);
if (msg.getType() != null) {
try {
if (msg.getType().equals(MsgTypeEnum.TEXT.getType())) {
String result = msgHandler.textMsgHandle(msg);
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
} else if (msg.getType().equals(MsgTypeEnum.PIC.getType())) {
String result = msgHandler.picMsgHandle(msg);
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
} else if (msg.getType().equals(MsgTypeEnum.VOICE.getType())) {
String result = msgHandler.voiceMsgHandle(msg);
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
} else if (msg.getType().equals(MsgTypeEnum.VIEDO.getType())) {
String result = msgHandler.viedoMsgHandle(msg);
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
} else if (msg.getType().equals(MsgTypeEnum.NAMECARD.getType())) {
String result = msgHandler.nameCardMsgHandle(msg);
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
} else if (msg.getType().equals(MsgTypeEnum.SYS.getType())) { // 系统消息
msgHandler.sysMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.VERIFYMSG.getType())) { // 确认添加好友消息
String result = msgHandler.verifyAddFriendMsgHandle(msg);
MessageTools.sendMsgById(result,
core.getMsgList().get(0).getRecommendInfo().getUserName());
} else if (msg.getType().equals(MsgTypeEnum.MEDIA.getType())) { // 多媒体消息
String result = msgHandler.mediaMsgHandle(msg);
MessageTools.sendMsgById(result, core.getMsgList().get(0).getFromUserName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
core.getMsgList().remove(0);
}
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -1,38 +0,0 @@
package com.xmzs.common.wechat.thread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xmzs.common.wechat.core.Core;
import com.xmzs.common.wechat.utils.SleepUtils;
/**
* 检查微信在线状态
* <p>
* 如何来感知微信状态?
* 微信会有心跳包LoginServiceImpl.syncCheck()正常在线情况下返回的消息中retcode报文应该为"0"心跳间隔一般在25秒
* 那么可以通过最后收到正常报文的时间来作为判断是否在线的依据。若报文间隔大于60秒则认为已掉线。
* </p>
*
* @author https://github.com/yaphone
* @date 创建时间2017年5月17日 下午10:53:15
* @version 1.0
*
*/
public class CheckLoginStatusThread implements Runnable {
private static Logger LOG = LoggerFactory.getLogger(CheckLoginStatusThread.class);
private Core core = Core.getInstance();
@Override
public void run() {
while (core.isAlive()) {
long t1 = System.currentTimeMillis(); // 秒为单位
if (t1 - core.getLastNormalRetcodeTime() > 60 * 1000) { // 超过60秒判为离线
core.setAlive(false);
LOG.info("微信已离线");
}
SleepUtils.sleep(10 * 1000); // 休眠10秒
}
}
}

View File

@@ -1,6 +0,0 @@
package com.xmzs.common.wechat.utils;
public class MsgKeywords {
public static String newFriendStr = "我通过了你的朋友验证请求";
}

View File

@@ -1,194 +0,0 @@
package com.xmzs.common.wechat.utils;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/**
* HTTP访问类对Apache HttpClient进行简单封装适配器模式
*
* @author https://github.com/yaphone
* @date 创建时间2017年4月9日 下午7:05:04
* @version 1.0
*
*/
public class MyHttpClient {
private Logger logger = Logger.getLogger("MyHttpClient");
private static CloseableHttpClient httpClient = HttpClients.createDefault();
private static MyHttpClient instance = null;
private static CookieStore cookieStore;
static {
cookieStore = new BasicCookieStore();
// 将CookieStore设置到httpClient中
httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
}
public static String getCookie(String name) {
List<Cookie> cookies = cookieStore.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equalsIgnoreCase(name)) {
return cookie.getValue();
}
}
return null;
}
private MyHttpClient() {
}
/**
* 获取cookies
*
* @author https://github.com/yaphone
* @date 2017年5月7日 下午8:37:17
* @return
*/
public static MyHttpClient getInstance() {
if (instance == null) {
synchronized (MyHttpClient.class) {
if (instance == null) {
instance = new MyHttpClient();
}
}
}
return instance;
}
/**
* 处理GET请求
*
* @author https://github.com/yaphone
* @date 2017年4月9日 下午7:06:19
* @param url
* @param params
* @return
*/
public HttpEntity doGet(String url, List<BasicNameValuePair> params, boolean redirect,
Map<String, String> headerMap) {
HttpEntity entity = null;
HttpGet httpGet = new HttpGet();
try {
if (params != null) {
String paramStr = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
httpGet = new HttpGet(url + "?" + paramStr);
} else {
httpGet = new HttpGet(url);
}
if (!redirect) {
httpGet.setConfig(RequestConfig.custom().setRedirectsEnabled(false).build()); // 禁止重定向
}
httpGet.setHeader("User-Agent", Config.USER_AGENT);
httpGet.setHeader("client-version", Config.UOS_PATCH_CLIENT_VERSION);
httpGet.setHeader("extspam", Config.UOS_PATCH_EXTSPAM);
httpGet.setHeader("referer", Config.REFERER);
if (headerMap != null) {
Set<Entry<String, String>> entries = headerMap.entrySet();
for (Entry<String, String> entry : entries) {
httpGet.setHeader(entry.getKey(), entry.getValue());
}
}
CloseableHttpResponse response = httpClient.execute(httpGet);
entity = response.getEntity();
} catch (ClientProtocolException e) {
logger.info(e.getMessage());
} catch (IOException e) {
logger.info(e.getMessage());
}
return entity;
}
/**
* 处理POST请求
*
* @author https://github.com/yaphone
* @date 2017年4月9日 下午7:06:35
* @param url
* @param params
* @return
*/
public HttpEntity doPost(String url, String paramsStr) {
HttpEntity entity = null;
HttpPost httpPost = new HttpPost();
try {
StringEntity params = new StringEntity(paramsStr, Consts.UTF_8);
httpPost = new HttpPost(url);
httpPost.setEntity(params);
httpPost.setHeader("Content-type", "application/json; charset=utf-8");
httpPost.setHeader("User-Agent", Config.USER_AGENT);
httpPost.setHeader("client-version", Config.UOS_PATCH_CLIENT_VERSION);
httpPost.setHeader("extspam", Config.UOS_PATCH_EXTSPAM);
httpPost.setHeader("referer", Config.REFERER);
CloseableHttpResponse response = httpClient.execute(httpPost);
entity = response.getEntity();
} catch (ClientProtocolException e) {
logger.info(e.getMessage());
} catch (IOException e) {
logger.info(e.getMessage());
}
return entity;
}
/**
* 上传文件到服务器
*
* @author https://github.com/yaphone
* @date 2017年5月7日 下午9:19:23
* @param url
* @param reqEntity
* @return
*/
public HttpEntity doPostFile(String url, HttpEntity reqEntity) {
HttpEntity entity = null;
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("User-Agent", Config.USER_AGENT);
httpPost.setHeader("client-version", Config.UOS_PATCH_CLIENT_VERSION);
httpPost.setHeader("extspam", Config.UOS_PATCH_EXTSPAM);
httpPost.setHeader("referer", Config.REFERER);
httpPost.setEntity(reqEntity);
try {
CloseableHttpResponse response = httpClient.execute(httpPost);
entity = response.getEntity();
} catch (Exception e) {
logger.info(e.getMessage());
}
return entity;
}
public static CloseableHttpClient getHttpClient() {
return httpClient;
}
}

View File

@@ -1,68 +0,0 @@
package com.xmzs.common.wechat.utils.enums;
/**
* 消息类型
*
* @author https://github.com/yaphone
* @date 创建时间2017年4月23日 下午12:15:00
* @version 1.0
*
*/
public enum MsgCodeEnum {
// public static final int MSGTYPE_TEXT = 1; // 文本消息类型
// public static final int MSGTYPE_IMAGE = 3; // 图片消息
// public static final int MSGTYPE_VOICE = 34; // 语音消息
// public static final int MSGTYPE_VIDEO = 43; // 小视频消息
// public static final int MSGTYPE_MICROVIDEO = 62; // 短视频消息
// public static final int MSGTYPE_EMOTICON = 47; // 表情消息
// public static final int MSGTYPE_APP = 49;
// public static final int MSGTYPE_VOIPMSG = 50;
// public static final int MSGTYPE_VOIPNOTIFY = 52;
// public static final int MSGTYPE_VOIPINVITE = 53;
// public static final int MSGTYPE_LOCATION = 48;
// public static final int MSGTYPE_STATUSNOTIFY = 51;
// public static final int MSGTYPE_SYSNOTICE = 9999;
// public static final int MSGTYPE_POSSIBLEFRIEND_MSG = 40;
// public static final int MSGTYPE_VERIFYMSG = 37;
// public static final int MSGTYPE_SHARECARD = 42;
// public static final int MSGTYPE_SYS = 10000;
// public static final int MSGTYPE_RECALLED = 10002;
MSGTYPE_TEXT(1, "文本消息类型"),
MSGTYPE_IMAGE(3, "图片消息"),
MSGTYPE_VOICE(34, "语音消息"),
MSGTYPE_VIDEO(43, "小视频消息"),
MSGTYPE_MICROVIDEO(62, "短视频消息"),
MSGTYPE_EMOTICON(47, "表情消息"),
MSGTYPE_MEDIA(49, "多媒体消息"),
MSGTYPE_VOIPMSG(50, ""),
MSGTYPE_VOIPNOTIFY(52, ""),
MSGTYPE_VOIPINVITE(53, ""),
MSGTYPE_LOCATION(48, ""),
MSGTYPE_STATUSNOTIFY(51, ""),
MSGTYPE_SYSNOTICE(9999, ""),
MSGTYPE_POSSIBLEFRIEND_MSG(40, ""),
MSGTYPE_VERIFYMSG(37, "好友请求"),
MSGTYPE_SHARECARD(42, ""),
MSGTYPE_SYS(10000, "系统消息"),
MSGTYPE_RECALLED(10002, "")
;
private int code;
private String type;
MsgCodeEnum(int code, String type) {
this.code = code;
this.type = type;
}
public int getCode() {
return code;
}
public String getType() {
return type;
}
}

View File

@@ -1,35 +0,0 @@
package com.xmzs.common.wechat.utils.enums;
/**
* 返回结构枚举类
* <p>
* Created by xiaoxiaomo on 2017/5/6.
*/
public enum ResultEnum {
SUCCESS("200", "成功"),
WAIT_CONFIRM("201", "请在手机上点击确认"),
WAIT_SCAN("400", "请扫描二维码");
private String code;
private String msg;
ResultEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
// public static MsgInfoEnum getCode(String code) {
// switch (code) {
// case "Text":
// return MsgInfoEnum.TEXT;
// default:
// return MsgInfoEnum.VIDEO;
// }
// }
}

View File

@@ -1,30 +0,0 @@
package com.xmzs.common.wechat.utils.enums;
public enum RetCodeEnum {
NORMAL("0", "普通"),
LOGIN_OUT("1102", "退出"),
LOGIN_OTHERWHERE("1101", "其它地方登陆"),
MOBILE_LOGIN_OUT("1102", "移动端退出"),
UNKOWN("9999", "未知")
;
private String code;
private String type;
RetCodeEnum(String code, String type) {
this.code = code;
this.type = type;
}
public String getCode() {
return code;
}
public String getType() {
return type;
}
}

View File

@@ -1,16 +1,7 @@
package com.xmzs.common.wechat.api;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.activation.MimetypesFileTypeMap;
package org.ruoyi.common.wechat.itchat4j.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
@@ -18,20 +9,22 @@ import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ruoyi.common.wechat.itchat4j.beans.BaseMsg;
import org.ruoyi.common.wechat.itchat4j.beans.RecommendInfo;
import org.ruoyi.common.wechat.itchat4j.core.Core;
import org.ruoyi.common.wechat.itchat4j.core.CoreManage;
import org.ruoyi.common.wechat.itchat4j.utils.Config;
import org.ruoyi.common.wechat.itchat4j.utils.LogInterface;
import org.ruoyi.common.wechat.itchat4j.utils.enums.SendMsgType;
import org.ruoyi.common.wechat.itchat4j.utils.enums.StorageLoginInfoEnum;
import org.ruoyi.common.wechat.itchat4j.utils.enums.URLEnum;
import org.ruoyi.common.wechat.itchat4j.utils.enums.VerifyFriendEnum;
import org.ruoyi.common.wechat.web.constant.UploadConstant;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xmzs.common.wechat.beans.BaseMsg;
import com.xmzs.common.wechat.beans.RecommendInfo;
import com.xmzs.common.wechat.core.Core;
import com.xmzs.common.wechat.utils.Config;
import com.xmzs.common.wechat.utils.MyHttpClient;
import com.xmzs.common.wechat.utils.enums.StorageLoginInfoEnum;
import com.xmzs.common.wechat.utils.enums.URLEnum;
import com.xmzs.common.wechat.utils.enums.VerifyFriendEnum;
import javax.activation.MimetypesFileTypeMap;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 消息处理类
@@ -40,41 +33,73 @@ import com.xmzs.common.wechat.utils.enums.VerifyFriendEnum;
* @date 创建时间2017年4月23日 下午2:30:37
* @version 1.0
*
* @author WesleyOne 修改
*/
public class MessageTools {
private static Logger LOG = LoggerFactory.getLogger(MessageTools.class);
private static Core core = Core.getInstance();
private static MyHttpClient myHttpClient = core.getMyHttpClient();
public class MessageTools implements LogInterface {
/**
* 通过UserName发送消息
* @param toUserName
* @param uniqueKey
* @param data
* @param type
* @return
*/
public static boolean send(String toUserName, String uniqueKey, String data, String type){
String nickName = WechatTools.getNickNameByUserName(toUserName, uniqueKey);
if (SendMsgType.TEXT.toValue().equals(type)){
LOG.info("发送文本 {}:{}", nickName, data);
return MessageTools.sendMsgById(data,toUserName,uniqueKey);
}else if (SendMsgType.IMG.toValue().equals(type)){
LOG.info("发送图片 {}:{}", nickName, UploadConstant.IMG_PATH_SEP+data);
return MessageTools.sendPicMsgByUserId(toUserName,UploadConstant.IMG_PATH_SEP+data,uniqueKey);
}else if (SendMsgType.FILE.toValue().equals(type)){
LOG.info("发送文件 {}:{}",nickName,UploadConstant.FILE_PATH_SEP+data);
return MessageTools.sendFileMsgByUserId(toUserName,UploadConstant.FILE_PATH_SEP+data,uniqueKey);
}
return false;
}
/**
* 通过NickName发送消息
* @param nickName
* @param uniqueKey
* @param data
* @param type
* @param isGroup
* @return
*/
public static boolean sendByNickName(String nickName, String uniqueKey, String data, String type,boolean isGroup){
if (SendMsgType.TEXT.toValue().equals(type)){
LOG.info("发送文本 {}:{}", nickName, data);
return MessageTools.sendMsgByNickNameApi(data, nickName, uniqueKey, isGroup);
}else if (SendMsgType.IMG.toValue().equals(type)){
LOG.info("发送图片 {}:{}", nickName, UploadConstant.IMG_PATH_SEP+data);
return MessageTools.sendPicMsgByNickNameApi(nickName, UploadConstant.IMG_PATH_SEP + data, uniqueKey, isGroup);
}else if (SendMsgType.FILE.toValue().equals(type)){
LOG.info("发送文件 {}:{}",nickName,UploadConstant.FILE_PATH_SEP+data);
return MessageTools.sendFileMsgByNickNameApi(nickName,UploadConstant.FILE_PATH_SEP+data,uniqueKey,isGroup);
}
return false;
}
/**
* 根据UserName发送文本消息
*
* @author https://github.com/yaphone
* @date 2017年5月4日 下午11:17:38
* @param msg
* @param toUserName
*/
private static void sendMsg(String text, String toUserName) {
if (text == null) {
return;
}
LOG.info(String.format("发送消息 %s: %s", toUserName, text));
webWxSendMsg(1, text, toUserName);
}
/**
* 根据ID发送文本消息
*
* @author https://github.com/yaphone
* @date 2017年5月6日 上午11:45:51
* @param text
* @param id
* @param toUserName
* @param uniqueKey
*/
public static void sendMsgById(String text, String id) {
public static boolean sendMsgById(String text, String toUserName, String uniqueKey) {
if (text == null) {
return;
return false;
}
sendMsg(text, id);
return webWxSendMsg(1, text, toUserName, uniqueKey);
}
/**
@@ -85,12 +110,38 @@ public class MessageTools {
* @param text
* @param nickName
*/
public static boolean sendMsgByNickName(String text, String nickName) {
public static boolean sendMsgByNickName(String text, String nickName, String uniqueKey) {
if (nickName != null) {
String toUserName = WechatTools.getUserNameByNickName(nickName);
String toUserName = WechatTools.getContactUserNameByNickName(nickName,uniqueKey);
if (toUserName != null) {
webWxSendMsg(1, text, toUserName);
return true;
return sendMsgById(text, toUserName, uniqueKey);
}
}
return false;
}
public static boolean sendMsgByNickNameApi(String text, String nickName, String uniqueKey, boolean isGroup){
if (isGroup){
return sendGroupMsgByNickName(text,nickName,uniqueKey);
}else{
return sendMsgByNickName(text,nickName,uniqueKey);
}
}
/**
* 根据NickName发送群文本消息
* @param text
* @param nickName
* @param uniqueKey
* @return
*/
private static boolean sendGroupMsgByNickName(String text, String nickName, String uniqueKey) {
if (nickName != null) {
String toUserName = WechatTools.getGroupUserNameByNickName(nickName,uniqueKey);
if (toUserName != null) {
return sendMsgById(text, toUserName, uniqueKey);
}
}
return false;
@@ -106,24 +157,30 @@ public class MessageTools {
* @param content
* @param toUserName
*/
public static void webWxSendMsg(int msgType, String content, String toUserName) {
public static boolean webWxSendMsg(int msgType, String content, String toUserName, String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
if (!core.isAlive()){
return false;
}
String url = String.format(URLEnum.WEB_WX_SEND_MSG.getUrl(), core.getLoginInfo().get("url"));
Map<String, Object> msgMap = new HashMap<String, Object>();
Map<String, Object> msgMap = new HashMap<String, Object>(12);
msgMap.put("Type", msgType);
msgMap.put("Content", content);
msgMap.put("FromUserName", core.getUserName());
msgMap.put("ToUserName", toUserName == null ? core.getUserName() : toUserName);
msgMap.put("LocalID", new Date().getTime() * 10);
msgMap.put("ClientMsgId", new Date().getTime() * 10);
msgMap.put("LocalID", System.currentTimeMillis() * 10);
msgMap.put("ClientMsgId", System.currentTimeMillis() * 10);
Map<String, Object> paramMap = core.getParamMap();
paramMap.put("Msg", msgMap);
paramMap.put("Scene", 0);
try {
String paramStr = JSON.toJSONString(paramMap);
HttpEntity entity = myHttpClient.doPost(url, paramStr);
HttpEntity entity = core.getMyHttpClient().doPost(url, paramStr);
EntityUtils.toString(entity, Consts.UTF_8);
return true;
} catch (Exception e) {
LOG.error("webWxSendMsg", e);
return false;
}
}
@@ -135,14 +192,15 @@ public class MessageTools {
* @param filePath
* @return
*/
private static JSONObject webWxUploadMedia(String filePath) {
File file = new File(filePath);
if (!file.exists() && file.isFile()) {
private static JSONObject webWxUploadMedia(String filePath, String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
File f = new File(filePath);
if (!f.exists() || !f.isFile()) {
LOG.info("file is not exist");
return null;
}
String url = String.format(URLEnum.WEB_WX_UPLOAD_MEDIA.getUrl(), core.getLoginInfo().get("fileUrl"));
String mimeType = new MimetypesFileTypeMap().getContentType(file);
String mimeType = new MimetypesFileTypeMap().getContentType(f);
String mediaType = "";
if (mimeType == null) {
mimeType = "text/plain";
@@ -150,11 +208,11 @@ public class MessageTools {
mediaType = mimeType.split("/")[0].equals("image") ? "pic" : "doc";
}
String lastModifieDate = new SimpleDateFormat("yyyy MM dd HH:mm:ss").format(new Date());
long fileSize = file.length();
long fileSize = f.length();
String passTicket = (String) core.getLoginInfo().get("pass_ticket");
String clientMediaId = new Date().getTime()
String clientMediaId = String.valueOf(System.currentTimeMillis())
+ String.valueOf(new Random().nextLong()).substring(0, 4);
String webwxDataTicket = MyHttpClient.getCookie("webwx_data_ticket");
String webwxDataTicket = core.getMyHttpClient().getCookie("webwx_data_ticket");
if (webwxDataTicket == null) {
LOG.error("get cookie webwx_data_ticket error");
return null;
@@ -180,9 +238,9 @@ public class MessageTools {
builder.addTextBody("uploadmediarequest", JSON.toJSONString(paramMap), ContentType.TEXT_PLAIN);
builder.addTextBody("webwx_data_ticket", webwxDataTicket, ContentType.TEXT_PLAIN);
builder.addTextBody("pass_ticket", passTicket, ContentType.TEXT_PLAIN);
builder.addBinaryBody("filename", file, ContentType.create(mimeType), filePath);
builder.addBinaryBody("filename", f, ContentType.create(mimeType), filePath);
HttpEntity reqEntity = builder.build();
HttpEntity entity = myHttpClient.doPostFile(url, reqEntity);
HttpEntity entity = core.getMyHttpClient().doPostFile(url, reqEntity);
if (entity != null) {
try {
String result = EntityUtils.toString(entity, Consts.UTF_8);
@@ -195,18 +253,45 @@ public class MessageTools {
return null;
}
public static boolean sendPicMsgByNickNameApi(String nickName, String filePath, String uniqueKey,boolean isGroup){
if (isGroup){
return sendGroupPicMsgByNickName(nickName, filePath, uniqueKey);
}else {
return sendPicMsgByNickName(nickName, filePath, uniqueKey);
}
}
/**
* 根据NickName发送图片消息
*
* @author https://github.com/yaphone
* @date 2017年5月7日 下午10:32:45
* @param nackName
* @param nickName
* @param filePath
* @return
*/
public static boolean sendPicMsgByNickName(String nickName, String filePath) {
String toUserName = WechatTools.getUserNameByNickName(nickName);
public static boolean sendPicMsgByNickName(String nickName, String filePath, String uniqueKey) {
String toUserName = WechatTools.getContactUserNameByNickName(nickName,uniqueKey);
if (toUserName != null) {
return sendPicMsgByUserId(toUserName, filePath);
LOG.info("发送图片 {}:{}",nickName,filePath);
return sendPicMsgByUserId(toUserName, filePath, uniqueKey);
}
return false;
}
/**
* 根据群的NickName发送图片消息到群
* @param nickName
* @param filePath
* @param uniqueKey
* @return
*/
public static boolean sendGroupPicMsgByNickName(String nickName, String filePath, String uniqueKey) {
String toUserName = WechatTools.getGroupUserNameByNickName(nickName,uniqueKey);
if (toUserName != null) {
LOG.info("发送群图片 {}:{}",nickName,filePath);
return sendPicMsgByUserId(toUserName, filePath, uniqueKey);
}
return false;
}
@@ -218,14 +303,15 @@ public class MessageTools {
* @date 2017年5月7日 下午10:34:24
* @param userId
* @param filePath
* @param uniqueKey
* @return
*/
public static boolean sendPicMsgByUserId(String userId, String filePath) {
JSONObject responseObj = webWxUploadMedia(filePath);
public static boolean sendPicMsgByUserId(String userId, String filePath, String uniqueKey) {
JSONObject responseObj = webWxUploadMedia(filePath, uniqueKey);
if (responseObj != null) {
String mediaId = responseObj.getString("MediaId");
if (mediaId != null) {
return webWxSendMsgImg(userId, mediaId);
return webWxSendMsgImg(userId, mediaId, uniqueKey);
}
}
return false;
@@ -238,15 +324,19 @@ public class MessageTools {
* @date 2017年5月7日 下午10:38:55
* @return
*/
private static boolean webWxSendMsgImg(String userId, String mediaId) {
private static boolean webWxSendMsgImg(String userId, String mediaId, String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
if (!core.isAlive()){
return false;
}
String url = String.format("%s/webwxsendmsgimg?fun=async&f=json&pass_ticket=%s", core.getLoginInfo().get("url"),
core.getLoginInfo().get("pass_ticket"));
Map<String, Object> msgMap = new HashMap<String, Object>();
Map<String, Object> msgMap = new HashMap<String, Object>(8);
msgMap.put("Type", 3);
msgMap.put("MediaId", mediaId);
msgMap.put("FromUserName", core.getUserSelf().getString("UserName"));
msgMap.put("ToUserName", userId);
String clientMsgId = String.valueOf(new Date().getTime())
String clientMsgId = String.valueOf(System.currentTimeMillis())
+ String.valueOf(new Random().nextLong()).substring(1, 5);
msgMap.put("LocalID", clientMsgId);
msgMap.put("ClientMsgId", clientMsgId);
@@ -254,7 +344,7 @@ public class MessageTools {
paramMap.put("BaseRequest", core.getParamMap().get("BaseRequest"));
paramMap.put("Msg", msgMap);
String paramStr = JSON.toJSONString(paramMap);
HttpEntity entity = myHttpClient.doPost(url, paramStr);
HttpEntity entity = core.getMyHttpClient().doPost(url, paramStr);
if (entity != null) {
try {
String result = EntityUtils.toString(entity, Consts.UTF_8);
@@ -276,25 +366,34 @@ public class MessageTools {
* @param filePath
* @return
*/
public static boolean sendFileMsgByUserId(String userId, String filePath) {
private static boolean sendFileMsgByUserId(String userId, String filePath, String uniqueKey) {
String title = new File(filePath).getName();
Map<String, String> data = new HashMap<String, String>();
Map<String, String> data = new HashMap<String, String>(12);
data.put("appid", Config.API_WXAPPID);
data.put("title", title);
data.put("totallen", "");
data.put("attachid", "");
data.put("type", "6"); // APPMSGTYPE_ATTACH
data.put("fileext", title.split("\\.")[1]); // 文件后缀
JSONObject responseObj = webWxUploadMedia(filePath);
JSONObject responseObj = webWxUploadMedia(filePath, uniqueKey);
if (responseObj != null) {
data.put("totallen", responseObj.getString("StartPos"));
data.put("attachid", responseObj.getString("MediaId"));
} else {
LOG.error("sednFileMsgByUserId 错误: ", data);
}
return webWxSendAppMsg(userId, data);
return webWxSendAppMsg(userId, data, uniqueKey);
}
public static boolean sendFileMsgByNickNameApi(String nickName, String filePath, String uniqueKey, boolean isGroup){
if (isGroup){
return sendGroupFileMsgByNickName(nickName,filePath,uniqueKey);
}else {
return sendFileMsgByNickName(nickName,filePath,uniqueKey);
}
}
/**
* 根据用户昵称发送文件消息
*
@@ -304,10 +403,27 @@ public class MessageTools {
* @param filePath
* @return
*/
public static boolean sendFileMsgByNickName(String nickName, String filePath) {
String toUserName = WechatTools.getUserNameByNickName(nickName);
private static boolean sendFileMsgByNickName(String nickName, String filePath, String uniqueKey) {
String toUserName = WechatTools.getContactUserNameByNickName(nickName,uniqueKey);
if (toUserName != null) {
return sendFileMsgByUserId(toUserName, filePath);
LOG.info("发送文件 {}:{}",nickName,filePath);
return sendFileMsgByUserId(toUserName, filePath, uniqueKey);
}
return false;
}
/**
* 根据群昵称发送文件消息
* @param nickName
* @param filePath
* @param uniqueKey
* @return
*/
private static boolean sendGroupFileMsgByNickName(String nickName, String filePath, String uniqueKey) {
String toUserName = WechatTools.getGroupUserNameByNickName(nickName,uniqueKey);
if (toUserName != null) {
LOG.info("发送文件 {}:{}",nickName,filePath);
return sendFileMsgByUserId(toUserName, filePath, uniqueKey);
}
return false;
}
@@ -319,18 +435,23 @@ public class MessageTools {
* @date 2017年5月10日 上午12:21:28
* @param userId
* @param data
* @param uniqueKey
* @return
*/
private static boolean webWxSendAppMsg(String userId, Map<String, String> data) {
private static boolean webWxSendAppMsg(String userId, Map<String, String> data, String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
if (!core.isAlive()){
return false;
}
String url = String.format("%s/webwxsendappmsg?fun=async&f=json&pass_ticket=%s", core.getLoginInfo().get("url"),
core.getLoginInfo().get("pass_ticket"));
String clientMsgId = String.valueOf(new Date().getTime())
String clientMsgId = String.valueOf(System.currentTimeMillis())
+ String.valueOf(new Random().nextLong()).substring(1, 5);
String content = "<appmsg appid='wxeb7ec651dd0aefa9' sdkver=''><title>" + data.get("title")
+ "</title><des></des><action></action><type>6</type><content></content><url></url><lowurl></lowurl>"
+ "<appattach><totallen>" + data.get("totallen") + "</totallen><attachid>" + data.get("attachid")
+ "</attachid><fileext>" + data.get("fileext") + "</fileext></appattach><extinfo></extinfo></appmsg>";
Map<String, Object> msgMap = new HashMap<String, Object>();
Map<String, Object> msgMap = new HashMap<String, Object>(12);
msgMap.put("Type", data.get("type"));
msgMap.put("Content", content);
msgMap.put("FromUserName", core.getUserSelf().getString("UserName"));
@@ -350,7 +471,7 @@ public class MessageTools {
paramMap.put("Msg", msgMap);
paramMap.put("Scene", 0);
String paramStr = JSON.toJSONString(paramMap);
HttpEntity entity = myHttpClient.doPost(url, paramStr);
HttpEntity entity = core.getMyHttpClient().doPost(url, paramStr);
if (entity != null) {
try {
String result = EntityUtils.toString(entity, Consts.UTF_8);
@@ -370,7 +491,8 @@ public class MessageTools {
* @param accept
* true 接受 false 拒绝
*/
public static void addFriend(BaseMsg msg, boolean accept) {
private static void addFriend(BaseMsg msg, boolean accept, String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
if (!accept) { // 不添加
return;
}
@@ -407,7 +529,7 @@ public class MessageTools {
String result = null;
try {
String paramStr = JSON.toJSONString(body);
HttpEntity entity = myHttpClient.doPost(url, paramStr);
HttpEntity entity = core.getMyHttpClient().doPost(url, paramStr);
result = EntityUtils.toString(entity, Consts.UTF_8);
} catch (Exception e) {
LOG.error("webWxSendMsg", e);

View File

@@ -0,0 +1,352 @@
package org.ruoyi.common.wechat.itchat4j.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.ruoyi.common.wechat.itchat4j.core.Core;
import org.ruoyi.common.wechat.itchat4j.core.CoreManage;
import org.ruoyi.common.wechat.itchat4j.utils.LogInterface;
import org.ruoyi.common.wechat.itchat4j.utils.enums.StorageLoginInfoEnum;
import org.ruoyi.common.wechat.itchat4j.utils.enums.URLEnum;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 微信小工具,如获好友列表,根据昵称查找好友或群等
*
* @author https://github.com/yaphone
* @date 创建时间2017年5月4日 下午10:49:16
* @version 1.0
*
* @author WesleyOne 修改
*/
public class WechatTools implements LogInterface {
/**
* 返回好友昵称列表
* @param uniqueKey
* @return
*/
public static List<String> getContactNickNameList(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
List<String> contactNickNameList = new ArrayList<String>();
for (JSONObject o : core.getContactList()) {
contactNickNameList.add(o.getString("NickName"));
// 顺便刷下缓存
core.getUserInfoMap().put(o.getString("NickName"),o);
core.getUserInfoMap().put(o.getString("UserName"),o);
}
return contactNickNameList;
}
/**
* 返回好友完整信息列表
* @param uniqueKey
* @return
*/
public static List<JSONObject> getContactList(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
return core.getContactList();
}
/**
* 返回群列表
* @param uniqueKey
* @return
*/
public static List<JSONObject> getGroupList(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
return core.getGroupList();
}
/**
* 获取群NickName列表
* @param uniqueKey
* @return
*/
public static List<String> getGroupNickNameList(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
List<String> groupNickNameList = new ArrayList<String>();
for (JSONObject o : core.getGroupList()) {
groupNickNameList.add(o.getString("NickName"));
}
return groupNickNameList;
}
/**
* 获取群所有成员信息
* @param groupId
* @param uniqueKey
* @return
*/
public static JSONArray getGroupMemberByGroupId(String groupId, String uniqueKey){
Core core = CoreManage.getInstance(uniqueKey);
JSONObject jsonObject = core.getGroupInfoMap().get(groupId);
if (jsonObject == null){
return new JSONArray();
}
return jsonObject.getJSONArray("MemberList");
}
/**
* 通过群成员ID获取昵称
* @param groupId
* @param uniqueKey
* @param memberId
* @return
*/
public static String getMemberNickName(String groupId, String uniqueKey, String memberId){
JSONArray members = getGroupMemberByGroupId(groupId, uniqueKey);
int size = members.size();
if (size > 0){
for (int i=0;i<size;i++){
JSONObject jsonObject = members.getJSONObject(i);
if (memberId.equals(jsonObject.getString("UserName"))){
return jsonObject.getString("NickName");
}
}
}
return "";
}
/**
* 退出微信
*
* @author https://github.com/yaphone
* @date 2017年5月18日 下午11:56:54
*/
public static void logout(String uniqueKey) {
webWxLogout(uniqueKey);
}
private static boolean webWxLogout(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
String url = String.format(URLEnum.WEB_WX_LOGOUT.getUrl(),
core.getLoginInfo().get(StorageLoginInfoEnum.url.getKey()));
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
params.add(new BasicNameValuePair("redirect", "1"));
params.add(new BasicNameValuePair("type", "1"));
params.add(
new BasicNameValuePair("skey", (String) core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey())));
try {
HttpEntity entity = core.getMyHttpClient().doGet(url, params, false, null);
String text = EntityUtils.toString(entity, Consts.UTF_8);
return true;
} catch (Exception e) {
LOG.debug(e.getMessage());
} finally {
// 强制退出,提示相关线程退出
core.setAlive(false);
}
return false;
}
public static void setUserInfo(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
for (JSONObject o : core.getContactList()) {
core.getUserInfoMap().put(o.getString("NickName"), o);
core.getUserInfoMap().put(o.getString("UserName"), o);
}
}
/**
*
* 根据用户昵称设置备注名称
*
* @date 2017年5月27日 上午12:21:40
* @param nickName
* @param remName
*/
public static void remarkNameByNickName(String nickName, String remName, String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
String url = String.format(URLEnum.WEB_WX_REMARKNAME.getUrl(), core.getLoginInfo().get("url"),
core.getLoginInfo().get(StorageLoginInfoEnum.pass_ticket.getKey()));
Map<String, Object> msgMap = new HashMap<String, Object>(8);
Map<String, Object> msgMap_BaseRequest = new HashMap<String, Object>(8);
msgMap.put("CmdId", 2);
msgMap.put("RemarkName", remName);
msgMap.put("UserName", core.getUserInfoMap().get(nickName).get("UserName"));
msgMap_BaseRequest.put("Uin", core.getLoginInfo().get(StorageLoginInfoEnum.wxuin.getKey()));
msgMap_BaseRequest.put("Sid", core.getLoginInfo().get(StorageLoginInfoEnum.wxsid.getKey()));
msgMap_BaseRequest.put("Skey", core.getLoginInfo().get(StorageLoginInfoEnum.skey.getKey()));
msgMap_BaseRequest.put("DeviceID", core.getLoginInfo().get(StorageLoginInfoEnum.deviceid.getKey()));
msgMap.put("BaseRequest", msgMap_BaseRequest);
try {
String paramStr = JSON.toJSONString(msgMap);
HttpEntity entity = core.getMyHttpClient().doPost(url, paramStr);
// String result = EntityUtils.toString(entity, Consts.UTF_8);
LOG.info("修改备注" + remName);
} catch (Exception e) {
LOG.error("remarkNameByUserName", e);
}
}
/**
* 获取微信在线状态
*
* @date 2017年6月16日 上午12:47:46
* @return
*/
public static boolean getWechatStatus(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
return core.isAlive();
}
/**
*
* @param userName
* @param nickName
* @return
*/
private static JSONObject getContactByNickNameAndUserName(String userName, String nickName, String uniqueKey){
Core core = CoreManage.getInstance(uniqueKey);
// 通过userName查询
if (StringUtils.isNotEmpty(userName) && StringUtils.isEmpty(nickName)){
for (JSONObject contact:core.getContactList()){
if (userName.equals(contact.getString("UserName"))){
return contact;
}
}
}
// 通过群昵称查询
if (StringUtils.isNotEmpty(nickName) && StringUtils.isEmpty(userName)){
for (JSONObject contact:core.getContactList()){
if (nickName.equals(contact.getString("NickName"))){
return contact;
}
}
}
// 通过userName和昵称联合查
if (StringUtils.isNotEmpty(userName) && StringUtils.isNotEmpty(nickName)){
for (JSONObject contact:core.getContactList()){
if (nickName.equals(contact.getString("NickName")) && userName.equals(contact.getString("UserName"))){
return contact;
}
}
}
return null;
}
/**
* 通过群id查找群昵称
* @param userName
* @return
*/
public static String getContactNickNameByUserName(String userName, String uniqueKey){
JSONObject contact = getContactByNickNameAndUserName(userName,null, uniqueKey);
if (contact!=null && StringUtils.isNotEmpty(contact.getString("NickName"))){
return contact.getString("NickName");
}else{
return "";
}
}
/**
* 通过群昵称查找群id
* @param nickName
* @return
*/
public static String getContactUserNameByNickName(String nickName, String uniqueKey){
JSONObject contact = getContactByNickNameAndUserName(null,nickName,uniqueKey);
if (contact!=null && StringUtils.isNotEmpty(contact.getString("UserName"))){
return contact.getString("UserName");
}else{
return null;
}
}
/**
* 通过userName或昵称查找群信息
* @param userName
* @return
*/
private static JSONObject getGroupByNickNameAndUserName(String userName, String nickName, String uniqueKey){
Core core = CoreManage.getInstance(uniqueKey);
// 通过userName查询
if (StringUtils.isNotEmpty(userName) && StringUtils.isEmpty(nickName)){
for (JSONObject group:core.getGroupList()){
if (userName.equals(group.getString("UserName"))){
return group;
}
}
}
// 通过群昵称查询
if (StringUtils.isNotEmpty(nickName) && StringUtils.isEmpty(userName)){
for (JSONObject group:core.getGroupList()){
if (nickName.equals(group.getString("NickName"))){
return group;
}
}
}
// 通过userName和昵称联合查
if (StringUtils.isNotEmpty(userName) && StringUtils.isNotEmpty(nickName)){
for (JSONObject group:core.getGroupList()){
if (nickName.equals(group.getString("NickName")) && userName.equals(group.getString("UserName"))){
return group;
}
}
}
return null;
}
/**
* 通过群id查找群昵称
* @param userName
* @return
*/
public static String getGroupNickNameByUserName(String userName, String uniqueKey){
JSONObject group = getGroupByNickNameAndUserName(userName,null,uniqueKey);
if (group!=null && StringUtils.isNotEmpty(group.getString("NickName"))){
return group.getString("NickName");
}else{
return "";
}
}
/**
* 通过群昵称查找群id
* @param nickName
* @return
*/
public static String getGroupUserNameByNickName(String nickName, String uniqueKey){
JSONObject group = getGroupByNickNameAndUserName(null,nickName, uniqueKey);
if (group!=null && StringUtils.isNotEmpty(group.getString("UserName"))){
return group.getString("UserName");
}else{
return null;
}
}
/**
* 通过UserName查找NickName
* 只查群名和好友名
* @param userName
* @param uniqueKey
* @return
*/
public static String getNickNameByUserName(String userName, String uniqueKey){
if (userName.startsWith("@@")){
return getGroupNickNameByUserName(userName,uniqueKey);
}else if (userName.startsWith("@")){
return getContactNickNameByUserName(userName,uniqueKey);
}else {
return "";
}
}
}

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.beans;
package org.ruoyi.common.wechat.itchat4j.beans;
import java.io.Serializable;

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.beans;
package org.ruoyi.common.wechat.itchat4j.beans;
import java.io.Serializable;
@@ -46,10 +46,15 @@ public class BaseMsg implements Serializable {
private String mediaId;
private String content;
private String statusNotifyUserName;
private boolean atMe;
// 群发送者ID昵称
private String sendMemberId;
private String memberNickname;
/** 消息发送者ID **/
private String fromUserName;
private String oriContent;
private String fileSize;
private String fromNickName;
public int getSubMsgType() {
return subMsgType;
@@ -290,4 +295,36 @@ public class BaseMsg implements Serializable {
public void setFileSize(String fileSize) {
this.fileSize = fileSize;
}
public String getMemberNickname() {
return memberNickname;
}
public void setMemberNickname(String memberNickname) {
this.memberNickname = memberNickname;
}
public String getFromNickName() {
return fromNickName;
}
public void setFromNickName(String fromNickName) {
this.fromNickName = fromNickName;
}
public String getSendMemberId() {
return sendMemberId;
}
public void setSendMemberId(String sendMemberId) {
this.sendMemberId = sendMemberId;
}
public boolean isAtMe() {
return atMe;
}
public void setAtMe(boolean atMe) {
this.atMe = atMe;
}
}

View File

@@ -0,0 +1,28 @@
package org.ruoyi.common.wechat.itchat4j.beans;
/**
* @author WesleyOne
* @create 2018/12/21
*/
@Deprecated
public class BaseResponse {
private Integer Ret;
private String ErrMsg;
public Integer getRet() {
return Ret;
}
public void setRet(Integer ret) {
Ret = ret;
}
public String getErrMsg() {
return ErrMsg;
}
public void setErrMsg(String errMsg) {
ErrMsg = errMsg;
}
}

View File

@@ -0,0 +1,306 @@
package org.ruoyi.common.wechat.itchat4j.beans;
import java.util.List;
/**
* 成员信息对象
*
* 来自获取好友列表
* /cgi-bin/mmwebwx-bin/webwxgetcontact
* MemberList中单体
* @author WesleyOne
* @create 2018/12/21
*/
@Deprecated
public class Member {
private String Alias;
private Integer AppAccountFlag;
private Integer AttrStatus;
private Integer ChatRoomId;
private String City;
private Integer ContactFlag;
/**
* 群昵称
*/
private String DisplayName;
private String EncryChatRoomId;
private String HeadImgUrl;
private Integer HideInputBarFlag;
private Integer IsOwner;
private String KeyWord;
private Integer MemberCount;
private List<Member> MemberList;
private String NickName;
private Integer OwnerUin;
private String PYInitial;
private String PYQuanPin;
private String Province;
/**
* 备注名、首拼、全拼
*/
private String RemarkName;
private String RemarkPYInitial;
private String RemarkPYQuanPin;
private Integer Sex;
private String Signature;
private Integer SnsFlag;
private Integer StarFriend;
private Integer Statues;
private Integer Uin;
private Integer UniFriend;
private String UserName;
/**
* 用来判断是否是公众号或服务号的字段
*/
private String VerifyFlag;
public String getAlias() {
return Alias;
}
public void setAlias(String alias) {
Alias = alias;
}
public Integer getAppAccountFlag() {
return AppAccountFlag;
}
public void setAppAccountFlag(Integer appAccountFlag) {
AppAccountFlag = appAccountFlag;
}
public Integer getAttrStatus() {
return AttrStatus;
}
public void setAttrStatus(Integer attrStatus) {
AttrStatus = attrStatus;
}
public Integer getChatRoomId() {
return ChatRoomId;
}
public void setChatRoomId(Integer chatRoomId) {
ChatRoomId = chatRoomId;
}
public String getCity() {
return City;
}
public void setCity(String city) {
City = city;
}
public Integer getContactFlag() {
return ContactFlag;
}
public void setContactFlag(Integer contactFlag) {
ContactFlag = contactFlag;
}
public String getDisplayName() {
return DisplayName;
}
public void setDisplayName(String displayName) {
DisplayName = displayName;
}
public String getEncryChatRoomId() {
return EncryChatRoomId;
}
public void setEncryChatRoomId(String encryChatRoomId) {
EncryChatRoomId = encryChatRoomId;
}
public String getHeadImgUrl() {
return HeadImgUrl;
}
public void setHeadImgUrl(String headImgUrl) {
HeadImgUrl = headImgUrl;
}
public Integer getHideInputBarFlag() {
return HideInputBarFlag;
}
public void setHideInputBarFlag(Integer hideInputBarFlag) {
HideInputBarFlag = hideInputBarFlag;
}
public Integer getIsOwner() {
return IsOwner;
}
public void setIsOwner(Integer isOwner) {
IsOwner = isOwner;
}
public String getKeyWord() {
return KeyWord;
}
public void setKeyWord(String keyWord) {
KeyWord = keyWord;
}
public Integer getMemberCount() {
return MemberCount;
}
public void setMemberCount(Integer memberCount) {
MemberCount = memberCount;
}
public List<Member> getMemberList() {
return MemberList;
}
public void setMemberList(List<Member> memberList) {
MemberList = memberList;
}
public String getNickName() {
return NickName;
}
public void setNickName(String nickName) {
NickName = nickName;
}
public Integer getOwnerUin() {
return OwnerUin;
}
public void setOwnerUin(Integer ownerUin) {
OwnerUin = ownerUin;
}
public String getPYInitial() {
return PYInitial;
}
public void setPYInitial(String PYInitial) {
this.PYInitial = PYInitial;
}
public String getPYQuanPin() {
return PYQuanPin;
}
public void setPYQuanPin(String PYQuanPin) {
this.PYQuanPin = PYQuanPin;
}
public String getProvince() {
return Province;
}
public void setProvince(String province) {
Province = province;
}
public String getRemarkName() {
return RemarkName;
}
public void setRemarkName(String remarkName) {
RemarkName = remarkName;
}
public String getRemarkPYInitial() {
return RemarkPYInitial;
}
public void setRemarkPYInitial(String remarkPYInitial) {
RemarkPYInitial = remarkPYInitial;
}
public String getRemarkPYQuanPin() {
return RemarkPYQuanPin;
}
public void setRemarkPYQuanPin(String remarkPYQuanPin) {
RemarkPYQuanPin = remarkPYQuanPin;
}
public Integer getSex() {
return Sex;
}
public void setSex(Integer sex) {
Sex = sex;
}
public String getSignature() {
return Signature;
}
public void setSignature(String signature) {
Signature = signature;
}
public Integer getSnsFlag() {
return SnsFlag;
}
public void setSnsFlag(Integer snsFlag) {
SnsFlag = snsFlag;
}
public Integer getStarFriend() {
return StarFriend;
}
public void setStarFriend(Integer starFriend) {
StarFriend = starFriend;
}
public Integer getStatues() {
return Statues;
}
public void setStatues(Integer statues) {
Statues = statues;
}
public Integer getUin() {
return Uin;
}
public void setUin(Integer uin) {
Uin = uin;
}
public Integer getUniFriend() {
return UniFriend;
}
public void setUniFriend(Integer uniFriend) {
UniFriend = uniFriend;
}
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public String getVerifyFlag() {
return VerifyFlag;
}
public void setVerifyFlag(String verifyFlag) {
VerifyFlag = verifyFlag;
}
}

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.beans;
package org.ruoyi.common.wechat.itchat4j.beans;
import java.io.Serializable;

View File

@@ -0,0 +1,59 @@
package org.ruoyi.common.wechat.itchat4j.beans;
import org.ruoyi.common.wechat.itchat4j.utils.enums.SendMsgType;
import java.io.Serializable;
/**
* 发送消息体
* @author WesleyOne
* @create 2019/1/7
*/
public class SendMsg implements Serializable {
private String userName;
private String nickName;
private String message;
private SendMsgType msgType;
private boolean isGroup;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SendMsgType getMsgType() {
return msgType;
}
public void setMsgType(SendMsgType msgType) {
this.msgType = msgType;
}
public boolean isGroup() {
return isGroup;
}
public void setGroup(boolean group) {
isGroup = group;
}
}

View File

@@ -0,0 +1,52 @@
package org.ruoyi.common.wechat.itchat4j.beans;
import java.util.List;
/**
* @author WesleyOne
* @create 2018/12/21
*/
@Deprecated
public class SyncKey {
private Integer Count;
private List<KV> List;
public Integer getCount() {
return Count;
}
public void setCount(Integer count) {
Count = count;
}
public java.util.List<KV> getList() {
return List;
}
public void setList(java.util.List<KV> list) {
List = list;
}
class KV{
private Integer Key;
private Long Val;
public Integer getKey() {
return Key;
}
public void setKey(Integer key) {
Key = key;
}
public Long getVal() {
return Val;
}
public void setVal(Long val) {
Val = val;
}
}
}

View File

@@ -0,0 +1,54 @@
package org.ruoyi.common.wechat.itchat4j.beans;
/*
AppAccountFlag: 0
ContactFlag: 0
HeadImgFlag: 1
HeadImgUrl: "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=778915892&username=@7e6934104b3cf1f92dd11344c63a06833ae54bd43b34229b5cc472c4d05eba4a&skey=@crypt_a24169c_f4c07f70afe861da5e8a6e1947044b6e"
HideInputBarFlag: 0
NickName: "[衰]晓炜"
PYInitial: ""
PYQuanPin: ""
RemarkName: ""
RemarkPYInitial: ""
RemarkPYQuanPin: ""
Sex: 1
Signature: "人工智障"
SnsFlag: 49
StarFriend: 0
Uin: 902478981
UserName: "@7e6934104b3cf1f92dd11344c63a06833ae54bd43b34229b5cc472c4d05eba4a"
VerifyFlag: 0
WebWxPluginSwitch: 0
*/
/**
* @author WesleyOne
* @create 2018/12/21
*/
@Deprecated
public class User {
private String AppAccountFlag;
private String ContactFlag;
private String HeadImgFlag;
private String HeadImgUrl;
private String HideInputBarFlag;
private String NickName;
private String PYInitial;
private String PYQuanPin;
private String RemarkName;
private String RemarkPYInitial;
private String RemarkPYQuanPin;
private String Sex;
/**
* 签名
*/
private String Signature;
private String SnsFlag;
private String StarFriend;
private String Uin;
private String UserName;
private String VerifyFlag;
private String WebWxPluginSwitch;
}

View File

@@ -0,0 +1,43 @@
package org.ruoyi.common.wechat.itchat4j.beans;
import java.util.List;
/**
* @author WesleyOne
* @create 2018/12/21
*/
@Deprecated
public class WebWxInit {
private BaseResponse BaseResponse;
private String ChatSet;
private Long ClickReportInterval;
private Long ClientVersion;
private List<Member> ContactList;
private Integer Count;
private Integer GrayScale;
private Integer InviteStartCount;
/**
* 订阅号字段省略
* MPSubscribeMsgCount
* MPSubscribeMsgList
*/
private String SKey;
private SyncKey SyncKey;
private Long SystemTime;
private User User;
}

View File

@@ -0,0 +1,34 @@
package org.ruoyi.common.wechat.itchat4j.client;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.CookieStore;
import java.util.HashMap;
/**
* 多开请求类管理
* @author WesleyOne
* @create 2018/12/15
*/
public class HttpClientManage {
private static HashMap<String,SingleHttpClient> clientMap = new HashMap<>(32);
public static SingleHttpClient getInstance(String uniqueKey){
return getInstance(uniqueKey,null);
}
public static SingleHttpClient getInstance(String uniqueKey,CookieStore outCookieStore) {
if (StringUtils.isEmpty(uniqueKey)){
return null;
}
SingleHttpClient client;
// outCookieStore不为空时也重新构造,主要用于热登录
if (!clientMap.containsKey(uniqueKey) || clientMap.get(uniqueKey) == null || outCookieStore != null){
client = SingleHttpClient.getInstance(outCookieStore);
clientMap.put(uniqueKey, client);
}
return clientMap.get(uniqueKey);
}
}

View File

@@ -0,0 +1,187 @@
package org.ruoyi.common.wechat.itchat4j.client;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.ruoyi.common.wechat.itchat4j.utils.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author WesleyOne
* @create 2018/12/15
*/
public class SingleHttpClient {
private Logger logger = LoggerFactory.getLogger("UTILLOG");
private CloseableHttpClient httpClient ;
private CookieStore cookieStore;
private String uniqueKey;
public String getCookie(String name) {
List<Cookie> cookies = cookieStore.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equalsIgnoreCase(name)) {
return cookie.getValue();
}
}
return null;
}
private SingleHttpClient(CookieStore outCookieStore){
if (outCookieStore == null){
outCookieStore = new BasicCookieStore();
}
this.cookieStore = outCookieStore;
httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).setRetryHandler(new DefaultHttpRequestRetryHandler(0,false)).build();
}
private SingleHttpClient(){
this(null);
}
public static SingleHttpClient getInstance(CookieStore outCookieStore){
return new SingleHttpClient(outCookieStore);
}
/**
* 处理GET请求
*
* @author https://github.com/yaphone
* @date 2017年4月9日 下午7:06:19
* @param url
* @param params
* @return
*/
public HttpEntity doGet(String url, List<BasicNameValuePair> params, boolean redirect,
Map<String, String> headerMap) {
HttpEntity entity = null;
HttpGet httpGet = new HttpGet();
try {
if (params != null) {
String paramStr = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
httpGet = new HttpGet(url + "?" + paramStr);
// System.out.println(url + "?" + paramStr);
} else {
httpGet = new HttpGet(url);
}
if (!redirect) {
// 禁止重定向
httpGet.setConfig(RequestConfig.custom().setRedirectsEnabled(false).build());
}
httpGet.setHeader("User-Agent", Config.USER_AGENT);
if (headerMap != null) {
Set<Map.Entry<String, String>> entries = headerMap.entrySet();
for (Map.Entry<String, String> entry : entries) {
httpGet.setHeader(entry.getKey(), entry.getValue());
}
}
CloseableHttpResponse response = httpClient.execute(httpGet);
entity = response.getEntity();
} catch (ClientProtocolException e) {
logger.error(e.getMessage());
} catch (IOException e) {
logger.error(e.getMessage());
} catch (Exception e){
logger.error(e.getMessage());
}
return entity;
}
/**
* 处理POST请求
*
* @author https://github.com/yaphone
* @date 2017年4月9日 下午7:06:35
* @param url
* @param paramsStr
* @return
*/
public HttpEntity doPost(String url, String paramsStr) {
return doPost(url,paramsStr,null);
}
public HttpEntity doPost(String url, String paramsStr, Map<String, String> headerMap) {
HttpEntity entity = null;
HttpPost httpPost = new HttpPost();
try {
StringEntity params = new StringEntity(paramsStr, Consts.UTF_8);
httpPost = new HttpPost(url);
httpPost.setEntity(params);
httpPost.setHeader("Content-type", "application/json; charset=utf-8");
httpPost.setHeader("User-Agent", Config.USER_AGENT);
if (headerMap != null) {
Set<Map.Entry<String, String>> entries = headerMap.entrySet();
for (Map.Entry<String, String> entry : entries) {
httpPost.setHeader(entry.getKey(), entry.getValue());
}
}
CloseableHttpResponse response = httpClient.execute(httpPost);
entity = response.getEntity();
} catch (ClientProtocolException e) {
logger.error(e.getMessage());
} catch (IOException e) {
logger.error(e.getMessage());
} catch (Exception e){
logger.error(e.getMessage());
}
return entity;
}
/**
* 上传文件到服务器
*
* @author https://github.com/yaphone
* @date 2017年5月7日 下午9:19:23
* @param url
* @param reqEntity
* @return
*/
public HttpEntity doPostFile(String url, HttpEntity reqEntity) {
HttpEntity entity = null;
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("User-Agent", Config.USER_AGENT);
httpPost.setEntity(reqEntity);
try {
CloseableHttpResponse response = httpClient.execute(httpPost);
entity = response.getEntity();
} catch (Exception e) {
logger.error(e.getMessage());
}
return entity;
}
public CookieStore getCookieStore() {
return this.cookieStore;
}
public void setCookieStore(CookieStore cookieStore) {
this.cookieStore = cookieStore;
}
}

View File

@@ -0,0 +1,148 @@
package org.ruoyi.common.wechat.itchat4j.controller;
import org.ruoyi.common.wechat.itchat4j.core.Core;
import org.ruoyi.common.wechat.itchat4j.core.CoreManage;
import org.ruoyi.common.wechat.itchat4j.core.MsgCenter;
import org.ruoyi.common.wechat.itchat4j.service.ILoginService;
import org.ruoyi.common.wechat.itchat4j.service.impl.LoginServiceImpl;
import org.ruoyi.common.wechat.itchat4j.utils.LogInterface;
import org.ruoyi.common.wechat.itchat4j.utils.SleepUtils;
import org.ruoyi.common.wechat.itchat4j.utils.enums.URLEnum;
import org.ruoyi.common.wechat.web.base.BaseException;
/**
* 登陆控制器
*
* @author https://github.com/yaphone
* @date 创建时间2017年5月13日 下午12:56:07
* @version 1.0
*
* @author WesleyOne 修改
*/
public class LoginController implements LogInterface {
private ILoginService loginService;
private String uniqueKey;
private Core core;
public LoginController(String uniqueKey){
this.uniqueKey = uniqueKey;
this.loginService = new LoginServiceImpl(uniqueKey);
this.core = CoreManage.getInstance(uniqueKey);
}
/**
* 获取二维码地址
* 风险:已登录账号不可调用该接口,会移除当前core信息
* @return
*/
public String login_1() throws BaseException {
if (core.isAlive()) {
LOG.warn("微信已登陆");
throw new BaseException("微信已登陆");
}
LOG.info("1.获取微信UUID");
while (loginService.getUuid() == null) {
LOG.warn("1.1. 获取微信UUID失败一秒后重新获取");
SleepUtils.sleep(1000);
}
LOG.info("2. 获取登陆二维码图片");
return URLEnum.QRCODE_URL.getUrl() + core.getUuid();
}
/**
* 确认登录
* @return
*/
public boolean login_2(){
boolean result = false;
LOG.info("3. 请扫描二维码图片,并在手机上确认");
if (!core.isAlive()) {
if (loginService.login()){
core.setAlive(true);
LOG.info(("3.1登陆成功"));
result = true;
}
}
return result;
}
/**
* 加载数据
* @return
*/
public boolean login_3() {
boolean result = true;
LOG.info("4.微信初始化");
if (!loginService.webWxInit()) {
LOG.info("4.1 微信初始化异常");
result = false;
}
if (result){
LOG.info("5. 开启微信状态通知");
loginService.wxStatusNotify();
LOG.info(String.format("欢迎回来, %s", core.getNickName()));
LOG.info("6.+++开启消息发送线程["+uniqueKey+"]+++");
Thread sendThread = new Thread(core.getThreadGroup(), () -> MsgCenter.sendMsg(uniqueKey), "SEND-" + uniqueKey);
sendThread.start();
LOG.info("8. +++开始接收消息线程["+uniqueKey+"]+++");
loginService.startReceiving();
LOG.info("9. 获取联系人信息");
loginService.webWxGetContact();
LOG.info("10. 获取群好友及群好友列表及缓存");
loginService.WebWxBatchGetContact();
}
if (!result){
core.setAlive(false);
return false;
}
core.setFinishInit(true);
return true;
}
public boolean reboot(){
core.setFinishInit(false);
// 重新加载数据
boolean result = true;
LOG.info("1.刷新初始化信息");
if (!loginService.webWxInit()) {
LOG.info("1.1 微信初始化异常");
result = false;
}
if (result){
LOG.info("2. 刷新开启微信状态通知");
loginService.wxStatusNotify();
LOG.info("3. 刷新获取联系人信息");
loginService.webWxGetContact();
LOG.info("4. 刷新获取群好友及群好友列表");
loginService.WebWxBatchGetContact();
}
if (!result){
core.setAlive(false);
return false;
}
core.setFinishInit(true);
return true;
}
}

View File

@@ -0,0 +1,371 @@
package org.ruoyi.common.wechat.itchat4j.core;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import org.ruoyi.common.wechat.itchat4j.beans.BaseMsg;
import org.ruoyi.common.wechat.itchat4j.beans.SendMsg;
import org.ruoyi.common.wechat.itchat4j.beans.User;
import org.ruoyi.common.wechat.itchat4j.client.HttpClientManage;
import org.ruoyi.common.wechat.itchat4j.client.SingleHttpClient;
import org.ruoyi.common.wechat.itchat4j.service.impl.LoginServiceImpl;
import org.ruoyi.common.wechat.itchat4j.utils.enums.parameters.BaseParaEnum;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 核心存储类,全局只保存一份,单例模式
*
* @author https://github.com/yaphone
* @author WesleyOne 修改
* @version 1.0
* @date 创建时间2017年4月23日 下午2:33:56
*/
public class Core {
private Core() {
}
private Core(String uniqueKey) {
this.uniqueKey = uniqueKey;
this.myHttpClient = HttpClientManage.getInstance(this.uniqueKey);
this.threadGroup = new ThreadGroup(this.uniqueKey);
}
protected static Core getInstance(String uniqueKey) {
return new Core(uniqueKey);
}
private String uniqueKey;
boolean alive = false;
/**
* 管理当前机器人的所有业务线程
*/
@JSONField(serialize = false)
private ThreadGroup threadGroup;
@JSONField(serialize = false)
boolean isFinishInit = false;
/**
* login,webWxInit
* 登录接口获取
*/
private String indexUrl;
private String userName;
private String nickName;
String uuid = null;
/**
* webWxInit
* InviteStartCount
* SyncKey
* synckey 随着每次获取最新消息后的返回值更新,其目的在于每次同步消息后记录一个当前同步的状态
*/
Map<String, Object> loginInfo = new HashMap<String, Object>();
/**
* webWxInit
* 登陆账号自身信息
*
* @see User
*/
private JSONObject userSelf;
/**
* 初始化/cgi-bin/mmwebwx-bin/webwxinit
* 最后一次收到正常retcode的时间秒为单位
* <p>
* synccheck刷新
*/
private long lastNormalRetcodeTime;
/**
* synccheck和webWxSync容错次数,超过退出
*/
int receivingRetryCount = 5;
@JSONField(serialize = false)
SingleHttpClient myHttpClient;
public SingleHttpClient getMyHttpClient() {
return HttpClientManage.getInstance(uniqueKey);
}
/**
* 初始话时获取联系人时创建
* @see LoginServiceImpl#webWxGetContact()
*/
/**
* memberList长度
*/
@JSONField(serialize = false)
private int memberCount = 0;
/**
* 好友+群聊+公众号+特殊账号
* 注意:不主动插入,获取时通过其他几个账号集合合并
*/
@JSONField(serialize = false)
private List<JSONObject> memberList = new ArrayList<JSONObject>();
/**
* 好友
*/
@JSONField(serialize = false)
private List<JSONObject> contactList = new ArrayList<JSONObject>();
/**
* 群
*/
@JSONField(serialize = false)
private List<JSONObject> groupList = new ArrayList<JSONObject>();
/**
* 公众号/服务号
*/
@Deprecated
@JSONField(serialize = false)
private List<JSONObject> publicUsersList = new ArrayList<JSONObject>();
/**
* 特殊账号
*/
@JSONField(serialize = false)
private List<JSONObject> specialUsersList = new ArrayList<JSONObject>();
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
/**
* synccheck和webWxSynct添加
* 异步接受消息存储
*/
@JSONField(serialize = false)
private List<BaseMsg> msgList = new ArrayList<>();
/**
* 异步发送消息存储
*/
@JSONField(serialize = false)
private List<SendMsg> sendList = new ArrayList();
/********************************
* 缓存字段,用于快速查找
********************************/
/**
* 微信昵称不能超过16位而ID比较长干脆用一个Map
* 群ID或昵称,群信息
* 注意:存在相同昵称会后者覆盖前者
* <p>
* WebWxBatchGetContact之后可以通过
* .getJSONArray("MemberList")获取群成员列表
*/
@JSONField(serialize = false)
private Map<String, JSONObject> groupInfoMap = new HashMap<>(1024);
/**
* 微信昵称不能超过16位而ID比较长干脆用一个Map
* 玩家ID或昵称玩家信息
* 注意:存在相同昵称会后者覆盖前者
*/
@JSONField(serialize = false)
private Map<String, JSONObject> userInfoMap = new HashMap<>(1024);
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
/**
* 请求参数
*/
@JSONField(serialize = false)
public Map<String, Object> getParamMap() {
return new HashMap<String, Object>(1) {
/**
*
*/
private static final long serialVersionUID = 1L;
{
Map<String, String> map = new HashMap<>(16);
for (BaseParaEnum baseRequest : BaseParaEnum.values()) {
map.put(baseRequest.para(), getLoginInfo().get(baseRequest.value()).toString());
}
put("BaseRequest", map);
}
};
}
public String getUniqueKey() {
return uniqueKey;
}
public void setUniqueKey(String uniqueKey) {
this.uniqueKey = uniqueKey;
}
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
if (!alive) {
this.isFinishInit = false;
}
}
public String getIndexUrl() {
return indexUrl;
}
public void setIndexUrl(String indexUrl) {
this.indexUrl = indexUrl;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public Map<String, Object> getLoginInfo() {
return loginInfo;
}
public void setLoginInfo(Map<String, Object> loginInfo) {
this.loginInfo = loginInfo;
}
public JSONObject getUserSelf() {
return userSelf;
}
public void setUserSelf(JSONObject userSelf) {
this.userSelf = userSelf;
}
public long getLastNormalRetcodeTime() {
return lastNormalRetcodeTime;
}
public void setLastNormalRetcodeTime(long lastNormalRetcodeTime) {
this.lastNormalRetcodeTime = lastNormalRetcodeTime;
}
public int getReceivingRetryCount() {
return receivingRetryCount;
}
public void setReceivingRetryCount(int receivingRetryCount) {
this.receivingRetryCount = receivingRetryCount;
}
public int getMemberCount() {
return getContactList().size() + getGroupList().size() + getPublicUsersList().size() + getSpecialUsersList().size();
}
public List<JSONObject> getMemberList() {
List<JSONObject> memberList = new ArrayList<>();
memberList.addAll(this.getContactList());
memberList.addAll(this.getGroupList());
memberList.addAll(this.getPublicUsersList());
memberList.addAll(this.getSpecialUsersList());
return memberList;
}
public List<JSONObject> getContactList() {
return contactList;
}
public void setContactList(List<JSONObject> contactList) {
this.contactList = contactList;
}
public List<JSONObject> getGroupList() {
return groupList;
}
public void setGroupList(List<JSONObject> groupList) {
this.groupList = groupList;
}
public List<JSONObject> getPublicUsersList() {
return publicUsersList;
}
public void setPublicUsersList(List<JSONObject> publicUsersList) {
this.publicUsersList = publicUsersList;
}
public List<JSONObject> getSpecialUsersList() {
return specialUsersList;
}
public void setSpecialUsersList(List<JSONObject> specialUsersList) {
this.specialUsersList = specialUsersList;
}
public List<BaseMsg> getMsgList() {
return msgList;
}
public void setMsgList(List<BaseMsg> msgList) {
this.msgList = msgList;
}
public Map<String, JSONObject> getGroupInfoMap() {
return groupInfoMap;
}
public void setGroupInfoMap(Map<String, JSONObject> groupInfoMap) {
this.groupInfoMap = groupInfoMap;
}
public Map<String, JSONObject> getUserInfoMap() {
return userInfoMap;
}
public void setUserInfoMap(Map<String, JSONObject> userInfoMap) {
this.userInfoMap = userInfoMap;
}
public boolean isFinishInit() {
return isFinishInit;
}
public void setFinishInit(boolean finishInit) {
isFinishInit = finishInit;
}
public ThreadGroup getThreadGroup() {
return threadGroup;
}
public void setThreadGroup(ThreadGroup threadGroup) {
this.threadGroup = threadGroup;
}
public List<SendMsg> getSendList() {
return sendList;
}
}

View File

@@ -0,0 +1,323 @@
package org.ruoyi.common.wechat.itchat4j.core;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.ruoyi.common.wechat.itchat4j.beans.SendMsg;
import org.ruoyi.common.wechat.itchat4j.client.HttpClientManage;
import org.ruoyi.common.wechat.itchat4j.controller.LoginController;
import org.ruoyi.common.wechat.itchat4j.utils.LogInterface;
import org.ruoyi.common.wechat.itchat4j.utils.enums.SendMsgType;
import org.ruoyi.common.wechat.itchat4j.utils.tools.CommonTools;
import java.io.*;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
/**
* 多开管理
*
* @author WesleyOne
* @create 2018/12/13
*/
public class CoreManage implements LogInterface {
static int MAX_CORE_NUM = 50;
private static HashMap<String, Core> coreMap = new HashMap<>(MAX_CORE_NUM / 3 * 4 + 1);
// 是否热加载
public static boolean USE_HOT_RELOAD = false;
public static String HOT_RELOAD_DIR = "/Users/wesley/output/hotreload/wxwobot.hot";
public static Core getInstance(String uniqueKey) {
if (StringUtils.isEmpty(uniqueKey)) {
return null;
}
Core core;
if (!coreMap.containsKey(uniqueKey) || coreMap.get(uniqueKey) == null) {
core = Core.getInstance(uniqueKey);
coreMap.put(uniqueKey, core);
}
return coreMap.get(uniqueKey);
}
/**
* 移除
*
* @param uniqueKey
*/
public static void remove(String uniqueKey) {
if (coreMap.containsKey(uniqueKey)) {
coreMap.remove(uniqueKey);
}
}
/**
* 查询是否在线
*
* @param uniqueKey
* @return
*/
public static boolean isActive(String uniqueKey) {
if (StringUtils.isNotEmpty(uniqueKey) && coreMap.containsKey(uniqueKey) && coreMap.get(uniqueKey).isAlive()) {
return true;
}
return false;
}
/**
* 持久化
*/
public static void persistence() {
// 格式化数据
Collection<Core> valueCollection = coreMap.values();
int size = valueCollection.size();
// 没有数据不操作
if (size <= 0) {
return;
}
LOG.info("登录数据持久化中");
Iterator<Core> iterator = valueCollection.iterator();
JSONArray jsonArray = new JSONArray();
while (iterator.hasNext()) {
Core core = iterator.next();
if (core.isAlive()) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("core", core);
jsonObject.put("cookies", core.getMyHttpClient().getCookieStore().getCookies());
jsonArray.add(jsonObject);
}
}
try {
File file = new File(HOT_RELOAD_DIR);
if (!file.exists()) {
file.createNewFile();
}
// 每次覆盖
FileWriter fileWritter = new FileWriter(HOT_RELOAD_DIR, false);
fileWritter.write(jsonArray.toJSONString());
fileWritter.close();
LOG.info("登录数据持久化完成");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 启动加载持久化文件
*/
public static void reload() {
if (USE_HOT_RELOAD) {
File file = new File(HOT_RELOAD_DIR);
if (file.exists()) {
LOG.info("登录数据热加载中");
StringBuilder stringBuilder = new StringBuilder();
try {
FileReader fr = new FileReader(HOT_RELOAD_DIR);
BufferedReader bf = new BufferedReader(fr);
String str;
// 按行读取字符串
while ((str = bf.readLine()) != null) {
stringBuilder.append(str);
}
bf.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
String result = stringBuilder.toString();
if (StringUtils.isEmpty(result)) {
return;
}
JSONArray jsonArray = JSONArray.parseArray(result);
int size = jsonArray.size();
if (size > 0) {
// 封装成线程操作
for (int i = 0; i < size; i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
ReloadThread reloadThread = new ReloadThread(jsonObject);
Thread thread = new Thread(reloadThread);
thread.start();
}
}
LOG.info("登录数据热加载完成");
}
}
}
private static class ReloadThread implements Runnable {
private JSONObject reloadObject;
public ReloadThread(JSONObject object) {
this.reloadObject = object;
}
@Override
public void run() {
Core core = null;
try {
/**
* 初始化Core,
* 1.获取登入的状态信息并装入CoreManage
* 2.构建ThreadGroup
* 3.获取Cookies并装入HttpClientManage
* 4.获取信息及启动线程
*/
JSONObject jsonObject = this.reloadObject;
core = jsonObject.getObject("core", Core.class);
String uniqueKey = core.getUniqueKey();
if (core.isAlive()) {
core.setThreadGroup(new ThreadGroup(uniqueKey));
coreMap.put(uniqueKey, core);
JSONArray cookiesJsonArray = jsonObject.getJSONArray("cookies");
int arraySize = cookiesJsonArray.size();
if (arraySize <= 0) {
return;
}
// 装载原cookie信息,json解析cookie异常干脆手动封装
BasicCookieStore cookieStore = new BasicCookieStore();
for (int ci = 0; ci < arraySize; ci++) {
JSONObject cookieJson = cookiesJsonArray.getJSONObject(ci);
String name = cookieJson.getString("name");
String value = cookieJson.getString("value");
String domain = cookieJson.getString("domain");
String path = cookieJson.getString("path");
Boolean persistent = cookieJson.getBoolean("persistent");
Boolean secure = cookieJson.getBoolean("secure");
Long expiryDate = cookieJson.getLong("expiryDate");
Integer version = cookieJson.getInteger("version");
BasicClientCookie cookie = new BasicClientCookie(name, value);
cookie.setDomain(domain);
cookie.setPath(path);
cookie.setSecure(secure);
cookie.setExpiryDate(new Date(expiryDate));
cookie.setVersion(version);
cookieStore.addCookie(cookie);
}
// 必须在构建client时就放入cookie
HttpClientManage.getInstance(uniqueKey, cookieStore);
//装载core信息及启动线程
LoginController login = new LoginController(uniqueKey);
if (!login.login_3()) {
// 加载失败退出
core.setAlive(false);
return;
}
LOG.info("热登录成功: {}", uniqueKey);
}
} catch (Exception e) {
e.printStackTrace();
if (core != null) {
core.setAlive(false);
core = null;
}
}
}
}
/**
* 存放新的群,昵称emoji处理
*
* @param core
* @param jsonObject
*/
public static void addNewGroup(Core core, JSONObject jsonObject) {
String userName = jsonObject.getString("UserName");
CommonTools.emojiFormatter2(jsonObject, "NickName");
// 删除重复的
core.getGroupList().removeIf(group -> userName.equals(group.getString("UserName")));
core.getGroupList().add(jsonObject);
core.getGroupInfoMap().put(jsonObject.getString("NickName"), jsonObject);
core.getGroupInfoMap().put(userName, jsonObject);
}
/**
* 存放新的联系人,昵称emoji处理
*
* @param core
* @param jsonObject
*/
public static void addNewContact(Core core, JSONObject jsonObject) {
String userName = jsonObject.getString("UserName");
CommonTools.emojiFormatter2(jsonObject, "NickName");
// 删除重复的
core.getContactList().removeIf(contact -> userName.equals(contact.getString("UserName")));
core.getContactList().add(jsonObject);
core.getUserInfoMap().put(jsonObject.getString("NickName"), jsonObject);
core.getUserInfoMap().put(userName, jsonObject);
}
/**
* 消息统一加到队列里处理1
* 用于已知UserName
*
* @param uniqueKey
* @param toUserName
* @param data
* @param type
*/
public static void addSendMsg4UserName(String uniqueKey, String toUserName, String data, SendMsgType type) {
if (StringUtils.isEmpty(uniqueKey) || StringUtils.isEmpty(toUserName) || StringUtils.isEmpty(data) || type == null) {
LOG.error("消息参数不完整 uk:{} un: {} data: {} ", uniqueKey, toUserName, data);
return;
}
SendMsg sendMsg = new SendMsg();
sendMsg.setUserName(toUserName);
sendMsg.setMessage(data);
sendMsg.setMsgType(type);
boolean isGroup = true;
if (toUserName != null && !toUserName.startsWith("@@")) {
isGroup = false;
}
sendMsg.setGroup(isGroup);
CoreManage.getInstance(uniqueKey).getSendList().add(sendMsg);
}
/**
* 消息统一加到队列里处理2
* 用于已知NickName
*
* @param uniqueKey
* @param toNickName
* @param data
* @param type
* @param isGroup
*/
public static void addSendMsg4NickName(String uniqueKey, String toNickName, String data, SendMsgType type, Boolean isGroup) {
if (StringUtils.isEmpty(uniqueKey) || StringUtils.isEmpty(toNickName) || StringUtils.isEmpty(data) || type == null) {
LOG.error("消息参数不完整 uk:{} nn: {} data: {} ", uniqueKey, toNickName, data);
return;
}
SendMsg sendMsg = new SendMsg();
sendMsg.setNickName(toNickName);
sendMsg.setMessage(data);
sendMsg.setMsgType(type);
sendMsg.setGroup(isGroup);
CoreManage.getInstance(uniqueKey).getSendList().add(sendMsg);
}
}

View File

@@ -0,0 +1,273 @@
package org.ruoyi.common.wechat.itchat4j.core;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.ruoyi.common.wechat.itchat4j.api.MessageTools;
import org.ruoyi.common.wechat.itchat4j.api.WechatTools;
import org.ruoyi.common.wechat.itchat4j.beans.BaseMsg;
import org.ruoyi.common.wechat.itchat4j.beans.SendMsg;
import org.ruoyi.common.wechat.itchat4j.face.IMsgHandlerFace;
import org.ruoyi.common.wechat.itchat4j.utils.LogInterface;
import org.ruoyi.common.wechat.itchat4j.utils.MoreConfig;
import org.ruoyi.common.wechat.itchat4j.utils.enums.MsgCodeEnum;
import org.ruoyi.common.wechat.itchat4j.utils.enums.MsgTypeEnum;
import org.ruoyi.common.wechat.itchat4j.utils.enums.SendMsgType;
import org.ruoyi.common.wechat.itchat4j.utils.tools.CommonTools;
import java.util.ArrayList;
import java.util.List;
/**
* 消息处理中心
*
* @author https://github.com/yaphone
* @author WesleyOne 修改
* @version 1.0
* @date 创建时间2017年5月14日 下午12:47:50
*/
public class MsgCenter implements LogInterface {
/**
* 接收消息,放入队列
*
* @param msgList
* @return
* @author https://github.com/yaphone
* @date 2017年4月23日 下午2:30:48
*/
public static JSONArray produceMsg(JSONArray msgList, String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
JSONArray result = new JSONArray();
// 用于暂存未知群ID,最后调用webwxbatchgetcontact获取
List<String> unknowGroup = new ArrayList<>();
for (int i = 0; i < msgList.size(); i++) {
JSONObject m = msgList.getJSONObject(i);
// 是否是群消息
boolean isGroupMsg = false;
boolean isAtMe = false;
if (m.getString("FromUserName").contains("@@") || m.getString("ToUserName").contains("@@")) {
// 群聊消息
isGroupMsg = true;
if (m.getString("FromUserName").contains("@@")
&& !core.getGroupInfoMap().containsKey(m.getString("FromUserName"))) {
unknowGroup.add(m.getString("FromUserName"));
} else if (m.getString("ToUserName").contains("@@")
&& !core.getGroupInfoMap().containsKey(m.getString("ToUserName"))) {
unknowGroup.add(m.getString("ToUserName"));
}
// 群消息与普通消息不同的是在其消息体Content中会包含发送者id及":<br/>"消息,这里需要处理一下,去掉多余信息,只保留消息内容
String splitCode = ":<br/>";
if (m.getString("Content").contains(splitCode)) {
String source = m.getString("Content");
String content = source.substring(source.indexOf(splitCode) + splitCode.length());
String sendMemberId = source.substring(0, source.indexOf(splitCode));
m.put("Content", content);
m.put(MoreConfig.SEND_MEMBER_ID, sendMemberId);
if (content.contains("@" + core.getNickName())) {
isAtMe = true;
}
}
}
m.put("groupMsg", isGroupMsg);
m.put("atMe", isAtMe);
// 1.文本消息
if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_TEXT.getCode())) {
if (m.getString("Url").length() != 0) {
// 1.1分享位置 不处理
continue;
// String[] contents = m.getString("Content").split(":");
// String data = "Map";
// if (contents.length>0) {
// data = contents[0]+":"+m.getString("Url");
// }
// m.put("Type", MsgTypeEnum.MAP.getType());
// m.put("Text", data);
// LOG.warn("MAP_CONTENT: {},URL: {}",m.getString("Content"),m.getString("Url"));
/**
* MAP_CONTENT: 滨兴小区(东区):/cgi-bin/mmwebwx-bin/webwxgetpubliclinkimg?url=xxx&msgid=7525662842661720095&pictype=location,URL: http://apis.map.qq.com/uri/v1/geocoder?coord=30.191660,120.200508
*/
} else {
// 1.2 普通文本
m.put("Type", MsgTypeEnum.TEXT.getType());
CommonTools.emojiFormatter2(m, "Content");
m.put("Text", m.getString("Content"));
}
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_IMAGE.getCode())
|| m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_EMOTICON.getCode())) {
// 2.图片消息 不处理
continue;
// m.put("Type", MsgTypeEnum.PIC.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VOICE.getCode())) {
// 3.语音消息 不处理
continue;
// m.put("Type", MsgTypeEnum.VOICE.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VERIFYMSG.getCode())) {
// 4.好友确认消息 不处理
continue;
// MessageTools.addFriend(core, userName, 3, ticket); // 确认添加好友
// m.put("Type", MsgTypeEnum.VERIFYMSG.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_SHARECARD.getCode())) {
// 5.共享名片 不处理
// m.put("Type", MsgTypeEnum.NAMECARD.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_VIDEO.getCode())
|| m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_MICROVIDEO.getCode())) {
// 6.视频 不处理
continue;
// m.put("Type", MsgTypeEnum.VIEDO.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_MEDIA.getCode())) {
// 7.分享链接 不处理
continue;
// m.put("Type", MsgTypeEnum.MEDIA.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_STATUSNOTIFY.getCode())) {
// 微信初始化消息 系统
m.put("Type", MsgTypeEnum.SYS.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_SYS.getCode())) {
// 系统消息 系统
m.put("Type", MsgTypeEnum.SYS.getType());
} else if (m.getInteger("MsgType").equals(MsgCodeEnum.MSGTYPE_RECALLED.getCode())) {
// 撤回消息 系统 不处理
continue;
// m.put("Type", MsgTypeEnum.SYS.getType());
} else {
LOG.error("Useless msg: {} \n {}", m.getInteger("MsgType"), m.getString("Content"));
}
/**
* 日志
* 显示收到的消息
*/
String nickName;
String memberName = "";
if (m.getBoolean("groupMsg")) {
nickName = WechatTools.getGroupNickNameByUserName(m.getString("FromUserName"), uniqueKey);
if (m.getString(MoreConfig.SEND_MEMBER_ID) != null) {
// 获取成员昵称
memberName = WechatTools.getMemberNickName(m.getString("FromUserName"), uniqueKey, m.getString(MoreConfig.SEND_MEMBER_ID));
m.put(MoreConfig.SEND_MEMBER_NICKNAMW, memberName);
}
} else {
nickName = WechatTools.getContactNickNameByUserName(m.getString("FromUserName"), uniqueKey);
}
m.put("fromNickName", nickName);
LOG.info("收到【{}】=>【{}】消息,来自: {} 内容:\n{} ",
MsgCodeEnum.fromCode(m.getInteger("MsgType")) == null ? "未知类型" + m.getInteger("MsgType") : MsgCodeEnum.fromCode(m.getInteger("MsgType")).getType(),
m.getString("Type"),
nickName + " : " + memberName,
StringUtils.isNotEmpty(m.getString("Content")) ? m.getString("Content") : "");
result.add(m);
}
return result;
}
/**
* 微信接收消息处理
*
* @param uniqueKey
* @author https://github.com/yaphone
* @date 2017年5月14日 上午10:52:34
*/
public static void handleMsg(String uniqueKey, IMsgHandlerFace msgHandler) {
Core core = CoreManage.getInstance(uniqueKey);
while (true) {
if (!core.isAlive()) {
LOG.info("停止消息处理");
break;
}
if (core.getMsgList().size() > 0 && core.getMsgList().get(0).getContent() != null) {
if (core.getMsgList().get(0).getContent().length() > 0) {
BaseMsg msg = core.getMsgList().get(0);
if (msg.getType() != null) {
try {
if (msg.getType().equals(MsgTypeEnum.TEXT.getType())) {
msgHandler.textMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.PIC.getType())) {
msgHandler.picMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.VOICE.getType())) {
msgHandler.voiceMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.VIEDO.getType())) {
msgHandler.videoMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.NAMECARD.getType())) {
msgHandler.nameCardMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.SYS.getType())) {
msgHandler.sysMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.VERIFYMSG.getType())) {
msgHandler.verifyAddFriendMsgHandle(msg);
} else if (msg.getType().equals(MsgTypeEnum.MEDIA.getType())) {
msgHandler.mediaMsgHandle(msg);
} else {
LOG.warn("暂未处理信息【{}】", msg.getType());
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
}
core.getMsgList().remove(0);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
LOG.error("消息处理中断");
break;
}
}
}
/**
* 统一发送消息
*
* @param uniqueKey
*/
public static void sendMsg(String uniqueKey) {
Core core = CoreManage.getInstance(uniqueKey);
while (true) {
if (core == null || !core.isAlive()) {
LOG.info("停止消息发送");
break;
}
if (CollectionUtil.isNotEmpty(core.getSendList())) {
SendMsg sendMsg = core.getSendList().get(0);
try {
String userName = sendMsg.getUserName();
String nickName = sendMsg.getNickName();
String message = sendMsg.getMessage();
boolean isGroup = sendMsg.isGroup();
SendMsgType msgType = sendMsg.getMsgType();
if (StringUtils.isNotEmpty(message) && msgType != null) {
if (StringUtils.isNotEmpty(userName)) {
MessageTools.send(userName, uniqueKey, message, msgType.toValue());
} else if (StringUtils.isNotEmpty(nickName)) {
MessageTools.sendByNickName(nickName, uniqueKey, message, msgType.toValue(), isGroup);
} else {
LOG.error("无效发送消息: {}", JSONObject.toJSONString(sendMsg));
}
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
core.getSendList().remove(0);
}
try {
// 控制发送频率
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
LOG.error("消息发送中断");
break;
}
}
}
}

View File

@@ -1,6 +1,6 @@
package com.xmzs.common.wechat.face;
package org.ruoyi.common.wechat.itchat4j.face;
import com.xmzs.common.wechat.beans.BaseMsg;
import org.ruoyi.common.wechat.itchat4j.beans.BaseMsg;
/**
* 消息处理接口
@@ -9,8 +9,10 @@ import com.xmzs.common.wechat.beans.BaseMsg;
* @date 创建时间2017年4月20日 上午12:13:49
* @version 1.0
*
* @author WesleyOne 修改
*/
public interface IMsgHandlerFace {
/**
*
* @author https://github.com/yaphone
@@ -18,7 +20,7 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public String textMsgHandle(BaseMsg msg);
void textMsgHandle(BaseMsg msg);
/**
* 处理图片消息
@@ -28,7 +30,7 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public String picMsgHandle(BaseMsg msg);
void picMsgHandle(BaseMsg msg);
/**
* 处理声音消息
@@ -38,7 +40,7 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public String voiceMsgHandle(BaseMsg msg);
void voiceMsgHandle(BaseMsg msg);
/**
* 处理小视频消息
@@ -48,7 +50,7 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public String viedoMsgHandle(BaseMsg msg);
void videoMsgHandle(BaseMsg msg);
/**
* 处理名片消息
@@ -58,7 +60,7 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public String nameCardMsgHandle(BaseMsg msg);
void nameCardMsgHandle(BaseMsg msg);
/**
* 处理系统消息
@@ -68,7 +70,7 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public void sysMsgHandle(BaseMsg msg);
void sysMsgHandle(BaseMsg msg);
/**
* 处理确认添加好友消息
@@ -77,7 +79,7 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public String verifyAddFriendMsgHandle(BaseMsg msg);
void verifyAddFriendMsgHandle(BaseMsg msg);
/**
* 处理收到的文件消息
@@ -86,6 +88,6 @@ public interface IMsgHandlerFace {
* @param msg
* @return
*/
public String mediaMsgHandle(BaseMsg msg);
void mediaMsgHandle(BaseMsg msg);
}

View File

@@ -1,4 +1,6 @@
package com.xmzs.common.wechat.service;
package org.ruoyi.common.wechat.itchat4j.service;
/**
* 登陆服务接口
@@ -7,6 +9,7 @@ package com.xmzs.common.wechat.service;
* @date 创建时间2017年5月13日 上午12:07:21
* @version 1.0
*
* @author WesleyOne 修改
*/
public interface ILoginService {
@@ -24,19 +27,19 @@ public interface ILoginService {
*
* @author https://github.com/yaphone
* @date 2017年5月13日 上午12:21:40
* @param qrPath
* @return
*/
String getUuid();
/**
* 获取二维码图片
*
* (直接获取图片链接,不下载文件)
* @author https://github.com/yaphone
* @date 2017年5月13日 上午12:13:51
* @param qrPath
* @return
*/
@Deprecated
boolean getQR(String qrPath);
/**

View File

@@ -1,13 +1,12 @@
package com.xmzs.common.wechat.utils;
package org.ruoyi.common.wechat.itchat4j.utils;
import com.xmzs.common.wechat.utils.enums.OsNameEnum;
import org.ruoyi.common.wechat.itchat4j.utils.enums.OsNameEnum;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 配置信息
*
@@ -20,20 +19,18 @@ public class Config {
public static final String API_WXAPPID = "API_WXAPPID";
public static final String picDir = "D://itchat4j";
public static final String VERSION = "1.4.1";
public static final String picDir = "D://org.ruoyi.common.wechat";
public static final String VERSION = "1.2.18";
public static final String BASE_URL = "https://login.weixin.qq.com";
public static final String REFERER = "https://wx.qq.com/?&lang=zh_CN&target=t";
public static final String OS = "";
public static final String DIR = "";
public static final String DEFAULT_QR = "QR.jpg";
public static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36";
public static final String UOS_PATCH_CLIENT_VERSION = "2.0.0";
public static final String UOS_PATCH_EXTSPAM =
"Go8FCIkFEokFCggwMDAwMDAwMRAGGvAESySibk50w5Wb3uTl2c2h64jVVrV7gNs06GFlWplHQbY/5FfiO++1yH4ykCyNPWKXmco+wfQzK5R98D3so7rJ5LmGFvBLjGceleySrc3SOf2Pc1gVehzJgODeS0lDL3/I/0S2SSE98YgKleq6Uqx6ndTy9yaL9qFxJL7eiA/R3SEfTaW1SBoSITIu+EEkXff+Pv8NHOk7N57rcGk1w0ZzRrQDkXTOXFN2iHYIzAAZPIOY45Lsh+A4slpgnDiaOvRtlQYCt97nmPLuTipOJ8Qc5pM7ZsOsAPPrCQL7nK0I7aPrFDF0q4ziUUKettzW8MrAaiVfmbD1/VkmLNVqqZVvBCtRblXb5FHmtS8FxnqCzYP4WFvz3T0TcrOqwLX1M/DQvcHaGGw0B0y4bZMs7lVScGBFxMj3vbFi2SRKbKhaitxHfYHAOAa0X7/MSS0RNAjdwoyGHeOepXOKY+h3iHeqCvgOH6LOifdHf/1aaZNwSkGotYnYScW8Yx63LnSwba7+hESrtPa/huRmB9KWvMCKbDThL/nne14hnL277EDCSocPu3rOSYjuB9gKSOdVmWsj9Dxb/iZIe+S6AiG29Esm+/eUacSba0k8wn5HhHg9d4tIcixrxveflc8vi2/wNQGVFNsGO6tB5WF0xf/plngOvQ1/ivGV/C1Qpdhzznh0ExAVJ6dwzNg7qIEBaw+BzTJTUuRcPk92Sn6QDn2Pu3mpONaEumacjW4w6ipPnPw+g2TfywJjeEcpSZaP4Q3YV5HG8D6UjWA4GSkBKculWpdCMadx0usMomsSS/74QgpYqcPkmamB4nVv1JxczYITIqItIKjD35IGKAUwAA==";
/**
* 仅仅用于参考
*/
@Deprecated
public static final ArrayList<String> API_SPECIAL_USER = new ArrayList<String>(Arrays.asList("filehelper", "weibo",
"qqmail", "fmessage", "tmessage", "qmessage", "qqsync", "floatbottle", "lbsapp", "shakeapp", "medianote",
"qqfriend", "readerapp", "blogapp", "facebookapp", "masssendapp", "meishiapp", "feedsapp", "voip",

View File

@@ -0,0 +1,13 @@
package org.ruoyi.common.wechat.itchat4j.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 公共日志接口
* @author WesleyOne
* @create 2018/12/12
*/
public interface LogInterface {
public final Logger LOG = LoggerFactory.getLogger("WXROBLOG");
}

View File

@@ -0,0 +1,12 @@
package org.ruoyi.common.wechat.itchat4j.utils;
/**
* @author WesleyOne
* @create 2018/12/19
*/
public class MoreConfig {
//存储群聊成员ID的键标识
public static final String SEND_MEMBER_ID = "sendMemberId";
public static final String SEND_MEMBER_NICKNAMW = "memberNickname";
}

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.utils;
package org.ruoyi.common.wechat.itchat4j.utils;
/**
* Created by xiaoxiaomo on 2017/5/6.

View File

@@ -0,0 +1,64 @@
package org.ruoyi.common.wechat.itchat4j.utils.enums;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/**
* 消息类型
*
* @author https://github.com/yaphone
* @date 创建时间2017年4月23日 下午12:15:00
* @version 1.0
*
*/
public enum MsgCodeEnum {
MSGTYPE_TEXT(1, "文本消息"),
MSGTYPE_IMAGE(3, "图片消息"),
MSGTYPE_VOICE(34, "语音消息"),
MSGTYPE_VERIFYMSG(37, "好友请求"),
MSGTYPE_POSSIBLEFRIEND_MSG(40, "POSSIBLEFRIEND_MSG"),
MSGTYPE_SHARECARD(42, "分享名片"),
MSGTYPE_VIDEO(43, "视频消息"),
MSGTYPE_EMOTICON(47, "表情消息"),
MSGTYPE_LOCATION(48, "位置消息"),
MSGTYPE_MEDIA(49, "分享链接"),
MSGTYPE_VOIPMSG(50, "VOIPMSG"),
MSGTYPE_STATUSNOTIFY(51, "状态通知"),
MSGTYPE_VOIPNOTIFY(52, "VOIPNOTIFY"),
MSGTYPE_VOIPINVITE(53, "VOIPINVITE"),
MSGTYPE_MICROVIDEO(62, "短视频消息"),
MSGTYPE_SYSNOTICE(9999, "SYSNOTICE"),
MSGTYPE_SYS(10000, "系统消息"),
MSGTYPE_RECALLED(10002, "撤回消息")
;
private static final Map<Integer, MsgCodeEnum> lookup = new HashMap<>();
static {
for (MsgCodeEnum s : EnumSet.allOf(MsgCodeEnum.class)){
lookup.put(s.getCode(), s);
}
}
public static MsgCodeEnum fromCode(int code) {
return lookup.get(code);
}
private int code;
private String type;
MsgCodeEnum(int code, String type) {
this.code = code;
this.type = type;
}
public int getCode() {
return code;
}
public String getType() {
return type;
}
}

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.utils.enums;
package org.ruoyi.common.wechat.itchat4j.utils.enums;
/**
@@ -11,12 +11,15 @@ package com.xmzs.common.wechat.utils.enums;
*/
public enum MsgTypeEnum {
TEXT("Text", "文本消息"),
MAP("MAP", "地理位置"),
PIC("Pic", "图片消息"),
VOICE("Voice", "语音消息"),
VIEDO("Viedo", "小视频消息"),
NAMECARD("NameCard", "名片消息"),
SYS("Sys", "系统消息"),
VERIFYMSG("VerifyMsg", "添加好友"),
// 地址分享
MEDIA("app", "文件消息");
private String type;

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.utils.enums;
package org.ruoyi.common.wechat.itchat4j.utils.enums;
/**
* 系统平台

View File

@@ -0,0 +1,25 @@
package org.ruoyi.common.wechat.itchat4j.utils.enums;
import lombok.Getter;
/**
* 返回结构枚举类
* <p>
* Created by xiaoxiaomo on 2017/5/6.
*/
@Getter
public enum ResultEnum {
SUCCESS("200", "成功"),
WAIT_CONFIRM("201", "请在手机上点击确认"),
WAIT_SCAN("400", "请扫描二维码");
private final String code;
private final String msg;
ResultEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,49 @@
package org.ruoyi.common.wechat.itchat4j.utils.enums;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
public enum RetCodeEnum {
UNKOWN("9999", "未知"),
SUCCESS("0", "成功"),
TICKET_ERROR("-14", "ticket错误"),
PARAM_ERROR("1", "传入参数错误"),
NOT_LOGIN_WARN("1100", "未登录提示"),
NOT_LOGIN_CHECK("1101", "未检测到登录"),
COOKIE_INVALID_ERROR("1102", "cookie值无效"),
LOGIN_ENV_ERROR("1203", "当前登录环境异常为了安全起见请不要在web端进行登录"),
TOO_OFEN("1205", "操作频繁")
;
private static final Map<String, RetCodeEnum> lookup = new HashMap<String, RetCodeEnum>();
static {
for (RetCodeEnum s : EnumSet.allOf(RetCodeEnum.class)){
lookup.put(s.getCode(), s);
}
}
public static RetCodeEnum fromCode(String code) {
return lookup.get(code);
}
private String code;
private String type;
RetCodeEnum(String code, String type) {
this.code = code;
this.type = type;
}
public String getCode() {
return code;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,48 @@
package org.ruoyi.common.wechat.itchat4j.utils.enums;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/**
* @author WesleyOne
* @create 2018/12/21
*/
public enum SelectorEnum {
UNKOWN("9999", "未知"),
NORMAL("0", "正常"),
NEW_MSG("2", "有新消息"),
SELECTOR_3("3", "访问频繁#"),
MOD_CONTACT("4", "有人修改了自己的昵称或你修改了别人的备注"),
ADD_OR_DEL_CONTACT("6", "存在删除或者新增的好友信息"),
ENTER_OR_LEAVE_CHAT("7", "进入或离开聊天界面");
private static final Map<String, SelectorEnum> lookup = new HashMap<>();
static {
for (SelectorEnum s : EnumSet.allOf(SelectorEnum.class)) {
lookup.put(s.getCode(), s);
}
}
public static SelectorEnum fromCode(String code) {
return lookup.get(code);
}
private String code;
private String type;
SelectorEnum(String code, String type) {
this.code = code;
this.type = type;
}
public String getCode() {
return code;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,65 @@
package org.ruoyi.common.wechat.itchat4j.utils.enums;
import com.jfinal.plugin.activerecord.Record;
import java.util.*;
/**
* 发送类型
* @author WesleyOne
* @create 2018/12/14
*/
public enum SendMsgType {
IMG("IMG","图片"),
FILE("FILE","文件"),
TEXT("TEXT","纯文本")
;
private String value;
private String name;
SendMsgType(String value, String name) {
this.value = value;
this.name = name;
}
private static final Map<String, SendMsgType> lookup = new HashMap<>();
public static List<Record> LIST_KV = new ArrayList<>();
static {
for (SendMsgType s : EnumSet.allOf(SendMsgType.class)){
lookup.put(s.toValue(), s);
LIST_KV.add(new Record().set("v",s.toValue()).set("n",s.toName()));
}
}
/**
* 获取枚举的值(整数值、字符串值等)
* @return
*/
public String toValue() {
return this.value;
}
public String toName() {
return this.name;
}
/**
* 根据值(整数值、字符串值等)获取相应的枚举类型
* @param value
* @return
*/
public static SendMsgType fromValue(String value) {
return lookup.get(value);
}
public boolean equal(SendMsgType type){
if (type != null && this.toValue().equals(type.toValue())){
return true;
}
return false;
}
}

View File

@@ -1,11 +1,8 @@
package com.xmzs.common.wechat.utils.enums;
package org.ruoyi.common.wechat.itchat4j.utils.enums;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.Map;
/**
* Created by xiaoxiaomo on 2017/5/7.
*/
@@ -15,8 +12,8 @@ public enum StorageLoginInfoEnum {
url("url",new String()),
fileUrl("fileUrl",new String()),
syncUrl("syncUrl",new String()),
deviceid("deviceid",new String()), //生成15位随机数
//生成15位随机数
deviceid("deviceid",new String()),
//baseRequest
skey("skey",new String()),
@@ -25,7 +22,8 @@ public enum StorageLoginInfoEnum {
pass_ticket("pass_ticket",new String()),
InviteStartCount("InviteStartCount",0),
InviteStartCount("InviteStartCount",new Integer(0)),
// 登录用户登录时信息
User("User",new JSONObject()),
SyncKey("SyncKey",new JSONObject()),
synckey("synckey",new String()),

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.utils.enums;
package org.ruoyi.common.wechat.itchat4j.utils.enums;
/**
* URL
@@ -15,7 +15,7 @@ public enum URLEnum {
LOGIN_URL(BASE_URL.url+"/cgi-bin/mmwebwx-bin/login","登陆URL"),
INIT_URL("%s/webwxinit?r=%s&pass_ticket=%s","初始化URL"),
SYNC_CHECK_URL("/synccheck","检查心跳URL"),
WEB_WX_SYNC_URL("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s","web微信消息同步URL"),
WEB_WX_SYNC_URL("%s/webwxsync?sid=%s&skey=%s&pass_ticket=%s&lang=zh_CN","web微信消息同步URL"),
WEB_WX_GET_CONTACT("%s/webwxgetcontact","web微信获取联系人信息URL"),
WEB_WX_SEND_MSG("%s/webwxsendmsg","发送消息URL"),
WEB_WX_UPLOAD_MEDIA("%s/webwxuploadmedia?f=json", "上传文件到服务器"),

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.utils.enums;
package org.ruoyi.common.wechat.itchat4j.utils.enums;
/**
* 确认添加好友Enum

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.utils.enums.parameters;
package org.ruoyi.common.wechat.itchat4j.utils.enums.parameters;
/**
*

View File

@@ -1,4 +1,4 @@
package com.xmzs.common.wechat.utils.enums.parameters;
package org.ruoyi.common.wechat.itchat4j.utils.enums.parameters;
/**
* 登陆

Some files were not shown because too many files have changed in this diff Show More