460 lines
17 KiB
C#
460 lines
17 KiB
C#
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; }
|
||
|
||
/// <summary>
|
||
/// 启用SSL加密
|
||
/// </summary>
|
||
public bool EnableSSL { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 服务器全局解密Key
|
||
/// </summary>
|
||
public byte[] RandomEncryKey { get; set; }
|
||
|
||
|
||
///// <summary>
|
||
///// 服务端地址
|
||
///// </summary>
|
||
//public string GrpcServer { get; set; }
|
||
|
||
///// <summary>
|
||
///// 备用服务器地址
|
||
///// </summary>
|
||
//public string GrpcServerBackup { get; set; }
|
||
|
||
/// <summary>
|
||
/// 版本号
|
||
/// </summary>
|
||
public string Version { get; set; }
|
||
|
||
/// <summary>
|
||
/// Grpc证书
|
||
/// </summary>
|
||
public string GrpcCredentials { get; set; }
|
||
|
||
/// <summary>
|
||
/// 机器人码
|
||
/// </summary>
|
||
public string MachineCode { get; set; }
|
||
|
||
|
||
private Metadata _authHeader;
|
||
/// <summary>
|
||
/// Grpc验证头
|
||
/// </summary>
|
||
public Metadata AuthHeader
|
||
{
|
||
get
|
||
{
|
||
if (_authHeader == null)
|
||
{
|
||
_authHeader = new Metadata();
|
||
_authHeader.Add("appid", Appid);
|
||
_authHeader.Add("appkey", Appkey);
|
||
}
|
||
return _authHeader;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 服务器IP
|
||
/// </summary>
|
||
public List<string> Servers { get; set; }
|
||
|
||
|
||
|
||
private static Dictionary<GrpcType, GrpcConfig> grpcConfig = new Dictionary<GrpcType, GrpcConfig>();
|
||
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<string>() { "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<string>() { "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<string>() { "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;
|
||
|
||
/// <summary>
|
||
/// GRpc配置信息
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化
|
||
/// </summary>
|
||
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<ChannelOption>
|
||
{
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停止GRpc
|
||
/// </summary>
|
||
public void Stop()
|
||
{
|
||
if (_channel != null)
|
||
{
|
||
try
|
||
{
|
||
_channel.ShutdownAsync().Wait();
|
||
_baseClient = null;
|
||
_channel = null;
|
||
}
|
||
catch
|
||
{
|
||
// ignored
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
public DateTime LastTime { get; private set; }
|
||
|
||
|
||
/// <summary>
|
||
/// Grpc发包(5次尝试)
|
||
/// </summary>
|
||
/// <param name="pack"></param>
|
||
/// <returns></returns>
|
||
public Task<WechatMsg> 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<WechatMsg>(() =>
|
||
{
|
||
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()
|
||
{
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 上次获取时间
|
||
/// </summary>
|
||
private readonly DateTime _checkDate = DateTime.Now;
|
||
|
||
/// <summary>
|
||
/// Grpc服务器IP
|
||
/// </summary>
|
||
private string _serverIp;
|
||
|
||
/// <summary>
|
||
/// Grpc服务器IP
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|