You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
7.3 KiB
C#

9 months ago
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;
/// <summary>
/// 数据表中配置的API接口
/// </summary>
private Dictionary<string,Apis> _apis;
/// <summary>
/// 数据表中API接口对应的URL列表
/// </summary>
private Dictionary<string , List<OpenApi>> _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<string , Apis>();
this._urls = new Dictionary<string , List<OpenApi>>();
Tuple<List<Apis> , List<Urls>> result = null;
using (var db = Global.Instance.OpenDataBase)
{
result = db.FetchMultiple<Apis , Urls>(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<OpenApi>();
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<OpenApi> routing = null;
if (!this._apis.ContainsKey(api.ToString())) {
return null;
}
string balance = this._apis[api.ToString()].Routing + "";
switch (balance)
{
case "0"://随机
routing = new RandomRouting<OpenApi>();
break;
case "1"://轮询
routing = new RoundRobinRouting<OpenApi>(this._urls.Values.Count);
break;
case "2"://一致性Hash
routing = new ConsistentHashRouting<OpenApi>(this._urls.Values.Count);
break;
case "3"://一致性Hash
routing = new ConsistentHashRouting<OpenApi>(this._urls.Values.Count);
break;
default:
routing = new RandomRouting<OpenApi>();
break;
}
var apis = routing.select("juweiyun.cn" , this._urls[api.ToString()].ToArray());
return apis;
}
/// <summary>
/// 获取当前时间戳兼容Java服务端
/// </summary>
/// <returns></returns>
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<string , string> NewParameters(OpenApi api)
{
SortedList<string , string> parameters = new SortedList<string , string>();
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;
}
/// <summary>
/// 开放平台签名算法
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
public string Sign(OpenApi api , SortedList<string , string> parameters)
{
return Sign(api , parameters , null);
}
/// <summary>
/// 开放平台签名算法
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
public string Sign(OpenApi api , SortedList<string , string> parameters , List<string> ignoreParameters)
{
IList<string> keys = parameters.Keys;
var paramNames = new List<string>(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[]转为字符串
}
/// <summary>
/// 字节数组转十六进制字符串
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
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();
}
}
}