using Chat.Framework.WXSdk.Implement; using Google.Protobuf; using System; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web.Script.Serialization; using WechatProto; using System.Linq; using System.Text.RegularExpressions; using Chat.Framework.WXSdk.Events; using Grpc.Core; namespace Chat.Framework.WXSdk.IPAD { /// /// 协议发送包 /// public class WechatPack { public class PackMsg { //(WechatCmd cmd, bool isAnalysis, object data = null, ByteString longHead = null,string text="" public WechatCmd cmd { get; set; } public object data { get; set; } } WXClientImpl_IPAD client; JavaScriptSerializer js = new JavaScriptSerializer(); public WechatPack(WXClientImpl_IPAD client) { this.client = client; this.js.MaxJsonLength = int.MaxValue; } public WechatMsg Req { get; private set; } private int ReadInt(byte[] buf, int index) { if (buf.Length >= 16) { var seqBuf = new byte[4]; Buffer.BlockCopy(buf, index, seqBuf, 0, 4); return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(seqBuf, 0)); } return 1; } public byte[] Analysis(int cmd, byte[] data) { return Send(cmd > 0 ? cmd * -1 : cmd, data); } public byte[] Analysis(WechatCmd cmd, object data) { return Send((int)cmd * -1, data); } public byte[] Analysis(byte[] data) { int cmd = Req.BaseMsg.Cmd * -1; return Send(cmd, data); } /// /// 发送完整包,并解析微信返回信息 /// public byte[] SendAll(WechatCmd cmd, bool isAnalysis, object data = null, ByteString longHead = null, string text = "") { var _data = Send(cmd, data, longHead); if (_data != null && !IsShortResult)//判断数据不为空,并且不是腾讯短连接返回的结果 { _data = SendWx(_data, text: text); } if (isAnalysis) { if (_data == null) return null; return this.Analysis(_data); } return _data; } private bool IsShortResult { get; set; } public byte[] Send(WechatCmd cmd, object data = null, ByteString longHead = null) { return Send((int)cmd, data, longHead); } public byte[] Send(WechatCmd cmd, byte[] data, ByteString longHead = null) { return Send((int)cmd, data, longHead); } // GrpcClient grpcClient = null; private GrpcClient GetGrpcClient(WechatMsg req) { //if (grpcClient != null && grpcClient.IsConnected) return grpcClient; GrpcClient grpcClient = null; if (codes.Contains(req.BaseMsg.Cmd)) { grpcClient = client.GetGrpcClient(GrpcType.Huangfan); //grpcClient = new GrpcClient(GrpcConfig.Get(GrpcType.Huangfan, false)); //client.GetGrpcClient(GrpcType.Huangfan); } else { grpcClient = client.GetGrpcClient(GrpcType.Laoyao); } return grpcClient; } public byte[] Send(WechatMsg req) { int number = 0; //GrpcClient grpc_client = null; try { Next: IsShortResult = false; number++; var msg = req.BaseMsg; var grpc = GetGrpcClient(req); //WechatMsg _req = SendGRPC(req, client).Result; WechatMsg _req = grpc.Send(req, client).Result; if (_req != null) Req = _req; else { if (number < 3) { Thread.Sleep(100); goto Next; } else throw new Exception("无法获取GRPC返回包!"); } var Data = new byte[Req.BaseMsg.LongHead.Length + Req.BaseMsg.Payloads.Length]; var Head = Req.BaseMsg.LongHead.ToByteArray(); var Seq = ReadInt(Head, 12); if (msg.Cmd < 0 && (int)WechatCmd.发送图片文件 != msg.Cmd) { ByteString key = null; if (Req.BaseMsg.User.AutoAuthKey.Length != 0) { key = Req.BaseMsg.User.AutoAuthKey; } else if (client.User.User.AutoAuthKey.Length != 0) key = client.User.User.AutoAuthKey; if (msg.Cmd == -138 || msg.Cmd == -1002 || msg.Cmd == -702 || msg.Cmd == -1001 || msg.Cmd == -380) { client.User.User = Req.BaseMsg.User; } if (key != null) { client.User.User.AutoAuthKey = key; } return Req.BaseMsg.Payloads.ToByteArray(); } if (msg.Cmd == (int)WechatCmd.获取标签 || msg.Cmd == (int)WechatCmd.添加标签 || msg.Cmd == (int)WechatCmd.修改标签 || msg.Cmd == (int)WechatCmd.搜索关键词 || msg.Cmd == 179 || msg.Cmd == (int)WechatCmd.编辑联系人信息 || msg.Cmd == (int)WechatCmd.删除好友 || msg.Cmd == 281 || msg.Cmd == 851 || msg.Cmd == 551 || msg.Cmd == 805 || msg.Cmd == 610 || msg.Cmd == 385 || msg.Cmd == 945 || msg.Cmd == (int)WechatCmd.评论或点赞 || msg.Cmd == (int)WechatCmd.邀请入群 || msg.Cmd == (int)WechatCmd.获取登录短信 || msg.Cmd == (int)WechatCmd.群公告) { IsShortResult = true; var data = client.Socket.SendWeChatPost(Req.BaseMsg.Payloads.ToByteArray(), Req.BaseMsg.CmdUrl, 3); //if (data == null) //{ // return this.SendWx(data); //} //else return data; //byte[] _data = null; //CsharpHttpHelper.HttpHelper http = new CsharpHttpHelper.HttpHelper(); //for (int i = 0; i < 2; i++) //{ // try // { // var item = new CsharpHttpHelper.HttpItem() // { // URL = "http://" + client.Host.GetSort() + Req.BaseMsg.CmdUrl, // Method = "post", // PostdataByte = Req.BaseMsg.Payloads.ToByteArray(), // UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", // ContentType = "application/x-www-form-urlencoded", // Allowautoredirect = true, // Timeout = 5000, // ReadWriteTimeout = 5000, // ResultType = CsharpHttpHelper.Enum.ResultType.Byte, // PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte // }; // _data = http.GetHtml(item).ResultByte; // if (_data == null) continue; // if (_data[0] != 191) continue; // break; // } // catch (Exception) // { // } //} //return _data; } try { var Body = Req.BaseMsg.Payloads.ToByteArray(); Buffer.BlockCopy(Head, 0, Data, 0, 16); Buffer.BlockCopy(Body, 0, Data, 16, Body.Length); return Data; } catch (Exception ex) { if (number < 3) { Thread.Sleep(100); goto Next; } else throw ex; } } catch (Exception ex) { throw ex; } } private static int[] codes = new int[] { };//1111, 2222, 702, 3333, 380 public byte[] Send(int cmd, object data, ByteString longHead = null) { try { ByteString param = null; if (data != null) { if (typeof(string) == data.GetType()) { param = ByteString.CopyFrom(Encoding.UTF8.GetBytes(data.ToString())); } else if (typeof(byte[]) != data.GetType()) { var json = js.Serialize(data); param = ByteString.CopyFrom(json, Encoding.UTF8); } else if (typeof(byte[]) == data.GetType()) { var _data = data as byte[]; param = ByteString.CopyFrom(_data); } } WechatProto.BaseMsg msg = null; if (param != null) msg = new BaseMsg() { Cmd = cmd, Payloads = param, User = client.User.User }; else msg = new BaseMsg() { Cmd = cmd, User = client.User.User }; if (longHead != null) msg.LongHead = longHead; Req = new WechatMsg { Token = WXClientTool.machine_code, Version = "7.0.3", TimeStamp = Util.GetTimeTotalSeconds(), IP = client.clientIp, BaseMsg = msg }; return Send(Req); } catch (Exception ex) { LogHelper.GetSingleObj().Error("发送GRPC-" + cmd, ex.Message); } return null; } public byte[] GetResult(int seq) { var buffers = this.client.Socket.GetResult(seq); var start = DateTime.Now; while (buffers == null) { Thread.Sleep(20); buffers = this.client.Socket.GetResult(seq); if (null == buffers && (DateTime.Now - start).Seconds > 10)//发送文字超时时间设置成40s { break; } } return buffers; } public byte[] SendWx(byte[] Data, int Seq = 0, int retry_number = 1, string text = "") { if (Seq == 0) { byte[] head = Data; Seq = Util.ReadInt(head, 12); } //执行此方法无须解包 必须删除字典里的未解包 // this.client.Socket.SendToWeChat(Seq,Data).Result; for (int i = 1; i <= retry_number; i++) { this.client.Socket.SendToWechat(Data, text); //if (!string.IsNullOrEmpty(rst)) //{ // this.client.WriteLog("发送失败:" + rst); // continue; //} var buffer = GetResult(Seq); if (buffer != null) return buffer; } LogHelper.GetSingleObj().Error("SendWx", $"{(string.IsNullOrEmpty(this.client.WeixinHao) ? string.Empty : this.client.WeixinHao)}执行{Seq},数据包发送失败!"); return null; //FastSocket 重构 //return client.Socket.SendToWeChat(Seq, Data); // int number = 0; //Next: // try // { // number++; // var source = new TaskCompletionSource();// // byte[] data = null; // var seq = Seq == 0 ? Req.BaseMsg.Cmd.ToString() : DateTime.Now.Ticks.ToString(); // var socket = client.Socket as FastSocket; // var request = socket.WeChatClient.NewRequest(seq, Data, 5000 * 3, // //绑定异常回调 // ex => // { //接收超时也会触发断开链接并且重连并自动清除队列 // //fClient.SocketNote.BeginInvoke(false, null, null); // Console.WriteLine("WeChat Socket Error:" + ex.Message); // source.TrySetException(ex); // }, // //绑定返回请求的回调 // onResultMessage => // { // //触发此回调必有数据 // //不触发则异常 发送收取超时等 // data = onResultMessage.Msg.BaseMsg.Payloads.ToByteArray(); // source.TrySetResult(data); // } // ); // socket.Send(request); // var Body = source.Task.Result; // //长链接解包判定 // if (Body != null && Body.Length > 16 && Body[16] != 191 && number <= 3) // { // //client.EventManage.OnEvent(this, QrcodeReq.BaseMsg.Cmd + ",非191,重试发包.."+number); // goto Next; // } // return source.Task; // } // catch (Exception ex) // { // client.WriteLog("SendWx(byte[] Data, int Seq = 0) Error:" + ex.Message); // throw ex; // } } private PackMsg NextSendData; public void SetNextData(PackMsg nextData) { this.NextSendData = nextData; } public void SendNextData() { try { this.SendAll(this.NextSendData.cmd, false, this.NextSendData.data); } catch (Exception) { } } } }