using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using POSV.Entity; using POSV.HttpApi; using POSV.LoadBalance; namespace POSV.Utils { public class OpenApiUtils { static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static object _lock = new object(); private static OpenApiUtils _instance = null; /// /// 数据表中配置的API接口 /// private Dictionary _apis; /// /// 数据表中API接口对应的URL列表 /// private Dictionary> _urls; public static OpenApiUtils Instance { get { if (_instance == null) { lock (_lock) { _instance = new OpenApiUtils(); _instance.Init(); } } return _instance; } } private void Init() { this._apis = new Dictionary(); this._urls = new Dictionary>(); Tuple , List> result = null; using (var db = Global.Instance.OpenDataBase) { result = db.FetchMultiple(SqlConstant.ApisQueryAll + SqlConstant.UrlsQueryAll); } if (result != null) { var apis = result.Item1; var urls = result.Item2; foreach (var api in apis) { this._apis[api.ApiType] = api; //查找ApiType匹配的全部URLS var servers = urls.FindAll(x => x.ApiType == api.ApiType); if (servers != null && servers.Count > 0) { var list = new List(); foreach (var url in servers) { var openApi = new OpenApi(); openApi.Url = string.Format("{0}://{1}/{2}/api" , url.Protocol , url.Url , url.ContextPath); openApi.Open = string.Format("{0}://{1}/{2}/open/api/extend" , url.Protocol , url.Url , url.ContextPath); openApi.ApiType = (ApiType)Enum.Parse(typeof(ApiType) , url.ApiType); openApi.AppKey = api.AppKey; openApi.AppSecret = api.AppSecret; openApi.Client = api.Client; openApi.Locale = api.Locale; openApi.Format = api.Format; openApi.Version = api.Version; openApi.Memo = url.Memo; list.Add(openApi); } this._urls[api.ApiType] = list; } } } } public void Refresh() { lock (_lock) { //Global.Instance.ReloadConfig(ConfigConstant.CONFIG_GROUP_SYSTEM); Init(); } } public OpenApi NextApi(ApiType api) { IRouting routing = null; if (!this._apis.ContainsKey(api.ToString())) { return null; } string balance = this._apis[api.ToString()].Routing + ""; switch (balance) { case "0"://随机 routing = new RandomRouting(); break; case "1"://轮询 routing = new RoundRobinRouting(this._urls.Values.Count); break; case "2"://一致性Hash routing = new ConsistentHashRouting(this._urls.Values.Count); break; case "3"://一致性Hash routing = new ConsistentHashRouting(this._urls.Values.Count); break; default: routing = new RandomRouting(); break; } var apis = routing.select("juweiyun.cn" , this._urls[api.ToString()].ToArray()); return apis; } /// /// 获取当前时间戳,兼容Java服务端 /// /// public string GetTimestamp() { TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(1970 , 1 , 1 , 0 , 0 , 0).Ticks); return Convert.ToString((long)ts.TotalMilliseconds); } public SortedList NewParameters(OpenApi api) { SortedList parameters = new SortedList(); parameters.Add("appKey" , api.AppKey); parameters.Add("format" , api.Format); parameters.Add("locale" , api.Locale); parameters.Add("timestamp" , GetTimestamp()); parameters.Add("client" , api.Client); parameters.Add("v" , api.Version); return parameters; } /// /// 开放平台签名算法 /// /// /// public string Sign(OpenApi api , SortedList parameters) { return Sign(api , parameters , null); } /// /// 开放平台签名算法 /// /// /// public string Sign(OpenApi api , SortedList parameters , List ignoreParameters) { IList keys = parameters.Keys; var paramNames = new List(keys.Count); paramNames.AddRange(keys); if (ignoreParameters != null && ignoreParameters.Count > 0) { foreach (string ignore in ignoreParameters) { paramNames.Remove(ignore); } } StringBuilder input = new StringBuilder(); input.Append(api.AppSecret); foreach (string key in paramNames) { input.Append(key + parameters[key]); } input.Append(api.AppSecret); SHA1 sha1 = new SHA1CryptoServiceProvider();//建立一个SHA1 byte[] source = Encoding.UTF8.GetBytes(input.ToString());//将字符串转为Byte[] byte[] crypto = sha1.ComputeHash(source);//进行SHA1加密 return ByteArrayToHexString(crypto);//把加密后的字符串从Byte[]转为字符串 } /// /// 字节数组转十六进制字符串 /// /// /// public string ByteArrayToHexString(byte[] data) { StringBuilder sb = new StringBuilder(data.Length * 3); foreach (byte b in data) { sb.Append(Convert.ToString(b , 16).PadLeft(2 , '0')); } return sb.ToString().ToUpper(); } } }