using Chat.Framework.Utils; using Chat.Framework.WXSdk.Events; using Chat.Framework.WXSdk.IPAD; using Chat.Framework.WXSdk.UIForm; using CsharpHttpHelper; using Google.Protobuf; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using WechatProto; using static Chat.Framework.WXSdk.Implement.WXClientTool; namespace Chat.Framework.WXSdk.Implement { /// /// 协议微信 /// public class WXClientImpl_IPAD : WeixinBase { /// /// 分析消息 /// /// private void AnalysisMessage(string result) { // Util result = result.Replace("🔑", "¥"); result = Util.RemoveEmoji(result); // LogHelper.GetSingleObj().Debug("收到消息", result + @" //"); var list = Util.ConvertJsonToObj(result); if (list == null) return; int count = 0; var guid = Guid.NewGuid(); // this.WriteLog($"{guid},Async数量{list.Count},排除重复后剩余:{count}",true); // this.WriteLog(); foreach (Dictionary xitem in list) { var time = DateTime.Now; var item = xitem; string json = Util.ObjectToJson(xitem); var msgType = int.Parse(xitem["MsgType"].ToString()); //Console.WriteLine("新消息:" + json); string md5 = Util.MD5Encrypt(json); if (this.pack.Contains(md5)) continue; if (this.pack.Count > 1000) this.pack.Clear(); this.pack.Add(md5); count++; var method = new Action(delegate () //Task.Factory.StartNew(delegate () { var logStrbs = new StringBuilder(); try { var events = ChatClient.Events; // int msgType = int.Parse(item["MsgType"].ToString()); switch (msgType) { case 10002://获取 { logStrbs.Append("1_"); string content = item["Content"].ToString(); var contentreg = Regex.Match(content, @"()"); if (contentreg.Success) { content = contentreg.Groups[1].Value.Replace("\n", "").Replace("\t", "");//.Replace("![CDATA[","").Replace("]]",""); XmlDocument doc = new XmlDocument(); doc.LoadXml(content); var xml = doc.SelectSingleNode("sysmsg"); var type = xml.Attributes["type"]; if (type != null) { xml = xml.SelectSingleNode(type.InnerText); switch (type.InnerText) { case "NewXmlChatRoomAccessVerifyApplication": { WXApplyGroup join = new WXApplyGroup(this); join.Usernick = Regex.Match(xml.SelectSingleNode("text").InnerText, @"""(.*?)""想邀请").Groups[1].Value; join.GroupId = xml.SelectSingleNode("RoomName").InnerText; var link = xml.SelectSingleNode("link"); join.Reason = link.SelectSingleNode("invitationreason").InnerText; join.Wxid = link.SelectSingleNode("inviterusername").InnerText; var memberlist = link.SelectSingleNode("memberlist"); var nodes = memberlist.SelectNodes("member"); foreach (XmlNode node in nodes) { var member = new WXApplyGroup.ApplyGroupMember() { wxid = node.SelectSingleNode("username").InnerText, headimgurl = node.SelectSingleNode("headimgurl").InnerText, nickname = node.SelectSingleNode("nickname").InnerText, quitchatroominfo = node.SelectSingleNode("nickname").InnerText }; join.Members.Add(member); } ChatClient.Events.OnEvent(join); } return; //case "delchatroommember": // { // } // return; } } Console.WriteLine(); } return; } case 51://打开用户的聊天窗口 { logStrbs.Append("2_"); if (item.ContainsKey("Status") && item["Status"].ToString() == "3") { var Content = item["Content"].ToString(); var reg = Regex.Match(Content, $"\n\n{item["ToUserName"]}\n\n"); if (reg.Success) { var friend = GetContact(item["ToUserName"].ToString(), true); events.OnEvent(new WXOpenWindow(this, friend)); } } break; } case 10000://系统消息 { logStrbs.Append("3_"); if (item.ContainsKey("Content")) { //{"MsgId":1647047807,"FromUserName":"wxid_8s44kddouuaj21","ToUserName":"wxid_7tki0tapwq2s22","MsgType":10000,"Content":"你已添加了千年老妖,现在可以开始聊天了。","Status":4,"ImgStatus":1,"ImgBuf":null,"CreateTime":1508670253,"MsgSource":"","PushContent":"","NewMsgId":6583959598552732769} #region 添加好友成功 if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新好友")) { var reg = Regex.Match(item["Content"].ToString(), "^你已添加了(.*?),现在可以开始聊天了。$"); if (reg.Success) { var friend = GetContact(item["FromUserName"].ToString(), true); events.OnEvent(new WXNewFriend(this, friend)); break; } reg = Regex.Match(item["Content"].ToString(), "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); if (reg.Success) { //Thread.Sleep(3000); Friend friend = null; for (int i = 0; i < 3; i++) { friend = GetContact(item["FromUserName"].ToString(), true); if (friend != null) break; Thread.Sleep(1500); } //var friend = GetContact(item["FromUserName"].ToString(), true); //LogHelper_.GetSingleObj().Info("BBBBBBBBBB", $"【{item["FromUserName"].ToString()}】 friend = " + friend); //if (friend == null) break; events.OnEvent(new WXNewFriend(this, friend)); break; } } #endregion #region 新成员进群 if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新群友")) { var User = this.User.User; //你邀请"A 小叮当20 - 不懂回复帮助、A 小叮当12 - 不懂回复帮助、A 小叮当16 - 不懂回复帮助、A 小叮当19 - 不懂回复帮助"加入了群聊 var groupid = item["FromUserName"].ToString(); var reg = Regex.Match(item["Content"].ToString(), @"""(?<邀请人>.*?)""邀请""(?<新人>.*?)""加入了群聊"); if (!reg.Success) reg = Regex.Match(item["Content"].ToString(), @"(?<邀请人>你)邀请""(?<新人>.*?)""加入了群聊"); if (!reg.Success) reg = Regex.Match(item["Content"].ToString(), @"""(?<新人>.*?)""通过扫描""(?<邀请人>.*?)""分享的二维码加入群聊"); if (!reg.Success) reg = Regex.Match(item["Content"].ToString(), @"""(?<新人>.*?)""通过扫描(?<邀请人>你)分享的二维码加入群聊"); if (reg.Success) { if (!GroupMemberCache.ContainsKey(groupid)) { var gmNew = GetMembers(groupid, true); if (gmNew != null) { if (!GroupMemberCache.ContainsKey(groupid)) GroupMemberCache.Add(groupid, gmNew.ToList()); var group = GetContact(groupid); if (group == null) return; events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = reg.Groups["新人"].Value, SourceNick = reg.Groups["邀请人"].Value == "你" ? Encoding.UTF8.GetString(User.Nickname.ToArray()) : reg.Groups[1].Value, SourceName = reg.Groups["邀请人"].Value == "你" ? User.Userame : "" }); return; } } if (!SyncGroups.ContainsKey(groupid)) { SyncGroups.Add(groupid, groupid); SyncGroup(); } break; } } #endregion } return; } case 37://通过名片添加好友 { logStrbs.Append("4_"); if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新申请")) { string content = item["Content"].ToString(); var reg = Regex.Match(content, @"fromusername=""(?.*?)""[\w\W]+fromnickname=""(?.*?)""[\w\W]+content=""(?.*?)""[\w\W]+sourceusername=""(?.*?)""[\w\W]+sourcenickname=""(?.*?)"""); if (reg.Success) { events.OnEvent(new WXApplyFriend(this, reg.Groups["newFriendWxid"].ToString(), reg.Groups["newFriendNick"].ToString(), reg.Groups["newFriendMsg"].ToString(), reg.Groups["sourceFriendWxid"].ToString(), reg.Groups["sourceFriendNick"].ToString(), content)); } } } return; case 1://文本消息 case 42: case 49: case 47://表情动画 { logStrbs.Append("5_"); if (item["FromUserName"].ToString() == "newsapp") return; if (item["FromUserName"].ToString() == "weixin") return; if (item["FromUserName"].ToString().StartsWith("gh_")) return; if (item["Content"].ToString().Contains("[CDATA[微信转账]]") && item["FromUserName"].ToString() != User.Username) { logStrbs.Append("5.1_"); if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("转账")) { logStrbs.Append("5.2_"); var content = item["Content"].ToString(); Console.WriteLine(content); logStrbs.Append("5.3_"); var transcationid = Regex.Match(content, "transferid\u003e\u003c!\\[CDATA\\[(\\d+)\\]\\]"); var invalidtime = Regex.Match(content, "invalidtime\u003e\u003c!\\[CDATA\\[(\\d+)\\]\\]"); var money = Regex.Match(content, ""); var fromusername = item["FromUserName"].ToString(); logStrbs.Append("5.4_"); var friend = GetContact(fromusername); logStrbs.Append("5.5_"); if (friend != null && transcationid.Success && invalidtime.Success && money.Success) { logStrbs.Append("5.6_"); var e = new WXReicevePay(this, friend, invalidtime.Groups[1].Value, transcationid.Groups[1].Value, double.Parse(money.Groups[1].Value)); logStrbs.Append("5.7_"); ChatClient.Events.OnEvent(e); return; } } } logStrbs.Append("5.8_"); if (item["Content"].ToString() == "我通过了你的朋友验证请求,现在我们可以开始聊天了" && item.ContainsKey("MsgSource") && string.IsNullOrWhiteSpace(item["MsgSource"].ToString())) { logStrbs.Append("5.9_"); if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新好友")) { logStrbs.Append("5.10_"); var UserName = item["FromUserName"].ToString(); logStrbs.Append("5.11_"); if (!string.IsNullOrWhiteSpace(UserName)) { logStrbs.Append("5.12_"); var friend = GetContact(UserName, true); logStrbs.Append("5.13_"); events.OnEvent(new WXNewFriend(this, friend)); return; } } } logStrbs.Append("5.14_"); var reg = Regex.Match(item["FromUserName"].ToString(), "^(\\d+@chatroom)$"); bool is_phpone = false; logStrbs.Append("5.15_"); if (item["FromUserName"].ToString() == User.Username) { logStrbs.Append("5.16_"); if (!reg.Success && item["ToUserName"].ToString().Contains("@")) return; else if (ChatClient.WXSdkConfig.MsgConvertToFriend) { logStrbs.Append("5.17_"); item["FromUserName"] = item["ToUserName"].ToString(); is_phpone = true; } } logStrbs.Append("5.18_"); if (reg.Success)//群消息 { if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) { logStrbs.Append("5.19_"); string groupid = reg.Groups[1].Value; var Content = System.Text.RegularExpressions.Regex.Match(item["Content"].ToString(), "^(.*?):\\s+([\\w\\W]+)$"); logStrbs.Append("5.20_"); var group = this.GetContact(groupid); if (group == null) { logStrbs.Append("5.21_"); this.WriteLog(string.Format("获取群{0}失败。", groupid)); return; } logStrbs.Append("5.22_"); #region 群用户缓存 if (!GroupMemberCache.ContainsKey(groupid)) { logStrbs.Append("5.23_"); var gmNew = GetMembers(groupid, true); if (gmNew != null) { logStrbs.Append("5.24_"); if (!GroupMemberCache.ContainsKey(groupid)) GroupMemberCache.Add(groupid, gmNew.ToList()); } } #endregion logStrbs.Append("5.25_"); string wxid = Content.Groups[1].Value; //string messsage = Content.Groups[2].Value.Replace("\n", ""); string messsage = Content.Groups[2].Value; logStrbs.Append("5.26_"); GroupMember member = this.GetMember(groupid, wxid); if (member == null) { logStrbs.Append("5.27_"); this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", groupid, wxid)); break; } logStrbs.Append("5.28_"); events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); return; } } else { logStrbs.Append("5.29_"); if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) { logStrbs.Append("5.30_"); string wxid = item["FromUserName"].ToString(); string messsage = item["Content"].ToString(); var friend = this.GetContact(wxid); //if (friend == null) //{ // //this.WriteLog(string.Format("获取微信好友{0}信息失败。", wxid)); // //break; // var nickname = item["PushContent"].ToString().Replace(": " + messsage, "").Trim(); // friend = new Friend() { Ticket = "", Alias = wxid, UserName = wxid, MsgType = 1, ExtInfo = "", NickName = nickname, ContactType = 0, City = "Chaoyang", ChatRoomOwner = "", Remark = "", Sex = 1, Signature = "", ChatroomVersion = "0", id = 0, Province = "BeiJing", BigHeadImgUrl = "", SmallHeadImgUrl = "" }; //} logStrbs.Append("5.31_"); var eventobj = new WXReiceveFriendMsg(this, friend, messsage); logStrbs.Append("5.32_"); eventobj.IsRobot = is_phpone; events.OnEvent(eventobj); return; } } break; } case 3://收到图片 { logStrbs.Append("6_"); #region 历史 //if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("图片")) //{ // var friend = GetContact(item["FromUserName"].ToString()); // if (friend == null) return; // var Content = item["Content"].ToString(); // var imagePath = DownlowdImage(int.Parse(item["MsgId"].ToString()), friend.UserName, int.Parse(Regex.Match(Content, " length=\"(\\d+)").Groups[1].Value)); // if (!string.IsNullOrEmpty(imagePath)) // { // #region 缓存CDN数据 // if (ChatClient.ImageCDNs.Count >= 10000)//到达一定数量清空数据 // ChatClient.ImageCDNs.Clear(); // var MD5Hash = FileTools.GetMD5Hash(imagePath); // if (!ChatClient.ImageCDNs.ContainsKey(MD5Hash)) // { // var reg = Regex.Match(Content, @" aeskey=""(?[^""]+)"".+?cdnthumburl=""(?[^""]+)"""); // if (reg.Success) // { // var aeskey = reg.Groups["aeskey"].Value; // var cdnthumburl = reg.Groups["cdnthumburl"].Value; // ChatClient.ImageCDNs.Add(MD5Hash, new { aeskey = aeskey, cdnurl = cdnthumburl }); // } // } // #endregion // if (!friend.UserName.Contains("@")) // { // if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) // { // bool is_phpone = false; // if (ChatClient.WXSdkConfig.MsgConvertToFriend) // { // if (item.ContainsKey("FromUserName") && item["FromUserName"].ToString() == User.Username) // { // if (item.ContainsKey("ToUserName")) // { // string wxid = item["ToUserName"].ToString(); // friend = this.GetContact(wxid); // is_phpone = true; // } // } // } // var eventobj = new WXReiceveFriendMsg(this, friend, $"[图片={imagePath}]"); // eventobj.IsRobot = is_phpone; // events.OnEvent(eventobj); // } // } // else // { // if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) // { // var groupid = friend.UserName; // var reg = Regex.Match(Content, "^(.*?):\\s+([\\w\\W]+)$"); // var group = this.GetContact(groupid); // if (group == null) // { // this.WriteLog(string.Format("获取群{0}失败。", groupid)); // return; // } // string wxid = reg.Groups[1].Value; // string messsage = $"[图片={imagePath}]"; // GroupMember member = this.GetMember(groupid, wxid); // if (member == null) // { // this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", groupid, wxid)); // break; // } // events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); // return; // } // } // } //} #endregion #region 新 if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("图片")) { logStrbs.Append("6.1_"); var friend = GetContact(item["FromUserName"].ToString()); if (friend == null) return; var Content = item["Content"].ToString(); logStrbs.Append("6.2_"); #region 将图片的信息保存起来 var ContentTmp = Content; if (friend.UserName.Contains("@")) { logStrbs.Append("6.3_"); var reg = Regex.Match(Content, "^.*?:\\s+([\\w\\W]+)$"); if (reg.Success) ContentTmp = reg.Groups[1].Value; } CDNImageMsgInfo imgInfo = GetCDNImage(ContentTmp); logStrbs.Append("6.4_"); var cdnstr = Util.HexToStr(Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(imgInfo))); #endregion logStrbs.Append("6.5_"); if (!friend.UserName.Contains("@")) { logStrbs.Append("6.6_"); if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) { logStrbs.Append("6.7_"); bool is_phpone = false; if (ChatClient.WXSdkConfig.MsgConvertToFriend) { logStrbs.Append("6.8_"); if (item.ContainsKey("FromUserName") && item["FromUserName"].ToString() == User.Username) { logStrbs.Append("6.9_"); if (item.ContainsKey("ToUserName")) { logStrbs.Append("6.10_"); string wxid = item["ToUserName"].ToString(); logStrbs.Append("6.11_"); friend = this.GetContact(wxid); logStrbs.Append("6.12_"); is_phpone = true; } } } var eventobj = new WXReiceveFriendMsg(this, friend, $"[图片={cdnstr}]"); logStrbs.Append("6.13_"); eventobj.IsRobot = is_phpone; logStrbs.Append("6.14_"); events.OnEvent(eventobj); } } else { if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) { logStrbs.Append("6.15_"); var groupid = friend.UserName; var reg = Regex.Match(Content, "^(.*?):\\s+([\\w\\W]+)$"); logStrbs.Append("6.16_"); Content = reg.Groups[2].Value; logStrbs.Append("6.17_"); var group = this.GetContact(groupid); logStrbs.Append("6.18_"); if (group == null) { logStrbs.Append("6.19_"); this.WriteLog(string.Format("获取群{0}失败。", groupid)); return; } #region 群用户缓存 if (!GroupMemberCache.ContainsKey(groupid)) { logStrbs.Append("6.20_"); var gmNew = GetMembers(groupid, true); logStrbs.Append("6.21_"); if (gmNew != null) { logStrbs.Append("6.22_"); if (!GroupMemberCache.ContainsKey(groupid)) GroupMemberCache.Add(groupid, gmNew.ToList()); } } #endregion logStrbs.Append("6.23_"); string wxid = reg.Groups[1].Value; logStrbs.Append("6.24_"); string messsage = $"[图片={cdnstr}]"; logStrbs.Append("6.25_"); GroupMember member = this.GetMember(groupid, wxid); logStrbs.Append("6.26_"); if (member == null) { logStrbs.Append("6.27_"); this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", groupid, wxid)); break; } logStrbs.Append("6.28_"); events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); } } } #endregion break; } case 43://收到视频 { logStrbs.Append("7_"); if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("视频")) { if (!item.ContainsKey("Content")) return; string content = item["Content"].ToString(); var reg = Regex.Match(content, "aeskey=\"([^\"]+).*?cdnthumburl=\"([^\"]+)"); if (reg.Success) { var aeskey = reg.Groups[1].Value; var cdnurl = reg.Groups[2].Value; var cdnstr = Util.HexToStr(Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { aeskey = aeskey, cdnurl = cdnurl }))); ChatClient.Events.OnEvent(new WXWriteLog(this) { Message = $"来自{item["PushContent"]}:[视频={cdnstr}]" }); if (item.ContainsKey("FromUserName")) { var fromUserName = item["FromUserName"].ToString(); if (!fromUserName.Contains("@")) { if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) { var friend = GetContact(fromUserName, false); var eventobj = new WXReiceveFriendMsg(this, friend, $"[视频={cdnstr}]"); events.OnEvent(eventobj); } } else { if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) { var Content = Regex.Match(item["Content"].ToString(), "^(.*?):\\s+([\\w\\W]+)$"); var group = this.GetContact(fromUserName); if (group == null) { this.WriteLog(string.Format("获取群{0}失败。", fromUserName)); return; } #region 群用户缓存 if (!GroupMemberCache.ContainsKey(fromUserName)) { var gmNew = GetMembers(fromUserName, true); if (gmNew != null) GroupMemberCache.Add(fromUserName, gmNew.ToList()); } #endregion string wxid = Content.Groups[1].Value; string messsage = $"[视频={cdnstr}]"; GroupMember member = this.GetMember(fromUserName, wxid); if (member == null) { this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", fromUserName, wxid)); break; } events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); return; } } } } } break; } default: return; } //47 动画表情 1 文本消息 } catch (Exception ex) { this.WriteLog("解析消息异常->" + ex.Message + "-" + ex.StackTrace + " - " + logStrbs); } }); method.BeginInvoke(null, null); Thread.Sleep(5); } } #region //private void NewMemberEvents(EventManage events, Friend group, string groupid, string membernicks, string sourcenick) //{ // try // { // var newNick = string.Empty; // var newName = string.Empty; // var sourceNick = string.Empty; // var sourceName = string.Empty; // if (sourcenick == "你") // { // sourceName = this.User.Username; // sourceNick = this.User.Nick; // } // else // { // sourceNick = sourcenick; // } // var msTmp = GetMembers(groupid); // var ms = GetMembers(groupid, true); // if (ms == null) return; // #region 没有、分隔的昵称(就判断为只有一个用户进群) // if (!membernicks.Contains("、")) // { // #region 判断昵称 // var equals = ms.Where(f => Util.RemoveEmoji(f.NickName) == membernicks).ToList(); // if (equals.Count != 0) // { // if (!string.IsNullOrWhiteSpace(sourceName)) // { // if (equals.Count == 1) // { // if (equals[0].InviterUserName == sourceName) // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = equals[0].Username, SourceNick = sourceNick, SourceName = sourceName }); // return; // } // else // { // } // } // else // { // //多个用户名称一样 // var tmps = equals.Where(f => f.InviterUserName == sourceName).ToList(); // if (tmps.Count == 1) // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = tmps[0].Username, SourceNick = sourceNick, SourceName = sourceName }); // return; // } // } // } // else // { // } // } // #endregion // } // #endregion // //else // { // #region 比较两个集合的差 // if (msTmp == null) return; // //获取缓存中不存在的用户集合 // var result = ms.Where(a => msTmp.FirstOrDefault(b => b.Username == a.Username) == null).ToList(); // if (result.Count == 0) // result = ms.ToList(); // if (result.Count != 0) // { // if (!membernicks.Contains("、")) // { // if (!string.IsNullOrWhiteSpace(sourceName)) // { // var equals = result.Where(f => f.InviterUserName == sourceName).ToList(); // if (equals.Count == 1) // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = equals[0].Username, SourceNick = sourceNick, SourceName = sourceName }); // return; // } // } // else // { // var tmps = msTmp.Where(f => Util.RemoveEmoji(f.NickName) == sourceNick).Select(f => f.Username).ToList(); // if (tmps.Count == 0) // { // tmps = Friends.Where(f => f.Value.Remark == sourceNick).Select(f => f.Key).Where(f => !f.Contains("@")).ToList(); // } // if (tmps.Count != 0) // { // if (tmps.Count == 1) // { // var InviterUserName = tmps[0]; // var nickTmps = result.Where(f => Util.RemoveEmoji(f.NickName) == membernicks && f.InviterUserName == InviterUserName).ToList(); // if (nickTmps.Count == 1) // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = nickTmps[0].Username, SourceNick = sourceNick, SourceName = sourceName }); // return; // } // } // else // { // //tmps.FirstOrDefault(f => f.InviterUserName == tmps.FirstOrDefault() != null) // var nickTmps = result.Where(f => Util.RemoveEmoji(f.NickName) == membernicks && tmps.FirstOrDefault(d => d == f.InviterUserName) != null).ToList(); // if (nickTmps.Count == 1) // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = nickTmps[0].Username, SourceNick = sourceNick, SourceName = sourceName }); // return; // } // } // } // } // } // else // { // var mnicks = "、" + membernicks + "、"; // if (!string.IsNullOrWhiteSpace(sourceName)) // { // var userTmps = result.Where(f => f.InviterUserName == sourceName).ToList(); // if (userTmps.Count != 0) // { // //var newTmps = userTmps.Where(f => (membernicks + "、").Contains(f.NickName + "、")).ToList(); // foreach (var item in userTmps) // { // if (mnicks.Contains("、" + Util.RemoveEmoji(item.NickName) + "、")) // { // var count = userTmps.Count(f => Util.RemoveEmoji(f.NickName) == Util.RemoveEmoji(item.NickName)); // if (count == 1) // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = item.NickName, MemberName = item.Username, SourceNick = sourceNick, SourceName = sourceName }); // Thread.Sleep(600); // } // else // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = Util.RemoveEmoji(item.NickName), SourceNick = sourceNick }); // } // } // } // return; // } // } // else // { // // // var sourceTmps = ms.Where(f => Util.RemoveEmoji(f.NickName) == sourceNick).Select(f => f.Username).ToList(); // if (sourceTmps.Count == 0) // { // //获取数据中的用户数据 和 缓存中的好友数据 // sourceTmps = Friends.Where(f => Util.RemoveEmoji(f.Value.Remark) == sourceNick).Select(f => f.Key).Where(f => !f.Contains("@")).ToList(); // } // //包含的昵称用户集合 // var userTmps = result.Where(f => mnicks.Contains("、" + Util.RemoveEmoji(f.NickName) + "、")).ToList(); // if (userTmps.Count != 0) // { // for (int i = 0; i < userTmps.Count; i++) // { // var nickTmps = ms.Where(f => f.Username == userTmps[i].Username).ToList(); // var user = nickTmps.FirstOrDefault(f => sourceTmps.FirstOrDefault(d => d == f.InviterUserName) != null);//这里邀请人不查询多条件符合 // if (user != null) // { // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = Util.RemoveEmoji(user.NickName), MemberName = user.Username, SourceNick = sourceNick, SourceName = sourceName }); // Thread.Sleep(600); // } // //else // //{ // //} // } // return; // } // } // return; // } // //events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, SourceNick = sourceNick }); // } // #endregion // } // { // #region // #endregion // } // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, SourceNick = sourceNick }); // } // catch (Exception ex) // { // this.WriteLog("新群用户解析异常->" + ex.Message + " - " + ex.StackTrace); // } //} #endregion #region 非及时通知新用户 /// /// 群用户缓存 /// private Dictionary> GroupMemberCache = null; private List isRunGroup = new List(); /// /// 保存需要同步的群号 /// private Dictionary SyncGroups = new Dictionary(); /// /// 同步群(群新用户事件) /// private void SyncGroup() { try { if (SyncGroups.Count != 0) { var groupids = SyncGroups.Keys.ToList(); for (int i = 0; i < groupids.Count; i++) { var groupid = groupids[i]; if (Util.GetCache(groupid)) continue; SyncGroups.Remove(groupid); Util.SetCache(groupid, 60); FlushGroup(groupid); } } } catch (Exception ex) { } } /// /// 刷新群用户,生成新用户事件 /// /// private void FlushGroup(string groupid) { try { if (isRunGroup.Contains(groupid)) return; isRunGroup.Add(groupid); if (!GroupMemberCache.ContainsKey(groupid)) { var gmNew = GetMembers(groupid, true); if (gmNew != null && !GroupMemberCache.ContainsKey(groupid)) GroupMemberCache.Add(groupid, gmNew.ToList()); } if (GroupMemberCache.ContainsKey(groupid)) { var gMembers = GroupMemberCache[groupid]; if (gMembers.Count != 0) { var gmOld = GroupMemberCache[groupid]; var gmNew = GetMembers(groupid, true); if (gmNew != null) { GroupMemberCache[groupid] = gmNew.ToList(); var jiaojis = gmNew.Where(a => gmOld.FirstOrDefault(b => b.Username == a.Username) == null).ToList(); //if (jiaojis.Count == 0) // jiaojis = gmNew.ToList(); if (jiaojis.Count == 0) return; var group = GetContact(groupid); if (group != null) { foreach (var item in jiaojis) { Friend inviter = null; if (!string.IsNullOrWhiteSpace(item.InviterUserName)) inviter = GetContact(item.InviterUserName); ChatClient.Events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = item.NickName, MemberName = item.Username, SourceNick = item.InviterUserName == null ? string.Empty : inviter.NickName, SourceName = item.InviterUserName }); Thread.Sleep(600); } } } } } } catch (Exception ex) { } finally { try { isRunGroup.Remove(groupid); } catch (Exception) { } } } #endregion public override string ToString() { if (!string.IsNullOrEmpty(WeixinHao) && this.User != null) { //var data = User.Data; //var host = Host; if (this.Host != null && this.Socket != null && !string.IsNullOrEmpty(this.Socket.ServerIp)) this.Host.BindLongip(this.Socket.ServerIp); var obj = new { data = User.Data, host = Host, username = WeixinHao, password = Password, login_type = (int)this.LoginDeviceType }; return CsharpHttpHelper.HttpHelper.ObjectToJson(obj); } return base.ToString(); } #region 删除好友 /// /// 删除好友(可以用户清理僵尸粉用) /// /// 微信id /// public override string DeleteFriend(string username) { try { WechatPack send = new WechatPack(this);//创建发送对象 var result = send.Send(WechatCmd.删除好友, new { Cmdid = 7, CmdBuf = username }); if (this.Friends.ContainsKey(username)) this.Friends.Remove(username); return string.Empty; } catch (Exception ex) { return ex.Message; } } ///// 删除好友 ///// 老版本的删除僵尸粉 ///// ///// //public void DeleteFriend(Friend friend) //{ // try // { // string payloadJson = "{\"Cmdid\":7,\"CmdBuf\":\"" + friend.UserName + "\"}"; // WechatPacket send = new WechatPacket(this); // var data = send.SendRpc(new BaseMsg // { // Cmd = 681, // User = this.User, // Payloads = ByteString.CopyFrom(Encoding.UTF8.GetBytes(payloadJson)) // }); // data = send.SendRpc(data); // var msg = Encoding.UTF8.GetString(data); // Console.WriteLine(msg); // if (this.Friends.ContainsKey(friend.UserName)) // this.Friends.Remove(friend.UserName); // } // catch (Exception ex) // { // EventManage.OnEvent(this, ex.Message); // } //} #endregion #region 邀请入群 /// /// 邀请入群 /// /// 用户wxid /// 群id /// public override string InviteIntoGroup(string username, string groupId) { try { //WechatPack send = new WechatPack(this);//创建发送对象 //var result = send.SendAll(WechatCmd.删除好友, true, new { Cmdid = 7, CmdBuf = username }); //var msg = Encoding.UTF8.GetString(result); //Console.WriteLine(msg); //if (this.Friends.ContainsKey(username)) this.Friends.Remove(username); //return msg; WechatPack send = new WechatPack(this);//创建发送对象 var result = send.Send(WechatCmd.邀请入群, new { ChatRoom = groupId, Username = username }); var msg = Encoding.UTF8.GetString(result); Console.WriteLine("msg = " + msg); return msg; //Console.WriteLine(msg); //string payloadJson = "{\"ChatRoom\":\"" + tb_ToUsername.Text + "\",\"Username\":\"" + tb_AtUserlist.Text + "\"}"; //WechatMsg InviteChatroomUserReq = new WechatMsg //{ // Token = ConstProtocol.MachineCode, // Version = ConstProtocol.Version, // TimeStamp = Utils.Time_Stamp(), // IP = ClientIP, // BaseMsg = new BaseMsg // { // Cmd = 610, // User = vUser, // Payloads = ByteString.CopyFrom(Encoding.UTF8.GetBytes(payloadJson)) // } //}; //WechatMsg InviteChatroomUserRsp = client.HelloWechat(InviteChatroomUserReq, authHeader); //byte[] body = InviteChatroomUserRsp.BaseMsg.Payloads.ToByteArray(); //byte[] buffers; //using (WebClient c = new WebClient()) //{ // buffers = c.UploadData("http://" + shortServer + InviteChatroomUserRsp.BaseMsg.CmdUrl, body); //} ////短链接解包判定 //if (buffers[0] != 191) //{ // Console.WriteLine("未知包:{0}", Utils.HexToStr(buffers)); // return; // //说明返回wx出错 //} } catch (Exception ex) { return ex.Message; } } #endregion public override string DeleteGroupMember(string username, string groupId) { WechatPack send = new WechatPack(this);//创建发送对象 var result = send.Send(WechatCmd.删除群用户, new { ChatRoom = groupId, Username = username }); var msg = Encoding.UTF8.GetString(result); Console.WriteLine("msg = " + msg); return msg; } private static string GetComputerName() { try { return System.Environment.GetEnvironmentVariable("ComputerName"); } catch { return "unknow"; } } public WXClientImpl_IPAD(string wei_xin_hao) : this() { SetWeixinHao(wei_xin_hao); this.DeviceName = WeixinHao + "_" + GetComputerName(); } public WXClientImpl_IPAD(string WeixinHao, string data) : this() { this.DeviceName = WeixinHao + "_" + GetComputerName(); var _data = Util.ConvertJsonToDic(data); var _host = _data["host"] as Dictionary; this.Host = new WechatHost(); var _list = _host["LongServerList"] as ArrayList; foreach (string item in _list) this.Host.LongServerList.Add(item); //Socket.UpdateServerIp(this.Host.LongServerList, true); _list = _host["ShortServerList"] as ArrayList; foreach (string item in _list) this.Host.ShortServerList.Add(item); //Socket.UpdateServerIp(this.Host.ShortServerList, false); this.Password = _data["password"] != null ? _data["password"].ToString() : string.Empty; this.User = new WeixinBaseUser(_data["data"].ToString()); if (_data.ContainsKey("login_type")) { this.LoginDeviceType = (LoginDeviceType)int.Parse(_data["login_type"].ToString()); } this.UUID = Util.MD5Encrypt(User.Username); SetWeixinHao(WeixinHao); } private string Ime; internal void SetWeixinHao(string wxh) { if (string.IsNullOrEmpty(wxh)) return; this.WeixinHao = wxh; if (string.IsNullOrEmpty(this.DeviceId)) { var WXGetDeviceResult = new WXGetDevice(this); ChatClient.Events.OnEvent(WXGetDeviceResult); this.DeviceId = WXGetDeviceResult.DeviceInfo; } if ((!this.DeviceId.StartsWith("62") && !this.DeviceId.EndsWith("7f"))) { Ime = Util.MD5Encrypt(WeixinHao + this.DeviceId); this.DeviceId = SixTwoData(Ime); } } #region 功能代码 /// /// 刷新通讯录信息(获取好友列表),刷新状态[true为更新中] /// public bool IsRefreshContact { get; private set; } private void GetContact(string[] wxid) { _GetContact(string.Join(",", wxid)); } private void _GetContact(string wxid) { try { // string payloadJson = "{\"UserNameList\":\"" + wxid + "\"}"; WechatPack send = new WechatPack(this); byte[] buffers = CGetContact(User.User, Encoding.UTF8.GetBytes(CsharpHttpHelper.HttpHelper.ObjectToJson(new { UserNameList = wxid, Chatroomid = "" }))); int Seq = Util.ReadInt(buffers, 12); var data = send.SendWx(buffers, Seq); if (data == null) return; byte[] encodeBuf = new byte[data.Length - 16];//提取长连接的body 去掉头16个字节 Buffer.BlockCopy(data, 16, encodeBuf, 0, data.Length - 16); data = CUnPackGetcontact(User.User, encodeBuf); string text = Encoding.UTF8.GetString(data); //System.Configuration.ConfigurationManager.AppSettings["OEM"] text = Util.RemoveEmoji(text); Friend[] frds = Util.ConvertJsonToObj(text) as Friend[]; // Console.WriteLine(text); foreach (Friend item in frds) { this.Friends[item.UserName] = item; } Console.WriteLine(); } catch (Exception) { } } /// /// 发送卡片消息 /// /// /// public override void SendCard(string username, string friendwxid) { if (friendwxid.Contains("@chatroom") || friendwxid.Contains("@im.chatroom")) { InviteIntoGroup(username, friendwxid); } else { //WechatPack pack = new WechatPack(this); //var data = pack.SendAll(WechatCmd.发送消息, false,send); var friend = GetContact(friendwxid); if (friend == null) return; string str = $""; var sendJson = new { ToUserName = username, AppId = "", Type = 42, Content = str }; var temp_pack = new WechatPack(this); temp_pack.SendAll(WechatCmd.发送文本消息, false, sendJson); } } /// /// 获得好友或群组信息 /// public override Friend GetContact(string wxid, bool refresh = false) { lock (this.Friends) { if (refresh || !Friends.ContainsKey(wxid)) _GetContact(wxid); if (Friends.ContainsKey(wxid)) return Friends[wxid]; else { return ChatClient.GetDBWechatFriend(wxid); } } } /// /// 刷新通讯录信息(获取好友列表) /// public override void RefreshContact(Action method = null) { //暂时取消刷新通讯录 //return; if (IsRefreshContact) return; IsRefreshContact = true; ThreadPool.QueueUserWorkItem(f => { bool is_error = false; List users = new List(); try { WriteLog("正在刷新通讯录详情..."); int CurrentWxcontactSeq = 0; int CurrentChatRoomContactSeq = 0; Next: var payloadJson = new { CurrentWxcontactSeq = CurrentWxcontactSeq,//初始为0 CurrentChatRoomContactSeq = CurrentChatRoomContactSeq// 初始为0 }; WechatPack send = new WechatPack(this); var data = send.Send(WechatCmd.读取通信录, payloadJson); data = send.Analysis(data); string text = Encoding.UTF8.GetString(data); var dic = Util.ConvertJsonToDic(text); #region 一次20 var count = 8; var list = dic["UsernameLists"] as ArrayList; if (list == null || list.Count == 0) { if (users.Count > 0) { int number = users.Count / count; if (users.Count % count != 0) number++; int yu = users.Count % count; int sum = 0; for (int i = 0; i < number; i++) { List temp = new List(); for (int j = 0; j < count; j++) { if (this.Status != WxStatus.在线) return; int index = i * count + j; if (users.Count == (index)) break; sum++; temp.Add(users[index]); } if ((i + 1) != number) { this.WriteLog(string.Format("读取通讯录详情,{0}/{1}。", sum, users.Count)); GetContact(temp.ToArray()); Thread.Sleep(600); } else { this.WriteLog(string.Format("读取通讯录详情,{0}/{1}。", sum, users.Count)); GetContact(temp.ToArray()); } temp.Clear(); } } return; } else { foreach (Dictionary item in list) { //if (item["Username"].ToString().EndsWith("@chatroom")) // users.Add(item["Username"].ToString()); users.Add(item["Username"].ToString()); } } #endregion if (this.Status != WxStatus.在线) return; CurrentWxcontactSeq = int.Parse(dic["CurrentWxcontactSeq"].ToString()); CurrentChatRoomContactSeq = int.Parse(dic["CurrentChatRoomContactSeq"].ToString()); if (CurrentWxcontactSeq != 0 || CurrentChatRoomContactSeq != 0) { Thread.Sleep(600); goto Next; } } catch (Exception) { is_error = true; } finally { IsRefreshContact = false; this.WriteLog(string.Format("读取通讯录完成!")); #region 群列表初始化 var groupTmps = users.Where(z => z.Contains("@chatroom")).ToList(); if (groupTmps.Count != 0) { foreach (var item in groupTmps) { if (!GroupMemberCache.ContainsKey(item)) { var members = GetMembers(item, true); if (members != null && members.Length != 0) GroupMemberCache[item] = members.ToList(); Thread.Sleep(1000); } } } #endregion if (!is_error) { ChatClient.Events.OnEvent(new WXRefreshContactSuccess(this)); if (method != null) method.Invoke(this); } else { } } }); } /// /// 同意添加我为好友 /// /// 收到的Token完整数据 public override string AgreeAddMe(string token) { try { string temp = Regex.Replace(token, @"\\""", "\""); var v2 = Regex.Match(temp, "ticket=\"([^\\s]+)\""); var v1 = Regex.Match(temp, "encryptusername=\"([^\\s]+)\""); var scene = 0; var sceneReg = Regex.Match(temp, @"scene=\""([^""]+?)\"""); if (sceneReg.Success) scene = int.Parse(sceneReg.Groups[1].Value); // var us = Regex.Match(temp, "fromusername=\"(.*?)\"").Groups[1].Value; // Console.WriteLine(us); if (v1.Success && v2.Success) { var payloadJson = new { Encryptusername = v1.Groups[1].Value,//v1_ Ticket = v2.Groups[1].Value,//v2_ Type = 3,//1关注公众号2打招呼 主动添加好友3通过好友请求 Sence = scene,//1来源QQ2来源邮箱3来源微信号14群聊15手机号18附近的人25漂流瓶29摇一摇30二维码 Content = "",//打招呼内容 }; WechatPack send = new WechatPack(this); var data = send.SendAll(WechatCmd.同意添加好友, true, payloadJson); string result = Encoding.UTF8.GetString(data); if (temp.Contains(result)) { var reg = Regex.Match(token, @"fromusername=""(?.*?)""[\w\W]+fromnickname=""(?.*?)""[\w\W]+content=""(?.*?)""[\w\W]+sourceusername=""(?.*?)""[\w\W]+sourcenickname=""(?.*?)"""); if (reg.Success) { Task.Factory.StartNew(delegate { Thread.Sleep(2000); var friend = GetContact(reg.Groups["newFriendWxid"].ToString()); //this.EventManage.OnEvent(new WXAddFriendSuccess() { FriendNick = reg.Groups["newFriendNick"].Value, FriendWxid = reg.Groups["newFriendWxid"].ToString() }); if (friend != null) ChatClient.Events.OnEvent(new WXNewFriend(this, friend)); }); } return null; } else this.WriteLog(result); return result; } else return "token 不满足指定条件"; } catch (Exception ex) { return ex.Message; } } /// /// 发送图片 /// /// 图片字节 /// 要发送给谁 public override void SendImage(byte[] img, string username) { int index = 0; Stream imgStream = new MemoryStream(img); try { int Startpos = 0;//起始位置 int datalen = 65535;//数据分块长度//dll img 最大缓冲区65535 在大了 wx 收不到包; int datatotalength = (int)imgStream.Length; string ClientImgId = User.Username + "_" + Util.TimeStamp().ToString(); while (Startpos != (int)datatotalength && index < 15) {// index++; int count = 0; if (datatotalength - Startpos > datalen) { count = datalen; } else { count = (int)datatotalength - Startpos; } byte[] data = new byte[65535]; imgStream.Seek(Startpos, SeekOrigin.Begin); imgStream.Read(data, 0, count); UploadImgInfo imginfo = new UploadImgInfo(); imginfo.ClientImgId = ClientImgId; imginfo.dwStartPos = Startpos; imginfo.dwTotalLen = datatotalength; imginfo.dwDataLen = count; imginfo.szImgBuf = data; imginfo.szToUserName = username; Startpos = Startpos + count; Console.WriteLine("Send Img Block {0} next {1}", count, Startpos); byte[] buffers = WXClientTool.CUploadImg(User.User, imginfo); Console.WriteLine(buffers == null ? "null" : buffers.Length.ToString()); int Seq = Util.ReadInt(buffers, 12); WechatPack pack = new WechatPack(this); buffers = pack.SendWx(buffers, Seq); //var _temp = pack.Analysis(1100, buffers); //Console.WriteLine(Encoding.UTF8.GetString(_temp)); //长链接解包判定 if (buffers[16] != 191) { //说明wx返回出错 //Console.WriteLine("未知包:{0}", Util.HexToStr(buffers)); return; } #region xxx //图片可以不用解包 要解的话就请求服务器好了。。。发送成功最终会返回msgid /* WechatMsg IMGMsgRsp = new WechatMsg { Token = ConstProtocol.MachineCode, Version = ConstProtocol.Version, TimeStamp = Utils.Time_Stamp(), IP = ClientIP }; IMGMsgRsp.BaseMsg = new BaseMsg { Cmd = -1100, User = vUser, }; IMGMsgRsp.BaseMsg.Payloads = ByteString.CopyFrom(buffers); IMGMsgRsp = client.HelloWechat(IMGMsgRsp, authHeader); buffers = IMGMsgRsp.BaseMsg.Payloads.ToByteArray(); //Console.WriteLine(Encoding.UTF8.GetString(buffers)); */ #endregion } } catch (Exception ex) { this.WriteLog($"发送图片失败:{ex.Message} - {ex.StackTrace}"); this.ResetConnection(); } finally { imgStream.Close(); imgStream.Dispose(); } } //public int SendImageCount; /// /// 发送图片 /// /// 要发送给谁 /// 图片路径,支持http,https public override void SendImage(string username, string address) { //SendImageCount++; try { //if (SendImageCount % 2 == 0) SendMessage("weixin", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); byte[] ImangByte = null; string extension = Path.GetExtension(address); if (address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) { var imagePath = Util.MapFile(DateTime.Now.Ticks.ToString() + "." + extension, "Cache\\image"); FileTools.DownloadImage(address, imagePath); address = imagePath; } if (File.Exists(address)) { ImangByte = File.ReadAllBytes(address); if (ImangByte != null && ImangByte.Length >= 3) { SendImage(ImangByte, username); } } else { SendCDNImage(username, address); } } catch (Exception ex) { this.WriteLog("发送图片失败:" + ex.Message); this.ResetConnection(); } } /// /// 发送语音文件 /// /// 名称 /// 地址 public override void SendVoice(string username, string url) { try { byte[] buf; if (url.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) { buf = new WebClient().DownloadData(url); } else { using (FileStream fsRead = new FileStream(url, FileMode.Open)) { int fsLen = (int)fsRead.Length; buf = new byte[fsLen]; fsRead.Read(buf, 0, buf.Length); } } MemoryStream imgStream = new MemoryStream(buf); int Startpos = 0;//起始位置 int datalen = 65535;//数据分块长度 long datatotalength = imgStream.Length; string ClientImgId = User.Username + "_" + Util.TimeStamp().ToString(); int EndFlag = 0; while (Startpos != (int)datatotalength) {// int count = 0; if (datatotalength - Startpos > datalen) { count = datalen; } else { count = (int)datatotalength - Startpos; EndFlag = 1;//最后一个块 } byte[] data = new byte[65535];//不能更改此参数 若要更改必须同步c++ 缓冲器长度 imgStream.Seek(Startpos, SeekOrigin.Begin); imgStream.Read(data, 0, count); UploadVoiceInfo voiceinfo = new UploadVoiceInfo(); voiceinfo.ClientMsgId = ClientImgId; voiceinfo.dwOffset = Startpos; voiceinfo.dwVoiceBufLength = count; voiceinfo.dwVoiceLength = 20000;//2s语音 超长语音好像手机端就不显示 多少秒了。。 voiceinfo.dwEndFlag = EndFlag; voiceinfo.szVoiceBuf = data; voiceinfo.dwVoiceFormat = 4;////0->Arm 无amr音频头 2->MP3 3->WAVE 4->SILK voiceinfo.szToUserName = username; Startpos = Startpos + count; byte[] buffers = WXClientTool.CUploadVoice(User.User, voiceinfo); int Seq = Util.ReadInt(buffers, 12); //Console.WriteLine("Send Seq {0}", Seq); WechatPack pack = new WechatPack(this); pack.SendWx(buffers, Seq); } imgStream.Close(); } catch (Exception ex) { WriteLog(ex.Message); } } #region 返回一个随机表情 private static string Expression = "[微笑],[憨笑],[呲牙],[爱心],[啤酒],[太阳],[礼物],[抱拳],[咖啡],[调皮],[激动],[回头],[色],[愉快],[爱情],[飞吻],[跳跳],[发抖],[转圈],[献吻],[耶],[红包],[嘿哈]"; private static List ExpressionList = null; private static Random random = new Random(); public static string FindRandomExpression() { if (ExpressionList == null) ExpressionList = Expression.Split(',').ToList(); return ExpressionList[random.Next(ExpressionList.Count)]; } #endregion /// /// 发送文本消息 /// /// 用户名 /// 消息正文 /// 是否艾特用户 public override Task SendMessage(string _username, string _content, string _atUsername = "") { string username = _username; string content = _content; string atUsername = _atUsername; return Task.Run(() => { if (string.IsNullOrEmpty(content)) return true; content = content.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); try { foreach (var msg in msgs) { var m = msg.Trim(); if (string.IsNullOrEmpty(m)) continue; var message = m.RandomMess(); message = message.Contains("[随机表情]") ? message.Replace("[随机表情]", FindRandomExpression()) : message; //if (message.StartsWith("[延迟=")) //{ // var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); // if (reg.Success) // { // message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); // // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); // Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); // } //} message = DelayMess(message); ChatClient.Events.OnEvent(new WXSendMessage(this, message, username)); //发送XML消息 if (message.Trim().ToLower().StartsWith("")) { WechatPack pack = new WechatPack(this); var sendJson = new { ToUserName = username, AppId = "", Type = 5, Content = message }; pack.SendAll(WechatCmd.发送XML消息, false, sendJson); //return true; continue; } //发送公告消息 var matchs = Regex.Matches(message, @"\[公告\=([^\]]+)\]", RegexOptions.IgnoreCase); if (username.Contains("@")) { foreach (Match match in matchs) { SetRoomNotice(match.Groups[1].Value, username); } } message = Regex.Replace(message, @"\[公告\=([^\]]+)\]", ""); message = DelayMess(message); //发送图片消息 matchs = Regex.Matches(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); foreach (Match match in matchs) { SendImage(username, match.Groups[1].Value); } message = Regex.Replace(message, @"\[图片\=([^\]]+)\]", ""); message = DelayMess(message); //发送语音消息 matchs = Regex.Matches(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); foreach (Match item in matchs) { SendVoice(username, item.Groups[1].Value); } message = Regex.Replace(message, @"\[语音\=([^\]]+)\]", ""); message = DelayMess(message); matchs = Regex.Matches(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); foreach (Match item in matchs) { try { var temp = item.Groups[1].Value; if (File.Exists(temp)) continue; var video = Util.StrToHex(temp); if (video != null) { var video_json = Encoding.UTF8.GetString(video); var video_data = HttpExtend.JsonToDictionary(video_json); if (video_data != null) { //SendCDNInfo(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString(), CDNType.发送视频); SendCDNVideo(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString()); } } } catch (Exception ex) { } } message = Regex.Replace(message, @"\[视频\=([^\]]+)\]", ""); message = DelayMess(message); matchs = Regex.Matches(message, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); foreach (Match item in matchs) { SendCard(username, item.Groups[1].Value == "自己" ? User.Username : item.Groups[1].Value); } message = Regex.Replace(message, @"\[卡片\=([^\]]+)\]", ""); message = DelayMess(message); if (string.IsNullOrWhiteSpace(message)) continue; if (message.StartsWith("\r\n")) message = message.Substring("\r\n".Length); if (message.StartsWith("\n")) message = message.Substring("\n".Length); WechatPack send = new WechatPack(this); #region 提取艾特用户id List atWxidList = new List(); var regTmp = Regex.Matches(message, @"(?<全部>\[@(?<账号>[A-Za-z0-9_]+)\])"); foreach (Match item in regTmp) { if (item.Success) { var name = item.Groups["账号"].Value; atWxidList.Add(name); var friend = GetContact(name); if (friend != null) message = message.Replace(item.Groups["全部"].Value, $"@{friend.NickName} "); } } if (atWxidList.Count != 0) { atUsername = string.Join(",", atWxidList); } #endregion var sendData = new { ToUserName = username, Content = message.Trim(), Type = 0, MsgSource = atUsername }; send.SetNextData(new WechatPack.PackMsg() { cmd = WechatCmd.发送文本消息, data = sendData }); RunSendMessageQueue(send); } return true; } catch (Exception ex) { this.WriteLog("SendMessage ERROR:" + ex.Message); return false; } }); } /// /// 消息延迟 /// /// public string DelayMess(string message) { try { message = message.Trim(); if (message.StartsWith("[延迟=")) { var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); if (reg.Success) { message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); } } } catch (Exception ex) { } return message; } /// /// /// private DateTime fragmentTime = DateTime.MinValue; private int fragmentCount = 0; /// /// 需要发送的消息队列 /// private ConcurrentQueue SendMessageQueue { get; set; } = new ConcurrentQueue(); private object lock_sendmessage = new object(); private bool lock_sendmessage_ing = false; Thread SendMessageThread; private void RunSendMessageQueue(WechatPack sendPack) { SendMessageQueue.Enqueue(sendPack); if (lock_sendmessage_ing) return; lock (lock_sendmessage) { if (lock_sendmessage_ing) return; lock_sendmessage_ing = true; ThreadPool.QueueUserWorkItem(x => { try { WechatPack pack = null; while (SendMessageQueue.TryDequeue(out pack)) { if (this.Status == WxStatus.在线) { pack.SendNextData(); #region 消息防止频繁,休眠操作 if (ChatClient.MessFrequentSleepTime != 0) { fragmentCount++; var totalSeconds = (DateTime.Now - fragmentTime).TotalSeconds;//上次休眠的时间差 bool rest = totalSeconds > 10; if (fragmentCount >= 10 && totalSeconds <= 10) { rest = true; Thread.Sleep(ChatClient.MessFrequentSleepTime * 1000); } if (rest) { fragmentCount = 1; fragmentTime = DateTime.Now; } } // if (ChatClient.MessFrequentSleepTime != 0) // { // var totalSeconds = (DateTime.Now - _SendTimePoint).TotalSeconds; // if (_SendTimePoint == DateTime.MinValue || _MessCount < 10 && totalSeconds > 10d) // { // _SendTimePoint = DateTime.Now; // _MessCount = -1; // Thread.Sleep(50); // } // else if (_MessCount >= 10 && totalSeconds <= 10d) // { // _SendTimePoint = DateTime.MinValue; // _MessCount = -1; // Thread.Sleep(ChatClient.MessFrequentSleepTime * 1000); // } // _MessCount++; //} #endregion } } } catch (Exception) { } finally { lock_sendmessage_ing = false; } }); } } private Dictionary ContactQRcodes = new Dictionary(); /// /// 获取联系人二维码 /// public override Bitmap GetRobotQRcode(bool Refresh = false) { try { var username = User.Username; WechatPack pack = new WechatPack(this); var data = pack.SendAll(WechatCmd.获取联系人二维码, true, new { Username = username }); var text = Encoding.UTF8.GetString(data); var _dic = Util.ConvertJsonToDic(text); var ba64 = _dic["QrcodeBuf"].ToString(); var result = WXClientTool.GetImageFromBase64(ba64); if (result != null) ContactQRcodes[username] = ba64; return result; } catch (Exception e) { this.WriteLog("GetContactQRcode:" + e.Message + " - " + e.StackTrace); return null; } } public override string DownlowdImage(int msgid, string fromUsername, int datatotalength) { try { List downImgData = new List(); int Startpos = 0;//起始位置 int datalen = 30720;//数据分块长度 // long datatotalength = 55843;//根据需要选择下载 高清图还是缩略图 长度自然是对应 高清长度和缩略长度 while (Startpos != (int)datatotalength) {// int count = 0; if (datatotalength - Startpos > datalen) { count = datalen; } else { count = (int)datatotalength - Startpos; } var payLoadJson = new { MsgId = msgid, ToUsername = fromUsername,//ToUserName 字段值 StartPos = Startpos, TotalLen = (int)datatotalength, DataLen = count, CompressType = 0,//hdlength 1高清0缩略 }; WechatPack pack = new WechatPack(this); var buffers = pack.SendAll(WechatCmd.下载图片, true, payLoadJson); //Console.WriteLine(Encoding.UTF8.GetString(buffers)); Startpos = Startpos + buffers.Length;//已实际接受的块的长度做好偏移 下次从 Startpos + buffers.Length 开始拼接 downImgData.AddRange(buffers); } string image = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); using (FileStream fs = new FileStream(image, FileMode.Create)) { fs.Write(downImgData.ToArray(), 0, downImgData.ToArray().Length); fs.Close(); } return image; } catch (Exception) { } return string.Empty; } public void SnsVerify(string code, bool isHongbao, string reqKey, BankCar bank, string token, string pass) { //确认支付时返回的JSON //此处只有短链接 object obj = null; if (bank != null) { obj = new { CgiCmd = isHongbao ? 1617 : 1592,//1617支付红包返回的短信验证 1592 转账支付时候返回的短信 ReqKey = reqKey, Bank_TYPE = bank.bank_type, Bind_SERIAL = bank.bind_serial,//Bank_TYPE=Bind_SERIAL=CFT时 使用零钱转支付 银行卡支付请填写银行卡id 获取银行卡ID btn_GetBlankID_Click Token = token,//在返回的json里寻找token字段 PassWord = pass, SMSVerityCode = code,//短信验证码 PayScene = bank == null ? "37" : "21" //37使用零钱支付 21银行卡支付(如果支付不成功请联系我重新抓) }; } else { obj = new { Bank_TYPE = "CFT", Bind_SERIAL = "CFT", CgiCmd = isHongbao ? 1617 : 1592,//1617支付红包返回的短信验证 1592 转账支付时候返回的短信 ReqKey = reqKey, Token = token,//在返回的json里寻找token字段 PassWord = pass, SMSVerityCode = code,//短信验证码 PayScene = bank == null ? "37" : "21" //37使用零钱支付 21银行卡支付(如果支付不成功请联系我重新抓) }; } string json = CsharpHttpHelper.HttpHelper.ObjectToJson(obj); WechatPack send = new WechatPack(this); send.Send(WechatCmd.获得银行卡, json); } public override string CreateChatRoom(string members) { try { WechatPack pack = new WechatPack(this); var data = pack.Send(WechatCmd.创建群, new { Membernames = members, ProtocolVer = 1,//值为 1 2 4 6 当然这里你填写3也就是mac的账号密码登陆 具体会出什么问题 自行尝试 }); var temp = pack.Analysis(data); var rest = Encoding.UTF8.GetString(temp); //var json = HttpHelper.ObjectToJson(rest); Lable[] temp_list = HttpHelper.JsonToObject(rest) as Lable[]; if (temp_list != null) Lables = temp_list.ToList(); } catch (Exception ex) { this.WriteLog("创建群异常:" + ex.Message + " - " + ex.StackTrace); } return string.Empty; } public override string CreateChatRoom(string[] wxids) { try { if (wxids == null || wxids.Length == 0) return string.Empty; WechatPack pack = new WechatPack(this); var data = pack.Send(WechatCmd.创建群, new { Membernames = string.Join(",", wxids), ProtocolVer = 1,//值为 1 2 4 6 当然这里你填写3也就是mac的账号密码登陆 具体会出什么问题 自行尝试 }); var temp = pack.Analysis(data); var rest = Encoding.UTF8.GetString(temp); //var json = HttpHelper.ObjectToJson(rest); Lable[] temp_list = HttpHelper.JsonToObject(rest) as Lable[]; if (temp_list != null) Lables = temp_list.ToList(); } catch (Exception ex) { this.WriteLog("创建群异常:" + ex.Message + " - " + ex.StackTrace); } return string.Empty; } public override void AddChatRoomMember(string groupid, string members) { try { WechatPack pack = new WechatPack(this); var payLoadJson = pack.Send(WechatCmd.创建群, new { Roomeid = groupid, Membernames = members, }); } catch (Exception ex) { this.WriteLog("添加群用户异常:" + ex.Message + " - " + ex.StackTrace); } } /// /// 设置公告 /// /// /// public override void SetRoomNotice(string notice, string groupId) { try { WechatPack pack = new WechatPack(this); pack.Send(WechatCmd.群公告, new { ChatRoomName = groupId,//群ID Announcement = notice//公告内容 }); } catch (Exception ex) { this.WriteLog("发送公告异常:" + ex.Message + " - " + ex.StackTrace); } } [Obsolete("该方法过时,发视频使用:SendCDNVideo,发图片使用:SendCDNImage")] public override void SendCDNInfo(string tousername, string cdnurl, string aeskey, CDNType type) { object payLoadJson = null; if (type == CDNType.发送视频) { payLoadJson = new { ToUserName = tousername, ThumbTotalLen = 2883,//中的值 cdnthumblength=\"2883\" ThumbStartPos = 2883,////中的值 cdnthumblength=\"2883\" VideoTotalLen = 401645,//中的值 length=\"401645\" VideoStartPos = 401645,//中的值 length=\"401645\" PlayLength = 2,//playlength=\"2\" AESKey = aeskey,//aeskey=\"ad5b38f66c5849499f294a725e9719a8\" CDNVideoUrl = cdnurl,//中的值 cdnvideourl=\"304b020100044430420201000204d26d70fe02033d0af802047130feb602045953265e0420777869645f6d307238796d61636f693670333234365f313439383632313533330201000201000400\" }; WechatPack sendPack = new WechatPack(this); sendPack.SendAll(WechatCmd.发送CDN数据, false, payLoadJson); } else if (type == CDNType.发送图片) { string ClientImgId = this.User.Username + "_" + Util.TimeStamp(); payLoadJson = JsonConvert.SerializeObject(new { ClientImgId = ClientImgId, ToUserName = tousername, StartPos = 0, TotalLen = 31572, DataLen = 31572, CDNMidImgUrl = cdnurl, AESKey = aeskey, CDNMidImgSize = 31572, CDNThumbImgSize = 3011, CDNThumbImgHeight = 100, CDNThumbImgWidth = 343 }); WechatPack sendPack = new WechatPack(this); sendPack.SendAll(WechatCmd.发送图片文件, false, payLoadJson); } } /// /// 发送CDN视频 /// /// /// /// public override void SendCDNVideo(string tousername, string cdnurl, string aeskey) { var payLoadJson = new { ToUserName = tousername, ThumbTotalLen = 2883,//中的值 cdnthumblength=\"2883\" ThumbStartPos = 2883,////中的值 cdnthumblength=\"2883\" VideoTotalLen = 401645,//中的值 length=\"401645\" VideoStartPos = 401645,//中的值 length=\"401645\" PlayLength = 2,//playlength=\"2\" AESKey = aeskey,//aeskey=\"ad5b38f66c5849499f294a725e9719a8\" CDNVideoUrl = cdnurl,//中的值 cdnvideourl=\"304b020100044430420201000204d26d70fe02033d0af802047130feb602045953265e0420777869645f6d307238796d61636f693670333234365f313439383632313533330201000201000400\" }; WechatPack sendPack = new WechatPack(this); sendPack.SendAll(WechatCmd.发送CDN数据, false, payLoadJson); } public override void SendCDNImage(string tousername, string data) { try { string ClientImgId = this.User.Username + "_" + Util.TimeStamp(); var tmp = Util.StrToHex(data); if (tmp != null) { var image_json = Encoding.UTF8.GetString(tmp); var cdnImgMsg = HttpHelper.JsonToObject(image_json) as CDNImageMsgInfo; if (cdnImgMsg != null) { var payLoadJson = string.Empty; if (!string.IsNullOrWhiteSpace(cdnImgMsg.CDNBigImgUrl)) { payLoadJson = JsonConvert.SerializeObject(new { ClientImgId = ClientImgId, ToUserName = tousername, StartPos = cdnImgMsg.StartPos, TotalLen = cdnImgMsg.TotalLen, DataLen = cdnImgMsg.DataLen, AESKey = cdnImgMsg.AESKey, CDNMidImgUrl = cdnImgMsg.CDNMidImgUrl, CDNMidImgSize = cdnImgMsg.CDNMidImgSize, CDNBigImgUrl = cdnImgMsg.CDNBigImgUrl, CDNBigImgSize = cdnImgMsg.CDNBigImgSize, CDNThumbImgSize = cdnImgMsg.CDNThumbImgSize, CDNThumbImgHeight = cdnImgMsg.CDNThumbImgHeight, CDNThumbImgWidth = cdnImgMsg.CDNThumbImgWidth, CompressType = 1,//高清 }); } else { payLoadJson = JsonConvert.SerializeObject(new { ClientImgId = ClientImgId, ToUserName = tousername, StartPos = cdnImgMsg.StartPos, TotalLen = cdnImgMsg.TotalLen, DataLen = cdnImgMsg.DataLen, AESKey = cdnImgMsg.AESKey, CDNMidImgUrl = cdnImgMsg.CDNMidImgUrl, CDNMidImgSize = cdnImgMsg.CDNMidImgSize, CDNThumbImgSize = cdnImgMsg.CDNThumbImgSize, CDNThumbImgHeight = cdnImgMsg.CDNThumbImgHeight, CDNThumbImgWidth = cdnImgMsg.CDNThumbImgWidth }); } WechatPack sendPack = new WechatPack(this); var result = sendPack.SendAll(WechatCmd.发送图片文件, false, payLoadJson); var text = Encoding.UTF8.GetString(result); var _dic = Util.ConvertJsonToDic(text); if (_dic != null) { } //for (int i = 0; i < 10; i++) //{ // try // { // if (i % 2 == 0) SendMessage("weixin", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); // } // catch (Exception ex) // { // } // Thread.Sleep(5000); //} } } } catch (Exception ex) { } } /// /// 发送朋友圈 /// /// /// public override string SendCircle(string msg) { try { msg = msg.RandomMess().Trim(); if (msg.StartsWith("") && msg.EndsWith("")) { try { msg = Regex.Replace(msg, @"videomd5=""(.{32})""", @"videomd5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @""""); msg = Regex.Replace(msg, @"md5=""(.{32})""", @"md5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @""""); } catch (Exception) { } return _UplodCirele(msg); } else { if (!msg.Contains("[图片")) throw new Exception("请插入任意一张图片!"); //检测图片、如果是本地图片或非微信服务器图片、将自动上传并返回最新地址 List images = null; var match = Regex.Matches(msg, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); if (match.Count > 0) { images = new List(); foreach (Match item in match) { images.Add(item.Groups[1].Value); } msg = Regex.Replace(msg, "\\[图片=.*?\\]", "").Trim(); } var t = SendCircle(msg, images); return t; } } catch (Exception ex) { } return string.Empty; } /// /// 获取朋友圈 /// /// 微信ID /// 页码 /// 页码ID /// public override List> FindCircle(string username, string firstPageMd5 = "", long MaxId = 0) { try { WechatPack send = new WechatPack(this); var data = send.SendAll(WechatCmd.获取朋友圈, true, new { firstPageMd5 = firstPageMd5, Username = username,//访问好友朋友圈的wxid MaxId = MaxId //首页为0 次页朋友圈数据id 的最小值 }); var message = Encoding.UTF8.GetString(data); //Console.WriteLine(message); var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(message); if (dic != null) { var objs = dic["SnsObjects"] as ArrayList; if (objs == null || objs.Count == 0) throw new Exception(username + ",朋友圈没有数据!"); List> _objs = new List>(); foreach (Dictionary item in objs) { _objs.Add(item); } int i, j; //先定义一下要用的变量 for (i = 0; i < _objs.Count - 1; i++) { for (j = i + 1; j < _objs.Count; j++) { var i_ = long.Parse(_objs[i]["CreateTime"].ToString()); var j_ = long.Parse(_objs[j]["CreateTime"].ToString()); if (i_ < j_) //如果第二个小于第一个数 { //交换两个数的位置,在这里你也可以单独写一个交换方法,在此调用就行了 var temp = _objs[i]; //把大的数放在一个临时存储位置 _objs[i] = _objs[j]; //然后把小的数赋给前一个,保证每趟排序前面的最小 _objs[j] = temp; //然后把临时位置的那个大数赋给后一个 } } } return _objs; } } catch (Exception) { } return new List>(); } /// /// 获取朋友圈内容 /// /// public override List> FindCircles() { try { var obj = new { ClientLatestId = 0 }; WechatPack pack = new WechatPack(this); var home = pack.SendAll(WechatCmd.获取朋友圈首页, true, obj); string text = Encoding.UTF8.GetString(home); var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(text); if (dic != null) { var objs = dic["SnsObjects"] as ArrayList; if (objs == null || objs.Count == 0) return new List>(); List> _objs = new List>(); foreach (Dictionary item in objs) { _objs.Add(item); } int i, j; //先定义一下要用的变量 for (i = 0; i < _objs.Count - 1; i++) { for (j = i + 1; j < _objs.Count; j++) { var i_ = long.Parse(_objs[i]["CreateTime"].ToString()); var j_ = long.Parse(_objs[j]["CreateTime"].ToString()); if (i_ < j_) //如果第二个小于第一个数 { //交换两个数的位置,在这里你也可以单独写一个交换方法,在此调用就行了 var temp = _objs[i]; //把大的数放在一个临时存储位置 _objs[i] = _objs[j]; //然后把小的数赋给前一个,保证每趟排序前面的最小 _objs[j] = temp; //然后把临时位置的那个大数赋给后一个 } } } return _objs; } } catch (Exception) { } return new List>(); } /// /// 发表评论 /// /// 发送的微信ID /// 朋友圈的ID /// 发送的内容 /// public override void SendCircleComment(string username, string circleId, string content) { #region 老妖的 //try //{ // WechatPack pack = new WechatPack(this); // var result = pack.Send(WechatCmd.评论或点赞, new // { // ID = circleId,//朋友圈ID // ToUsername = username,//欲被点赞的或评论的wxid 发送该朋友圈的wxid // Type = 2,//1点赞2评论 // Content = content //评论的内容 // }); // //return Encoding.UTF8.GetString(result); //} //catch (Exception ex) //{ // WriteLog("SendCircleComment Error:" + ex.Message); //} #endregion //string username = _username; //string circleId = _circleId; //string content = _content; if (string.IsNullOrEmpty(content)) return; content = content.Replace("\r\n", "\n").Trim(); var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); //Task.Run(delegate //{ try { WechatPack pack = new WechatPack(this); foreach (var msgTmp in msgs) { var msg = msgTmp.RandomMess(); pack.Send(WechatCmd.评论或点赞, new { ID = circleId,//朋友圈ID ToUsername = username,//欲被点赞的或评论的wxid 发送该朋友圈的wxid Type = 2,//1点赞2评论 Content = msg //评论的内容 }); Thread.Sleep(2450 + new Random().Next(50, 1000)); } } catch (Exception ex) { WriteLog("SendCircleComment Error:" + ex.Message); } //}); } private List Lables = new List(); /// /// 获取标签 /// public override List GetLabelList(bool refresh = false) { try { if (!refresh && Lables.Count != 0) return Lables; WechatPack pack = new WechatPack(this); var data = pack.Send(WechatCmd.获取标签, null); var temp = pack.Analysis(data); var rest = Encoding.UTF8.GetString(temp); //var json = HttpHelper.ObjectToJson(rest); Lable[] temp_list = HttpHelper.JsonToObject(rest) as Lable[]; if (temp_list != null) Lables = temp_list.ToList(); } catch (Exception) { } return Lables; } /// /// 添加标签 /// public override bool AddLabel(string TagName) { try { if (Lables.Count == 0) GetLabelList(); if (Lables.FirstOrDefault(f => f.LabelName == TagName) != null) return true; string payloadJson = "{\"LabelName\":\"" + TagName + "\"}"; WechatPack pack = new WechatPack(this); var data = pack.Send(WechatCmd.添加标签, payloadJson); var rest = pack.Analysis(data); var json = HttpHelper.JsonToObject(Encoding.UTF8.GetString(rest)) as Lable[]; if (json != null) { foreach (var item in json) { if (Lables.FirstOrDefault(f => f.LabelID == item.LabelID) == null) Lables.Add(item); } return true; } //Console.WriteLine(); } catch (Exception) { } return false; } /// /// 修改标签 /// public override bool EditUserLabel(string[] Users, List Lable) { try { List list = new List(); foreach (var item in Lable) list.Add(item.LabelID); string payloadJson = JsonConvert.SerializeObject(new { Labelids = string.Join(",", list),//标签id ,号分割 1,2,3,4 UserLists = string.Join(",", Users) //微信id 逗号分隔如1,2,2, }); WechatPack pack = new WechatPack(this); var data = pack.Send(WechatCmd.修改标签, payloadJson); //var rest = pack.Analysis(data); //var json = Encoding.UTF8.GetString(rest); return true; } catch (Exception) { } return false; } /// /// 点赞 /// /// /// public override void SendCirclePraise(string username, string circleId) { try { WechatPack pack = new WechatPack(this); var result = pack.Send(WechatCmd.评论或点赞, new { ID = circleId,//朋友圈ID ToUsername = username,//欲被点赞的或评论的wxid 发送该朋友圈的wxid Type = 1,//1点赞2评论 Content = "" //评论的内容 }); //return Encoding.UTF8.GetString(result); } catch (Exception ex) { WriteLog("SendCirclePraise Error:" + ex.Message); } } #region 发送朋友圈 private string SendCircle(string content, List images = null) { string str = UplodCircleStr(content, images); return _UplodCirele(str); } private string _UplodCirele(string content) { try { var match = Regex.Matches(content, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); foreach (Match item in match) { try { var url = item.Groups[1].Value; url = UplodCircleImage(url); if (string.IsNullOrWhiteSpace(url)) continue; content = content.Replace($"[图片={item.Groups[1].Value}]", url); } catch (Exception) { } } var payloadJson = new { Content = Encoding.UTF8.GetBytes(content) }; WechatPack send = new WechatPack(this); return Encoding.UTF8.GetString(send.SendAll(WechatCmd.发送朋友圈, true, payloadJson)); } catch (Exception ex) { WriteLog("发送朋友圈失败:" + ex.Message); return null; } } /// /// 关注公众号 /// /// /// public override bool FocusWechat(string username) { try { var qr_reg = Regex.Match(username, "http://weixin.qq.com/r/([a-zA-Z0-9]+)"); string data = string.Empty; if (qr_reg.Success) data = qr_reg.Groups[1].Value + "@qr"; else if (!Regex.Match(username, "^gh_.*?$").Success) throw new Exception("公众号格式错误,请重新输入!"); else data = username; string payloadJson = JsonConvert.SerializeObject(new { Encryptusername = data,//非原始id 或扫码后的id 识别二维码后得到http://weixin.qq.com/r/RjndxWXExji5rSGm92xU 账号为RjndxWXExji5rSGm92xU@qr 直接关注即可 Ticket = "",//v2_ Type = 1,//1关注公众号2打招呼 主动添加好友3通过好友请求 Sence = 3, Content = "",//打招呼内容 ProtocolVer = 1 //ProtocolVer 1-5 }); WechatPack pack = new WechatPack(this); pack.SendAll(WechatCmd.同意添加好友, false, payloadJson); return true; } catch (Exception ex) { WriteLog("FocusWechat 异常:" + ex.Message); } return false; } public override Dictionary SerchKeyword(string keyword) { try { WechatPack pack = new WechatPack(this); var result = pack.Send(WechatCmd.搜索关键词, new { Searchinfo = keyword }); result = pack.Analysis(result); var json = Encoding.UTF8.GetString(result); return HttpExtend.JsonToDictionary(json); } catch (Exception ex) { WriteLog("SerchKeyword 异常:" + ex.Message); } return null; } /// /// 编辑用户信息 /// /// 操作用户 /// 操作类型 /// 如果Type=备注,为空表示取消备注,不为空表示备注所填写内容 public override void EditContacts(string username, EditContactsType type, string remark = "") { for (int i = 0; i < 3; i++) { try { if (!string.IsNullOrEmpty(remark)) { if (remark.Length > 55) { remark = remark.Substring(0, 55); } } var payloadJson = "{\"Cmdid\":2,\"CmdBuf\":\"" + username + "\",\"BitVal\":" + (int)type + ",\"Remark\":\"" + remark + "\"}"; WechatPack pack = new WechatPack(this); pack.Send(WechatCmd.编辑联系人信息, payloadJson); } catch (Exception) { this.WriteLog($"更新用户信息[{username}]失败!" + type + "," + remark); } Thread.Sleep(300); } } /// /// 拼接上传信息 /// private string UplodCircleStr(string content, List images = null) { StringBuilder sb = new StringBuilder(); sb.Append("" + Util.GenerateRandomCode(20) + "weixin" + Util.TimeStamp() + "000"); sb.Append("" + content + ""); sb.Append("0"); sb.Append(""); sb.Append("1"); sb.Append("0"); sb.Append(""); sb.Append(""); sb.Append("https://support.weixin.qq.com/cgi-bin/mmsupport-bin/readtemplate?t=page/common_page__upgrade&v=1"); sb.Append(""); if (images != null) { foreach (string temp in images) { var url = UplodCircleImage(temp); //Console.WriteLine("url=" + url); if (string.IsNullOrEmpty(url)) continue; sb.Append(""); sb.Append("" + Util.GenerateRandomCode(20) + ""); sb.Append("2"); sb.Append(""); sb.Append(""); sb.Append("0"); sb.Append("" + url + ""); sb.Append("" + url + ""); sb.Append(""); sb.Append(""); } } sb.Append(""); sb.Append(""); return sb.ToString(); } /// /// 开始上传图片 /// private string UplodCircleImage(string url) { try { var urlResult = string.Empty; for (int i = 0; i < 8; i++) { byte[] data; if (url.StartsWith("http")) { url = url.Replace("&", ""); if (url.Contains("qpic.cn")) return url; HttpHelper http = new HttpHelper(); var item = http.GetItem(url); item.ResultType = CsharpHttpHelper.Enum.ResultType.Byte; data = http.GetHtml(item).ResultByte; } else { FileInfo aFileInfo = new FileInfo(url); using (FileStream fsRead = aFileInfo.Open(FileMode.Open)) { int fsLen = (int)fsRead.Length; data = new byte[fsLen]; fsRead.Read(data, 0, data.Length); } } data = Util.CompressionImage(new MemoryStream(data), 25); WechatPack send = new WechatPack(this); byte[] result = null; string ClientImgId = User.Username + "_" + Util.TimeStamp().ToString(); var send_data = new { StartPos = 0, ClientId = ClientImgId, TotalLen = data.Length, Uploadbuf = data, }; result = send.SendAll(WechatCmd.上传朋友圈图片, true, send_data); urlResult = Encoding.UTF8.GetString(result); if (string.IsNullOrWhiteSpace(urlResult)) { Thread.Sleep(100); continue; } break; } return urlResult; } catch { return string.Empty; } } #endregion #endregion #region 基础函数 private string HexToStr(byte[] bytes) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("x2"); } } return returnStr; } private string SixTwoData(string imei) { string hexStr = HexToStr(Encoding.UTF8.GetBytes(imei)).Replace(" ", ""); string str = "62706c6973743030d4010203040506090a582476657273696f6e58246f626a65637473592461726368697665725424746f7012000186a0a2070855246e756c6c5f1020" + hexStr + "5f100f4e534b657965644172636869766572d10b0c54726f6f74800108111a232d32373a406375787d0000000000000101000000000000000d0000000000000000000000000000007f"; return str; } WxQrcode _loginWxQrcode; WechatPack _loginPack; /// /// 获得登录图片 /// public void FindLoginImage(LoginDeviceType type) { try { Connection(); this.User = new WeixinBaseUser(new User() { SessionKey = ByteString.CopyFrom(WXClientTool.random_encry_key), DeviceId = DeviceId }); this.LoginDeviceType = type; _loginPack = new WechatPack(this); var data = new { ProtocolVer = (int)this.LoginDeviceType,//此处只有1 3 5值 DeviceName = DeviceName }; ChangeStatus(WxStatus.登录中); //WriteLog("获取二维码0"); var byteData = _loginPack.Send(WechatCmd.获取登录二维码, data); //WriteLog("获取二维码1"); byteData = _loginPack.SendWx(byteData); //WriteLog("获取二维码2"); byteData = _loginPack.Analysis(byteData); //WriteLog("获取二维码3"); string _temp = Encoding.UTF8.GetString(byteData); _loginWxQrcode = JsonConvert.DeserializeObject(_temp); this._loginTemp = new LoginTemp(); this._loginTemp.UUId = _loginWxQrcode.Uuid; this._loginTemp.NotifyKey = _loginWxQrcode.NotifyKey; this._loginTemp.LongHead = _loginPack.Req.BaseMsg.LongHead; this._loginTemp.HeadFlag = false; ChangeStatus(WxStatus.扫码中, new WXChangeStatus(this) { ImageByte = _loginWxQrcode.ImgBuf }); } catch (Exception ex) { throw ex; } } private LoginTemp _loginTemp; private string UUID { get; set; } private string DeviceType { get; set; } class LoginTemp { public string UUId { get; set; } public byte[] NotifyKey { get; set; } public ByteString LongHead { get; set; } public bool HeadFlag { get; set; } } /// /// 实现发红包 /// /// /// /// /// /// /// /// /// /// public override string SendPay(string toUsername, string content, int TotalAmount, string password, int count, PayType type, BankCar bank = null, Dictionary param = null) { try { int code = 385; string payloadJson = string.Empty; if (type == PayType.红包) { payloadJson = "{\"CgiCmd\":1,\"HBType\":\"0\",\"HBFrom\":\"0\",\"ToUsername\":\"" + toUsername + "\",\"Count\":\"" + count + "\",\"TotalAmount\":\"" + TotalAmount + "\",\"HBContent\":\" " + content + "\"}"; } else { payloadJson = "{\"CgiCmd\":83,\"Desc\":\"" + content + "\",\"ToUsername\":\"" + toUsername + "\",\"Count\":\"" + TotalAmount + "\"}"; } WechatPack send = new WechatPack(this); //CMD = 385 var data = send.Send(code, payloadJson); data = send.Analysis(data); string text = Encoding.UTF8.GetString(data); string ReqKey = string.Empty; if (type == PayType.红包) ReqKey = WXClientTool.BetweenArr(text, "reqkey\":\"", "\",\"scene"); else ReqKey = WXClientTool.BetweenArr(text, "req_key\":\"", "\",\"tansfering_status"); if (bank != null) { payloadJson = Util.ObjectToJson(new { CgiCmd = 0, ReqKey = ReqKey, PassWord = password, Bank_TYPE = bank.bank_type, Bind_SERIAL = bank.bind_serial }); } else { payloadJson = Util.ObjectToJson(new { CgiCmd = 0, ReqKey = ReqKey, PassWord = password }); } data = send.Send(code, payloadJson); //data = send.SendWx(data); if (data == null) throw new Exception("服务器繁忙,请稍后重试"); data = send.Analysis(data); text = Encoding.UTF8.GetString(data); //Console.WriteLine(text); if (text.Contains("支付成功") || text.Contains("请确认银行卡是否扣款后再试")) return null; else { if (param != null) { param["reqKey"] = ReqKey; param["bank"] = bank; param["isHongbao"] = type == PayType.红包 ? true : false; param["result"] = text; param["pass"] = password; } this.WriteLog("支付失败:" + text); return text; } } catch (Exception ex) { if (ex.Message.Contains("请确认银行卡是否扣款后再试")) return null; //else if (ex.Message.Contains("服务器繁忙,请稍后重试")) return null; this.WriteLog("支付失败:" + ex.Message); return ex.Message; } } /// /// 登录状态检测 /// public void FindLoginStatus() { try { if (_loginWxQrcode.Status == 2) { return; } if (_loginWxQrcode == null) return; if (_loginWxQrcode.Status == 4) { ChangeStatus(WxStatus.取消扫码); return; } if (_loginWxQrcode.Status == 1 && !_loginTemp.HeadFlag) { //lab_ShowMsg.Text = "已扫描 未确认"; using (WebClient _client = new WebClient()) { _loginTemp.HeadFlag = true; ChangeStatus(WxStatus.获取头像成功, new WXChangeStatus(this) { ImageByte = _client.DownloadData(_loginWxQrcode.HeadImgUrl) }); } } this.User.User.MaxSyncKey = ByteString.CopyFrom(this._loginTemp.NotifyKey); var data = _loginPack.Send(WechatCmd.获取二维码状态, Encoding.UTF8.GetBytes(this._loginTemp.UUId), this._loginTemp.LongHead); data = _loginPack.SendWx(data); data = _loginPack.Analysis(data); var text = Encoding.UTF8.GetString(data); _loginWxQrcode = JsonConvert.DeserializeObject(text); if (_loginWxQrcode != null) ChatClient.Events.OnEvent(new WXScavengEvents(this) { Status = _loginWxQrcode.Status }); if (_loginWxQrcode.Status == 2) { UUID = Util.MD5Encrypt(_loginWxQrcode.Username); Password = _loginWxQrcode.Password; Login(_loginWxQrcode.Username, _loginWxQrcode.Password); } } catch (Exception ex) { //ChatClient.Events.OnEvent(new WXWriteLog(this) { Message = ex.Message+","+ex.StackTrace} ); } } private LoginDeviceType LoginDeviceType = LoginDeviceType.未知; /// /// 登录密码 /// public string Password { get; set; } internal bool Login(string username, string userpass, string data62 = "") { try { //if (LoginDeviceType == LoginDeviceType.未知) LoginDeviceType = LoginDeviceType.Windows; #region 执行登录 Status = WxStatus.登录中; //构造二维码登陆封包结构 string UUid = Guid.NewGuid().ToString();//随机uuid 667D18B2-BCE3-4AA2-8ED1-7FDC19446567 string md5 = Util.MD5Encrypt(username); this.DeviceType = string.Format("TP_lINKS_5G中国移动{0}:{1}:{2}:{3}:{4}:{5}", md5.Substring(0, 2), md5.Substring(2, 4), md5.Substring(4, 6), md5.Substring(6, 8), md5.Substring(8, 10), md5.Substring(8, 12)); // string DeviceType = "TP_lINKS_5G中国移动c1:cd:2d:1c:5b:11";//随机 单号保持同一设备信息 if (this.LoginDeviceType == LoginDeviceType.未知) this.LoginDeviceType = LoginDeviceType.Windows; // "{\"Username\":\"" + username + "\",\"PassWord\":\"" + userpass + "\",\"UUid\":\"" + UUid + "\",\"DeviceType\":\"" + DeviceType + "\"}"; var payLoadJson = new { Username = username, PassWord = userpass, UUid = UUid, DeviceType = DeviceType, DeviceName = DeviceName,//新增的字段 ProtocolVer = (int)this.LoginDeviceType }; //this.User = new User() { SessionKey = ByteString.CopyFrom(randomEncryKey), DeviceId = DeviceId }; int cmd = (this.LoginDeviceType == LoginDeviceType.QQBrowser) ? 380 : 1111; if (userpass.Length <= 32 && !string.IsNullOrEmpty(data62)) { Connection(); //this.LoginDeviceType = LoginDeviceType.Ipad; this.DeviceId = data62; _loginPack = new WechatPack(this); cmd = 2222; this.User = new WeixinBaseUser(new User() { SessionKey = ByteString.CopyFrom(WXClientTool.random_encry_key), DeviceId = DeviceId }); this.User.User.MaxSyncKey = ByteString.CopyFrom(WXClientTool.random_encry_key); } byte[] data = _loginPack.Send(cmd, payLoadJson); //Socket.Connect(); var _data = _loginPack.SendWx(data); _loginPack.Req.BaseMsg.Cmd = (cmd == 380) ? -380 : -1001; _loginPack.Req.BaseMsg.Payloads = ByteString.CopyFrom(_data); _data = _loginPack.Send(_loginPack.Req); var ret = _loginPack.Req.BaseMsg.Ret; if (ret >= 10000001) { switch (ret) { case 10000001: case 10000002: case 10000003: case 10000004: case 10000005: //Console.WriteLine(Encoding.UTF8.GetString(_data)); break; } } var str = Encoding.UTF8.GetString(_data); if (ret < 0 && ret != -301) { throw new Exception(str); } var retData = _loginPack.Req.BaseMsg.Playloadextend.ToByteArray(); string json = Encoding.UTF8.GetString(_loginPack.Req.BaseMsg.Playloadextend.ToByteArray()); var list = Util.ConvertJsonToDic(json); //bool flag = false; //Next: string longServer = _loginPack.Req.BaseMsg.LongHost; string shortServer = _loginPack.Req.BaseMsg.ShortHost; this.Host = new WechatHost(); // Console.WriteLine(shortServer); string msg = Encoding.UTF8.GetString(_loginPack.Req.BaseMsg.Playloadextend.ToByteArray()); var LongServerList = Util.ConvertJsonToDic(msg)["LongServerList"] as ArrayList; var ShortServerList = Util.ConvertJsonToDic(msg)["ShortServerList"] as ArrayList; //this.Host.LongServerList.Add(longServer); //this.Host.LongServerList.Add(shortServer); //foreach (string item in LongServerList) //{ // this.Host.LongServerList.Add(item); //} foreach (string item in ShortServerList) { if (item == "127.0.0.1") continue; this.Host.ShortServerList.Add(item); } //Socket.UpdateServerIp(msg); //Socket.Send //重新注册及连接微信 if (_loginPack.Req.BaseMsg.Ret == -301)//重定向 { this.Host.BindLongip(_loginPack.Req.BaseMsg.LongHost); Socket.Connect(); //Console.WriteLine("WX longServer IP:{0}", longServer); //Console.WriteLine("WX shortServer IP:{0}", shortServer); Thread.Sleep(200); _data = _loginPack.SendWx(data);//获得微信返回数据 Thread.Sleep(200); _data = _loginPack.Analysis(cmd == 380 ? -380 : -1001, _data); } if (_loginPack.Req.BaseMsg.Ret == 0)//登陆成功 { this.Host.BindLongip(this.Socket.ServerIp); //保存用户解构信息 User.User = _loginPack.Req.BaseMsg.User; //如果为0,暂时不验证授权 //Console.WriteLine(User.Uin.ToString()); if (User.Uin.ToString() != "0") { Grant.Framework.GrantClient.Get().Login(User.Uin.ToString(), User.Nick, int.Parse(WXClientTool.auth_info[0]), WXClientTool.auth_info[1]); } shortServer = _loginPack.Req.BaseMsg.ShortHost; Initialization(); ChangeStatus(WxStatus.在线); return true; } else { string message = string.Empty; if (_loginPack.Req.BaseMsg.Ret == -301) message = "暂时无法识别您的帐号,请更换帐号。"; else message = Encoding.UTF8.GetString(_data); Console.WriteLine(message); throw new Exception(message); //ChangeStatus(WxStatus.登录失败, new WXChangeStatus(this, message)); } #endregion } catch (Exception ex) { LoginErrorMessage = ex.Message; ChangeStatus(WxStatus.登录失败, new WXChangeStatus(this, ex.Message)); return false; } finally { if (Status != WxStatus.在线) { this.Socket.Stop(); } else LoginErrorMessage = string.Empty; } } public string LoginErrorMessage { get; private set; } internal string GetLoginCode(string username) { Connection(); this.User = new WeixinBaseUser(new User() { SessionKey = ByteString.CopyFrom(WXClientTool.random_encry_key), DeviceId = DeviceId }); var obj = new { Opcode = 16, Mobile = username,//自己微信号绑定的手机号 没有绑定手机的 获取不聊 Imei = this.Ime + "-" + Util.TimeStamp().ToString(), DeviceName = this.DeviceName, Language = "CN" }; WechatPack pack = new WechatPack(this); var req = pack.Send(145, obj); var rsp = pack.Analysis(req); var str = Encoding.UTF8.GetString(rsp); //string msg = Encoding.UTF8.GetString(_loginPack.Req.BaseMsg.Playloadextend.ToByteArray()); //var LongServerList = Util.ConvertJsonToDic(str)["LongServerList"] as ArrayList; //var ShortServerList = Util.ConvertJsonToDic(str)["ShortServerList"] as ArrayList; //foreach (string item in LongServerList) //{ // this.Host.LongServerList.Add(item); //} //foreach (string item in ShortServerList) //{ // if (item == "127.0.0.1") continue; // this.Host.ShortServerList.Add(item); //} //Socket.UpdateServerIp(new string[] { pack.Req.BaseMsg.ShortHost }.ToList()); //重新注册及连接微信 if (pack.Req.BaseMsg.Ret == 0) { return string.Empty; } else if (pack.Req.BaseMsg.Ret == -301)//重定向 { //var shortServer = pack.Req.BaseMsg.ShortHost; //var _data = Socket.SendWeChatPost(req, pack.Req.BaseMsg.CmdUrl); //rsp = pack.Analysis(req); //str = Encoding.UTF8.GetString(rsp); //return str; } else { return str; } return null; } internal string VerifyLoginSmsCode(string username, string code) { object obj = new { Opcode = 17, Mobile = username,//手机号 Imei = this.Ime + "-" + Util.TimeStamp().ToString(), Verifycode = code, DeviceName = DeviceName, Language = "CN" }; WechatPack pack = new WechatPack(this); var req = pack.Send(145, obj); var rsp = pack.Analysis(req); var str = Encoding.UTF8.GetString(rsp); return str; } /// /// 获得银行卡 /// /// public List FindBankCar() { var username = "wxid_8s44kddouuaj21"; if (Status != WxStatus.在线) throw new Exception("请先登录微信!"); int code = 385; string payloadJson = "{\"CgiCmd\":1,\"HBType\":\"0\",\"HBFrom\":\"0\",\"ToUsername\":\"" + username + "\",\"Count\":\"1\",\"TotalAmount\":\"1\",\"HBContent\":\"测试\"}"; WechatPack send = new WechatPack(this); var data = send.Send(WechatCmd.获得银行卡, payloadJson); data = send.Analysis(data); string text = Encoding.UTF8.GetString(data); string ReqKey = WXClientTool.BetweenArr(text, "reqkey\":\"", "\",\"scene"); payloadJson = CsharpHttpHelper.HttpHelper.ObjectToJson(new { CgiCmd = 1569, ReqKey = ReqKey//创建好支付解构 调用调用此方法 查询银行卡的绑定ID以及类型 }); data = send.Send(WechatCmd.获得银行卡, payloadJson); data = send.Analysis(data); string json = Encoding.UTF8.GetString(data); var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(json); if (dic.ContainsKey("bindqueryresp")) { dic = dic["bindqueryresp"] as Dictionary; var list = dic["Array"] as ArrayList; if (list != null && list.Count > 0) { List cars = new List(); foreach (Dictionary item in list) { cars.Add(new BankCar() { bank_name = item["bank_name"].ToString(), bind_serial = item["bind_serial"].ToString(), bind_tail = item["bind_tail"].ToString(), bank_type = item["bank_type"].ToString() }); } return cars; } } return new List(); } /// /// 显示登录窗口 /// public override void ShowLogin() { try { //Connection();//链接 new LoginForm(this).ShowDialog(); } catch (Exception ex) { } } internal void ShowPasswordForm() { Connection(); new LoginwxPassForm(this).ShowDialog(); } #endregion #region 连接 public void CloseGRPC(bool timeout) { lock (lock_grpcp) { foreach (var item in GrpcPool.Values) { try { if (timeout) { var time = DateTime.Now - item.LastTime; if (time.TotalMinutes > 15) item.Stop(); } else item.Stop(); } catch (Exception) { } } } } private object lock_grpcp = new object(); /// /// Grpc 池 /// private Dictionary GrpcPool = new Dictionary(); internal GrpcClient GetGrpcClient(GrpcType type, bool refresh = false) { lock (lock_grpcp) { GrpcClient client = null; if (GrpcPool.ContainsKey(type)) client = GrpcPool[type]; else { client = new GrpcClient(GrpcConfig.Get(type, true)); GrpcPool[type] = client; } if (refresh || !client.IsConnected) client.Init(); return client; } } private bool Connection() { //this.GetGrpcClient(GrpcType.Huangfan).Init(); //this.GetGrpcClient(GrpcType.Huangfan).Init(); return this.Socket.Connect(); } #endregion #region Win32 #endregion #region IPAD协议 public WechatHost Host { get; private set; } public WechatSocket Socket { get; private set; } /// /// 强制拉取消息 /// /// public bool AsyncSyncMessage() { bool is_netxt = false; Next: try { WechatPack send = new WechatPack(this); var buffers = WXClientTool.CPackSync(this.User.User); if (buffers == null) throw new Exception("WeChat 未响应数据!1"); int Seq = Util.ReadInt(buffers, 12); buffers = send.SendWx(buffers, Seq); if (buffers == null) throw new Exception("WeChat 未响应数据!2"); byte[] encodeBuf = new byte[buffers.Length - 16];//提取长连接的body 去掉头16个字节 Buffer.BlockCopy(buffers, 16, encodeBuf, 0, buffers.Length - 16); byte[] syncKey = new byte[] { }; var data = CUnPackSync(this.User.User, encodeBuf, ref syncKey); if (data == null) this.FastLogin(); if (syncKey.Length > 0) { User.User.CurrentsyncKey = ByteString.CopyFrom(syncKey); //if (this.Status != WxStatus.在线) ChangeStatus(WxStatus.在线); } var result = Encoding.UTF8.GetString(data); if (result == "offline") { if (!is_netxt) { is_netxt = true; goto Next; } return false; } if (this.Status != WxStatus.在线) ChangeStatus(WxStatus.在线); if (result == "null") return true; if (User.LoginTime > DateTime.Now.AddSeconds(-10)) return true; AnalysisMessage(result); return true; } catch (Exception ex) { if (this.Status == WxStatus.在线) WriteLog($"同步消息失败:{ex.Message}"); else LogHelper.GetSingleObj().Error("AsyncSyncMessage", $"{this.WeixinHao}-{ex.Message}"); } return false; } private List pack = new List(); /// /// 快速初始化通讯录列表 /// /// public bool Initialization() { try { this.Friends.Clear(); Next: WechatPack send = new WechatPack(this); var data = send.SendAll(WechatCmd.初始化用户信息, true); if (send.Req.BaseMsg.Ret != 8888) { var json = Encoding.UTF8.GetString(data); if (json != "null") { var list = Util.ConvertJsonToObj(json); foreach (Friend item in list) { if (item == null || string.IsNullOrEmpty(item.UserName)) Console.WriteLine(); else Friends[item.UserName] = item; } } goto Next; } return true; } catch (Exception ex) { LogHelper.GetSingleObj().Error("Initialization ERROR: ", $"{this.WeixinHao}-{ex.Message}"); } return false; } internal bool DecodeSecureNotifyThread(byte[] data) { return false; } internal string _client_ip; internal string clientIp { get { if (string.IsNullOrEmpty(_client_ip)) _client_ip = Util.GetPublicIpAdress(); return _client_ip; } } public string DeviceId { get; internal set; } internal string DeviceName = "FLSystem"; //internal int ProtocolVer = 7; public WXClientImpl_IPAD() { this.Host = new WechatHost(); this.Socket = new WechatSocket(this); WeixinType = WeixinType.Grpc微信; GroupMembers = new Dictionary(); Friends = new Dictionary(); Status = WxStatus.未登录; //Socket.ReceivedNotifyMessage += Socket_ReceivedNotifyMessage; Socket.ReceivedOnConnected += Socket_ReceivedOnConnected; Socket.ReceivedOnDisconnected += Socket_ReceivedOnDisconnected; GroupMemberCache = new Dictionary>(); ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(true), new WaitOrTimerCallback((state, timedout) => { try { if (Status == WxStatus.在线) SyncGroup(); } catch (Exception ex) { } }), null, 10 * 1000, false);//30秒执行一次 } private void Socket_ReceivedOnDisconnected(object sender, IPAddress e) { //Console.WriteLine(); //try //{ // this.Socket.Connect(this.Host.GetLong()); //} //catch (Exception) //{ //} } private void Socket_ReceivedOnConnected(object sender, IPAddress e) { //this.WriteLog($"服务器 {e.ToString()} 重连成功!"); //this.WriteLog($"服务器 {e.ToString()} 已链接!"); //this.WriteLog($"服务器 {e.ToString()} 已链接!" + Status); //if (Status == WxStatus.在线) //{ // this.WriteLog($"服务器 {e.ToString()} 重连成功!", false); // Thread.Sleep(300); // AsyncSyncMessage(); //} //else //{ // this.WriteLog($"服务器 {e.ToString()} 连接成功!", false); //} //ChangeStatus(this.Status); } //private void Socket_ReceivedNotifyMessage(object sender, WeChatMessage message) //{ // //新起线程,否则会影响socket // Task.Factory.StartNew(() => // { // var buffer = message.Msg.BaseMsg.Payloads.ToByteArray(); // switch (message.CmdID) // { // case 24: // if (Util.HexToStr(buffer) == "0000001400100001000000180000000000000100") // { // //朋友圈更新Notify // //Client.SyncMessage(true); // } // else // { // //普通消息Notify // Task.Factory.StartNew(AsyncSyncMessage); // } // break; // case 318: // DecodeSecureNotifyThread(buffer); // break; // default: // Console.WriteLine($"ReceivedUnKnowMessage CMD:{message.CmdID}"); // break; // } // }); //} public bool IsRunning => throw new NotImplementedException(); public RegisteredWaitHandle RegisterdHandler { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public WaitHandle WaitHandler { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } #endregion private HeadPack head = null; private DateTime lastGetInfo; /// /// 获取群信息 /// /// private void GetGroupInfo(string groupid) { lock (GroupMembers) { try { if (!Friends.ContainsKey(groupid)) { var f = GetContact(groupid); if (f != null) Friends[groupid] = f; } if (lastGetInfo > DateTime.Now.AddSeconds(-1)) { Thread.Sleep(1000); } WechatPack send = new WechatPack(this); var data = send.Send(WechatCmd.获取群信息, new { Chatroom = groupid }); data = send.Analysis(data); string text = Encoding.UTF8.GetString(data); var dic = Util.ConvertJsonToDic(text); var obj = Util.ObjectToJson(dic["MemberDetails"]); GroupMember[] temp = Util.ConvertJsonToObj(obj) as GroupMember[]; if (temp != null) GroupMembers[groupid] = temp; lastGetInfo = DateTime.Now; //Console.WriteLine(); } catch (Exception ex) { this.WriteLog(ex.Message); } } } public Dictionary GroupMembers { get; private set; } public override GroupMember[] GetMembers(string groupid, bool flag = false) { if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("取群成员")) { if (flag || !GroupMembers.ContainsKey(groupid)) GetGroupInfo(groupid); if (GroupMembers.ContainsKey(groupid)) return GroupMembers[groupid]; else return null; } else return null; } public override GroupMember GetMember(string groupid, string wxid) { if (!GroupMembers.ContainsKey(groupid)) GetGroupInfo(groupid); if (GroupMembers.ContainsKey(groupid)) { var member = GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); if (member == null) GetGroupInfo(groupid); else return member; } else return new GroupMember() { Groupid = groupid, Username = wxid }; if (GroupMembers.ContainsKey(groupid) && GroupMembers[groupid] != null) return GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); else return new GroupMember() { Groupid = groupid, Username = wxid }; } //private void OnAnalysisMessage /// /// 执行二次登录 /// /// public string FastLogin() { try { this.Status = WxStatus.登录中; if (LoginDeviceType == LoginDeviceType.未知) return $"此版本升级,需要重新登陆!"; byte[] data = null; WechatPack send = new WechatPack(this); if (this.LoginDeviceType == LoginDeviceType.QQBrowser) { var obj = new { UUId = UUID, DeviceType = DeviceType, DeviceName = DeviceName, ProtocolVer = (int)this.LoginDeviceType, PassWord = Password }; data = send.SendAll(WechatCmd.浏览器加密登录, true, obj); //return null; } else { var obj = new { UUId = UUID, DeviceType = DeviceType, DeviceName = DeviceName, ProtocolVer = (int)this.LoginDeviceType, }; data = send.SendAll(WechatCmd.执行二次登陆, true, obj); } string result = Encoding.UTF8.GetString(data); if (string.IsNullOrEmpty(result)) return null; var reg = Regex.Match(result, @""); if (reg.Success) { this.WriteLog("快速登陆失败:" + reg.Groups[1].Value); ChangeStatus(WxStatus.已掉线, null, false); return result; } else { if (result.Length > 15 || result == "登录出现错误,请你重新登录。") return null; var msg = GetChineseWord(result); if (string.IsNullOrEmpty(msg)) return null; this.WriteLog("快速登陆失败:" + result); return result; } } catch (Exception ex) { return ex.Message; } } private string GetChineseWord(string oriText) { string x = @"[\u4E00-\u9FFF]+"; MatchCollection Matches = Regex.Matches (oriText, x, RegexOptions.IgnoreCase); StringBuilder sb = new StringBuilder(); foreach (Match NextMatch in Matches) { sb.Append(NextMatch.Value); } return sb.ToString(); } public override void ChangeStatus(WxStatus status, WXChangeStatus e = null, bool is_next = true) { if (status == WxStatus.已掉线 || status == WxStatus.已退出 || status == WxStatus.未登录 || status == WxStatus.登录失败) { if (this.User != null && this.User.Uin != 0) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); if (this.Socket != null) this.Socket.Stop(); this.CloseGRPC(false); if (head != null) ThreadExcutor.UnRegisterIntervaluObject(head); head = null; } if (status == WxStatus.在线) { var v = this.User.User; if (head == null) { try { if (User.Uin.ToString() != "0") Grant.Framework.GrantClient.Get().Login(User.Uin.ToString(), User.Nick, int.Parse(WXClientTool.auth_info[0]), WXClientTool.auth_info[1]); head = new HeadPack(this); } catch (Exception ex) { status = WxStatus.登录失败; this.WriteLog("检测授权异常:" + ex.Message); } } } else { this.Lables.Clear(); } if (this.Status == WxStatus.已掉线 && status == WxStatus.已退出) return; //if (this.Status == WxStatus.未登录) return; base.ChangeStatus(status, e, is_next); } public bool IsResetConnection { get; private set; } /// /// 重新连接 /// public override void ResetConnection(int next = 3) { if (IsResetConnection) return; IsResetConnection = true; try { if (string.IsNullOrEmpty(this.DeviceType)) { string md5 = Util.MD5Encrypt(this.User.Username); this.DeviceType = string.Format("TP_lINKS_5G中国移动{0}:{1}:{2}:{3}:{4}:{5}", md5.Substring(0, 2), md5.Substring(2, 4), md5.Substring(4, 6), md5.Substring(6, 8), md5.Substring(8, 10), md5.Substring(8, 12)); } for (int i = 1; i <= next; i++) { //if (i > 2) this.Host.LongServerList.Clear(); Connection(); if (i > 1) { var msg = this.FastLogin(); if (msg != null && Regex.Match(msg, "(已退出)|(重新登录)|安全").Success) { ChangeStatus(WxStatus.已退出); return; } } //var flag = this.Initialization(); //else //{ // this.Initialization(); //} if (this.AsyncSyncMessage()) { ChangeStatus(WxStatus.在线); break; } //this.Initialization(); //if (this.AsyncSyncMessage()) //{ //} Thread.Sleep(2000); } if (Status != WxStatus.在线) { ChangeStatus(WxStatus.已掉线); WriteLog($"经过了{next}次登陆,无法自动登陆!"); } else { //RefreshContact();//刷新通讯录 } } catch (Exception ex) { this.WriteLog("WxSocket连接异常:" + ex.Message); this.Socket.Stop(); ChangeStatus(WxStatus.登录失败); } finally { IsResetConnection = false; } } /// /// 退出登录 /// public override void LoginOut() { //Console.WriteLine($"登录前:{DeviceId}\r\n登陆后:{this.User.User.DeviceId}"); if (this.Status != WxStatus.已掉线) ChangeStatus(WxStatus.已退出); } public void Dispose() { if (this.User != null && this.User.Uin != 0) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); if (this.Socket != null) this.Socket.Stop(); if (head != null) ThreadExcutor.UnRegisterIntervaluObject(head); } public override Dictionary GetBalance() { //此处只有短链接 WechatPack pack = new WechatPack(this); var result = pack.Send(WechatCmd.获得银行卡, new { CgiCmd = 72 }); result = pack.Analysis(WechatCmd.获得银行卡, result); var info = Encoding.UTF8.GetString(result); return CsharpHttpHelper.HttpExtend.JsonToDictionary(info); } /// /// 阅读文章 /// /// /// public void ReadURL(string requrl) { WechatPack web = new WechatPack(this); var obj2 = new { ReqUrl = requrl,//要获取key的连接 授权登陆时的链接即为转跳链接https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx53c677b55caa45fd&redirect_uri=http%3A%2F%2Fmeidang.cimiworld.com%2Fh5%2Fchourenpin%3Fs%3D77e881961fee12eb65f5497bbff02fac%26from%3Dsinglemessage%26isappinstalled%3D0&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect Scene = 2,//Scene = 2 来源好友或群 必须设置来源的id 3 历史阅读 4 二维码连接 7 来源公众号 必须设置公众号的id Username = "", //来源 来源设置wxid 来源群id@chatroom 来源公众号gh_e09c57858a0c原始id ProtocolVer = 1 //ProtocolVer 1-5 }; var data = web.SendAll(WechatCmd.GetA8Key, true, obj2); var str = WXClientTool.Usc2ToAnsi(Encoding.UTF8.GetString(data)); var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(str); var __biz = Regex.Match(json["Url"].ToString(), "__biz=([^&]+)").Groups[1].Value; var mid = Regex.Match(json["Url"].ToString(), "mid=([^&]+)").Groups[1].Value; var sn = Regex.Match(json["Url"].ToString(), "sn=([^&]+)").Groups[1].Value; var idx = Regex.Match(json["Url"].ToString(), "idx=([^&]+)").Groups[1].Value; var pass_ticket = Regex.Match(json["Url"].ToString(), "pass_ticket=([^&]+)").Groups[1].Value; var http = new CsharpHttpHelper.HttpHelper(); //https://mp.weixin.qq.com/s?__biz=MzI3ODIxNDcyOQ==&mid=2247486232&idx=1&sn=b8f60db37aa502af496baa4207feca38&ascene=2&devicetype=iPad+iPhone+OS9.3.3&version=16060520&nettype=WIFI&lang=zh_CN&fontScale=100&pass_ticket=mED1lf4PhfHVcXJj9bQsRRNi9wtql9pzkw1ZY5TrjPeIdU9iqbGD0hYz4fxDz%2FI8&wx_header=1 var url = $"https://mp.weixin.qq.com/s?__biz={__biz}&mid={mid}&idx={idx}&sn={sn}&chksm=fa24a0c0cd5329d66f837dd1d7a36301011ed081faef006fa8a5f7829cd6dc1347a792f44ff8&mpshare=1&scene=1&srcid=&key={json["XWechatKey"]}&ascene=1&uin={json["XWechatUin"]}&devicetype=Windows+10&version=62060739&lang=zh_CN&pass_ticket={pass_ticket}&winzoom=1"; var item = http.GetItem(url); item.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.1021.400 QQBrowser/9.0.2524.400"; var html = http.GetHtml(item).Html; var appmsg_type = Regex.Match(html, "appmsg_type = \"(\\d+)\";").Groups[1].Value; //comment_id var comment_id = Regex.Match(html, "comment_id = \"(\\d+)\"").Groups[1].Value; var ct = Regex.Match(html, "ct = \"(\\d+)\";").Groups[1].Value; var msg_title = Regex.Match(html, "msg_title = \"(.*?)\";").Groups[1].Value; var req_id = Regex.Match(html, "req_id = '(.*?)';").Groups[1].Value; var appmsg_token = Regex.Match(html, "appmsg_token = \"(.*?)\";").Groups[1].Value; string goto_url = $"https://mp.weixin.qq.com/mp/getappmsgext?f=json&mock=&uin={json["XWechatUin"]}&key={json["XWechatKey"]}&pass_ticket={pass_ticket}&wxtoken=777&devicetype=Windows%26nbsp%3B10&clientversion=62060739&appmsg_token={appmsg_token}&x5=0&f=json"; string goto_data = $"r={new Random(Guid.NewGuid().GetHashCode()).NextDouble()}&__biz={__biz}&appmsg_type={appmsg_type}&mid={mid}&sn={sn}&idx={idx}&scene=&title={HttpHelper.URLEncode(msg_title)}&ct={ct}&abtest_cookie=&devicetype=Windows%2010&version=62060739&is_need_ticket=0&is_need_ad=0&comment_id={comment_id}&is_need_reward=0&both_ad=0&reward_uin_count=0&send_time=&msg_daily_idx=1&is_original=0&is_only_read=1&req_id={req_id}&pass_ticket={pass_ticket}&is_temp_url=0&item_show_type=0&tmp_version=1&more_read_type=0&appmsg_like_type=2"; //var post_html = HttpPost(goto_url,goto_data); item = new HttpItem() { URL = goto_url, Method = "POST", Timeout = 5000, ReadWriteTimeout = 5000, IsToLower = false, Cookie = "", UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.656.400 QQBrowser/9.0.2524.400", Accept = "text/html, application/xhtml+xml, */*", ContentType = "application/json", Referer = json["Url"].ToString(), Allowautoredirect = true, AutoRedirectCookie = true, Postdata = goto_data, }; var _data = http.GetHtml(item).Html; } /// /// 自动确认收款接口 /// /// /// /// /// public override int TenPayTransferConfirm(string Invalidtime, string Transferid, string FromUsername) { var data = new { CgiCmd = 85, Invalidtime = Invalidtime,//"1487236689" Transferid = Transferid,//"1000050201791702151058985957" FromUsername = FromUsername //"wxid" }; WechatPack pack = new WechatPack(this); var result = pack.Send(WechatCmd.获得银行卡, data); result = pack.Analysis(WechatCmd.获得银行卡, result); var text = Encoding.UTF8.GetString(result); var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(text); if (dic["retmsg"].ToString().ToUpper() == "OK") { return int.Parse(dic["fee"].ToString()); } return -1; } //xml解析到cdn图片数据 private CDNImageMsgInfo GetCDNImage(string content) { try { content = content.Trim().Replace("\n", ""); XmlDocument doc = new XmlDocument(); doc.LoadXml(content); XmlNodeList list = doc.SelectNodes("/msg/img"); if (list != null && list.Count > 0) { XmlNode item = list[0]; CDNImageMsgInfo image = new CDNImageMsgInfo(); image.AESKey = item.Attributes["aeskey"].Value.ToString(); XmlAttribute att = item.Attributes["hdlength"]; if (att != null && !string.IsNullOrWhiteSpace(att.Value)) { //有大图时使用大图 image.TotalLen = long.Parse(item.Attributes["hdlength"].Value); image.DataLen = long.Parse(item.Attributes["hdlength"].Value); image.CDNBigImgUrl = item.Attributes["cdnbigimgurl"].Value.ToString(); image.CDNBigImgSize = long.Parse(item.Attributes["hdlength"].Value); image.CDNMidImgUrl = item.Attributes["cdnmidimgurl"].Value.ToString(); if (long.Parse(item.Attributes["length"].Value) == long.Parse(item.Attributes["cdnthumblength"].Value)) { image.CDNMidImgSize = long.Parse(item.Attributes["hdlength"].Value); } else { image.CDNMidImgSize = long.Parse(item.Attributes["length"].Value); } } else { //使用中图 image.TotalLen = long.Parse(item.Attributes["length"].Value); image.DataLen = long.Parse(item.Attributes["length"].Value); image.CDNMidImgUrl = item.Attributes["cdnmidimgurl"].Value.ToString(); image.CDNMidImgSize = long.Parse(item.Attributes["length"].Value); } image.CDNThumbImgSize = long.Parse(item.Attributes["cdnthumblength"].Value); //image.CDNThumbImgHeight = long.Parse(item.Attributes["cdnthumbheight"].Value); //image.CDNThumbImgWidth = long.Parse(item.Attributes["cdnthumbwidth"].Value); image.CDNThumbImgHeight = 0; image.CDNThumbImgWidth = 0; if (!string.IsNullOrWhiteSpace(image.AESKey)) { return image; } } return null; } catch (Exception ee) { return null; } } } }