using Chat.Framework.WXSdk.Implement; using Grpc.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using WechatProto; using static WechatProto.Wechat; namespace Chat.Framework.WXSdk.IPAD { public enum GrpcType : int { Awei = 0, Laoyao = 1, Huangfan = 2, 未知 = -1 } internal class GrpcConfig { public GrpcType Type { get; set; } public string Appid { get; set; } public string Appkey { get; set; } /// /// 启用SSL加密 /// public bool EnableSSL { get; set; } = true; /// /// 服务器全局解密Key /// public byte[] RandomEncryKey { get; set; } ///// ///// 服务端地址 ///// //public string GrpcServer { get; set; } ///// ///// 备用服务器地址 ///// //public string GrpcServerBackup { get; set; } /// /// 版本号 /// public string Version { get; set; } /// /// Grpc证书 /// public string GrpcCredentials { get; set; } /// /// 机器人码 /// public string MachineCode { get; set; } private Metadata _authHeader; /// /// Grpc验证头 /// public Metadata AuthHeader { get { if (_authHeader == null) { _authHeader = new Metadata(); _authHeader.Add("appid", Appid); _authHeader.Add("appkey", Appkey); } return _authHeader; } } /// /// 服务器IP /// public List Servers { get; set; } private static Dictionary grpcConfig = new Dictionary(); public static GrpcConfig Get(GrpcType type, bool refresh = false) { //if (type == GrpcType.Huangfan) //{ //} ////type = GrpcType.Laoyao;//TODO 这里强制用老妖的 lock (grpcConfig) { GrpcConfig config = grpcConfig.ContainsKey(type) ? grpcConfig[type] : null; if (config != null && !refresh) return config; switch (type) { case GrpcType.Awei: config = new GrpcConfig() { Appid = "v1_meesii_CodeVip", Appkey = "v2_d6fb34d020a209471fe7122d4a55e69c", Servers = new List() { "grpc.wxipad.com:12580" }, MachineCode = "v3_e9de924f32fae3126b42fac40b0f5b6d", RandomEncryKey = CsharpHttpHelper.HttpExtend.RandomByte(16), EnableSSL = true, GrpcCredentials = @"-----BEGIN CERTIFICATE----- MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs -----END CERTIFICATE-----", Version = "7.0.3" }; break; case GrpcType.Laoyao: config = new GrpcConfig() { Appid = "v1_LCEO_Code", Appkey = "v2_4d5d55d6fbb6ce87b0f53019fefebb89", Servers = new List() { "111.230.216.32:12588" }, MachineCode = "v3_7af2592d5c49d94424bac95e80cb07a4", RandomEncryKey = CsharpHttpHelper.HttpExtend.RandomByte(16), EnableSSL = true, GrpcCredentials = @"-----BEGIN CERTIFICATE----- MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs -----END CERTIFICATE-----", Version = "7.0.3" }; //Console.WriteLine(config.AuthHeader); break; case GrpcType.Huangfan: config = new GrpcConfig() { Appid = "v1_23229f55b208d33b_CodeVip", Appkey = "v2_d72d0b8d148afb50e8a0beed37efd1b5", Servers = new List() { "47.93.227.173:12580" }, MachineCode = "v3_951b8b394d904962d981f02e5d4cee31", RandomEncryKey = CsharpHttpHelper.HttpExtend.RandomByte(16), GrpcCredentials = @"-----BEGIN CERTIFICATE----- MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs -----END CERTIFICATE-----", Version = "7.0.3" }; Console.WriteLine(config.AuthHeader); break; default: break; } if (config != null) { config.Type = type; grpcConfig[type] = config; } return config; } } } class GrpcClient : IDisposable { private Channel _channel; private WechatClient _baseClient; /// /// GRpc配置信息 /// public GrpcConfig Config { get; private set; } public GrpcClient(GrpcConfig config = null) { if (config != null) { Config = config; } Init(); } public bool IsConnected { get { if (_channel != null && (_channel.State == ChannelState.Ready || _channel.State == ChannelState.Connecting || _channel.State == ChannelState.Idle)) { return true; } return false; } } /// /// 初始化 /// public void Init() { if (Config.Servers.Count == 0) { LogHelper.GetSingleObj().Error("Grpc服务器", "当前无可用的Grpc服务器"); return; } this.Stop(); Config.Servers = ChatClient.GetServerDataMethod("grpc_type_" + Config.Type.ToString().ToLower()).Split(',').ToList(); //if (Config.Type == GrpcType.Huangfan) Config.Servers = new string[] { "106.15.26.141:12580" }.ToList(); // Config.Servers = new string[] { "45.253.67.81:12580" }.ToList(); //switch (Config.Type) //{ // case GrpcType.Awei: // break; // case GrpcType.Laoyao: // break; // case GrpcType.Huangfan: // break; // default: // break; //} var channelOptions = new List { new ChannelOption(ChannelOptions.SslTargetNameOverride,"wechat@root"), new ChannelOption(ChannelOptions.MaxConcurrentStreams,int.MaxValue), new ChannelOption(ChannelOptions.MaxSendMessageLength,int.MaxValue), new ChannelOption(ChannelOptions.MaxReceiveMessageLength,int.MaxValue) }; if (Config.EnableSSL) { var grpcCredentials = new SslCredentials(Config.GrpcCredentials); _channel = new Channel(ServerIp, grpcCredentials, channelOptions); } else _channel = new Channel(ServerIp, ChannelCredentials.Insecure, channelOptions); _baseClient = new WechatClient(_channel); } /// /// 停止GRpc /// public void Stop() { if (_channel != null) { try { _channel.ShutdownAsync().Wait(); _baseClient = null; _channel = null; } catch { // ignored } } } public DateTime LastTime { get; private set; } /// /// Grpc发包(5次尝试) /// /// /// public Task Send(WechatMsg _pack, WXClientImpl_IPAD weixin) { #region 2019年8月1日21:49:42 ////while (_baseClient == null) ////{ //// Thread.Sleep(100); ////} //return Task.Run(() => //{ // var tryTimes = 3; //again: // var cmd = 0; // try // { // if (this._channel == null) this.Init(); // LastTime = DateTime.Now; // cmd = pack.BaseMsg.Cmd; // var send = pack.Clone(); // send.Token = Config.MachineCode; // //return _baseClient.HelloWechat(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)); // return _baseClient.HelloWechatAsync(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)).ResponseAsync.Result; // } // catch (RpcException ex) // { // if (tryTimes >= 0) // { // tryTimes--; // Thread.Sleep(1000); // if (ex.StatusCode == StatusCode.Unknown || ex.StatusCode == StatusCode.DeadlineExceeded) // { // this.Init(); // goto again; // } // else if (ex.StatusCode == StatusCode.Unavailable) goto again; // } // LogHelper.GetSingleObj().Error("Grpc异常" + cmd, $"StatusCode ->{ex.StatusCode} Msg ->{ex.Message}"); // return null; // } //}); #endregion #region //while (_baseClient == null) //{ // Thread.Sleep(100); //} WechatMsg pack = _pack; return Task.Run(() => { var tryTimes = 3; for (int i = 0; i < tryTimes; i++) { if (i > 0) Thread.Sleep(1000); var cmd = 0; try { if (this._channel == null || _baseClient == null) this.Init(); LastTime = DateTime.Now; cmd = pack.BaseMsg.Cmd; var send = pack.Clone(); send.Token = Config.MachineCode; //return _baseClient.HelloWechat(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)); return _baseClient.HelloWechatAsync(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)).ResponseAsync.Result; } catch (RpcException ex) { LogHelper.GetSingleObj().Error("Grpc异常" + cmd, $"StatusCode ->{ex.StatusCode} Msg ->{ex.Message}"); if (ex.StatusCode == StatusCode.Unavailable) continue; else if (ex.StatusCode == StatusCode.Unknown || ex.StatusCode == StatusCode.DeadlineExceeded) { this.Init(); continue; } } catch (Exception ex) { LogHelper.GetSingleObj().Error("Grpc异常" + cmd, $"Msg ->{ex.InnerException}"); continue; } } return null; }); #endregion } public void Dispose() { } /// /// 上次获取时间 /// private readonly DateTime _checkDate = DateTime.Now; /// /// Grpc服务器IP /// private string _serverIp; /// /// Grpc服务器IP /// public string ServerIp { get { //return "grpc.wxipad.com:12580"; //if (string.IsNullOrEmpty(ServerIp) || (DateTime.Now - _checkDate).TotalSeconds >= 300) //{ // GetConfig(); //} var random = new Random(); var index = random.Next(0, Config.Servers.Count); _serverIp = Config.Servers[index]; return _serverIp; } } } }