├── README.md ├── assert ├── code0.png ├── console1.png ├── demo1.png └── wechat4j.jar └── wechat4j-common ├── .classpath ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── dependency-reduced-pom.xml ├── pom.xml ├── src └── main │ ├── java │ └── com │ │ └── iyuexian │ │ └── wechat4j │ │ ├── WechatStartup.java │ │ ├── bean │ │ ├── BaseRequest.java │ │ ├── ChatRoom.java │ │ ├── ChatRoomMember.java │ │ ├── ContactUser.java │ │ ├── GroupMember.java │ │ └── Msg.java │ │ ├── config │ │ ├── Constant.java │ │ ├── Enums.java │ │ └── MsgType.java │ │ ├── core │ │ ├── WechatApiUtil.java │ │ └── WechatMeta.java │ │ ├── demo │ │ └── Demo1.java │ │ ├── exception │ │ └── WechatException.java │ │ ├── plugin │ │ ├── ContactManager.java │ │ ├── ContactUserUtil.java │ │ ├── FileHandler.java │ │ ├── FriendAddTask.java │ │ ├── MessageListener.java │ │ ├── QRCodeWindow.java │ │ ├── QrUtil.java │ │ ├── Storage.java │ │ ├── Task.java │ │ ├── TulingRobot.java │ │ ├── TxtMessageRobot.java │ │ ├── WxLocalCache.java │ │ ├── message │ │ │ ├── AbstractMessageHandler.java │ │ │ ├── IMessageHandler.java │ │ │ ├── MessageManager.java │ │ │ ├── MpMessageHandler.java │ │ │ ├── PictureMessageHandler.java │ │ │ ├── TxtMessageHandler.java │ │ │ ├── VideoMessageHandler.java │ │ │ └── VoiceMessageHandler.java │ │ └── storage │ │ │ ├── FilePipeLine.java │ │ │ ├── MessagePipeLine.java │ │ │ └── PipeLineManager.java │ │ └── util │ │ ├── Converter.java │ │ ├── CookieUtil.java │ │ ├── DigestUtils.java │ │ ├── Emptys.java │ │ ├── FileUploadHelper.java │ │ ├── FileUtil.java │ │ ├── HttpClient.java │ │ ├── IOKit.java │ │ ├── Matchers.java │ │ ├── PropertyReader.java │ │ └── TulingUtil.java │ └── resources │ ├── config.properties │ ├── log4j.properties │ └── logging.properties └── target ├── classes ├── .gitignore ├── META-INF │ ├── MANIFEST.MF │ └── maven │ │ └── com.iyuexian.wechat4j │ │ └── wechat4j-common │ │ ├── pom.properties │ │ └── pom.xml ├── com │ └── iyuexian │ │ └── wechat4j │ │ ├── WechatStartup$1.class │ │ ├── WechatStartup.class │ │ ├── bean │ │ ├── BaseRequest.class │ │ ├── ChatRoom.class │ │ ├── ChatRoomMember.class │ │ ├── ContactUser.class │ │ ├── GroupMember.class │ │ └── Msg.class │ │ ├── config │ │ ├── Constant.class │ │ ├── Enums$FileType.class │ │ ├── Enums$MsgType.class │ │ ├── Enums$OS.class │ │ └── Enums.class │ │ ├── core │ │ ├── WechatApiUtil.class │ │ └── WechatMeta.class │ │ ├── demo │ │ └── Demo1.class │ │ ├── exception │ │ └── WechatException.class │ │ ├── plugin │ │ ├── ContactManager.class │ │ ├── ContactUserUtil.class │ │ ├── FileHandler.class │ │ ├── FriendAddTask.class │ │ ├── MessageListener.class │ │ ├── QRCodeWindow$1.class │ │ ├── QRCodeWindow.class │ │ ├── QrUtil.class │ │ ├── Storage.class │ │ ├── Task$1.class │ │ ├── Task.class │ │ ├── TulingRobot$InputText.class │ │ ├── TulingRobot$Location.class │ │ ├── TulingRobot$UserInfo.class │ │ ├── TulingRobot.class │ │ ├── TxtMessageRobot.class │ │ ├── WxLocalCache$CacheItem.class │ │ ├── WxLocalCache$Holder.class │ │ ├── WxLocalCache.class │ │ ├── message │ │ │ ├── AbstractMessageHandler.class │ │ │ ├── IMessageHandler.class │ │ │ ├── MessageManager.class │ │ │ ├── MpMessageHandler.class │ │ │ ├── PictureMessageHandler.class │ │ │ ├── TxtMessageHandler.class │ │ │ ├── VideoMessageHandler.class │ │ │ └── VoiceMessageHandler.class │ │ └── storage │ │ │ ├── FilePipeLine.class │ │ │ ├── MessagePipeLine.class │ │ │ ├── PipeLineManager$Holder.class │ │ │ └── PipeLineManager.class │ │ └── util │ │ ├── Converter.class │ │ ├── CookieUtil.class │ │ ├── DigestUtils.class │ │ ├── Emptys$NullPlaceholder.class │ │ ├── Emptys.class │ │ ├── FileUploadHelper.class │ │ ├── FileUtil.class │ │ ├── HttpClient.class │ │ ├── IOKit.class │ │ ├── Matchers.class │ │ ├── PropertyReader.class │ │ └── TulingUtil.class ├── config.properties ├── log4j.properties └── logging.properties ├── maven-archiver └── pom.properties ├── maven-status └── maven-compiler-plugin │ ├── compile │ └── default-compile │ │ ├── createdFiles.lst │ │ └── inputFiles.lst │ └── testCompile │ └── default-testCompile │ └── inputFiles.lst ├── original-wechat4j.jar ├── wechat4j-common-0.0.1-SNAPSHOT-shaded.jar └── wechat4j.jar /README.md: -------------------------------------------------------------------------------- 1 | # wechat4j 2 | 用java实现的微信客户端,支持自动聊天, 消息监听,自动回复,添加好友,获取群成员列表,自动记录聊天记录,自动下载图片,语音,视频消息 3 | 4 | QQ交流群:580889921 5 | 6 | 7 | # 启动方式 8 | ### 1:控制台启动 9 | 自定任意类,在main方法下用WecahtStartup.login()实现扫码登陆 10 | ``` 11 | WechatMeta meta = WechatStartup.login(); 12 | ``` 13 | 登陆成功后,会返回WechatMeta实例,里面包含了当前扫码用户的登陆信息,后面所有的功能都需要该实例 14 | WechatApiUtil类封装微信的相关接口,具体功能实现在plugin及其实子包里,您也可以在这基础上扩展 15 | 16 | 17 | 18 | ### 下载jar包体验 19 | [wechat4j.jar](https://github.com/hexiangtao/wechat4j/blob/master/assert/wechat4j.jar) 20 | 21 | #### 运行方式 22 | ```` 23 | java -jar wechat4j.jar 24 | ```` 25 | 26 | 27 | 启动后控制台如下: 28 | ![demo](https://github.com/hexiangtao/wechat4j/blob/master/assert/console1.png) 29 | 30 | 31 | #### 代码示例 32 | ![demo](https://github.com/hexiangtao/wechat4j/blob/master/assert/code0.png) 33 | 34 | 35 | 36 | #### 运行示例图 37 | ![demo](https://github.com/hexiangtao/wechat4j/blob/master/assert/demo1.png) 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /assert/code0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/assert/code0.png -------------------------------------------------------------------------------- /assert/console1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/assert/console1.png -------------------------------------------------------------------------------- /assert/demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/assert/demo1.png -------------------------------------------------------------------------------- /assert/wechat4j.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/assert/wechat4j.jar -------------------------------------------------------------------------------- /wechat4j-common/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /wechat4j-common/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | wechat4j-common 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /wechat4j-common/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /wechat4j-common/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.methodParameters=generate 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.8 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 13 | org.eclipse.jdt.core.compiler.source=1.8 14 | -------------------------------------------------------------------------------- /wechat4j-common/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /wechat4j-common/dependency-reduced-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.iyuexian.wechat4j 5 | wechat4j-common 6 | wechat4j Maven Webapp 7 | 0.0.1-SNAPSHOT 8 | http://maven.apache.org 9 | 10 | compile 11 | wechat4j 12 | 13 | 14 | maven-shade-plugin 15 | 16 | 17 | package 18 | 19 | shade 20 | 21 | 22 | 23 | 24 | com.iyuexian.wechat4j.demo.Demo1 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | maven-compiler-plugin 33 | 34 | 1.8 35 | 1.8 36 | 37 | -parameters 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | junit 46 | junit 47 | 3.8.1 48 | test 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /wechat4j-common/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.iyuexian.wechat4j 5 | wechat4j-common 6 | jar 7 | 0.0.1-SNAPSHOT 8 | wechat4j Maven Webapp 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 3.8.1 15 | test 16 | 17 | 18 | com.bladejava 19 | blade-kit 20 | 1.3.4 21 | 22 | 23 | org.slf4j 24 | slf4j-log4j12 25 | 1.7.21 26 | 27 | 28 | com.alibaba 29 | fastjson 30 | 1.2.44 31 | 32 | 33 | commons-io 34 | commons-io 35 | 2.7 36 | 37 | 38 | mysql 39 | mysql-connector-java 40 | 8.0.16 41 | 42 | 43 | org.sql2o 44 | sql2o 45 | 1.6.0-RC3 46 | 47 | 48 | 49 | com.qiniu 50 | qiniu-java-sdk 51 | 7.0.2 52 | 53 | 54 | 55 | 56 | wechat4j 57 | 58 | 59 | org.apache.maven.plugins 60 | maven-shade-plugin 61 | 62 | 63 | package 64 | 65 | shade 66 | 67 | 68 | 69 | 70 | com.iyuexian.wechat4j.demo.Demo1 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-compiler-plugin 80 | 81 | 1.8 82 | 1.8 83 | 84 | -parameters 85 | 86 | 87 | 88 | 89 | compile 90 | 91 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/WechatStartup.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j; 2 | 3 | import java.awt.EventQueue; 4 | 5 | import javax.swing.UIManager; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import com.blade.kit.json.JSONArray; 11 | import com.blade.kit.json.JSONObject; 12 | import com.iyuexian.wechat4j.config.Constant; 13 | import com.iyuexian.wechat4j.core.WechatApiUtil; 14 | import com.iyuexian.wechat4j.core.WechatMeta; 15 | import com.iyuexian.wechat4j.exception.WechatException; 16 | import com.iyuexian.wechat4j.plugin.QRCodeWindow; 17 | import com.iyuexian.wechat4j.plugin.WxLocalCache; 18 | import com.iyuexian.wechat4j.util.Matchers; 19 | 20 | public class WechatStartup { 21 | 22 | protected Logger logger = LoggerFactory.getLogger(WechatStartup.class); 23 | private QRCodeWindow qrCodeFrame; 24 | private WechatMeta meta; 25 | 26 | private WechatStartup() { 27 | System.setProperty("https.protocols", "TLSv1"); 28 | System.setProperty("jsse.enableSNIExtension", "false"); 29 | } 30 | 31 | public static WechatMeta login() { 32 | try { 33 | WechatStartup instance = new WechatStartup(); 34 | instance.doLogin(); 35 | return instance.meta; 36 | } catch (Exception ex) { 37 | ex.printStackTrace(); 38 | } 39 | return null; 40 | 41 | } 42 | 43 | private void doLogin() throws Exception { 44 | String uuid = WechatApiUtil.getUUID(); 45 | showQrCode(uuid); 46 | 47 | while (true) { 48 | 49 | String res = WechatApiUtil.waitLogin(0, uuid); 50 | String code = Matchers.match("window.code=(\\d+);", res); 51 | 52 | if (!Constant.HTTP_OK.equals(code)) { 53 | Thread.sleep(2000); 54 | continue; 55 | } 56 | closeQrWindow(); 57 | WechatMeta meta = WechatApiUtil.newWechatMeta(res); 58 | WechatApiUtil.login(meta); 59 | JSONObject wxInitObj = WechatApiUtil.wxInit(meta); 60 | WechatApiUtil.openStatusNotify(meta); 61 | this.meta = meta; 62 | JSONArray contactList = wxInitObj.get("ContactList").asArray(); 63 | WxLocalCache.init(this.meta).setLatestContactList(contactList); 64 | break; 65 | } 66 | } 67 | 68 | private void showQrCode(String uuid) throws WechatException { 69 | 70 | final String path = WechatApiUtil.getQrCode(uuid); 71 | EventQueue.invokeLater(new Runnable() { 72 | public void run() { 73 | try { 74 | UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); 75 | qrCodeFrame = new QRCodeWindow(path); 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | } 80 | }); 81 | 82 | } 83 | 84 | private void closeQrWindow() { 85 | qrCodeFrame.dispose(); 86 | } 87 | 88 | public WechatMeta getMeta() { 89 | return meta; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/bean/BaseRequest.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.bean; 2 | 3 | public class BaseRequest { 4 | 5 | private String Uin; 6 | private String Sid = ""; 7 | private String Skey = ""; 8 | private String DeviceID = ""; 9 | 10 | public String getUin() { 11 | return Uin; 12 | } 13 | 14 | public String getSid() { 15 | return Sid; 16 | } 17 | 18 | public String getSkey() { 19 | return Skey; 20 | } 21 | 22 | public String getDeviceID() { 23 | return DeviceID; 24 | } 25 | 26 | public void setUin(String uin) { 27 | Uin = uin; 28 | } 29 | 30 | public void setSid(String sid) { 31 | Sid = sid; 32 | } 33 | 34 | public void setSkey(String skey) { 35 | Skey = skey; 36 | } 37 | 38 | public void setDeviceID(String deviceID) { 39 | DeviceID = deviceID; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/bean/ChatRoom.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.bean; 2 | 3 | import java.util.List; 4 | 5 | import com.blade.kit.json.JSONObject; 6 | 7 | public class ChatRoom { 8 | 9 | private int Uin; 10 | private String UserName; 11 | private String NickName; 12 | private String HeadImgUrl; 13 | private int ContactFlag; 14 | private int MemberCount; 15 | private List MemberList; 16 | 17 | public ChatRoom() { 18 | } 19 | 20 | public static ChatRoom parseFromJSON(JSONObject data) { 21 | ChatRoom chatroom = new ChatRoom(); 22 | chatroom.Uin = data.getInt("Uin"); 23 | chatroom.UserName = data.getString("UserName"); 24 | chatroom.NickName = data.getString("NickName"); 25 | chatroom.HeadImgUrl = data.getString("HeadImgUrl"); 26 | chatroom.ContactFlag = data.getInt("ContactFlag"); 27 | chatroom.MemberCount = data.getInt("MemberCount"); 28 | return chatroom; 29 | } 30 | 31 | public ChatRoom(int uin, String userName, String nickName, String headImgUrl, int contactFlag, int memberCount) { 32 | super(); 33 | Uin = uin; 34 | UserName = userName; 35 | NickName = nickName; 36 | HeadImgUrl = headImgUrl; 37 | ContactFlag = contactFlag; 38 | MemberCount = memberCount; 39 | } 40 | 41 | public int getUin() { 42 | return Uin; 43 | } 44 | 45 | public String getUserName() { 46 | return UserName; 47 | } 48 | 49 | public String getNickName() { 50 | return NickName; 51 | } 52 | 53 | public String getHeadImgUrl() { 54 | return HeadImgUrl; 55 | } 56 | 57 | public int getContactFlag() { 58 | return ContactFlag; 59 | } 60 | 61 | public int getMemberCount() { 62 | return MemberCount; 63 | } 64 | 65 | public List getMemberList() { 66 | return MemberList; 67 | } 68 | 69 | public void setUin(int uin) { 70 | Uin = uin; 71 | } 72 | 73 | public void setUserName(String userName) { 74 | UserName = userName; 75 | } 76 | 77 | public void setNickName(String nickName) { 78 | NickName = nickName; 79 | } 80 | 81 | public void setHeadImgUrl(String headImgUrl) { 82 | HeadImgUrl = headImgUrl; 83 | } 84 | 85 | public void setContactFlag(int contactFlag) { 86 | ContactFlag = contactFlag; 87 | } 88 | 89 | public void setMemberCount(int memberCount) { 90 | MemberCount = memberCount; 91 | } 92 | 93 | public void setMemberList(List memberList) { 94 | MemberList = memberList; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/bean/ChatRoomMember.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.bean; 2 | 3 | import com.blade.kit.json.JSONObject; 4 | 5 | public class ChatRoomMember { 6 | 7 | private Integer Uin; 8 | private String UserName; 9 | private String NickName; 10 | private String AttrStatus; 11 | private String PYInitial; 12 | private String PYQuanPin; 13 | private String RemarkPYInitial; 14 | private String RemarkPYQuanPin; 15 | private Integer MemberStatus; // 0 16 | private String DisplayName; 17 | private String KeyWord; 18 | 19 | public ChatRoomMember() { 20 | } 21 | 22 | public ChatRoomMember(Integer uin, String userName, String nickName, String attrStatus, String pYInitial, String pYQuanPin, String remarkPYInitial, 23 | String remarkPYQuanPin, Integer memberStatus, String displayName, String keyWord) { 24 | this.Uin = uin; 25 | this.UserName = userName; 26 | this.NickName = nickName; 27 | this.AttrStatus = attrStatus; 28 | this.PYInitial = pYInitial; 29 | this.PYQuanPin = pYQuanPin; 30 | this.RemarkPYInitial = remarkPYInitial; 31 | this.RemarkPYQuanPin = remarkPYQuanPin; 32 | this.MemberStatus = memberStatus; 33 | this.DisplayName = displayName; 34 | this.KeyWord = keyWord; 35 | } 36 | 37 | public ChatRoomMember(JSONObject item) { 38 | this.Uin = item.getInt("Uin"); 39 | this.UserName = item.getString("UserName"); 40 | this.NickName = item.getString("NickName"); 41 | this.AttrStatus = item.get("AttrStatus").toString(); 42 | this.PYInitial = item.getString("PYInitial"); 43 | this.PYQuanPin = item.getString("PYQuanPin"); 44 | this.RemarkPYInitial = item.getString("RemarkPYInitial"); 45 | this.RemarkPYQuanPin = item.getString("RemarkPYQuanPin"); 46 | this.MemberStatus = item.getInt("MemberStatus"); 47 | this.DisplayName = item.getString("DisplayName"); 48 | this.KeyWord = item.getString("KeyWord"); 49 | } 50 | 51 | public Integer getUin() { 52 | return Uin; 53 | } 54 | 55 | public String getUserName() { 56 | return UserName; 57 | } 58 | 59 | public String getNickName() { 60 | return NickName; 61 | } 62 | 63 | public String getAttrStatus() { 64 | return AttrStatus; 65 | } 66 | 67 | public String getPYInitial() { 68 | return PYInitial; 69 | } 70 | 71 | public String getPYQuanPin() { 72 | return PYQuanPin; 73 | } 74 | 75 | public String getRemarkPYInitial() { 76 | return RemarkPYInitial; 77 | } 78 | 79 | public String getRemarkPYQuanPin() { 80 | return RemarkPYQuanPin; 81 | } 82 | 83 | public Integer getMemberStatus() { 84 | return MemberStatus; 85 | } 86 | 87 | public String getDisplayName() { 88 | return DisplayName; 89 | } 90 | 91 | public String getKeyWord() { 92 | return KeyWord; 93 | } 94 | 95 | public void setUin(Integer uin) { 96 | Uin = uin; 97 | } 98 | 99 | public void setUserName(String userName) { 100 | UserName = userName; 101 | } 102 | 103 | public void setNickName(String nickName) { 104 | NickName = nickName; 105 | } 106 | 107 | public void setAttrStatus(String attrStatus) { 108 | AttrStatus = attrStatus; 109 | } 110 | 111 | public void setPYInitial(String pYInitial) { 112 | PYInitial = pYInitial; 113 | } 114 | 115 | public void setPYQuanPin(String pYQuanPin) { 116 | PYQuanPin = pYQuanPin; 117 | } 118 | 119 | public void setRemarkPYInitial(String remarkPYInitial) { 120 | RemarkPYInitial = remarkPYInitial; 121 | } 122 | 123 | public void setRemarkPYQuanPin(String remarkPYQuanPin) { 124 | RemarkPYQuanPin = remarkPYQuanPin; 125 | } 126 | 127 | public void setMemberStatus(Integer memberStatus) { 128 | MemberStatus = memberStatus; 129 | } 130 | 131 | public void setDisplayName(String displayName) { 132 | DisplayName = displayName; 133 | } 134 | 135 | public void setKeyWord(String keyWord) { 136 | KeyWord = keyWord; 137 | } 138 | 139 | @Override 140 | public String toString() { 141 | return "GroupMember [Uin=" + Uin + ", UserName=" + UserName + ", NickName=" + NickName + ", AttrStatus=" + AttrStatus + ", PYInitial=" 142 | + PYInitial + ", PYQuanPin=" + PYQuanPin + ", RemarkPYInitial=" + RemarkPYInitial + ", RemarkPYQuanPin=" + RemarkPYQuanPin 143 | + ", MemberStatus=" + MemberStatus + ", DisplayName=" + DisplayName + ", KeyWord=" + KeyWord + "]"; 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/bean/ContactUser.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.bean; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 会话用户,包括 普通用户,群,公众号,服务号 7 | * 8 | * @author hexia 9 | * 10 | */ 11 | public class ContactUser { 12 | 13 | public static final int CONTACT_FLAG_OF_FILE_HELPER = 1; 14 | public static final int CONTACT_FLAG_OF_GROUP = 3;// 群 15 | public static final int CONTACT_FLAG_OF_USER = 3;// 普通用户 16 | 17 | /****** 如果该值为0 ****/ 18 | private int Uin; 19 | /****** 用户惟一标识,例如:@84a60bd0094062b1ff98bbbd195035d2 ****/ 20 | private String UserName; 21 | /***** 用户昵称:例如eno ******/ 22 | private String NickName; 23 | /***** 头像 **/ 24 | private String HeadImgUrl; 25 | /****** 未知,一般为1 ****/ 26 | private int ContactFlag; //1-好友, 2-群组, 3-公众号 27 | /*** 成员数,如果是群,该值应该大于0,如果是用户,该值为0 ***/ 28 | private int MemberCount; 29 | /**** 群成员列表 ***/ 30 | private List MemberList; 31 | /*** 未知 **/ 32 | private String RemarkName; 33 | /****** 一般为0 **/ 34 | private int HideInputBarFlag; 35 | /***** 性别 *****/ 36 | private int Sex; 37 | /*** 签名? **/ 38 | private String Signature; 39 | /***********/ 40 | private int VerifyFlag; 41 | /************/ 42 | private int OwnerUin; 43 | private String PYInitial; 44 | 45 | private String PYQuanPin; 46 | 47 | private String RemarkPYInitial; 48 | private String RemarkPYQuanPin; 49 | private int StarFriend; 50 | private int AppAccountFlag; 51 | private int Statues; 52 | private int AttrStatus; 53 | private String Province; 54 | private String City; 55 | private String Alias; 56 | private int SnsFlag; 57 | private int UniFriend; 58 | private String DisplayName; 59 | private Integer ChatRoomId; 60 | private String KeyWord; 61 | private String EncryChatRoomId; 62 | /***** 是否本人:0:否,1:是 *****/ 63 | private Integer IsOwner; 64 | 65 | public ContactUser() { 66 | } 67 | 68 | public ContactUser(String userName, String nickName, int memberCount, List memberList) { 69 | UserName = userName; 70 | NickName = nickName; 71 | MemberCount = memberCount; 72 | MemberList = memberList; 73 | } 74 | 75 | public int getUin() { 76 | return Uin; 77 | } 78 | 79 | public String getUserName() { 80 | return UserName; 81 | } 82 | 83 | public String getNickName() { 84 | return NickName; 85 | } 86 | 87 | public String getHeadImgUrl() { 88 | return HeadImgUrl; 89 | } 90 | 91 | public int getContactFlag() { 92 | return ContactFlag; 93 | } 94 | 95 | public int getMemberCount() { 96 | return MemberCount; 97 | } 98 | 99 | public String getRemarkName() { 100 | return RemarkName; 101 | } 102 | 103 | public int getHideInputBarFlag() { 104 | return HideInputBarFlag; 105 | } 106 | 107 | public int getSex() { 108 | return Sex; 109 | } 110 | 111 | public String getSignature() { 112 | return Signature; 113 | } 114 | 115 | public int getVerifyFlag() { 116 | return VerifyFlag; 117 | } 118 | 119 | public int getOwnerUin() { 120 | return OwnerUin; 121 | } 122 | 123 | public String getPYInitial() { 124 | return PYInitial; 125 | } 126 | 127 | public String getPYQuanPin() { 128 | return PYQuanPin; 129 | } 130 | 131 | public String getRemarkPYInitial() { 132 | return RemarkPYInitial; 133 | } 134 | 135 | public String getRemarkPYQuanPin() { 136 | return RemarkPYQuanPin; 137 | } 138 | 139 | public int getStarFriend() { 140 | return StarFriend; 141 | } 142 | 143 | public int getAppAccountFlag() { 144 | return AppAccountFlag; 145 | } 146 | 147 | public int getStatues() { 148 | return Statues; 149 | } 150 | 151 | public int getAttrStatus() { 152 | return AttrStatus; 153 | } 154 | 155 | public String getProvince() { 156 | return Province; 157 | } 158 | 159 | public String getCity() { 160 | return City; 161 | } 162 | 163 | public String getAlias() { 164 | return Alias; 165 | } 166 | 167 | public int getSnsFlag() { 168 | return SnsFlag; 169 | } 170 | 171 | public int getUniFriend() { 172 | return UniFriend; 173 | } 174 | 175 | public String getDisplayName() { 176 | return DisplayName; 177 | } 178 | 179 | public Integer getChatRoomId() { 180 | return ChatRoomId; 181 | } 182 | 183 | public String getKeyWord() { 184 | return KeyWord; 185 | } 186 | 187 | public String getEncryChatRoomId() { 188 | return EncryChatRoomId; 189 | } 190 | 191 | public Integer getIsOwner() { 192 | return IsOwner; 193 | } 194 | 195 | public void setUin(int uin) { 196 | Uin = uin; 197 | } 198 | 199 | public void setUserName(String userName) { 200 | UserName = userName; 201 | } 202 | 203 | public void setNickName(String nickName) { 204 | NickName = nickName; 205 | } 206 | 207 | public void setHeadImgUrl(String headImgUrl) { 208 | HeadImgUrl = headImgUrl; 209 | } 210 | 211 | public void setContactFlag(int contactFlag) { 212 | ContactFlag = contactFlag; 213 | } 214 | 215 | public void setMemberCount(int memberCount) { 216 | MemberCount = memberCount; 217 | } 218 | 219 | public void setRemarkName(String remarkName) { 220 | RemarkName = remarkName; 221 | } 222 | 223 | public void setHideInputBarFlag(int hideInputBarFlag) { 224 | HideInputBarFlag = hideInputBarFlag; 225 | } 226 | 227 | public void setSex(int sex) { 228 | Sex = sex; 229 | } 230 | 231 | public void setSignature(String signature) { 232 | Signature = signature; 233 | } 234 | 235 | public void setVerifyFlag(int verifyFlag) { 236 | VerifyFlag = verifyFlag; 237 | } 238 | 239 | public void setOwnerUin(int ownerUin) { 240 | OwnerUin = ownerUin; 241 | } 242 | 243 | public void setPYInitial(String pYInitial) { 244 | PYInitial = pYInitial; 245 | } 246 | 247 | public void setPYQuanPin(String pYQuanPin) { 248 | PYQuanPin = pYQuanPin; 249 | } 250 | 251 | public void setRemarkPYInitial(String remarkPYInitial) { 252 | RemarkPYInitial = remarkPYInitial; 253 | } 254 | 255 | public void setRemarkPYQuanPin(String remarkPYQuanPin) { 256 | RemarkPYQuanPin = remarkPYQuanPin; 257 | } 258 | 259 | public void setStarFriend(int starFriend) { 260 | StarFriend = starFriend; 261 | } 262 | 263 | public void setAppAccountFlag(int appAccountFlag) { 264 | AppAccountFlag = appAccountFlag; 265 | } 266 | 267 | public void setStatues(int statues) { 268 | Statues = statues; 269 | } 270 | 271 | public void setAttrStatus(int attrStatus) { 272 | AttrStatus = attrStatus; 273 | } 274 | 275 | public void setProvince(String province) { 276 | Province = province; 277 | } 278 | 279 | public void setCity(String city) { 280 | City = city; 281 | } 282 | 283 | public void setAlias(String alias) { 284 | Alias = alias; 285 | } 286 | 287 | public void setSnsFlag(int snsFlag) { 288 | SnsFlag = snsFlag; 289 | } 290 | 291 | public void setUniFriend(int uniFriend) { 292 | UniFriend = uniFriend; 293 | } 294 | 295 | public void setDisplayName(String displayName) { 296 | DisplayName = displayName; 297 | } 298 | 299 | public void setChatRoomId(Integer chatRoomId) { 300 | ChatRoomId = chatRoomId; 301 | } 302 | 303 | public void setKeyWord(String keyWord) { 304 | KeyWord = keyWord; 305 | } 306 | 307 | public void setEncryChatRoomId(String encryChatRoomId) { 308 | EncryChatRoomId = encryChatRoomId; 309 | } 310 | 311 | public void setIsOwner(Integer isOwner) { 312 | IsOwner = isOwner; 313 | } 314 | 315 | public List getMemberList() { 316 | return MemberList; 317 | } 318 | 319 | public void setMemberList(List memberList) { 320 | MemberList = memberList; 321 | } 322 | 323 | } 324 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/bean/GroupMember.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.bean; 2 | 3 | import com.blade.kit.json.JSONObject; 4 | 5 | public class GroupMember { 6 | 7 | private Integer Uin; 8 | private String UserName; 9 | private String NickName; 10 | private Integer AttrStatus; 11 | private String PYInitial; 12 | private String PYQuanPin; 13 | private String RemarkPYInitial; 14 | private String RemarkPYQuanPin; 15 | private Integer MemberStatus; // 0 16 | private String DisplayName; 17 | private String KeyWord; 18 | 19 | public GroupMember() { 20 | } 21 | 22 | public GroupMember(Integer uin, String userName, String nickName, Integer attrStatus, String pYInitial, String pYQuanPin, String remarkPYInitial, 23 | String remarkPYQuanPin, Integer memberStatus, String displayName, String keyWord) { 24 | this.Uin = uin; 25 | this.UserName = userName; 26 | this.NickName = nickName; 27 | this.AttrStatus = attrStatus; 28 | this.PYInitial = pYInitial; 29 | this.PYQuanPin = pYQuanPin; 30 | this.RemarkPYInitial = remarkPYInitial; 31 | this.RemarkPYQuanPin = remarkPYQuanPin; 32 | this.MemberStatus = memberStatus; 33 | this.DisplayName = displayName; 34 | this.KeyWord = keyWord; 35 | } 36 | 37 | public GroupMember(JSONObject item) { 38 | this.Uin = item.getInt("Uin"); 39 | this.UserName = item.getString("UserName"); 40 | this.NickName = item.getString("NickName"); 41 | this.AttrStatus = item.getInt("AttrStatus"); 42 | this.PYInitial = item.getString("PYInitial"); 43 | this.PYQuanPin = item.getString("PYQuanPin"); 44 | this.RemarkPYInitial = item.getString("RemarkPYInitial"); 45 | this.RemarkPYQuanPin = item.getString("RemarkPYQuanPin"); 46 | this.MemberStatus = item.getInt("MemberStatus"); 47 | this.DisplayName = item.getString("DisplayName"); 48 | this.KeyWord = item.getString("KeyWord"); 49 | } 50 | 51 | public Integer getUin() { 52 | return Uin; 53 | } 54 | 55 | public String getUserName() { 56 | return UserName; 57 | } 58 | 59 | public String getNickName() { 60 | return NickName; 61 | } 62 | 63 | public Integer getAttrStatus() { 64 | return AttrStatus; 65 | } 66 | 67 | public String getPYInitial() { 68 | return PYInitial; 69 | } 70 | 71 | public String getPYQuanPin() { 72 | return PYQuanPin; 73 | } 74 | 75 | public String getRemarkPYInitial() { 76 | return RemarkPYInitial; 77 | } 78 | 79 | public String getRemarkPYQuanPin() { 80 | return RemarkPYQuanPin; 81 | } 82 | 83 | public Integer getMemberStatus() { 84 | return MemberStatus; 85 | } 86 | 87 | public String getDisplayName() { 88 | return DisplayName; 89 | } 90 | 91 | public String getKeyWord() { 92 | return KeyWord; 93 | } 94 | 95 | public void setUin(Integer uin) { 96 | Uin = uin; 97 | } 98 | 99 | public void setUserName(String userName) { 100 | UserName = userName; 101 | } 102 | 103 | public void setNickName(String nickName) { 104 | NickName = nickName; 105 | } 106 | 107 | public void setAttrStatus(Integer attrStatus) { 108 | AttrStatus = attrStatus; 109 | } 110 | 111 | public void setPYInitial(String pYInitial) { 112 | PYInitial = pYInitial; 113 | } 114 | 115 | public void setPYQuanPin(String pYQuanPin) { 116 | PYQuanPin = pYQuanPin; 117 | } 118 | 119 | public void setRemarkPYInitial(String remarkPYInitial) { 120 | RemarkPYInitial = remarkPYInitial; 121 | } 122 | 123 | public void setRemarkPYQuanPin(String remarkPYQuanPin) { 124 | RemarkPYQuanPin = remarkPYQuanPin; 125 | } 126 | 127 | public void setMemberStatus(Integer memberStatus) { 128 | MemberStatus = memberStatus; 129 | } 130 | 131 | public void setDisplayName(String displayName) { 132 | DisplayName = displayName; 133 | } 134 | 135 | public void setKeyWord(String keyWord) { 136 | KeyWord = keyWord; 137 | } 138 | 139 | @Override 140 | public String toString() { 141 | return "GroupMember [Uin=" + Uin + ", UserName=" + UserName + ", NickName=" + NickName + ", AttrStatus=" + AttrStatus + ", PYInitial=" 142 | + PYInitial + ", PYQuanPin=" + PYQuanPin + ", RemarkPYInitial=" + RemarkPYInitial + ", RemarkPYQuanPin=" + RemarkPYQuanPin 143 | + ", MemberStatus=" + MemberStatus + ", DisplayName=" + DisplayName + ", KeyWord=" + KeyWord + "]"; 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/bean/Msg.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.bean; 2 | 3 | public class Msg { 4 | 5 | private String msgId; 6 | private String fromUserName; 7 | private String toUserName; 8 | private Integer msgType; 9 | private String content; 10 | private Integer status; 11 | private Integer imgStatus; 12 | private Integer createTime; 13 | private Integer voiceLength; 14 | private Integer playLength; 15 | private String fileName; 16 | private String fileSize; 17 | private String mediaId; 18 | private String url; 19 | private Integer appMsgType; 20 | private Integer statusNotifyCode; 21 | private String statusNotifyUserName; 22 | private String recommendInfo; 23 | 24 | public String getMsgId() { 25 | return msgId; 26 | } 27 | 28 | public String getFromUserName() { 29 | return fromUserName; 30 | } 31 | 32 | public String getToUserName() { 33 | return toUserName; 34 | } 35 | 36 | public Integer getMsgType() { 37 | return msgType; 38 | } 39 | 40 | public String getContent() { 41 | return content; 42 | } 43 | 44 | public Integer getStatus() { 45 | return status; 46 | } 47 | 48 | public Integer getImgStatus() { 49 | return imgStatus; 50 | } 51 | 52 | public Integer getCreateTime() { 53 | return createTime; 54 | } 55 | 56 | public Integer getVoiceLength() { 57 | return voiceLength; 58 | } 59 | 60 | public Integer getPlayLength() { 61 | return playLength; 62 | } 63 | 64 | public String getFileName() { 65 | return fileName; 66 | } 67 | 68 | public String getFileSize() { 69 | return fileSize; 70 | } 71 | 72 | public String getMediaId() { 73 | return mediaId; 74 | } 75 | 76 | public String getUrl() { 77 | return url; 78 | } 79 | 80 | public Integer getAppMsgType() { 81 | return appMsgType; 82 | } 83 | 84 | public Integer getStatusNotifyCode() { 85 | return statusNotifyCode; 86 | } 87 | 88 | public String getStatusNotifyUserName() { 89 | return statusNotifyUserName; 90 | } 91 | 92 | public String getRecommendInfo() { 93 | return recommendInfo; 94 | } 95 | 96 | public void setMsgId(String msgId) { 97 | this.msgId = msgId; 98 | } 99 | 100 | public void setFromUserName(String fromUserName) { 101 | this.fromUserName = fromUserName; 102 | } 103 | 104 | public void setToUserName(String toUserName) { 105 | this.toUserName = toUserName; 106 | } 107 | 108 | public void setMsgType(Integer msgType) { 109 | this.msgType = msgType; 110 | } 111 | 112 | public void setContent(String content) { 113 | this.content = content; 114 | } 115 | 116 | public void setStatus(Integer status) { 117 | this.status = status; 118 | } 119 | 120 | public void setImgStatus(Integer imgStatus) { 121 | this.imgStatus = imgStatus; 122 | } 123 | 124 | public void setCreateTime(Integer createTime) { 125 | this.createTime = createTime; 126 | } 127 | 128 | public void setVoiceLength(Integer voiceLength) { 129 | this.voiceLength = voiceLength; 130 | } 131 | 132 | public void setPlayLength(Integer playLength) { 133 | this.playLength = playLength; 134 | } 135 | 136 | public void setFileName(String fileName) { 137 | this.fileName = fileName; 138 | } 139 | 140 | public void setFileSize(String fileSize) { 141 | this.fileSize = fileSize; 142 | } 143 | 144 | public void setMediaId(String mediaId) { 145 | this.mediaId = mediaId; 146 | } 147 | 148 | public void setUrl(String url) { 149 | this.url = url; 150 | } 151 | 152 | public void setAppMsgType(Integer appMsgType) { 153 | this.appMsgType = appMsgType; 154 | } 155 | 156 | public void setStatusNotifyCode(Integer statusNotifyCode) { 157 | this.statusNotifyCode = statusNotifyCode; 158 | } 159 | 160 | public void setStatusNotifyUserName(String statusNotifyUserName) { 161 | this.statusNotifyUserName = statusNotifyUserName; 162 | } 163 | 164 | public void setRecommendInfo(String recommendInfo) { 165 | this.recommendInfo = recommendInfo; 166 | } 167 | 168 | // {"UserName":"","NickName":"","QQNum":0,"Province":"","City":"","Content":"","Signature":"","Alias":"","Scene":0,"VerifyFlag":0,"AttrStatus":0,"Sex":0,"Ticket":"","OpCode":0}, 169 | // "ForwardFlag":0,"AppInfo":{"AppID":"","Type":0},"HasProductId":0,"Ticket":"","ImgHeight":0,"ImgWidth":0,"SubMsgType":0,"NewMsgId":2692073074812973378,"OriContent":""} 170 | 171 | } 172 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/config/Constant.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.config; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import com.iyuexian.wechat4j.util.PropertyReader; 7 | 8 | public class Constant { 9 | 10 | // 特殊用户 须过滤 11 | public static final List FILTER_USERS = Arrays.asList("newsapp", "fmessage", "filehelper", "weibo", "qqmail", "fmessage", "tmessage", 12 | "qmessage", "qqsync", "floatbottle", "lbsapp", "shakeapp", "medianote", "qqfriend", "readerapp", "blogapp", "facebookapp", "masssendapp", 13 | "meishiapp", "feedsapp", "voip", "blogappweixin", "weixin", "brandsessionholder", "weixinreminder", "wxid_novlwrv3lqwv11", 14 | "gh_22b87fa7cb3c", "officialaccounts", "notification_messages", "wxid_novlwrv3lqwv11", "gh_22b87fa7cb3c", "wxitil", 15 | "userexperience_alarm", "notification_messages"); 16 | 17 | public static final String[] SYNC_HOST = { "webpush.weixin.qq.com", "webpush2.weixin.qq.com", "webpush.wechat.com", "webpush1.wechat.com", 18 | "webpush2.wechat.com" }; 19 | 20 | public static final String QINIU_AK = "qiniu_ak"; 21 | /**** 七牛access secret ***/ 22 | public static final String QINIU_SK = "qiniu_sk"; 23 | /**** 图片域名地址 ***/ 24 | public static final String QIUNIU_IMG_URL = "qiuniu_img_url"; 25 | /****** 视频域名地址 *****/ 26 | public static final String QIUNIU_VDEO_URL = "qiuniu_video_url"; 27 | /**** 七牛图片bucket名称 ****/ 28 | public static final String QINIU_BUCKET_IMAGE0 = "qiniu_bucket_image0"; 29 | /**** 七牛视频bucket名称 ****/ 30 | public static final String QINIU_BUCKET_VIDEO = "qiniu_bucket_video"; 31 | 32 | 33 | /***** 是否开启自动回复 ******/ 34 | public static final boolean AUTO_REPLY = false; 35 | /***** 是否打印成员信息 ****/ 36 | public static final boolean PRINT_MEMBER_INFO = false; 37 | /****** 是否开启自动添加好友 ******/ 38 | public static final boolean ADD_FRIEND = false; 39 | 40 | public static final String HTTP_OK = "200"; 41 | public static final String BASE_URL = "https://webpush2.weixin.qq.com/cgi-bin/mmwebwx-bin"; 42 | public static final String JS_LOGIN_URL = "https://login.weixin.qq.com/jslogin"; 43 | public static final String QRCODE_URL = "https://login.weixin.qq.com/qrcode/"; 44 | public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"; 45 | public static PropertyReader configReader = PropertyReader.load("config.properties"); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/config/Enums.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.config; 2 | 3 | public class Enums { 4 | public static enum OS { 5 | WINDOWS, LINUX, DARWIN, MAC, OTHER 6 | } 7 | 8 | public enum FileType { 9 | Picture, Video, File 10 | } 11 | 12 | public static enum MsgType { 13 | MEDIA(-1, "媒体消息", "ebwxgetvideo"), 14 | 15 | TXT(1, "文本消息", ""), 16 | 17 | PICTURE(3, "图片消息", "webwxgetmsgimg"), 18 | 19 | VOICE(34, "语音消息", "webwxgetvoice"), 20 | 21 | FRIEND_VERIFY(37, "好友确认消息", ""), 22 | 23 | POSSIBLEFRIEND_MSG(40, "POSSIBLEFRIEND_MSG", ""), 24 | 25 | SHARE_MP(42, "共享名片", ""), 26 | 27 | VIDEO(43, "视频消息", "webwxgetvideo"), 28 | 29 | ANIMATION(47, "动画消息", ""), 30 | 31 | LOCATION(48, "位置消息", ""), 32 | 33 | SHARE_LINK(49, "分享链接", ""), 34 | 35 | VOIPMSG(50, "VOIPMSG", ""), 36 | 37 | WX_INIT(51, "微信初始化消息", ""), 38 | 39 | VOIPNOTIFY(52, "VOIPNOTIFY", ""), 40 | 41 | VOIPINVITE(53, "VOIPINVITE", ""), 42 | 43 | SMALL_VIDEO(62, "小视频", "webwxgetvideo"), 44 | 45 | SYSNOTICE(9999, "SYSNOTICE", ""), 46 | 47 | SYSTEM(10000, "", "系统消息E"), 48 | 49 | MSG_ROLLBACK(10002, "撤回消息", ""); 50 | 51 | private int type; 52 | private String name; 53 | private String downloadPath; 54 | 55 | private MsgType(int type, String name, String downloadPath) { 56 | this.type = type; 57 | this.downloadPath = downloadPath; 58 | } 59 | 60 | public int getType() { 61 | return type; 62 | } 63 | 64 | public String getName() { 65 | return name; 66 | } 67 | 68 | public String getDownloadPath() { 69 | return downloadPath; 70 | } 71 | 72 | public static MsgType getType(int type) { 73 | MsgType[] types = MsgType.values(); 74 | for (MsgType msgType : types) { 75 | if (msgType.getType() == type) { 76 | return msgType; 77 | } 78 | } 79 | return null; 80 | } 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/config/MsgType.java: -------------------------------------------------------------------------------- 1 | //package com.iyuexian.wechat4j.config; 2 | // 3 | //public class MsgType { 4 | // 5 | // public static final int MSGTYPE_TEXT = 1; // 文本消息类型 6 | // public static final int MSGTYPE_IMAGE = 3; // 图片消息 7 | // public static final int MSGTYPE_VOICE = 34; // 语音消息 8 | // public static final int MSGTYPE_VIDEO = 43; // 小视频消息 9 | // public static final int MSGTYPE_MICROVIDEO = 62; 10 | // public static final int MSGTYPE_EMOTICON = 47; 11 | // public static final int MSGTYPE_APP = 49; 12 | // public static final int MSGTYPE_VOIPMSG = 50; 13 | // public static final int MSGTYPE_VOIPNOTIFY = 52; 14 | // public static final int MSGTYPE_VOIPINVITE = 53; 15 | // public static final int MSGTYPE_LOCATION = 48; 16 | // public static final int MSGTYPE_STATUSNOTIFY = 51; 17 | // public static final int MSGTYPE_SYSNOTICE = 9999; 18 | // public static final int MSGTYPE_POSSIBLEFRIEND_MSG = 40; 19 | // public static final int MSGTYPE_VERIFYMSG = 37; 20 | // public static final int MSGTYPE_SHARECARD = 42; 21 | // public static final int MSGTYPE_SYS = 10000; 22 | // public static final int MSGTYPE_RECALLED = 10002; 23 | // 24 | // // 文本信息 25 | // public static String TEXT = "Text"; 26 | // // 图片信息 27 | // public static String PIC = "Pic"; 28 | // // 语音信息 29 | // public static String VOICE = "Voice"; 30 | // // 小视频消息 31 | // public static String VIEDO = "Video"; 32 | // // name card 明片消息 33 | // public static String NAMECARD = "NameCard"; 34 | //} -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/core/WechatApiUtil.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.core; 2 | 3 | import java.io.File; 4 | import java.text.MessageFormat; 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import com.blade.kit.DateKit; 12 | import com.blade.kit.StringKit; 13 | import com.blade.kit.http.HttpRequest; 14 | import com.blade.kit.json.JSONArray; 15 | import com.blade.kit.json.JSONKit; 16 | import com.blade.kit.json.JSONObject; 17 | import com.iyuexian.wechat4j.config.Constant; 18 | import com.iyuexian.wechat4j.exception.WechatException; 19 | import com.iyuexian.wechat4j.plugin.Storage; 20 | import com.iyuexian.wechat4j.util.CookieUtil; 21 | import com.iyuexian.wechat4j.util.HttpClient; 22 | import com.iyuexian.wechat4j.util.Matchers; 23 | 24 | public class WechatApiUtil { 25 | static final Logger LOGGER = LoggerFactory.getLogger(WechatApiUtil.class); 26 | 27 | public static String getUUID() throws WechatException { 28 | HttpRequest request = HttpRequest.get(Constant.JS_LOGIN_URL, true, "appid", "wx782c26e4c19acffb", "fun", "new", "lang", "zh_CN", "_", 29 | DateKit.getCurrentUnixTime()); 30 | String res = request.body(); 31 | request.disconnect(); 32 | if (StringKit.isBlank(res)) { 33 | throw new WechatException("获取UUID失败"); 34 | } 35 | String code = Matchers.match("window.QRLogin.code = (\\d+);", res); 36 | if (null == code || !code.equals("200")) { 37 | throw new WechatException("获取UUID失败," + code); 38 | } 39 | String uuid = Matchers.match("window.QRLogin.uuid = \"(.*)\";", res); 40 | return uuid; 41 | } 42 | 43 | public static String getQrCode(String uuid) throws WechatException { 44 | 45 | if (StringKit.isBlank(uuid)) { 46 | throw new WechatException("请先获取UUID"); 47 | } 48 | String url = Constant.QRCODE_URL + uuid; 49 | String folder=System.getProperty("java.io.tmpdir"); 50 | final File output = new File(folder+File.separator+"wechat4j_qrcode.jpg"); 51 | HttpRequest.post(url, true, "t", "webwx", "_", DateKit.getCurrentUnixTime()).receive(output); 52 | 53 | if (null == output || !output.exists() || !output.isFile()) { 54 | throw new WechatException("获取登陆二维码失败"); 55 | } 56 | return output.getPath(); 57 | 58 | } 59 | 60 | public static String waitLogin(int tip, String uuid) { 61 | String url = "https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login"; 62 | HttpRequest request = HttpRequest.get(url, true, "tip", tip, "uuid", uuid, "_", DateKit.getCurrentUnixTime()); 63 | LOGGER.warn("等待登陆"); 64 | String res = request.body(); 65 | request.disconnect(); 66 | return res; 67 | 68 | } 69 | 70 | public static WechatMeta newWechatMeta(String waitloginRes) { 71 | String pm = Matchers.match("window.redirect_uri=\"(\\S+?)\";", waitloginRes); 72 | String redirectUrl = pm + "&fun=new"; 73 | String baseUrl = redirectUrl.substring(0, redirectUrl.lastIndexOf("/")); 74 | WechatMeta meta = new WechatMeta(); 75 | meta.setRedirect_uri(redirectUrl); 76 | meta.setBase_uri(baseUrl); 77 | meta.setLoginDate(new Date()); 78 | return meta; 79 | } 80 | 81 | public static void login(WechatMeta meta) throws WechatException { 82 | 83 | if (StringKit.isBlank(meta.getRedirect_uri())) { 84 | throw new WechatException("redirect_url不能为空"); 85 | } 86 | 87 | HttpRequest request = HttpRequest.get(meta.getRedirect_uri()); 88 | String res = request.body(); 89 | meta.setCookie(CookieUtil.getCookie(request)); 90 | request.disconnect(); 91 | if (StringKit.isBlank(res)) { 92 | throw new WechatException("登录失败"); 93 | } 94 | meta.setSkey(Matchers.match("(\\S+)", res)); 95 | meta.setWxsid(Matchers.match("(\\S+)", res)); 96 | meta.setWxuin(Matchers.match("(\\S+)", res)); 97 | meta.setPass_ticket(Matchers.match("(\\S+)", res)); 98 | 99 | JSONObject baseRequest = new JSONObject(); 100 | baseRequest.put("Uin", meta.getWxuin()); 101 | baseRequest.put("Sid", meta.getWxsid()); 102 | baseRequest.put("Skey", meta.getSkey()); 103 | baseRequest.put("DeviceID", meta.getDeviceId()); 104 | meta.setBaseRequest(baseRequest); 105 | } 106 | 107 | public static JSONObject wxInit(WechatMeta meta) throws WechatException { 108 | String url = meta.getBase_uri() + "/webwxinit?r=" + DateKit.getCurrentUnixTime() + "&lang=zh_CN"; 109 | JSONObject body = new JSONObject(); 110 | body.put("BaseRequest", meta.getBaseRequest()); 111 | HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8").header("Cookie", meta.getCookie()) 112 | .send(body.toString()); 113 | String res = request.body(); 114 | request.disconnect(); 115 | 116 | JSONObject jsonObject = null; 117 | if (StringKit.isBlank(res) || (jsonObject = JSONKit.parseObject(res)) == null) { 118 | throw new WechatException("微信初始化失败"); 119 | } 120 | 121 | JSONObject BaseResponse = jsonObject.get("BaseResponse").asJSONObject(); 122 | if (null == BaseResponse || BaseResponse.getInt("Ret", -1) != 0) { 123 | throw new WechatException("微信初始化失败," + BaseResponse); 124 | } 125 | 126 | meta.setSyncKey(jsonObject.get("SyncKey").asJSONObject()); 127 | meta.setUser(jsonObject.get("User").asJSONObject()); 128 | 129 | StringBuffer synckey = new StringBuffer(); 130 | JSONArray list = meta.getSyncKey().get("List").asArray(); 131 | for (int i = 0, len = list.size(); i < len; i++) { 132 | JSONObject item = list.get(i).asJSONObject(); 133 | synckey.append("|" + item.getInt("Key", 0) + "_" + item.getInt("Val", 0)); 134 | } 135 | meta.setSynckey(synckey.substring(1)); 136 | return jsonObject; 137 | } 138 | 139 | public static void openStatusNotify(WechatMeta meta) throws WechatException { 140 | String url = meta.getBase_uri() + "/webwxstatusnotify?lang=zh_CN&pass_ticket=" + meta.getPass_ticket(); 141 | 142 | JSONObject body = new JSONObject(); 143 | body.put("BaseRequest", meta.getBaseRequest()); 144 | body.put("Code", 3); 145 | body.put("FromUserName", meta.getUser().getString("UserName")); 146 | body.put("ToUserName", meta.getUser().getString("UserName")); 147 | body.put("ClientMsgId", DateKit.getCurrentUnixTime()); 148 | 149 | HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8").header("Cookie", meta.getCookie()) 150 | .send(body.toString()); 151 | String res = request.body(); 152 | request.disconnect(); 153 | 154 | if (StringKit.isBlank(res)) { 155 | throw new WechatException("状态通知开启失败"); 156 | } 157 | 158 | JSONObject jsonObject = JSONKit.parseObject(res); 159 | JSONObject BaseResponse = jsonObject.get("BaseResponse").asJSONObject(); 160 | if (null == BaseResponse || BaseResponse.getInt("Ret", -1) != 0) { 161 | throw new WechatException("状态通知开启失败"); 162 | } 163 | LOGGER.debug("状态通知已开启"); 164 | } 165 | 166 | public static int[] syncCheck(WechatMeta meta, String url) { 167 | int[] arr = new int[] { -1, -1 }; 168 | try { 169 | url = url == null ? meta.getWebpush_url() + "/synccheck" : "https://" + url + "/cgi-bin/mmwebwx-bin/synccheck"; 170 | JSONObject body = new JSONObject(); 171 | body.put("BaseRequest", meta.getBaseRequest()); 172 | HttpRequest request = HttpRequest 173 | .get(url, true, "r", DateKit.getCurrentUnixTime() + StringKit.getRandomNumber(5), "skey", meta.getSkey(), "uin", meta.getWxuin(), 174 | "sid", meta.getWxsid(), "deviceid", meta.getDeviceId(), "synckey", meta.getSynckey(), "_", System.currentTimeMillis()) 175 | .header("Cookie", meta.getCookie()); 176 | String res = request.body(); 177 | request.disconnect(); 178 | if (StringKit.isBlank(res)) { 179 | return arr; 180 | } 181 | 182 | String retcode = Matchers.match("retcode:\"(\\d+)\",", res); 183 | String selector = Matchers.match("selector:\"(\\d+)\"}", res); 184 | if (null != retcode && null != selector) { 185 | arr[0] = Integer.parseInt(retcode); 186 | arr[1] = Integer.parseInt(selector); 187 | return arr; 188 | } 189 | return arr; 190 | } catch (Exception ex) { 191 | return arr; 192 | } 193 | } 194 | 195 | public static int[] syncCheck(WechatMeta meta) throws WechatException { 196 | return syncCheck(meta, null); 197 | } 198 | 199 | public static void choiceSyncLine(WechatMeta meta) throws WechatException { 200 | boolean enabled = false; 201 | for (String syncUrl : Constant.SYNC_HOST) { 202 | int[] res = syncCheck(meta, syncUrl); 203 | if (res[0] == 0) { 204 | String url = "https://" + syncUrl + "/cgi-bin/mmwebwx-bin"; 205 | meta.setWebpush_url(url); 206 | LOGGER.info("选择线路:[{}]", syncUrl); 207 | enabled = true; 208 | break; 209 | } 210 | } 211 | if (!enabled) { 212 | throw new WechatException("同步线路不通畅"); 213 | } 214 | } 215 | 216 | public static JSONObject webwxsync(WechatMeta meta) throws WechatException { 217 | String url = meta.getBase_uri() + "/webwxsync?skey=" + meta.getSkey() + "&sid=" + meta.getWxsid(); 218 | 219 | JSONObject body = new JSONObject(); 220 | body.put("BaseRequest", meta.getBaseRequest()); 221 | body.put("SyncKey", meta.getSyncKey()); 222 | body.put("rr", DateKit.getCurrentUnixTime()); 223 | 224 | HttpClient httpRequsetUtil = new HttpClient(meta); 225 | JSONObject jsonObject = httpRequsetUtil.postJSON(url, body); 226 | JSONObject BaseResponse = jsonObject.get("BaseResponse").asJSONObject(); 227 | if (null != BaseResponse) { 228 | int ret = BaseResponse.getInt("Ret", -1); 229 | if (ret == 0) { 230 | meta.setSyncKey(jsonObject.get("SyncKey").asJSONObject()); 231 | StringBuffer synckey = new StringBuffer(); 232 | JSONArray list = meta.getSyncKey().get("List").asArray(); 233 | for (int i = 0, len = list.size(); i < len; i++) { 234 | JSONObject item = list.get(i).asJSONObject(); 235 | synckey.append("|" + item.getInt("Key", 0) + "_" + item.getInt("Val", 0)); 236 | } 237 | meta.setSynckey(synckey.substring(1)); 238 | return jsonObject; 239 | } 240 | } 241 | return null; 242 | } 243 | 244 | public static String webwxsendmsg(WechatMeta meta, String content, JSONObject to) { 245 | String url = meta.getBase_uri() + "/webwxsendmsg?lang=zh_CN&pass_ticket=" + meta.getPass_ticket(); 246 | final JSONObject body = new JSONObject(); 247 | String clientMsgId = DateKit.getCurrentUnixTime() + StringKit.getRandomNumber(5); 248 | JSONObject Msg = new JSONObject(); 249 | 250 | Msg.put("Type", 1); 251 | Msg.put("Content", content); 252 | Msg.put("FromUserName", meta.getUser().getString("UserName")); 253 | Msg.put("ToUserName", to.get("UserName")); 254 | Msg.put("LocalID", clientMsgId); 255 | Msg.put("ClientMsgId", clientMsgId); 256 | 257 | body.put("BaseRequest", meta.getBaseRequest()); 258 | body.put("Msg", Msg); 259 | final HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8").header("Cookie", meta.getCookie()); 260 | request.send(body.toString()); 261 | String msgResult = request.body(); 262 | request.disconnect(); 263 | return msgResult; 264 | 265 | } 266 | 267 | /** 268 | * 添加好友 269 | * 270 | * @param userName 271 | * @param status 272 | * 2,default=2 273 | * @param verifyContent 274 | * @param autoUpdate 275 | */ 276 | public static JSONObject addFriend(WechatMeta meta, String userName, String verifyContent) { 277 | String url = "{0}/webwxverifyuser?r={1}&pass_ticket={2}"; 278 | url = MessageFormat.format(url, meta.getBase_uri(), DateKit.getCurrentUnixTime(), meta.getPass_ticket()); 279 | 280 | JSONObject body = new JSONObject(); 281 | body.put("BaseRequest", meta.getBaseRequest()); 282 | body.put("Opcode", 2); 283 | body.put("VerifyUserListSize", 1); 284 | JSONArray VerifyUserList = new JSONArray(); 285 | JSONObject verifyItem = new JSONObject(); 286 | verifyItem.put("Value", userName); 287 | verifyItem.put("VerifyUserTicket", ""); 288 | VerifyUserList.add(verifyItem); 289 | body.put("VerifyUserList", VerifyUserList); 290 | body.put("VerifyContent", verifyContent); 291 | body.put("SceneListCount", 1); 292 | JSONArray sceneList = new JSONArray(); 293 | sceneList.add(33); 294 | body.put("SceneList", sceneList); 295 | body.put("skey", meta.getSkey()); 296 | 297 | HttpClient httpRequsetUtil = new HttpClient(meta); 298 | JSONObject resp = httpRequsetUtil.postJSON(url, body); 299 | return resp; 300 | 301 | } 302 | 303 | /** 304 | * 获取通讯录列表 305 | */ 306 | public static JSONArray getContactList(WechatMeta meta) { 307 | String url = meta.getBase_uri() + "/webwxgetcontact?&seq=0&pass_ticket=" + meta.getPass_ticket() + "&skey=" + meta.getSkey() + "&r=" 308 | + DateKit.getCurrentUnixTime(); 309 | JSONObject body = new JSONObject(); 310 | body.put("BaseRequest", meta.getBaseRequest()); 311 | HttpClient httpRequsetUtil = new HttpClient(meta); 312 | JSONObject response = httpRequsetUtil.postJSON(url, body); 313 | JSONArray memberList = response.get("MemberList").asArray(); 314 | return memberList; 315 | 316 | } 317 | 318 | /*** 319 | * 初始化群(群名称需要从最新联系人或通过录里筛选) 320 | * 321 | * @param meta 322 | * @param chatRommNames 323 | */ 324 | public static void initLatestChatroom(WechatMeta meta, List chatRommNames) { 325 | JSONArray groupArray = new JSONArray(); 326 | // for (String groupUserName : 327 | // Storage.instance().getLatestChatRoomUserNameList()) { 328 | for (String groupUserName : chatRommNames) { 329 | JSONObject groupItem = new JSONObject(); 330 | groupItem.put("UserName", groupUserName); 331 | groupItem.put("ChatRoomId", ""); 332 | groupArray.add(groupItem); 333 | } 334 | JSONArray latestChatRoomList = getMemberListByChatroom(meta, groupArray); 335 | Storage.instance().setLatestChatRoomList(latestChatRoomList); 336 | 337 | } 338 | 339 | /** 340 | * 获取取成员列表 341 | * @param meta 342 | * @param chatRoomList 343 | * @return 344 | */ 345 | public static JSONArray getMemberListByChatroom(WechatMeta meta, JSONArray chatRoomList) { 346 | String url = meta.getBase_uri() + "/webwxbatchgetcontact?type=ex&r=" + DateKit.getCurrentUnixTime() + "&lang=zh_CN"; 347 | JSONObject body = new JSONObject(); 348 | body.put("BaseRequest", meta.getBaseRequest()); 349 | body.put("Count", chatRoomList.size()); 350 | body.put("List", chatRoomList); 351 | HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8").header("Cookie", meta.getCookie()) 352 | .send(body.toString()); 353 | String res = request.body(); 354 | request.disconnect(); 355 | if (StringKit.isBlank(res)) { 356 | throw new WechatException("获取群成员列表失败"); 357 | } 358 | JSONObject jsonObject = JSONKit.parseObject(res); 359 | JSONObject baseResponse = jsonObject.get("BaseResponse").asJSONObject(); 360 | if (null == baseResponse || baseResponse.getInt("Ret", -1) != 0) { 361 | LOGGER.warn("获取群列表失败,{}", baseResponse); 362 | return null; 363 | } 364 | JSONArray memberList = jsonObject.get("ContactList").asArray(); 365 | // LOGGER.info("获取群成员:{}", memberList); 366 | return memberList; 367 | 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/core/WechatMeta.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.core; 2 | 3 | import java.util.Date; 4 | 5 | import com.blade.kit.DateKit; 6 | import com.blade.kit.json.JSONObject; 7 | import com.iyuexian.wechat4j.config.Constant; 8 | 9 | public class WechatMeta { 10 | 11 | private String mobile; 12 | protected String base_uri, redirect_uri, webpush_url = Constant.BASE_URL; 13 | protected String uuid; 14 | protected String skey; 15 | protected String synckey; 16 | protected String wxsid; 17 | protected String wxuin; 18 | protected String pass_ticket; 19 | protected boolean alive; 20 | protected String deviceId = "e" + DateKit.getCurrentUnixTime(); 21 | 22 | protected String cookie; 23 | 24 | protected JSONObject baseRequest; 25 | protected JSONObject SyncKey; 26 | protected JSONObject User; 27 | 28 | protected Date loginDate; 29 | 30 | 31 | public boolean isAlive() { 32 | return alive; 33 | } 34 | 35 | public void setAlive(boolean alive) { 36 | this.alive = alive; 37 | } 38 | 39 | public String getUuid() { 40 | return uuid; 41 | } 42 | 43 | public void setUuid(String uuid) { 44 | this.uuid = uuid; 45 | } 46 | 47 | public String getSkey() { 48 | return skey; 49 | } 50 | 51 | public void setSkey(String skey) { 52 | this.skey = skey; 53 | } 54 | 55 | public String getSynckey() { 56 | return synckey; 57 | } 58 | 59 | public void setSynckey(String synckey) { 60 | this.synckey = synckey; 61 | } 62 | 63 | public String getWxsid() { 64 | return wxsid; 65 | } 66 | 67 | public void setWxsid(String wxsid) { 68 | this.wxsid = wxsid; 69 | } 70 | 71 | public String getWxuin() { 72 | return wxuin; 73 | } 74 | 75 | public void setWxuin(String wxuin) { 76 | this.wxuin = wxuin; 77 | } 78 | 79 | public String getPass_ticket() { 80 | return pass_ticket; 81 | } 82 | 83 | public void setPass_ticket(String pass_ticket) { 84 | this.pass_ticket = pass_ticket; 85 | } 86 | 87 | public String getDeviceId() { 88 | return deviceId; 89 | } 90 | 91 | public void setDeviceId(String deviceId) { 92 | this.deviceId = deviceId; 93 | } 94 | 95 | public String getCookie() { 96 | return cookie; 97 | } 98 | 99 | public void setCookie(String cookie) { 100 | this.cookie = cookie; 101 | } 102 | 103 | public JSONObject getBaseRequest() { 104 | return baseRequest; 105 | } 106 | 107 | public void setBaseRequest(JSONObject baseRequest) { 108 | this.baseRequest = baseRequest; 109 | } 110 | 111 | public JSONObject getSyncKey() { 112 | return SyncKey; 113 | } 114 | 115 | public void setSyncKey(JSONObject syncKey) { 116 | SyncKey = syncKey; 117 | } 118 | 119 | public JSONObject getUser() { 120 | return User; 121 | } 122 | 123 | public void setUser(JSONObject user) { 124 | User = user; 125 | } 126 | 127 | public String getBase_uri() { 128 | return base_uri; 129 | } 130 | 131 | public void setBase_uri(String base_uri) { 132 | this.base_uri = base_uri; 133 | } 134 | 135 | public String getRedirect_uri() { 136 | return redirect_uri; 137 | } 138 | 139 | public void setRedirect_uri(String redirect_uri) { 140 | this.redirect_uri = redirect_uri; 141 | } 142 | 143 | public String getWebpush_url() { 144 | return webpush_url; 145 | } 146 | 147 | public void setWebpush_url(String webpush_url) { 148 | this.webpush_url = webpush_url; 149 | } 150 | 151 | public String getMobile() { 152 | return mobile; 153 | } 154 | 155 | public void setMobile(String mobile) { 156 | this.mobile = mobile; 157 | } 158 | 159 | public Date getLoginDate() { 160 | return loginDate; 161 | } 162 | 163 | public void setLoginDate(Date loginDate) { 164 | this.loginDate = loginDate; 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/demo/Demo1.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.demo; 2 | 3 | import com.blade.kit.json.JSONArray; 4 | import com.blade.kit.json.JSONObject; 5 | import com.iyuexian.wechat4j.WechatStartup; 6 | import com.iyuexian.wechat4j.core.WechatApiUtil; 7 | import com.iyuexian.wechat4j.core.WechatMeta; 8 | import com.iyuexian.wechat4j.plugin.FriendAddTask; 9 | import com.iyuexian.wechat4j.plugin.MessageListener; 10 | import com.iyuexian.wechat4j.plugin.WxLocalCache; 11 | 12 | public class Demo1 { 13 | 14 | public static void main(String[] args) { 15 | test3(); 16 | } 17 | 18 | // 给指定人发消息 19 | public static void test1() throws InterruptedException { 20 | WechatMeta meta = WechatStartup.login(); 21 | JSONObject contact = WxLocalCache.instance().getContactByRemarkName("Test"); 22 | if (contact == null) { 23 | return; 24 | } 25 | WechatApiUtil.webwxsendmsg(meta, "哈哈", contact); 26 | } 27 | 28 | // 给所有联系人发消息 29 | public static void test2() { 30 | WechatMeta meta = WechatStartup.login(); 31 | JSONArray contactList = WxLocalCache.instance().getContactList(); 32 | for (int i = 0; i < contactList.size(); i++) { 33 | WechatApiUtil.webwxsendmsg(meta, "^^", contactList.get(i).asJSONObject()); 34 | } 35 | } 36 | 37 | // 监听消息 38 | public static void test3() { 39 | WechatMeta meta = WechatStartup.login(); 40 | MessageListener listener = new MessageListener(meta); 41 | listener.listen(); 42 | } 43 | 44 | // 批量添加群里的人(该方法不稳定,没控制好间隔时间很容易被微信服务器察觉,返回失败) 45 | public static void batchAddChatRoomFriend() { 46 | WechatMeta meta = WechatStartup.login(); 47 | FriendAddTask task = new FriendAddTask(meta, "添加添加好友的群名称", 15); 48 | task.start(); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/exception/WechatException.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.exception; 2 | 3 | public class WechatException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 209248116271894410L; 6 | 7 | public WechatException() { 8 | super(); 9 | } 10 | 11 | public WechatException(String message) { 12 | super(message); 13 | } 14 | 15 | public WechatException(Throwable cause) { 16 | super(cause); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/ContactManager.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.util.List; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import com.blade.kit.DateKit; 9 | import com.blade.kit.StringKit; 10 | import com.blade.kit.http.HttpRequest; 11 | import com.blade.kit.json.JSONArray; 12 | import com.blade.kit.json.JSONKit; 13 | import com.blade.kit.json.JSONObject; 14 | import com.iyuexian.wechat4j.core.WechatMeta; 15 | import com.iyuexian.wechat4j.exception.WechatException; 16 | import com.iyuexian.wechat4j.util.HttpClient; 17 | 18 | public class ContactManager { 19 | 20 | public static Logger LOGGER = LoggerFactory.getLogger(ContactManager.class); 21 | private WechatMeta meta; 22 | 23 | private HttpClient httpRequsetUtil; 24 | 25 | public ContactManager(WechatMeta meta) { 26 | super(); 27 | this.meta = meta; 28 | this.httpRequsetUtil = new HttpClient(meta); 29 | } 30 | 31 | /** 32 | * 获取通讯录列表 33 | */ 34 | public JSONArray getContactList() { 35 | String url = meta.getBase_uri() + "/webwxgetcontact?&seq=0&pass_ticket=" + meta.getPass_ticket() + "&skey=" + meta.getSkey() + "&r=" 36 | + DateKit.getCurrentUnixTime(); 37 | JSONObject body = new JSONObject(); 38 | body.put("BaseRequest", meta.getBaseRequest()); 39 | JSONObject response = httpRequsetUtil.postJSON(url, body); 40 | JSONArray memberList = response.get("MemberList").asArray(); 41 | return memberList; 42 | 43 | } 44 | 45 | public void initLatestChatroom(List chatRommNames) { 46 | JSONArray groupArray = new JSONArray(); 47 | // for (String groupUserName : 48 | // Storage.instance().getLatestChatRoomUserNameList()) { 49 | for (String groupUserName : chatRommNames) { 50 | JSONObject groupItem = new JSONObject(); 51 | groupItem.put("UserName", groupUserName); 52 | groupItem.put("ChatRoomId", ""); 53 | groupArray.add(groupItem); 54 | } 55 | JSONArray latestChatRoomList = getMemberListByChatroom(groupArray); 56 | Storage.instance().setLatestChatRoomList(latestChatRoomList); 57 | 58 | } 59 | 60 | public JSONArray getMemberListByChatroom(JSONArray chatRoomList) { 61 | String url = meta.getBase_uri() + "/webwxbatchgetcontact?type=ex&r=" + DateKit.getCurrentUnixTime() + "&lang=zh_CN"; 62 | JSONObject body = new JSONObject(); 63 | body.put("BaseRequest", meta.getBaseRequest()); 64 | body.put("Count", chatRoomList.size()); 65 | body.put("List", chatRoomList); 66 | HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8").header("Cookie", meta.getCookie()) 67 | .send(body.toString()); 68 | String res = request.body(); 69 | request.disconnect(); 70 | if (StringKit.isBlank(res)) { 71 | throw new WechatException("获取群成员列表失败"); 72 | } 73 | JSONObject jsonObject = JSONKit.parseObject(res); 74 | JSONObject baseResponse = jsonObject.get("BaseResponse").asJSONObject(); 75 | if (null == baseResponse || baseResponse.getInt("Ret", -1) != 0) { 76 | LOGGER.warn("获取群列表失败,{}", baseResponse); 77 | return null; 78 | } 79 | JSONArray memberList = jsonObject.get("ContactList").asArray(); 80 | // LOGGER.info("获取群成员:{}", memberList); 81 | return memberList; 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/ContactUserUtil.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.blade.kit.json.JSONArray; 10 | import com.blade.kit.json.JSONObject; 11 | import com.iyuexian.wechat4j.bean.ChatRoom; 12 | import com.iyuexian.wechat4j.bean.ChatRoomMember; 13 | import com.iyuexian.wechat4j.bean.GroupMember; 14 | import com.iyuexian.wechat4j.config.Constant; 15 | 16 | public class ContactUserUtil { 17 | 18 | public static final Logger LOGGER = LoggerFactory.getLogger(ContactUserUtil.class); 19 | 20 | @Deprecated 21 | public static List processMemberJSON(JSONArray memberList) { 22 | List members = new ArrayList(); 23 | for (int i = 0; i < memberList.size(); i++) { 24 | JSONObject member = memberList.get(i).asJSONObject(); 25 | GroupMember item = new GroupMember(member); 26 | members.add(item); 27 | } 28 | return members; 29 | } 30 | 31 | public static List processChatRoomMember(JSONArray memberList) { 32 | List members = new ArrayList(); 33 | for (int i = 0; i < memberList.size(); i++) { 34 | JSONObject member = memberList.get(i).asJSONObject(); 35 | ChatRoomMember item = new ChatRoomMember(member); 36 | if (Constant.PRINT_MEMBER_INFO) { 37 | LOGGER.warn("当前群成员:{}", item.getNickName()); 38 | } 39 | members.add(item); 40 | } 41 | return members; 42 | } 43 | 44 | public static List processChatRoom(JSONArray chatrooms) { 45 | 46 | List roomList = new ArrayList(); 47 | for (int i = 0; i < chatrooms.size(); i++) { 48 | JSONObject item = chatrooms.get(i).asJSONObject(); 49 | ChatRoom chatRoom = ChatRoom.parseFromJSON(item); 50 | LOGGER.warn("当前群:{},人数:{}", chatRoom.getNickName(), chatRoom.getMemberCount()); 51 | JSONArray memberArray = item.get("MemberList").asArray(); 52 | List memberList = processChatRoomMember(memberArray); 53 | chatRoom.setMemberList(memberList); 54 | roomList.add(chatRoom); 55 | } 56 | return roomList; 57 | 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/FileHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.io.File; 4 | import java.nio.file.Path; 5 | import java.nio.file.Paths; 6 | import java.util.Date; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Random; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import com.blade.kit.StringKit; 15 | import com.blade.kit.http.HttpRequest; 16 | import com.blade.kit.json.JSONObject; 17 | import com.iyuexian.wechat4j.core.WechatMeta; 18 | import com.iyuexian.wechat4j.exception.WechatException; 19 | import com.iyuexian.wechat4j.util.CookieUtil; 20 | import com.iyuexian.wechat4j.util.FileUtil; 21 | 22 | public class FileHandler { 23 | public static Logger LOGGER = LoggerFactory.getLogger(FileHandler.class); 24 | private WechatMeta meta; 25 | 26 | public FileHandler(WechatMeta meta) { 27 | super(); 28 | this.meta = meta; 29 | } 30 | 31 | public String uploadFile(String filePath, String toUserName) { 32 | 33 | Map params = new HashMap(); 34 | 35 | Path path = Paths.get(filePath); 36 | String contentType = FileUtil.getContentType(path, "text/plain"); 37 | File file = path.toFile(); 38 | params.put("id", "WU_FILE_0"); 39 | params.put("name", file.getName()); 40 | params.put("type", contentType); 41 | params.put("size", file.length()); 42 | params.put("mediatype", FileUtil.isDoc(contentType) ? "doc" : FileUtil.isPicture(contentType) ? "pic" : "video"); // doc,video,pic 43 | String fileMD5 = FileUtil.getMD5(file); 44 | params.put("uploadmediarequest", getUploadmediaRequest(fileMD5, file.length(), 0, file.length(), toUserName)); 45 | params.put("webwx_data_ticket", CookieUtil.getValueFromCookieStr(meta.getCookie(), "webwx_data_ticket")); 46 | params.put("pass_ticket", meta.getPass_ticket()); 47 | HttpRequest request = HttpRequest.post("https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json") 48 | .contentType("multipart/form-data").part("filename", file.getName(), contentType, file).send(params.toString().getBytes()); 49 | 50 | String res = request.body(); 51 | LOGGER.debug("response from wechat:{}", res); 52 | request.disconnect(); 53 | if (StringKit.isBlank(res)) { 54 | throw new WechatException(res.toString()); 55 | } 56 | return res; 57 | 58 | } 59 | 60 | private JSONObject getUploadmediaRequest(String fileMD5, long totalLen, long startPos, long dataLen, String toUserName) { 61 | String clientMediaId = String.valueOf(new Date().getTime()) + String.valueOf(new Random().nextLong()).substring(0, 4); 62 | JSONObject mediaRequest = new JSONObject(); 63 | // TODO unkonw the meaning of uploadType 64 | mediaRequest.put("UploadType", 2); 65 | mediaRequest.put("BaseRequest", this.meta.getBaseRequest()); 66 | mediaRequest.put("ClientMediaId", clientMediaId); 67 | mediaRequest.put("TotalLen", totalLen); 68 | mediaRequest.put("StartPos", startPos); 69 | mediaRequest.put("DataLen", dataLen); 70 | // TODO unkonw the meaning of MediaType 71 | mediaRequest.put("MediaType", 4); 72 | mediaRequest.put("FromUserName", meta.getUser().getString("UserName")); 73 | 74 | mediaRequest.put("ToUserName", toUserName == null ? "filehelper" : toUserName); 75 | mediaRequest.put("FileMd5", fileMD5); 76 | return mediaRequest; 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/FriendAddTask.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.util.Random; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import com.blade.kit.json.JSONArray; 9 | import com.blade.kit.json.JSONObject; 10 | import com.iyuexian.wechat4j.core.WechatApiUtil; 11 | import com.iyuexian.wechat4j.core.WechatMeta; 12 | 13 | public class FriendAddTask implements Runnable { 14 | private long sleepSecond = 5; 15 | private String chatRoomName = ""; 16 | protected Logger logger = LoggerFactory.getLogger(FriendAddTask.class); 17 | private WechatMeta meta; 18 | 19 | public void start() { 20 | new Thread(this).start(); 21 | } 22 | 23 | public FriendAddTask(WechatMeta meta) { 24 | } 25 | 26 | public FriendAddTask(WechatMeta meta, String chatRoom, long sleepSecond) { 27 | this.meta = meta; 28 | this.sleepSecond = sleepSecond; 29 | this.chatRoomName = chatRoom; 30 | } 31 | 32 | @Override 33 | public void run() { 34 | JSONArray rooms = Storage.instance().getLatestChatRoomList(); 35 | for (int i = 0; i < rooms.size(); i++) { 36 | JSONObject room = rooms.get(i).asJSONObject(); 37 | logger.info("发现群:【{}】,人数:{}", room.getString("NickName"), room.getInt("MemberCount")); 38 | if (chatRoomName == null || chatRoomName.trim().length() == 0) { 39 | continue; 40 | } 41 | if (!room.getString("NickName").contains(chatRoomName)) { 42 | continue; 43 | } 44 | addFriend(room); 45 | } 46 | } 47 | 48 | private void addFriend(JSONObject room) { 49 | JSONArray members = room.get("MemberList").asArray(); 50 | for (int j = 0; j < members.size(); j++) { 51 | JSONObject member = members.get(j).asJSONObject(); 52 | String userName = member.getString("UserName"); 53 | String nickName = member.getString("NickName"); 54 | if (Storage.instance().isFriend(userName)) { 55 | logger.info("发现您的好友 【{}】,在【{}】群中,忽略", nickName, room.getString("NickName")); 56 | continue; 57 | } 58 | 59 | logger.info("开始添加好友 【{}】", nickName); 60 | WechatApiUtil.addFriend(meta, userName, "nihao"); 61 | long sleep = this.sleepSecond + new Random().nextInt(100); 62 | logger.info("休眠:{}秒", sleep); 63 | try { 64 | Thread.sleep(sleep * 1000); 65 | } catch (InterruptedException e) { 66 | e.printStackTrace(); 67 | } 68 | } 69 | } 70 | 71 | public long getSleepSecond() { 72 | return sleepSecond; 73 | } 74 | 75 | public String getChatRoomName() { 76 | return chatRoomName; 77 | } 78 | 79 | public void setSleepSecond(long sleepSecond) { 80 | this.sleepSecond = sleepSecond; 81 | } 82 | 83 | public void setChatRoomName(String chatRoomName) { 84 | this.chatRoomName = chatRoomName; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/MessageListener.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import com.blade.kit.json.JSONObject; 9 | import com.iyuexian.wechat4j.core.WechatApiUtil; 10 | import com.iyuexian.wechat4j.core.WechatMeta; 11 | import com.iyuexian.wechat4j.plugin.message.MessageManager; 12 | 13 | public class MessageListener implements Runnable { 14 | 15 | private Logger logger = LoggerFactory.getLogger(MessageListener.class); 16 | private WechatMeta meta; 17 | private MessageManager messageManager; 18 | 19 | public MessageListener(WechatMeta meta) { 20 | this.meta = meta; 21 | messageManager = new MessageManager(meta); 22 | } 23 | 24 | public void listen() { 25 | new Thread(this).start(); 26 | } 27 | 28 | @Override 29 | public void run() { 30 | WechatApiUtil.choiceSyncLine(meta); 31 | while (true) { 32 | int[] arr = WechatApiUtil.syncCheck(meta); // 消息检查 33 | logger.debug("正在监听消息,retcode={}, selector={}", arr[0], arr[1]); 34 | 35 | // retcode: 0 正常 1100 失败/登出微信 selector: 0 正常 2 新的消息 7 进入/离开聊天界面 ``` 36 | int retcode = arr[0], selector = arr[1]; 37 | 38 | if (retcode == 1100 || retcode == 1101) { 39 | logger.warn("用户微信退出"); 40 | break; 41 | } 42 | if (retcode != 0) { 43 | sleep(2); 44 | continue; 45 | } 46 | if (selector == 7) { 47 | logger.debug("进入(离开)聊天界面"); 48 | } else if (selector == 0 || selector == 3) { 49 | continue; 50 | } else if (selector == 2 || selector == 6) { 51 | handleMsg(); 52 | } 53 | sleep(4); 54 | 55 | } 56 | 57 | } 58 | 59 | private void handleMsg() { 60 | try { 61 | JSONObject data = WechatApiUtil.webwxsync(meta); 62 | messageManager.process(data); 63 | } catch (Exception ex) { 64 | logger.error("处理消息异常,ex:{}", ex); 65 | } 66 | 67 | } 68 | 69 | private void sleep(int seconds) { 70 | try { 71 | TimeUnit.SECONDS.sleep(seconds); 72 | } catch (InterruptedException e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/QRCodeWindow.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.awt.Color; 4 | import java.awt.Font; 5 | import java.awt.Graphics; 6 | 7 | import javax.swing.ImageIcon; 8 | import javax.swing.JFrame; 9 | import javax.swing.JLabel; 10 | import javax.swing.JPanel; 11 | import javax.swing.SwingConstants; 12 | import javax.swing.border.EmptyBorder; 13 | 14 | public class QRCodeWindow extends JFrame { 15 | 16 | private static final long serialVersionUID = 8550014433017811556L; 17 | private JPanel contentPane; 18 | 19 | /** 20 | * Create the frame. 21 | */ 22 | @SuppressWarnings("serial") 23 | public QRCodeWindow(final String filePath) { 24 | setBackground(Color.WHITE); 25 | this.setResizable(false); 26 | this.setTitle("\u8BF7\u7528\u624B\u673A\u626B\u63CF\u5FAE\u4FE1\u4E8C\u7EF4\u7801"); 27 | this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 28 | this.setBounds(100, 100, 297, 362); 29 | this.contentPane = new JPanel(); 30 | contentPane.setBackground(new Color(102, 153, 255)); 31 | this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 32 | this.setContentPane(contentPane); 33 | contentPane.setLayout(null); 34 | 35 | JPanel qrcodePanel = new JPanel() { 36 | public void paintComponent(Graphics g) { 37 | ImageIcon icon = new ImageIcon(filePath); 38 | // 图片随窗体大小而变化 39 | g.drawImage(icon.getImage(), 0, 0, 301, 301, this); 40 | } 41 | }; 42 | qrcodePanel.setBounds(0, 0, 295, 295); 43 | 44 | JLabel tipLable = new JLabel("扫描二维码登录微信"); 45 | tipLable.setFont(new Font("微软雅黑", Font.PLAIN, 18)); 46 | tipLable.setHorizontalAlignment(SwingConstants.CENTER); 47 | tipLable.setBounds(0, 297, 291, 37); 48 | 49 | contentPane.add(qrcodePanel); 50 | contentPane.add(tipLable); 51 | 52 | this.setLocationRelativeTo(null); 53 | this.setVisible(true); 54 | } 55 | } -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/QrUtil.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import com.iyuexian.wechat4j.config.Enums.OS; 4 | 5 | public class QrUtil { 6 | 7 | public static OS getOsName() { 8 | String os = System.getProperty("os.name").toUpperCase(); 9 | if (os.indexOf(OS.DARWIN.toString()) >= 0) { 10 | return OS.DARWIN; 11 | } else if (os.indexOf(OS.WINDOWS.toString()) >= 0) { 12 | return OS.WINDOWS; 13 | } else if (os.indexOf(OS.LINUX.toString()) >= 0) { 14 | return OS.LINUX; 15 | } else if (os.indexOf(OS.MAC.toString()) >= 0) { 16 | return OS.MAC; 17 | } 18 | return OS.OTHER; 19 | } 20 | 21 | public static void printQr(String qrPath) throws Exception { 22 | String cmd = ""; 23 | switch (getOsName()) { 24 | case WINDOWS: { 25 | cmd = " cmd /c start "; 26 | break; 27 | } 28 | case MAC: 29 | cmd = " open "; 30 | break; 31 | default: 32 | throw new RuntimeException("operation not supported"); 33 | } 34 | Runtime runtime = Runtime.getRuntime(); 35 | runtime.exec(cmd + qrPath); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/Storage.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.blade.kit.json.JSONArray; 10 | import com.blade.kit.json.JSONObject; 11 | import com.iyuexian.wechat4j.config.Constant; 12 | 13 | public class Storage { 14 | 15 | public static final Logger LOGGER = LoggerFactory.getLogger(Storage.class); 16 | 17 | private List LATEST_GROUP_USERNAME_LIST = new ArrayList(); 18 | private JSONArray latestChatRoomList; 19 | 20 | private JSONArray allContact = new JSONArray(); 21 | private JSONArray chatRoomList = new JSONArray(); 22 | private JSONArray mpList = new JSONArray(); 23 | private JSONArray specailList = new JSONArray(); 24 | private JSONArray friendList = new JSONArray(); 25 | 26 | private static Storage instance = null; 27 | 28 | private Storage() { 29 | }; 30 | 31 | public synchronized static Storage instance() { 32 | if (instance != null) 33 | return instance; 34 | instance = new Storage(); 35 | return instance; 36 | 37 | } 38 | 39 | public void addLasetChatroomUserName(String userName) { 40 | this.LATEST_GROUP_USERNAME_LIST.add(userName); 41 | } 42 | 43 | public void loadMemberList(JSONArray all) { 44 | 45 | this.allContact = all; 46 | if (all != null) { 47 | parseMemberList(allContact); 48 | } 49 | 50 | } 51 | 52 | private void clear() { 53 | this.mpList = new JSONArray(); 54 | this.specailList = new JSONArray(); 55 | this.chatRoomList = new JSONArray(); 56 | 57 | } 58 | 59 | private void parseMemberList(JSONArray contactList) { 60 | clear(); 61 | for (int i = 0; i < contactList.size(); i++) { 62 | JSONObject item = contactList.get(i).asJSONObject(); 63 | if (item.getInt("VerifyFlag", 0) == 8) { 64 | mpList.add(item); 65 | } else if (Constant.FILTER_USERS.contains(item.getString("UserName"))) { 66 | specailList.add(item); 67 | 68 | } else if (item.getString("UserName").indexOf("@@") != -1) { 69 | chatRoomList.add(item); 70 | 71 | } else { 72 | friendList.add(item); 73 | 74 | } 75 | } 76 | LOGGER.info("初始化联系人完成,当前共加载{}个联系人,公众号:{}个,好友:{}个,群:{}个", allContact.size(), mpList.size(), friendList.size(), chatRoomList.size()); 77 | } 78 | 79 | public boolean isFriend(String userName) { 80 | for (int i = 0; i < friendList.size(); i++) { 81 | JSONObject member = friendList.get(i).asJSONObject(); 82 | if (member.getString("UserName").equals(userName)) { 83 | return true; 84 | } 85 | } 86 | return false; 87 | } 88 | 89 | public List getLatestChatRoomUserNameList() { 90 | return this.LATEST_GROUP_USERNAME_LIST; 91 | } 92 | 93 | public JSONArray getAllContact() { 94 | return allContact; 95 | } 96 | 97 | public JSONArray getChatRoomList() { 98 | return chatRoomList; 99 | } 100 | 101 | public JSONArray getMpList() { 102 | return mpList; 103 | } 104 | 105 | public JSONArray getSpecailList() { 106 | return specailList; 107 | } 108 | 109 | public JSONArray getFriendList() { 110 | return friendList; 111 | } 112 | 113 | public JSONArray getLatestChatRoomList() { 114 | return latestChatRoomList; 115 | } 116 | 117 | public void setLatestChatRoomList(JSONArray latestChatRoomList) { 118 | this.latestChatRoomList = latestChatRoomList; 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/Task.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | public abstract class Task { 4 | public void start() { 5 | try { 6 | new Thread(wrapWithRunnable(), "user-tasks-" + System.currentTimeMillis()).start(); 7 | } catch (Exception ex) { 8 | ex.printStackTrace(); 9 | } 10 | } 11 | 12 | public Runnable wrapWithRunnable() { 13 | return new Runnable() { 14 | @Override 15 | public void run() { 16 | initTask(); 17 | } 18 | }; 19 | } 20 | public abstract void initTask(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/TulingRobot.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.blade.kit.http.HttpRequest; 7 | import com.blade.kit.json.JSON; 8 | import com.blade.kit.json.JSONObject; 9 | import com.iyuexian.wechat4j.util.TulingUtil; 10 | 11 | public class TulingRobot { 12 | public static final Logger LOGGER = LoggerFactory.getLogger(TulingRobot.class); 13 | private String key = "7507257e2872417d9e4fb0e2764cf0ac"; 14 | private String secret = "36c3be794b4950dc"; 15 | private String url = "http://www.tuling123.com/openapi/api"; 16 | private static TulingRobot instance = null; 17 | 18 | private static final int V1 = 1; 19 | private static final int V2 = 2; 20 | 21 | private TulingRobot() { 22 | } 23 | 24 | public static TulingRobot instance() { 25 | if (instance != null) { 26 | return instance; 27 | } 28 | instance = new TulingRobot(); 29 | return instance; 30 | } 31 | 32 | public String chat(String userId, String content) { 33 | return chat(userId, content, null); 34 | } 35 | 36 | public String chat(String userId, String content, Location location) { 37 | if (content == null) 38 | throw new IllegalArgumentException("content不能为null"); 39 | try { 40 | JSONObject params = populateV2Param(content, userId); 41 | String resp = send(params, V1); 42 | if (resp == null) 43 | return ""; 44 | return JSON.parse(resp).asJSONObject().getString("text"); 45 | } catch (Exception ex) { 46 | ex.printStackTrace(); 47 | return ""; 48 | } 49 | 50 | } 51 | 52 | public JSONObject populateV2Param(String content, String userId) { 53 | 54 | JSONObject params = new JSONObject(); 55 | params.put("key", key); 56 | params.put("info", content); 57 | params.put("userid", userId); 58 | return params; 59 | } 60 | 61 | public JSONObject populateV2Param(String content, String userId, Location location) { 62 | JSONObject params = new JSONObject(); 63 | JSONObject perception = new JSONObject(); 64 | perception.put("inputText", new InputText(content)); 65 | 66 | JSONObject userInfo = new JSONObject(); 67 | userInfo.put("apiKey", key); 68 | new UserInfo(key, userId); 69 | params.put("userInfo", userInfo); 70 | params.put("perception", perception); 71 | 72 | if (location != null) { 73 | JSONObject selfInfo = new JSONObject(); 74 | selfInfo.put("location", location); 75 | params.put("selfInfo", selfInfo); 76 | 77 | } 78 | return params; 79 | 80 | } 81 | 82 | public String encryptSend(JSONObject reqParams) throws Exception { 83 | long timestamp = System.currentTimeMillis(); 84 | String keyParam = secret + timestamp + key; 85 | String aesKey = TulingUtil.MD5(keyParam); 86 | String data = TulingUtil.encrypt(aesKey, reqParams.toString()); 87 | 88 | JSONObject req = new JSONObject(); 89 | req.put("key", key); 90 | req.put("timestamp", String.valueOf(timestamp)); 91 | req.put("data", data); 92 | return send(req, V2); 93 | 94 | } 95 | 96 | public String send(JSONObject params, int version) { 97 | 98 | if (version == V2) { 99 | url = url + "/v2"; 100 | } 101 | 102 | HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8"); 103 | request.send(params.toString()); 104 | String resp = request.body(); 105 | request.disconnect(); 106 | return resp; 107 | } 108 | 109 | // private String encryptReq(Map reqParam) throws Exception 110 | // { 111 | // long timestamp = System.currentTimeMillis(); 112 | // String keyParam = secret + timestamp + key; 113 | // String aesKey = TulingUtil.MD5(keyParam); 114 | // String data = TulingUtil.encrypt(aesKey, JSON.toJSONString(reqParam)); 115 | // Map req = new HashMap(); 116 | // req.put("key", key); 117 | // req.put("timestamp", String.valueOf(timestamp)); 118 | // req.put("data", data); 119 | // String str = 120 | // TulingUtil.sendPost(com.alibaba.fastjson.JSON.toJSONString(req), url); 121 | // if (str == null || str.trim().length() == 0) 122 | // return ""; 123 | // 124 | // JSONObject repJSON = JSON.parseObject(str); 125 | // // int code = repJSON.getIntValue("code"); 126 | // String text = repJSON.getString("text"); 127 | // return text; 128 | // 129 | // } 130 | 131 | public String getKey() { 132 | return key; 133 | } 134 | 135 | public void setKey(String key) { 136 | this.key = key; 137 | } 138 | 139 | public String getSecret() { 140 | return secret; 141 | } 142 | 143 | public void setSecret(String secret) { 144 | this.secret = secret; 145 | } 146 | 147 | public String getUrl() { 148 | return url; 149 | } 150 | 151 | public void setUrl(String url) { 152 | this.url = url; 153 | } 154 | 155 | public static class InputText { 156 | 157 | private String text; 158 | 159 | public InputText(String text) { 160 | super(); 161 | this.text = text; 162 | } 163 | 164 | public String getText() { 165 | return text; 166 | } 167 | 168 | public void setText(String text) { 169 | this.text = text; 170 | } 171 | 172 | } 173 | 174 | public static class Location { 175 | 176 | private String city; // 例如:北京 177 | private String latitude; 178 | private String longitude; 179 | private String nearest_poi_name;// 例如:上地环岛南 180 | private String province;// 例如:北京 181 | private String street; // 例如:信息路 182 | 183 | public String getCity() { 184 | return city; 185 | } 186 | 187 | public String getLatitude() { 188 | return latitude; 189 | } 190 | 191 | public String getLongitude() { 192 | return longitude; 193 | } 194 | 195 | public String getNearest_poi_name() { 196 | return nearest_poi_name; 197 | } 198 | 199 | public String getProvince() { 200 | return province; 201 | } 202 | 203 | public String getStreet() { 204 | return street; 205 | } 206 | 207 | public void setCity(String city) { 208 | this.city = city; 209 | } 210 | 211 | public void setLatitude(String latitude) { 212 | this.latitude = latitude; 213 | } 214 | 215 | public void setLongitude(String longitude) { 216 | this.longitude = longitude; 217 | } 218 | 219 | public void setNearest_poi_name(String nearest_poi_name) { 220 | this.nearest_poi_name = nearest_poi_name; 221 | } 222 | 223 | public void setProvince(String province) { 224 | this.province = province; 225 | } 226 | 227 | public void setStreet(String street) { 228 | this.street = street; 229 | } 230 | 231 | } 232 | 233 | public static class UserInfo { 234 | 235 | private String apiKey; 236 | private String userId; 237 | 238 | public UserInfo(String apiKey, String userId) { 239 | this.apiKey = apiKey; 240 | this.userId = userId; 241 | } 242 | 243 | public String getApiKey() { 244 | return apiKey; 245 | } 246 | 247 | public String getUserId() { 248 | return userId; 249 | } 250 | 251 | public void setApiKey(String apiKey) { 252 | this.apiKey = apiKey; 253 | } 254 | 255 | public void setUserId(String userId) { 256 | this.userId = userId; 257 | } 258 | 259 | } 260 | 261 | } 262 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/TxtMessageRobot.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | public interface TxtMessageRobot { 4 | 5 | public String reply(String uid, String content); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/WxLocalCache.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.blade.kit.json.JSONArray; 10 | import com.blade.kit.json.JSONObject; 11 | import com.iyuexian.wechat4j.core.WechatMeta; 12 | 13 | public class WxLocalCache { 14 | 15 | private final String CONTACT = "webwxgetcontact"; 16 | private final String LATEST_CONTACT = "latest_webwxgetcontact"; 17 | 18 | private Map cacheInstance; 19 | private ContactManager contactManager; 20 | 21 | private Logger logger = LoggerFactory.getLogger(WxLocalCache.class); 22 | 23 | private WxLocalCache(WechatMeta meta) { 24 | super(); 25 | this.cacheInstance = new HashMap(); 26 | this.contactManager = new ContactManager(meta); 27 | } 28 | 29 | static class Holder { 30 | static WxLocalCache instance = null; 31 | } 32 | 33 | public static WxLocalCache instance() { 34 | if (Holder.instance == null) { 35 | throw new IllegalStateException("wxLocalCache not init"); 36 | } 37 | return Holder.instance; 38 | 39 | } 40 | 41 | public static WxLocalCache init(WechatMeta meta) { 42 | if (Holder.instance != null) { 43 | return Holder.instance; 44 | } 45 | Holder.instance = new WxLocalCache(meta); 46 | return Holder.instance; 47 | } 48 | 49 | public JSONArray getContactList() { 50 | JSONArray arr = get(CONTACT); 51 | if (arr == null && (arr = contactManager.getContactList()) == null) { 52 | logger.error("获取联系人失败"); 53 | return null; 54 | } 55 | return arr; 56 | } 57 | 58 | public JSONObject getContactByRemarkName(String remarkName) { 59 | return getContactByName("RemarkName", remarkName); 60 | } 61 | 62 | public JSONObject getContactByNickName(String nickName) { 63 | return getContactByName("NickName", nickName); 64 | } 65 | 66 | public JSONObject getContactByUserName(String ContactName) { 67 | return getContactByName("UserName", ContactName); 68 | } 69 | 70 | private JSONObject getContactByName(String fieldName, String fieldVal) { 71 | JSONArray arr = getContactList(); 72 | if (arr == null) { 73 | return null; 74 | } 75 | 76 | for (int i = 0; i < arr.size(); i++) { 77 | JSONObject val = arr.get(i).asJSONObject(); 78 | String userName = val.getString("UserName"); 79 | String nickName = val.getString("NickName"); 80 | String remarkName = val.getString("RemarkName"); 81 | if (fieldName.equals("UserName") && userName.equals(fieldVal)) { 82 | return val; 83 | } else if (fieldName.equals("NickName") && nickName.equals(fieldVal)) { 84 | return val; 85 | } else if (fieldName.equals("RemarkName") && remarkName.equals(fieldVal)) { 86 | return val; 87 | } 88 | } 89 | logger.error("can't find the contact of " + fieldName + " named " + fieldName); 90 | return null; 91 | 92 | } 93 | 94 | public void put(String key, Object data) { 95 | CacheItem item = new CacheItem(key, data); 96 | cacheInstance.put(key, item); 97 | } 98 | 99 | @SuppressWarnings("unchecked") 100 | public T get(String key) { 101 | CacheItem item = cacheInstance.get(key); 102 | if (item == null) { 103 | return null; 104 | } 105 | return (T) item.getData(); 106 | 107 | } 108 | 109 | public static class CacheItem { 110 | 111 | private String key; 112 | private Object data; 113 | private long timestamp; 114 | 115 | public CacheItem(String key, Object data) { 116 | this.key = key; 117 | this.data = data; 118 | this.timestamp = System.currentTimeMillis(); 119 | 120 | } 121 | 122 | public String getKey() { 123 | return key; 124 | } 125 | 126 | public Object getData() { 127 | return data; 128 | } 129 | 130 | public long getTimestamp() { 131 | return timestamp; 132 | } 133 | } 134 | 135 | public JSONArray getLatestContactList() { 136 | return get(LATEST_CONTACT); 137 | } 138 | 139 | 140 | 141 | public void setLatestContactList(JSONArray contactList) { 142 | put(LATEST_CONTACT, contactList); 143 | 144 | for (int i = 0; i < contactList.size(); i++) { 145 | JSONObject item = contactList.get(i).asJSONObject(); 146 | logger.info("初始化最新联系人 ,item:{}", item.getString("NickName")); 147 | String userName = item.getString("UserName"); 148 | // 最近联系的群 149 | if (userName.startsWith("@@")) { 150 | Storage.instance().addLasetChatroomUserName(userName); 151 | continue; 152 | } 153 | // TODO 最近联系的用户 154 | } 155 | 156 | } 157 | } -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/AbstractMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.blade.kit.DateKit; 10 | import com.blade.kit.StringKit; 11 | import com.blade.kit.http.HttpRequest; 12 | import com.blade.kit.io.ByteArrayOutputStream; 13 | import com.blade.kit.json.JSONArray; 14 | import com.blade.kit.json.JSONObject; 15 | import com.iyuexian.wechat4j.config.Constant; 16 | import com.iyuexian.wechat4j.config.Enums.MsgType; 17 | import com.iyuexian.wechat4j.core.WechatMeta; 18 | import com.iyuexian.wechat4j.plugin.Storage; 19 | import com.iyuexian.wechat4j.plugin.TulingRobot; 20 | import com.iyuexian.wechat4j.plugin.TxtMessageRobot; 21 | import com.iyuexian.wechat4j.plugin.storage.PipeLineManager; 22 | import com.iyuexian.wechat4j.util.FileUploadHelper; 23 | 24 | public abstract class AbstractMessageHandler implements IMessageHandler, TxtMessageRobot { 25 | 26 | public static final Logger LOGGER = LoggerFactory.getLogger(AbstractMessageHandler.class); 27 | protected WechatMeta meta; 28 | 29 | private FileUploadHelper fileUploadHelper = new FileUploadHelper(); 30 | 31 | public AbstractMessageHandler(WechatMeta meta) { 32 | super(); 33 | this.meta = meta; 34 | } 35 | 36 | public String webwxsendmsg(String content, String to) { 37 | String url = meta.getBase_uri() + "/webwxsendmsg?lang=zh_CN&pass_ticket=" + meta.getPass_ticket(); 38 | final JSONObject body = new JSONObject(); 39 | String clientMsgId = DateKit.getCurrentUnixTime() + StringKit.getRandomNumber(5); 40 | JSONObject Msg = new JSONObject(); 41 | 42 | Msg.put("Type", 1); 43 | Msg.put("Content", content); 44 | Msg.put("FromUserName", meta.getUser().getString("UserName")); 45 | Msg.put("ToUserName", to); 46 | Msg.put("LocalID", clientMsgId); 47 | Msg.put("ClientMsgId", clientMsgId); 48 | 49 | body.put("BaseRequest", meta.getBaseRequest()); 50 | body.put("Msg", Msg); 51 | final HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8").header("Cookie", meta.getCookie()); 52 | request.send(body.toString()); 53 | String msgResult = request.body(); 54 | request.disconnect(); 55 | return msgResult; 56 | 57 | } 58 | 59 | public boolean download(JSONObject msg, MsgType msgType) { 60 | 61 | Map headers = new HashMap(); 62 | headers.put("Cookie", meta.getCookie()); 63 | Map params = new HashMap(); 64 | 65 | String ext = ""; 66 | if (msgType == MsgType.PICTURE) { 67 | ext = "jpg"; 68 | } else if (msgType == MsgType.VOICE) { 69 | ext = "mp3"; 70 | } else if (msgType == MsgType.VIDEO || msgType == MsgType.SMALL_VIDEO) { 71 | LOGGER.warn("暂时不能处理video类消息,msg:{}", msg); 72 | ext = "mp4"; 73 | } else if (msgType == MsgType.MEDIA) { 74 | headers.put("Range", "bytes=0-"); 75 | params.put("sender", msg.getString("FromUserName")); 76 | params.put("mediaid", msg.getString("MediaId")); 77 | params.put("filename", msg.getString("FileName")); 78 | } 79 | params.put("msgid", msg.getString("MsgId")); 80 | params.put("skey", meta.getSkey()); 81 | String host = meta.getBase_uri().endsWith("/") ? meta.getBase_uri() : meta.getBase_uri() + "/"; 82 | String url = host + msgType.getDownloadPath() + "?MsgID=" + msg.getString("MsgId") + "&skey=" + meta.getSkey() + "&type=slave"; 83 | LOGGER.info(" begin download resource for url:{}", url); 84 | ByteArrayOutputStream bios = new ByteArrayOutputStream(); 85 | HttpRequest.get(url, params, true).headers(headers).receive(bios); 86 | String fileKey = fileUploadHelper.uploadToQiniu(bios.toInputStream(), "file." + ext); 87 | PipeLineManager.instance().process(meta, fileKey, msgType); 88 | return true; 89 | } 90 | 91 | public String getUserRemarkName(String id) { 92 | String name = ""; 93 | for (int i = 0, len = Storage.instance().getAllContact().size(); i < len; i++) { 94 | JSONObject member = Storage.instance().getAllContact().get(i).asJSONObject(); 95 | if (!member.getString("UserName").equals(id)) { 96 | continue; 97 | } 98 | if (StringKit.isNotBlank(member.getString("RemarkName"))) { 99 | name = member.getString("RemarkName"); 100 | } else { 101 | name = member.getString("NickName"); 102 | } 103 | return name; 104 | } 105 | return name; 106 | } 107 | 108 | public String getMemberRemarkName(String chatRoomUserName, String memberUserName) { 109 | JSONArray chatRoomList = Storage.instance().getLatestChatRoomList(); 110 | for (int i = 0; i < chatRoomList.size(); i++) { 111 | JSONObject chatroom = chatRoomList.get(i).asJSONObject(); 112 | if (!chatroom.getString("UserName").equals(chatRoomUserName)) { 113 | continue; 114 | } 115 | JSONArray memberList = chatroom.get("MemberList").asArray(); 116 | for (int j = 0; j < memberList.size(); j++) { 117 | JSONObject member = memberList.get(j).asJSONObject(); 118 | if (member.getString("UserName").equals(memberUserName)) { 119 | return member.getString("NickName"); 120 | } 121 | } 122 | } 123 | return "未知昵称"; 124 | 125 | } 126 | 127 | public boolean preHandle(JSONObject msg) { 128 | 129 | if (Constant.FILTER_USERS.contains(msg.getString("ToUserName"))) { 130 | LOGGER.info("你收到一条被过滤的消息"); 131 | return false; 132 | } 133 | if (isSlefSend(msg)) { 134 | LOGGER.info("你发送了一条消息 "); 135 | return true; 136 | } 137 | 138 | if (msg.getString("FromUserName").startsWith("@@")) { 139 | LOGGER.info("您收到一条群聊消息"); 140 | return true; 141 | } 142 | if (msg.getString("FromUserName").startsWith("@")) { 143 | LOGGER.info("您收到一条好友消息"); 144 | return true; 145 | } 146 | LOGGER.warn("您收到一条 未知类型消息:{}", msg.toString()); 147 | return true; 148 | 149 | } 150 | 151 | public boolean isSlefSend(JSONObject msg) { 152 | return msg.getString("FromUserName").equals(this.meta.getUser().getString("UserName")); 153 | } 154 | 155 | public String getSelfNickName() { 156 | return this.meta.getUser().getString("NickName"); 157 | } 158 | 159 | public String getGroupMemberName(JSONObject msg) { 160 | String memberUserName = msg.getString("Content").split(":")[0]; 161 | return getMemberRemarkName(msg.getString("FromUserName"), memberUserName); 162 | } 163 | 164 | public String getMemberNickName(JSONObject msg) { 165 | if (isSlefSend(msg)) { 166 | return getSelfNickName(); 167 | } else if (isGroupMsg(msg)) { 168 | return getGroupMemberName(msg); 169 | } else { 170 | return getUserRemarkName(msg.getString("FromUserName")); 171 | } 172 | } 173 | 174 | public boolean isGroupMsg(JSONObject msg) { 175 | return msg.getString("FromUserName").startsWith("@@"); 176 | } 177 | 178 | @Override 179 | public String reply(String uid, String content) { 180 | return TulingRobot.instance().chat(uid, content); 181 | } 182 | 183 | } 184 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/IMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import com.blade.kit.json.JSONObject; 4 | 5 | public interface IMessageHandler { 6 | public void process(JSONObject msg); 7 | 8 | 9 | } 10 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/MessageManager.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.blade.kit.json.JSONArray; 10 | import com.blade.kit.json.JSONObject; 11 | import com.iyuexian.wechat4j.config.Enums.MsgType; 12 | import com.iyuexian.wechat4j.core.WechatMeta; 13 | 14 | public class MessageManager implements IMessageHandler { 15 | protected Logger logger = LoggerFactory.getLogger(MessageManager.class); 16 | 17 | private WechatMeta meta; 18 | private Map handlers = new HashMap(); 19 | 20 | public MessageManager(WechatMeta meta) { 21 | this.meta = meta; 22 | register(); 23 | } 24 | 25 | private IMessageHandler getMessageHandler(int type) { 26 | MsgType msgType = MsgType.getType(type); 27 | if (msgType == null) 28 | return handlers.get(MsgType.TXT); 29 | return handlers.get(msgType); 30 | 31 | } 32 | 33 | private void register() { 34 | handlers.put(MsgType.TXT, new TxtMessageHandler(meta)); 35 | handlers.put(MsgType.TXT, new TxtMessageHandler(meta)); 36 | handlers.put(MsgType.VOICE, new VoiceMessageHandler(meta)); 37 | handlers.put(MsgType.PICTURE, new PictureMessageHandler(meta)); 38 | handlers.put(MsgType.SHARE_MP, new MpMessageHandler(meta)); 39 | VideoMessageHandler videoMessageHandler = new VideoMessageHandler(meta); 40 | handlers.put(MsgType.SMALL_VIDEO, videoMessageHandler); 41 | handlers.put(MsgType.VIDEO, videoMessageHandler); 42 | } 43 | 44 | @Override 45 | public void process(JSONObject data) { 46 | if (null == data) { 47 | logger.warn("data不能为空"); 48 | } 49 | JSONArray AddMsgList = data.get("AddMsgList").asArray(); 50 | for (int i = 0, len = AddMsgList.size(); i < len; i++) { 51 | JSONObject msg = AddMsgList.get(i).asJSONObject(); 52 | processSingleMsg(msg); 53 | } 54 | 55 | } 56 | 57 | private void processSingleMsg(JSONObject msg) { 58 | int msgType = msg.getInt("MsgType", 0); 59 | if (msgType == 51) { 60 | logger.info("msgType:{},do nothing", msgType); 61 | return; 62 | } 63 | IMessageHandler messageHandler = getMessageHandler(msgType); 64 | if (messageHandler == null) { 65 | logger.error("msgType:{},无法找到对应的消息处理器", msgType); 66 | return; 67 | } 68 | messageHandler.process(msg); 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/MpMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.blade.kit.json.JSONObject; 7 | import com.iyuexian.wechat4j.core.WechatMeta; 8 | 9 | public class MpMessageHandler extends AbstractMessageHandler { 10 | 11 | private static final Logger LOGGER = LoggerFactory.getLogger(VoiceMessageHandler.class); 12 | 13 | public MpMessageHandler(WechatMeta meta) { 14 | super(meta); 15 | this.meta = meta; 16 | } 17 | 18 | @Override 19 | public void process(JSONObject msg) { 20 | LOGGER.info("do nothing"); 21 | webwxsendmsg("不知道你在说什么", msg.getString("FromUserName")); 22 | } 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/PictureMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.blade.kit.json.JSONObject; 7 | import com.iyuexian.wechat4j.config.Enums.MsgType; 8 | import com.iyuexian.wechat4j.core.WechatMeta; 9 | 10 | public class PictureMessageHandler extends AbstractMessageHandler { 11 | 12 | private static final Logger LOGGER = LoggerFactory.getLogger(PictureMessageHandler.class); 13 | 14 | public PictureMessageHandler(WechatMeta meta) { 15 | super(meta); 16 | this.meta = meta; 17 | } 18 | 19 | @Override 20 | public void process(JSONObject msg) { 21 | LOGGER.info("开始处理图片消息"); 22 | download(msg, MsgType.PICTURE); 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/TxtMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.blade.kit.json.JSONObject; 7 | import com.iyuexian.wechat4j.config.Enums.MsgType; 8 | import com.iyuexian.wechat4j.core.WechatMeta; 9 | import com.iyuexian.wechat4j.plugin.storage.PipeLineManager; 10 | 11 | public class TxtMessageHandler extends AbstractMessageHandler { 12 | 13 | private static final Logger LOGGER = LoggerFactory.getLogger(TxtMessageHandler.class); 14 | 15 | // private AccountConfigDao accountConfigDao = new AccountConfigDao(); 16 | 17 | public TxtMessageHandler(WechatMeta meta) { 18 | super(meta); 19 | this.meta = meta; 20 | } 21 | 22 | @Override 23 | public void process(JSONObject msg) { 24 | String content = msg.getString("Content"); 25 | LOGGER.info("content:{}", content); 26 | if (!preHandle(msg)) { 27 | return; 28 | } 29 | 30 | String fromUserName = msg.getString("FromUserName"); 31 | String fromNickName = getUserRemarkName(fromUserName); 32 | String selftName = getSelfNickName(); 33 | String[] contentArray = content.split(":"); 34 | if (contentArray.length == 0 || contentArray.length == 1) { 35 | } else { 36 | content = contentArray[1].replace("
", "\n"); 37 | } 38 | PipeLineManager.instance().process(meta, fromNickName + "-" + selftName + ":" + content, MsgType.TXT); 39 | // String autoReplay = accountConfigDao.selectOne(meta.getMobile(), 40 | // AccountConfig.NAME_AUTO_REPLAY); 41 | // if (!AccountConfig.ON.equals(autoReplay)) { 42 | // LOGGER.warn("auto reply setting was off,you can switch on it"); 43 | // return; 44 | // } 45 | String ans = reply(fromUserName, content); 46 | webwxsendmsg(ans, msg.getString("FromUserName")); 47 | PipeLineManager.instance().process(meta, selftName + "-" + fromNickName + ":" + ans, MsgType.TXT); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/VideoMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.blade.kit.json.JSONObject; 7 | import com.iyuexian.wechat4j.config.Enums.MsgType; 8 | import com.iyuexian.wechat4j.core.WechatMeta; 9 | 10 | public class VideoMessageHandler extends AbstractMessageHandler { 11 | 12 | private static final Logger LOGGER = LoggerFactory.getLogger(VideoMessageHandler.class); 13 | 14 | public VideoMessageHandler(WechatMeta meta) { 15 | super(meta); 16 | this.meta = meta; 17 | } 18 | 19 | @Override 20 | public void process(JSONObject msg) { 21 | LOGGER.info("开始处理视频消息"); 22 | download(msg, MsgType.VIDEO); 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/message/VoiceMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.message; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.blade.kit.json.JSONObject; 7 | import com.iyuexian.wechat4j.config.Enums; 8 | import com.iyuexian.wechat4j.core.WechatMeta; 9 | 10 | public class VoiceMessageHandler extends AbstractMessageHandler { 11 | 12 | private static final Logger LOGGER = LoggerFactory.getLogger(VoiceMessageHandler.class); 13 | 14 | public VoiceMessageHandler(WechatMeta meta) { 15 | super(meta); 16 | this.meta = meta; 17 | } 18 | 19 | @Override 20 | public void process(JSONObject msg) { 21 | LOGGER.info("开始处理语音消息"); 22 | download(msg, Enums.MsgType.VOICE); 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/storage/FilePipeLine.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.storage; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Paths; 7 | import java.nio.file.StandardOpenOption; 8 | 9 | import com.iyuexian.wechat4j.config.Constant; 10 | import com.iyuexian.wechat4j.config.Enums.MsgType; 11 | import com.iyuexian.wechat4j.core.WechatMeta; 12 | 13 | public class FilePipeLine implements MessagePipeLine { 14 | 15 | @Override 16 | public void processs(WechatMeta meta, String line, MsgType msgType) { 17 | 18 | File f = new File(Constant.configReader.get("app.msg_location")); 19 | if (!f.exists()) { 20 | f.mkdirs(); 21 | } 22 | try { 23 | Files.write(Paths.get(Constant.configReader.get("app.msg_location")), line.toString().getBytes(), StandardOpenOption.CREATE, 24 | StandardOpenOption.WRITE, StandardOpenOption.APPEND); 25 | } catch (IOException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/storage/MessagePipeLine.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.storage; 2 | 3 | import com.iyuexian.wechat4j.config.Enums.MsgType; 4 | import com.iyuexian.wechat4j.core.WechatMeta; 5 | 6 | public interface MessagePipeLine { 7 | public void processs(WechatMeta meata, String line, MsgType msgType); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/plugin/storage/PipeLineManager.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.plugin.storage; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.iyuexian.wechat4j.config.Enums.MsgType; 7 | import com.iyuexian.wechat4j.core.WechatMeta; 8 | 9 | public class PipeLineManager { 10 | private List pipelines; 11 | 12 | static class Holder { 13 | static PipeLineManager instance = new PipeLineManager(); 14 | } 15 | 16 | public static PipeLineManager instance() { 17 | return Holder.instance; 18 | } 19 | 20 | private PipeLineManager() { 21 | pipelines = new ArrayList(); 22 | } 23 | 24 | public void process(WechatMeta meta, String line, MsgType msgType) { 25 | for (MessagePipeLine pipeLine : pipelines) { 26 | if (pipeLine != null) { 27 | pipeLine.processs(meta, line, msgType); 28 | } 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/Converter.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | public interface Converter { 4 | public T convert(S s); 5 | 6 | } 7 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/CookieUtil.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | import java.net.HttpURLConnection; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import com.blade.kit.http.HttpRequest; 8 | 9 | public class CookieUtil { 10 | 11 | public static String getCookie(HttpRequest request) { 12 | HttpURLConnection conn = request.getConnection(); 13 | Map> resHeaders = conn.getHeaderFields(); 14 | StringBuffer sBuffer = new StringBuffer(); 15 | for (Map.Entry> entry : resHeaders.entrySet()) { 16 | String name = entry.getKey(); 17 | if (name == null) 18 | continue; // http/1.1 line 19 | List values = entry.getValue(); 20 | if (name.equalsIgnoreCase("Set-Cookie")) { 21 | for (String value : values) { 22 | if (value == null) { 23 | continue; 24 | } 25 | String cookie = value.substring(0, value.indexOf(";") + 1); 26 | sBuffer.append(cookie); 27 | } 28 | } 29 | } 30 | if (sBuffer.length() > 0) { 31 | return sBuffer.toString(); 32 | } 33 | return sBuffer.toString(); 34 | } 35 | 36 | public static String getValueFromCookieStr(String cookieStr, String name) { 37 | 38 | if (cookieStr == null || cookieStr.trim().length() == 0) { 39 | return null; 40 | } 41 | String[] kvPairs = cookieStr.split(";"); 42 | 43 | for (String item : kvPairs) { 44 | String[] kv = item.split("="); 45 | if (kv.length == 0) { 46 | continue; 47 | } 48 | 49 | String cookieName = kv[0]; 50 | if (name.equals(cookieName)) { 51 | return kv.length > 1 ? kv[1] : ""; 52 | } 53 | 54 | } 55 | return ""; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/DigestUtils.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | public abstract class DigestUtils { 7 | 8 | 9 | private static final String MD5_ALGORITHM_NAME = "MD5"; 10 | 11 | private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 12 | 13 | /** 14 | * Calculate the MD5 digest of the given bytes. 15 | * 16 | * @param bytes 17 | * the bytes to calculate the digest over 18 | * @return the digest 19 | */ 20 | public static byte[] md5Digest(byte[] bytes) { 21 | return digest(MD5_ALGORITHM_NAME, bytes); 22 | } 23 | 24 | /** 25 | * Return a hexadecimal string representation of the MD5 digest of the given 26 | * bytes. 27 | * 28 | * @param bytes 29 | * the bytes to calculate the digest over 30 | * @return a hexadecimal digest string 31 | */ 32 | public static String md5DigestAsHex(byte[] bytes) { 33 | return digestAsHexString(MD5_ALGORITHM_NAME, bytes); 34 | } 35 | 36 | /** 37 | * Append a hexadecimal string representation of the MD5 digest of the given 38 | * bytes to the given {@link StringBuilder}. 39 | * 40 | * @param bytes 41 | * the bytes to calculate the digest over 42 | * @param builder 43 | * the string builder to append the digest to 44 | * @return the given string builder 45 | */ 46 | public static StringBuilder appendMd5DigestAsHex(byte[] bytes, StringBuilder builder) { 47 | return appendDigestAsHex(MD5_ALGORITHM_NAME, bytes, builder); 48 | } 49 | 50 | /** 51 | * Creates a new {@link MessageDigest} with the given algorithm. Necessary 52 | * because {@code MessageDigest} is not thread-safe. 53 | */ 54 | private static MessageDigest getDigest(String algorithm) { 55 | try { 56 | return MessageDigest.getInstance(algorithm); 57 | } catch (NoSuchAlgorithmException ex) { 58 | throw new IllegalStateException("Could not find MessageDigest with algorithm \"" + algorithm + "\"", ex); 59 | } 60 | } 61 | 62 | private static byte[] digest(String algorithm, byte[] bytes) { 63 | return getDigest(algorithm).digest(bytes); 64 | } 65 | 66 | private static String digestAsHexString(String algorithm, byte[] bytes) { 67 | char[] hexDigest = digestAsHexChars(algorithm, bytes); 68 | return new String(hexDigest); 69 | } 70 | 71 | private static StringBuilder appendDigestAsHex(String algorithm, byte[] bytes, StringBuilder builder) { 72 | char[] hexDigest = digestAsHexChars(algorithm, bytes); 73 | return builder.append(hexDigest); 74 | } 75 | 76 | private static char[] digestAsHexChars(String algorithm, byte[] bytes) { 77 | byte[] digest = digest(algorithm, bytes); 78 | return encodeHex(digest); 79 | } 80 | 81 | private static char[] encodeHex(byte[] bytes) { 82 | char chars[] = new char[32]; 83 | for (int i = 0; i < chars.length; i = i + 2) { 84 | byte b = bytes[i / 2]; 85 | chars[i] = HEX_CHARS[(b >>> 0x4) & 0xf]; 86 | chars[i + 1] = HEX_CHARS[b & 0xf]; 87 | } 88 | return chars; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/Emptys.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | /** 4 | * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.com) 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import java.io.Serializable; 20 | 21 | /** 22 | * 定义各种代表“空”的常量 23 | * 24 | * @author biezhi 25 | * @since 1.0 26 | */ 27 | public abstract class Emptys { 28 | 29 | // ============================================================= 30 | // 数组常量 31 | // ============================================================= 32 | 33 | // primitive arrays 34 | 35 | /** 空的byte数组。 */ 36 | public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 37 | public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0]; 38 | 39 | /** 空的short数组。 */ 40 | public static final short[] EMPTY_SHORT_ARRAY = new short[0]; 41 | public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0]; 42 | 43 | /** 空的int数组。 */ 44 | public static final int[] EMPTY_INT_ARRAY = new int[0]; 45 | public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0]; 46 | 47 | /** 空的long数组。 */ 48 | public static final long[] EMPTY_LONG_ARRAY = new long[0]; 49 | public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0]; 50 | 51 | /** 空的float数组。 */ 52 | public static final float[] EMPTY_FLOAT_ARRAY = new float[0]; 53 | public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0]; 54 | 55 | /** 空的double数组。 */ 56 | public static final double[] EMPTY_DOUBLE_ARRAY = new double[0]; 57 | public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0]; 58 | 59 | /** 空的char数组。 */ 60 | public static final char[] EMPTY_CHAR_ARRAY = new char[0]; 61 | public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0]; 62 | 63 | /** 空的boolean数组。 */ 64 | public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0]; 65 | public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0]; 66 | 67 | // object arrays 68 | 69 | /** 空的Object数组。 */ 70 | public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; 71 | 72 | /** 空的Class数组。 */ 73 | public static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; 74 | 75 | /** 空的String数组。 */ 76 | public static final String[] EMPTY_STRING_ARRAY = new String[0]; 77 | 78 | // ============================================================= 79 | // 对象常量 80 | // ============================================================= 81 | 82 | // 0-valued primitive wrappers 83 | public static final Byte BYTE_ZERO = new Byte((byte) 0); 84 | public static final Short SHORT_ZERO = new Short((short) 0); 85 | public static final Integer INT_ZERO = new Integer(0); 86 | public static final Long LONG_ZERO = new Long(0L); 87 | public static final Float FLOAT_ZERO = new Float(0); 88 | public static final Double DOUBLE_ZERO = new Double(0); 89 | public static final Character CHAR_NULL = new Character('\0'); 90 | public static final Boolean BOOL_FALSE = Boolean.FALSE; 91 | 92 | /** 代表null值的占位对象。 */ 93 | public static final Object NULL_PLACEHOLDER = new NullPlaceholder(); 94 | 95 | private final static class NullPlaceholder implements Serializable { 96 | 97 | /** 98 | * 99 | */ 100 | private static final long serialVersionUID = 5893921848518437319L; 101 | 102 | @Override 103 | public String toString() { 104 | return "null"; 105 | } 106 | 107 | private Object readResolve() { 108 | return NULL_PLACEHOLDER; 109 | } 110 | } 111 | 112 | /** 空字符串。 */ 113 | public static final String EMPTY_STRING = ""; 114 | 115 | } -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/FileUploadHelper.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | import java.io.InputStream; 4 | import java.util.Calendar; 5 | import java.util.UUID; 6 | 7 | import org.apache.commons.io.IOUtils; 8 | 9 | import com.iyuexian.wechat4j.config.Constant; 10 | import com.qiniu.http.Response; 11 | import com.qiniu.storage.UploadManager; 12 | import com.qiniu.util.Auth; 13 | 14 | public class FileUploadHelper { 15 | 16 | private String ak = Constant.configReader.get(Constant.QINIU_AK); 17 | private String secret = Constant.configReader.get(Constant.QINIU_SK); 18 | private String bucket = Constant.configReader.get(Constant.QINIU_BUCKET_IMAGE0); 19 | private UploadManager uploadManager = new UploadManager(); 20 | 21 | public FileUploadHelper(String ak, String secret, String bucket, UploadManager uploadManager) { 22 | if (ak != null && ak.trim().length() > 0) 23 | this.ak = ak; 24 | 25 | if (secret != null && secret.trim().length() > 0) 26 | this.secret = secret; 27 | 28 | if (bucket != null && bucket.trim().length() > 0) 29 | this.bucket = bucket; 30 | 31 | if (uploadManager != null) { 32 | this.uploadManager = uploadManager; 33 | } 34 | 35 | } 36 | 37 | public FileUploadHelper(String ak, String secret, String bucket) { 38 | this(ak, secret, bucket, null); 39 | } 40 | 41 | public FileUploadHelper(String ak, String secret) { 42 | this(ak, secret, null, null); 43 | } 44 | 45 | public FileUploadHelper() { 46 | this(null, null, null, null); 47 | } 48 | 49 | public static String generateFileKey(String fileName) { 50 | String ext = fileName.lastIndexOf(".") > 0 ? fileName.substring(fileName.lastIndexOf(".")) : ""; 51 | return Calendar.getInstance().get(Calendar.YEAR) + "/" + UUID.randomUUID().toString().replace("-", "").toLowerCase() + ext; 52 | } 53 | 54 | public String uploadToQiniu(InputStream is, String fileName) { 55 | try { 56 | String host = Constant.configReader.get(Constant.QIUNIU_IMG_URL); 57 | String fileKey = generateFileKey(fileName); 58 | Auth auth = Auth.create(ak, secret); 59 | String uploadToken = auth.uploadToken(bucket); 60 | byte[] buffer = new byte[is.available()]; 61 | IOUtils.readFully(is, buffer); 62 | Response response = uploadManager.put(buffer, fileKey, uploadToken); 63 | return response.isOK() ? host + fileKey : ""; 64 | } catch (Exception ex) { 65 | return ""; 66 | } 67 | 68 | } 69 | 70 | public String uploadToQiniu(byte[] bytes, String originalName) { 71 | try { 72 | Auth auth = Auth.create(ak, secret); 73 | String uploadToken = auth.uploadToken(bucket); 74 | String fileKey = generateFileKey(originalName); 75 | Response response = uploadManager.put(bytes, fileKey, uploadToken); 76 | if (!response.isOK()) { 77 | return ""; 78 | } 79 | String host = Constant.configReader.get(Constant.QIUNIU_IMG_URL); 80 | return host + fileKey; 81 | } catch (Exception ex) { 82 | ex.printStackTrace(); 83 | return ""; 84 | } 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | public class FileUtil { 15 | 16 | protected static final Logger logger = LoggerFactory.getLogger(FileUtil.class); 17 | 18 | private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 19 | 20 | 21 | 22 | public static final String getContentType(Path path, String defaultValue) { 23 | try { 24 | return Files.probeContentType(path); 25 | } catch (IOException e) { 26 | return defaultValue; 27 | } 28 | } 29 | 30 | public static boolean isVideo(String contentType) { 31 | // TODO 32 | return false; 33 | } 34 | 35 | public static boolean isPicture(String contentType) { 36 | if (contentType == null) 37 | return false; 38 | return contentType.contains("image"); 39 | } 40 | 41 | public static boolean isDoc(String contentType) { 42 | if (contentType == null) 43 | return false; 44 | return contentType.contains("document") || contentType.contains("vnd.openxml"); 45 | } 46 | 47 | /** 48 | * 计算文件的MD5码 49 | * 50 | * @param file 51 | * @return 52 | */ 53 | public static String getMD5(File file) { 54 | FileInputStream fis = null; 55 | try { 56 | MessageDigest md = MessageDigest.getInstance("MD5"); 57 | fis = new FileInputStream(file); 58 | byte[] buffer = new byte[8192]; 59 | int length = -1; 60 | while ((length = fis.read(buffer)) != -1) { 61 | md.update(buffer, 0, length); 62 | } 63 | return new String(encodeHex(md.digest())); 64 | } catch (IOException ex) { 65 | logger.warn(ex.toString()); 66 | return null; 67 | } catch (NoSuchAlgorithmException ex) { 68 | logger.warn(ex.toString()); 69 | return null; 70 | } finally { 71 | try { 72 | fis.close(); 73 | } catch (IOException ex) { 74 | logger.warn(ex.toString()); 75 | } 76 | } 77 | } 78 | 79 | private static char[] encodeHex(byte[] bytes) { 80 | char chars[] = new char[32]; 81 | for (int i = 0; i < chars.length; i = i + 2) { 82 | byte b = bytes[i / 2]; 83 | chars[i] = HEX_CHARS[(b >>> 0x4) & 0xf]; 84 | chars[i + 1] = HEX_CHARS[b & 0xf]; 85 | } 86 | return chars; 87 | } 88 | 89 | /** 90 | * 得到文件的SHA码,用于校验 91 | * 92 | * @param file 93 | * @return 94 | */ 95 | public static String getSHA(File file) { 96 | FileInputStream fis = null; 97 | try { 98 | MessageDigest md = MessageDigest.getInstance("SHA"); 99 | fis = new FileInputStream(file); 100 | byte[] buffer = new byte[8192]; 101 | int length = -1; 102 | while ((length = fis.read(buffer)) != -1) { 103 | md.update(buffer, 0, length); 104 | } 105 | return new String(encodeHex(md.digest())); 106 | } catch (IOException ex) { 107 | logger.warn(ex.toString()); 108 | return null; 109 | } catch (NoSuchAlgorithmException ex) { 110 | logger.warn(ex.toString()); 111 | return null; 112 | } finally { 113 | try { 114 | fis.close(); 115 | } catch (IOException ex) { 116 | logger.warn(ex.toString()); 117 | } 118 | } 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/HttpClient.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.blade.kit.StringKit; 7 | import com.blade.kit.http.HttpRequest; 8 | import com.blade.kit.json.JSONKit; 9 | import com.blade.kit.json.JSONObject; 10 | import com.iyuexian.wechat4j.core.WechatMeta; 11 | import com.iyuexian.wechat4j.exception.WechatException; 12 | 13 | public class HttpClient { 14 | 15 | public static Logger LOGGER = LoggerFactory.getLogger(HttpClient.class); 16 | private WechatMeta meta; 17 | 18 | public HttpClient(WechatMeta meta) { 19 | super(); 20 | this.meta = meta; 21 | } 22 | 23 | public JSONObject postJSON(String url, JSONObject body) { 24 | HttpRequest request = HttpRequest.post(url).contentType("application/json;charset=utf-8").header("Cookie", meta.getCookie()) 25 | .send(body.toString()); 26 | String res = request.body(); 27 | request.disconnect(); 28 | if (StringKit.isBlank(res)) { 29 | throw new WechatException("请求微信接口异常"); 30 | } 31 | 32 | JSONObject jsonObject = JSONKit.parseObject(res); 33 | JSONObject BaseResponse = jsonObject.get("BaseResponse").asJSONObject(); 34 | if (null == BaseResponse || BaseResponse.getInt("Ret", -1) != 0) { 35 | LOGGER.warn("操作失败,{}", jsonObject); 36 | } 37 | return jsonObject; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/IOKit.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | 4 | 5 | import java.io.BufferedReader; 6 | import java.io.Closeable; 7 | import java.io.File; 8 | import java.io.FileOutputStream; 9 | import java.io.FileReader; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.InputStreamReader; 13 | import java.io.OutputStream; 14 | import java.io.PrintWriter; 15 | import java.io.Reader; 16 | import java.io.StringWriter; 17 | import java.io.Writer; 18 | import java.net.HttpURLConnection; 19 | import java.net.ServerSocket; 20 | import java.net.Socket; 21 | import java.net.URLConnection; 22 | import java.nio.channels.Selector; 23 | import java.nio.charset.Charset; 24 | import java.util.zip.ZipFile; 25 | 26 | 27 | /** 28 | * IO工具类 29 | * 30 | * @author biezhi 31 | * @since 1.0 32 | */ 33 | public final class IOKit { 34 | 35 | public static final String LINE_SEPARATOR; 36 | 37 | private static final int EOF = -1; 38 | 39 | static { 40 | // avoid security issues 41 | StringWriter buf = new StringWriter(4); // NOSONAR 42 | PrintWriter out = new PrintWriter(buf); 43 | out.println(); 44 | LINE_SEPARATOR = buf.toString(); 45 | } 46 | 47 | /** 48 | * The default buffer size to use. 49 | */ 50 | public static final int DEFAULT_BUFFER_SIZE = 0x1000; 51 | 52 | private IOKit() { 53 | } 54 | 55 | public static String toString(InputStream input) throws IOException { 56 | StringWriter sw = new StringWriter(); 57 | copy(input, sw); 58 | return sw.toString(); 59 | } 60 | 61 | public static String toString(File file) throws IOException { 62 | try { 63 | BufferedReader reader = new BufferedReader(new FileReader(file)); 64 | StringBuilder data = readFromBufferedReader(reader); 65 | reader.close(); 66 | return new String(data.toString().getBytes(), "utf-8"); 67 | } catch (IOException ex) { 68 | throw new RuntimeException("File " + file + " not found."); 69 | } 70 | } 71 | 72 | private static StringBuilder readFromBufferedReader(BufferedReader reader) throws IOException { 73 | StringBuilder builder = new StringBuilder(); 74 | char[] buffer = new char[DEFAULT_BUFFER_SIZE]; 75 | int numRead = 0; 76 | while((numRead = reader.read(buffer)) != EOF) { 77 | builder.append(String.valueOf(buffer, 0, numRead)); 78 | buffer = new char[DEFAULT_BUFFER_SIZE]; 79 | } 80 | return builder; 81 | } 82 | 83 | 84 | 85 | 86 | public static long copyLarge(final InputStream input, final OutputStream output) 87 | throws IOException { 88 | byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 89 | long count = 0L; 90 | int n = 0; 91 | while (EOF != (n = input.read(buffer))) { 92 | output.write(buffer, 0, n); 93 | count += n; 94 | } 95 | return count; 96 | } 97 | 98 | public static void copy(InputStream input, Writer output) 99 | throws IOException { 100 | InputStreamReader in = new InputStreamReader(input); // NOSONAR 101 | copy(in, output); 102 | } 103 | 104 | public static long copyLarge(Reader input, Writer output) throws IOException { 105 | char[] buffer = new char[DEFAULT_BUFFER_SIZE]; 106 | long count = 0L; 107 | int n = 0; 108 | while (EOF != (n = input.read(buffer))) { 109 | output.write(buffer, 0, n); 110 | count += n; 111 | } 112 | return count; 113 | } 114 | 115 | public static void write(byte[] data, File file) { 116 | OutputStream os = null; 117 | try { 118 | os = new FileOutputStream(file); 119 | os.write(data); 120 | } catch (IOException e) { 121 | throw new IllegalStateException(e); 122 | } finally { 123 | closeQuietly(os); 124 | } 125 | } 126 | 127 | public static void write(char[] data, File file, String charsetName) { 128 | write(data, file, Charset.forName(charsetName)); 129 | } 130 | 131 | public static void write(char[] data, File file, Charset charset) { 132 | OutputStream os = null; 133 | try { 134 | os = new FileOutputStream(file); 135 | os.write(new String(data).getBytes(charset)); 136 | } catch (IOException e) { 137 | throw new IllegalStateException(e); 138 | } finally { 139 | closeQuietly(os); 140 | } 141 | } 142 | 143 | public static void write(String data, File file, String charsetName) { 144 | write(data, file, Charset.forName(charsetName)); 145 | } 146 | 147 | public static void write(String data, File file, Charset charset) { 148 | OutputStream os = null; 149 | try { 150 | os = new FileOutputStream(file); 151 | os.write(data.getBytes(charset)); 152 | } catch (IOException e) { 153 | throw new IllegalStateException(e); 154 | } finally { 155 | closeQuietly(os); 156 | } 157 | } 158 | 159 | public static int copy(InputStream input, OutputStream output) 160 | throws IOException { 161 | long count = copyLarge(input, output); 162 | if (count > Integer.MAX_VALUE) { 163 | return -1; 164 | } 165 | return (int) count; 166 | } 167 | 168 | public static int copy(InputStream input, Writer output, String charsetName) 169 | throws IOException { 170 | return copy(new InputStreamReader(input, Charset.forName(charsetName)), 171 | output); 172 | } 173 | 174 | public static int copy(InputStream input, Writer output, Charset charset) 175 | throws IOException { 176 | return copy(new InputStreamReader(input, charset), output); 177 | } 178 | 179 | public static int copy(Reader input, Writer output) throws IOException { 180 | long count = copyLarge(input, output); 181 | if (count > Integer.MAX_VALUE) { 182 | return -1; 183 | } 184 | return (int) count; 185 | } 186 | 187 | public static void closeQuietly(ZipFile obj) { 188 | try { 189 | if (obj != null) { 190 | obj.close(); 191 | } 192 | } catch (IOException e) { 193 | } 194 | } 195 | 196 | public static void closeQuietly(Socket socket) { 197 | try { 198 | if (socket != null) { 199 | socket.close(); 200 | } 201 | } catch (IOException e) { 202 | } 203 | } 204 | 205 | public static void closeQuietly(ServerSocket socket) { 206 | try { 207 | if (socket != null) { 208 | socket.close(); 209 | } 210 | } catch (IOException e) { 211 | } 212 | } 213 | 214 | public static void closeQuietly(Selector selector) { 215 | try { 216 | if (selector != null) { 217 | selector.close(); 218 | } 219 | } catch (IOException e) { 220 | } 221 | } 222 | 223 | public static void closeQuietly(URLConnection conn) { 224 | if (conn != null) { 225 | if (conn instanceof HttpURLConnection) { 226 | ((HttpURLConnection) conn).disconnect(); 227 | } 228 | } 229 | } 230 | 231 | public static void closeQuietly(Closeable closeable) { 232 | if (null != closeable) { 233 | try { 234 | closeable.close(); 235 | } catch (IOException e) { 236 | e.printStackTrace(); 237 | } 238 | } 239 | } 240 | 241 | public static String toString(Reader input) throws IOException { 242 | StringBuilder output = new StringBuilder(); 243 | char[] buffer = new char[DEFAULT_BUFFER_SIZE]; 244 | int n; 245 | while (EOF != (n = input.read(buffer))) { 246 | output.append(buffer, 0, n); 247 | } 248 | return output.toString(); 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/Matchers.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | 4 | import java.util.regex.Matcher; 5 | import java.util.regex.Pattern; 6 | 7 | public class Matchers { 8 | 9 | public static String match(String p, String str){ 10 | Pattern pattern = Pattern.compile(p); 11 | Matcher m = pattern.matcher(str); 12 | if(m.find()){ 13 | return m.group(1); 14 | } 15 | return null; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/PropertyReader.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.UnsupportedEncodingException; 8 | import java.net.URL; 9 | import java.net.URLDecoder; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.Properties; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | public class PropertyReader { 18 | 19 | private static final Logger LOGGER = LoggerFactory.getLogger(PropertyReader.class); 20 | 21 | private final Map config; 22 | 23 | public PropertyReader() { 24 | config = new HashMap(32); 25 | } 26 | 27 | public PropertyReader load(Properties props) { 28 | for (String key : props.stringPropertyNames()) { 29 | String value = props.getProperty(key); 30 | config.put(key, value); 31 | } 32 | return this; 33 | } 34 | 35 | /* 36 | * private String getWildcard(String str) { if (null != str && str.indexOf("${") 37 | * != -1) { int start = str.indexOf("${"); int end = str.indexOf("}"); if (start 38 | * != -1 && end != -1) { return str.substring(start + 2, end); } } return null; 39 | * } 40 | */ 41 | 42 | public PropertyReader load(Map map) { 43 | config.putAll(map); 44 | return this; 45 | } 46 | 47 | /** 48 | * 从文件路径或者classpath路径中载入配置. 49 | * 50 | * @param location 51 | * - 配置文件路径 52 | * @return this 53 | */ 54 | public static PropertyReader load(String location) { 55 | return new PropertyReader().loadLoaction(location); 56 | } 57 | 58 | private PropertyReader loadLoaction(String location) { 59 | if (location.startsWith("classpath:")) { 60 | location = location.substring("classpath:".length()); 61 | return loadClasspath(location); 62 | } else if (location.startsWith("file:")) { 63 | location = location.substring("file:".length()); 64 | return load(new File(location)); 65 | } else { 66 | return loadClasspath(location); 67 | } 68 | } 69 | 70 | public void add(String location) { 71 | PropertyReader config = loadLoaction(location); 72 | if (null != config) { 73 | this.config.putAll(config.asMap()); 74 | } 75 | } 76 | 77 | // 从 URL 载入 78 | public PropertyReader load(URL url) { 79 | String location = url.getPath(); 80 | try { 81 | location = URLDecoder.decode(location, "utf-8"); 82 | } catch (UnsupportedEncodingException e) { 83 | } 84 | 85 | try { 86 | return loadInputStream(url.openStream(), location); 87 | } catch (IOException e) { 88 | throw new IllegalStateException(e); 89 | } 90 | } 91 | 92 | // 从 classpath 下面载入 93 | private PropertyReader loadClasspath(String classpath) { 94 | if (classpath.startsWith("/")) { 95 | classpath = classpath.substring(1); 96 | } 97 | InputStream is = getDefault().getResourceAsStream(classpath); 98 | LOGGER.info("Load config [classpath:" + classpath + "]"); 99 | return loadInputStream(is, classpath); 100 | } 101 | 102 | // 从 File 载入 103 | public PropertyReader load(File file) { 104 | try { 105 | LOGGER.info("Load config [file:" + file.getPath() + "]"); 106 | return loadInputStream(new FileInputStream(file), file.getName()); 107 | } catch (IOException e) { 108 | throw new IllegalStateException(e); 109 | } 110 | } 111 | 112 | private PropertyReader loadInputStream(InputStream is, String location) { 113 | if (is == null) { 114 | throw new IllegalStateException("InputStream not found: " + location); 115 | } 116 | location = location.toLowerCase(); 117 | try { 118 | Properties config = new Properties(); 119 | config.load(is); 120 | load(config); 121 | return this; 122 | } catch (IOException e) { 123 | throw new IllegalStateException(e); 124 | } finally { 125 | IOKit.closeQuietly(is); 126 | } 127 | } 128 | 129 | public PropertyReader loadSystemProperties() { 130 | return load(System.getProperties()); 131 | } 132 | 133 | public PropertyReader loadSystemEnvs() { 134 | return load(System.getenv()); 135 | } 136 | 137 | public Map asMap() { 138 | return this.config; 139 | } 140 | 141 | /** 142 | * Returns current thread's context class loader 143 | */ 144 | private static ClassLoader getDefault() { 145 | ClassLoader loader = null; 146 | try { 147 | loader = Thread.currentThread().getContextClassLoader(); 148 | } catch (Exception e) { 149 | } 150 | if (loader == null) { 151 | loader = PropertyReader.class.getClassLoader(); 152 | if (loader == null) { 153 | try { 154 | // getClassLoader() returning null indicates the bootstrap 155 | // ClassLoader 156 | loader = ClassLoader.getSystemClassLoader(); 157 | } catch (Exception e) { 158 | // Cannot access system ClassLoader - oh well, maybe the 159 | // caller can live with null... 160 | } 161 | } 162 | } 163 | return loader; 164 | } 165 | 166 | public String get(String key) { 167 | return config.get(key); 168 | } 169 | 170 | public String get(String key, String defaultValue) { 171 | return null != config.get(key) ? config.get(key) : defaultValue; 172 | } 173 | 174 | public Integer getInt(String key) { 175 | String value = get(key); 176 | if (isNotBlank(value)) { 177 | return Integer.valueOf(value); 178 | } 179 | return null; 180 | } 181 | 182 | public Integer getInt(String key, Integer defaultValue) { 183 | return null != getInt(key) ? getInt(key) : defaultValue; 184 | } 185 | 186 | public Long getLong(String key) { 187 | String value = get(key); 188 | if (isNotBlank(value)) { 189 | return Long.valueOf(value); 190 | } 191 | return null; 192 | } 193 | 194 | public Long getLong(String key, Long defaultValue) { 195 | return null != getLong(key) ? getLong(key) : defaultValue; 196 | } 197 | 198 | public Double getDouble(String key) { 199 | String value = get(key); 200 | if (isNotBlank(value)) { 201 | return Double.valueOf(value); 202 | } 203 | return null; 204 | } 205 | 206 | public double getDouble(String key, double defaultValue) { 207 | return null != getDouble(key) ? getDouble(key) : defaultValue; 208 | } 209 | 210 | public Boolean getBoolean(String key) { 211 | String value = get(key); 212 | if (isNotBlank(value)) { 213 | return Boolean.valueOf(value); 214 | } 215 | return null; 216 | } 217 | 218 | public Boolean getBoolean(String key, boolean defaultValue) { 219 | return null != getBoolean(key) ? getBoolean(key) : defaultValue; 220 | } 221 | 222 | public boolean isNotBlank(String str) { 223 | return str != null && str.trim().length() > 0; 224 | } 225 | 226 | } 227 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/java/com/iyuexian/wechat4j/util/TulingUtil.java: -------------------------------------------------------------------------------- 1 | package com.iyuexian.wechat4j.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.OutputStreamWriter; 7 | import java.io.UnsupportedEncodingException; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.security.Key; 11 | import java.security.MessageDigest; 12 | 13 | import javax.crypto.Cipher; 14 | import javax.crypto.spec.IvParameterSpec; 15 | import javax.crypto.spec.SecretKeySpec; 16 | 17 | import com.blade.kit.Base64; 18 | 19 | public class TulingUtil { 20 | 21 | /** 22 | * 向后台发送post请求 23 | * 24 | * @param param 25 | * @param url 26 | * @return 27 | * @throws IOException 28 | * @throws UnsupportedEncodingException 29 | */ 30 | public static String sendPost(String param, String url) throws Exception { 31 | OutputStreamWriter out = null; 32 | BufferedReader in = null; 33 | String result = ""; 34 | URL realUrl = new URL(url); 35 | HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); 36 | conn.setDoOutput(true); 37 | conn.setDoInput(true); 38 | conn.setUseCaches(false); 39 | conn.setRequestMethod("POST"); 40 | conn.setConnectTimeout(50000); 41 | conn.setReadTimeout(50000); 42 | conn.setRequestProperty("Content-Type", "application/json"); 43 | conn.setRequestProperty("Accept", "application/json"); 44 | conn.setRequestProperty("Authorization", "token"); 45 | conn.setRequestProperty("tag", "htc_new"); 46 | conn.connect(); 47 | out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); 48 | out.write(param); 49 | out.flush(); 50 | out.close(); 51 | in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 52 | String line = ""; 53 | while ((line = in.readLine()) != null) { 54 | result += line; 55 | } 56 | return result; 57 | } 58 | 59 | /** 60 | * 加密方法 61 | * 62 | * 说明:采用128位 63 | * 64 | * @return 加密结果 65 | * @throws Exception 66 | */ 67 | public static String encrypt(String strKey, String strContent) throws Exception { 68 | 69 | Key key = new SecretKeySpec(getHash("MD5", strKey), "AES"); 70 | IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); 71 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 72 | byte[] data = strContent.getBytes("UTF-8"); 73 | cipher.init(Cipher.ENCRYPT_MODE, key, iv); 74 | byte[] encryptData = cipher.doFinal(data); 75 | String encryptResult = new String(Base64.encodeBytes(encryptData)); 76 | return encryptResult; 77 | } 78 | 79 | /** 80 | * 81 | * @param algorithm 82 | * @param text 83 | * @return 84 | * @throws Exception 85 | */ 86 | public static byte[] getHash(String algorithm, String text) throws Exception { 87 | byte[] bytes = text.getBytes("UTF-8"); 88 | final MessageDigest digest = MessageDigest.getInstance(algorithm); 89 | digest.update(bytes); 90 | return digest.digest(); 91 | } 92 | 93 | /** 94 | * MD5加密算法 95 | * 96 | * 说明:32位加密算法 97 | * 98 | * @param 待加密的数据 99 | * @return 加密结果,全小写的字符串 100 | * @throws Exception 101 | */ 102 | public static String MD5(String s) throws Exception { 103 | char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 104 | byte[] btInput = s.getBytes("utf-8"); 105 | // 获得MD5摘要算法的 MessageDigest 对象 106 | MessageDigest mdInst = MessageDigest.getInstance("MD5"); 107 | // 使用指定的字节更新摘要 108 | mdInst.update(btInput); 109 | // 获得密文 110 | byte[] md = mdInst.digest(); 111 | // 把密文转换成十六进制的字符串形式 112 | int j = md.length; 113 | char str[] = new char[j * 2]; 114 | int k = 0; 115 | for (int i = 0; i < j; i++) { 116 | byte byte0 = md[i]; 117 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 118 | str[k++] = hexDigits[byte0 & 0xf]; 119 | } 120 | return new String(str); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/resources/config.properties: -------------------------------------------------------------------------------- 1 | # media save path 2 | app.media_path=C\:/wechat 3 | app.msg_location=C\:/wechat/msg.txt 4 | 5 | db.url=jdbc\:mysql\://rm-8vbl9c7po6w334tr4o.mysql.zhangbei.rds.aliyuncs.com\:3306/xmall?&useUnicode\=true&characterEncoding\=UTF-8&autoReconnect\=true&failOverReadOnly\=false&zeroDateTimeBehavior\=convertToNull 6 | db.username=root 7 | db.pass=123456 8 | 9 | qiniu_ak=0FlyZYZsYM6xhaW2UM2gREQ2dINcz59M-PP6cIby10 10 | qiniu_sk=0Zo0gLdlp9uYsh2T312iCm4kUeKVu5_j295Wlm5O80 11 | qiuniu_img_url=http\://img.iyuexian.com/ 12 | qiuniu_video_url=http\://v.iyuexian.com/ 13 | qiniu_bucket_image0=image1 14 | qiniu_bucket_video=video 15 | -------------------------------------------------------------------------------- /wechat4j-common/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=debug,console 2 | 3 | #log4j.appender.stdout = org.apache.log4j.ConsoleAppender 4 | #log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 5 | #log4j.appender.stdout.layout.ConversionPattern = %d %-5p => %m%n 6 | 7 | 8 | log4j.appender.console=org.apache.log4j.ConsoleAppender 9 | log4j.appender.console.Target=System.out 10 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 11 | log4j.appender.console.layout.ConversionPattern=wechat4j-[%-5p] %d{MM-dd HH\:mm\:ss} %l\: %m %x %n 12 | #log4j.appender.console.layout.ConversionPattern=wechat4j-[%-5p] %d{MM-dd HH\:mm}:%m %n -------------------------------------------------------------------------------- /wechat4j-common/src/main/resources/logging.properties: -------------------------------------------------------------------------------- 1 | handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 2 | 3 | ############################################################ 4 | # Handler specific properties. 5 | # Describes specific configuration info for Handlers. 6 | ############################################################ 7 | 8 | org.apache.juli.FileHandler.level = FINE 9 | org.apache.juli.FileHandler.directory = ${catalina.base}/logs 10 | org.apache.juli.FileHandler.prefix = error-debug. 11 | 12 | java.util.logging.ConsoleHandler.level = FINE 13 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -------------------------------------------------------------------------------- /wechat4j-common/target/classes/.gitignore: -------------------------------------------------------------------------------- 1 | /com/ 2 | /META-INF/ 3 | -------------------------------------------------------------------------------- /wechat4j-common/target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Built-By: hexia 3 | Build-Jdk: 1.8.0_101 4 | Created-By: Maven Integration for Eclipse 5 | 6 | -------------------------------------------------------------------------------- /wechat4j-common/target/classes/META-INF/maven/com.iyuexian.wechat4j/wechat4j-common/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Sat Jul 21 15:08:17 CST 2018 3 | version=0.0.1-SNAPSHOT 4 | groupId=com.iyuexian.wechat4j 5 | m2e.projectName=wechat4j-common 6 | m2e.projectLocation=C\:\\Users\\hexia\\git\\wechat4j\\README.md\\wechat4j-common 7 | artifactId=wechat4j-common 8 | -------------------------------------------------------------------------------- /wechat4j-common/target/classes/META-INF/maven/com.iyuexian.wechat4j/wechat4j-common/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.iyuexian.wechat4j 5 | wechat4j-common 6 | jar 7 | 0.0.1-SNAPSHOT 8 | wechat4j Maven Webapp 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 4.13.1 15 | test 16 | 17 | 18 | com.bladejava 19 | blade-kit 20 | 1.3.4 21 | 22 | 23 | org.slf4j 24 | slf4j-log4j12 25 | 1.7.21 26 | 27 | 28 | com.alibaba 29 | fastjson 30 | 1.2.44 31 | 32 | 33 | commons-io 34 | commons-io 35 | 2.7 36 | 37 | 38 | mysql 39 | mysql-connector-java 40 | 8.0.16 41 | 42 | 43 | org.sql2o 44 | sql2o 45 | 1.6.0-RC3 46 | 47 | 48 | 49 | com.qiniu 50 | qiniu-java-sdk 51 | 7.0.2 52 | 53 | 54 | 55 | 56 | wechat4j 57 | 58 | 59 | org.apache.maven.plugins 60 | maven-shade-plugin 61 | 62 | 63 | package 64 | 65 | shade 66 | 67 | 68 | 69 | 70 | com.iyuexian.wechat4j.demo.Demo1 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | org.apache.maven.plugins 79 | maven-compiler-plugin 80 | 81 | 1.8 82 | 1.8 83 | 84 | -parameters 85 | 86 | 87 | 88 | 89 | compile 90 | 91 | -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/WechatStartup$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/WechatStartup$1.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/WechatStartup.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/WechatStartup.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/BaseRequest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/BaseRequest.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/ChatRoom.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/ChatRoom.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/ChatRoomMember.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/ChatRoomMember.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/ContactUser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/ContactUser.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/GroupMember.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/GroupMember.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/Msg.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/bean/Msg.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Constant.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Constant.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums$FileType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums$FileType.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums$MsgType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums$MsgType.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums$OS.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums$OS.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/config/Enums.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/core/WechatApiUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/core/WechatApiUtil.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/core/WechatMeta.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/core/WechatMeta.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/demo/Demo1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/demo/Demo1.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/exception/WechatException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/exception/WechatException.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/ContactManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/ContactManager.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/ContactUserUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/ContactUserUtil.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/FileHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/FileHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/FriendAddTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/FriendAddTask.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/MessageListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/MessageListener.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/QRCodeWindow$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/QRCodeWindow$1.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/QRCodeWindow.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/QRCodeWindow.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/QrUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/QrUtil.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/Storage.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/Storage.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/Task$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/Task$1.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/Task.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/Task.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot$InputText.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot$InputText.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot$Location.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot$Location.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot$UserInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot$UserInfo.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TulingRobot.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TxtMessageRobot.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/TxtMessageRobot.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/WxLocalCache$CacheItem.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/WxLocalCache$CacheItem.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/WxLocalCache$Holder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/WxLocalCache$Holder.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/WxLocalCache.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/WxLocalCache.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/AbstractMessageHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/AbstractMessageHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/IMessageHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/IMessageHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/MessageManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/MessageManager.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/MpMessageHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/MpMessageHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/PictureMessageHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/PictureMessageHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/TxtMessageHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/TxtMessageHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/VideoMessageHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/VideoMessageHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/VoiceMessageHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/message/VoiceMessageHandler.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/FilePipeLine.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/FilePipeLine.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/MessagePipeLine.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/MessagePipeLine.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/PipeLineManager$Holder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/PipeLineManager$Holder.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/PipeLineManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/plugin/storage/PipeLineManager.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Converter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Converter.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/CookieUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/CookieUtil.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/DigestUtils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/DigestUtils.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Emptys$NullPlaceholder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Emptys$NullPlaceholder.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Emptys.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Emptys.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/FileUploadHelper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/FileUploadHelper.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/FileUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/FileUtil.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/HttpClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/HttpClient.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/IOKit.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/IOKit.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Matchers.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/Matchers.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/PropertyReader.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/PropertyReader.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/com/iyuexian/wechat4j/util/TulingUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/classes/com/iyuexian/wechat4j/util/TulingUtil.class -------------------------------------------------------------------------------- /wechat4j-common/target/classes/config.properties: -------------------------------------------------------------------------------- 1 | # media save path 2 | app.media_path=C\:/wechat 3 | app.msg_location=C\:/wechat/msg.txt 4 | 5 | db.url=jdbc\:mysql\://rm-8vbl9c7po6w334tr4o.mysql.zhangbei.rds.aliyuncs.com\:3306/xmall?&useUnicode\=true&characterEncoding\=UTF-8&autoReconnect\=true&failOverReadOnly\=false&zeroDateTimeBehavior\=convertToNull 6 | db.username=root 7 | db.pass=123456 8 | 9 | qiniu_ak=0FlyZYZsYM6xhaW2UM2gREQ2dINcz59M-PP6cIby10 10 | qiniu_sk=0Zo0gLdlp9uYsh2T312iCm4kUeKVu5_j295Wlm5O80 11 | qiuniu_img_url=http\://img.iyuexian.com/ 12 | qiuniu_video_url=http\://v.iyuexian.com/ 13 | qiniu_bucket_image0=image1 14 | qiniu_bucket_video=video 15 | -------------------------------------------------------------------------------- /wechat4j-common/target/classes/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=debug,console 2 | 3 | #log4j.appender.stdout = org.apache.log4j.ConsoleAppender 4 | #log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 5 | #log4j.appender.stdout.layout.ConversionPattern = %d %-5p => %m%n 6 | 7 | 8 | log4j.appender.console=org.apache.log4j.ConsoleAppender 9 | log4j.appender.console.Target=System.out 10 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 11 | log4j.appender.console.layout.ConversionPattern=wechat4j-[%-5p] %d{MM-dd HH\:mm\:ss} %l\: %m %x %n 12 | #log4j.appender.console.layout.ConversionPattern=wechat4j-[%-5p] %d{MM-dd HH\:mm}:%m %n -------------------------------------------------------------------------------- /wechat4j-common/target/classes/logging.properties: -------------------------------------------------------------------------------- 1 | handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 2 | 3 | ############################################################ 4 | # Handler specific properties. 5 | # Describes specific configuration info for Handlers. 6 | ############################################################ 7 | 8 | org.apache.juli.FileHandler.level = FINE 9 | org.apache.juli.FileHandler.directory = ${catalina.base}/logs 10 | org.apache.juli.FileHandler.prefix = error-debug. 11 | 12 | java.util.logging.ConsoleHandler.level = FINE 13 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter -------------------------------------------------------------------------------- /wechat4j-common/target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven 2 | #Sat Mar 31 11:49:25 CST 2018 3 | version=0.0.1-SNAPSHOT 4 | groupId=com.iyuexian.wechat4j 5 | artifactId=wechat4j-common 6 | -------------------------------------------------------------------------------- /wechat4j-common/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com\iyuexian\wechat4j\plugin\QrUtil$1.class 2 | com\iyuexian\wechat4j\util\Emptys$1.class 3 | com\iyuexian\wechat4j\plugin\storage\PipeLineManager$1.class 4 | -------------------------------------------------------------------------------- /wechat4j-common/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\storage\MessagePipeLine.java 2 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\bean\ContactUser.java 3 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\Converter.java 4 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\CookieUtil.java 5 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\FriendAddTask.java 6 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\TxtMessageRobot.java 7 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\FileUtil.java 8 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\config\MsgType.java 9 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\demo\Demo1.java 10 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\TxtMessageHandler.java 11 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\MessageListener.java 12 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\VoiceMessageHandler.java 13 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\QrUtil.java 14 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\storage\FilePipeLine.java 15 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\FileUploadHelper.java 16 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\AbstractMessageHandler.java 17 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\Storage.java 18 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\DigestUtils.java 19 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\ContactUserUtil.java 20 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\WxLocalCache.java 21 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\IOKit.java 22 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\core\WechatMeta.java 23 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\exception\WechatException.java 24 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\MpMessageHandler.java 25 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\TulingUtil.java 26 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\bean\ChatRoomMember.java 27 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\TulingRobot.java 28 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\bean\ChatRoom.java 29 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\bean\GroupMember.java 30 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\Task.java 31 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\MessageManager.java 32 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\HttpClient.java 33 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\ContactManager.java 34 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\QRCodeWindow.java 35 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\PictureMessageHandler.java 36 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\WechatStartup.java 37 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\IMessageHandler.java 38 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\Matchers.java 39 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\message\VideoMessageHandler.java 40 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\FileHandler.java 41 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\config\Constant.java 42 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\config\Enums.java 43 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\bean\Msg.java 44 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\Emptys.java 45 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\core\WechatApiUtil.java 46 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\plugin\storage\PipeLineManager.java 47 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\bean\BaseRequest.java 48 | D:\dev\work\eclipse-workspace2\wechat4j-common\src\main\java\com\iyuexian\wechat4j\util\PropertyReader.java 49 | -------------------------------------------------------------------------------- /wechat4j-common/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst -------------------------------------------------------------------------------- /wechat4j-common/target/original-wechat4j.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/original-wechat4j.jar -------------------------------------------------------------------------------- /wechat4j-common/target/wechat4j-common-0.0.1-SNAPSHOT-shaded.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/wechat4j-common-0.0.1-SNAPSHOT-shaded.jar -------------------------------------------------------------------------------- /wechat4j-common/target/wechat4j.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hexiangtao/wechat4j/ae79c9ea52d6eed17fa0f1126f2229c3407ecc18/wechat4j-common/target/wechat4j.jar --------------------------------------------------------------------------------