Files
PaySharp/src/PaySharp.Core/Gateways/GatewayData.cs
T
2020-11-30 19:21:04 +08:00

596 lines
17 KiB
C#

#if NETCOREAPP
using Microsoft.AspNetCore.Http;
#endif
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PaySharp.Core.Utils;
namespace PaySharp.Core
{
/// <summary>
/// 网关数据
/// </summary>
public class GatewayData
{
#region 私有字段
private readonly SortedDictionary<string, object> _values;
#endregion
#region 属性
public object this[string key]
{
get => _values[key];
set => _values[key] = value;
}
public SortedDictionary<string, object>.KeyCollection Keys => _values.Keys;
public SortedDictionary<string, object>.ValueCollection Values => _values.Values;
public KeyValuePair<string, object> this[int index] => _values.ElementAt(index);
public int Count => _values.Count;
/// <summary>
/// 原始值
/// </summary>
public string Raw { get; set; }
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
public GatewayData()
{
_values = new SortedDictionary<string, object>();
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="comparer">排序策略</param>
public GatewayData(IComparer<string> comparer)
{
_values = new SortedDictionary<string, object>(comparer);
}
#endregion
#region 方法
/// <summary>
/// 添加参数
/// </summary>
/// <param name="key">参数名</param>
/// <param name="value">参数值</param>
/// <returns></returns>
public bool Add(string key, object value)
{
Raw = null;
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException("key", "参数名不能为空");
}
if (value is null || string.IsNullOrEmpty(value.ToString()))
{
return false;
}
if (Exists(key))
{
_values[key] = value;
}
else
{
_values.Add(key, value);
}
return true;
}
/// <summary>
/// 添加参数
/// </summary>
/// <param name="obj">对象</param>
/// <param name="stringCase">字符串策略</param>
/// <returns></returns>
public bool Add(object obj, StringCase stringCase)
{
ValidateUtil.Validate(obj, null);
Raw = null;
var type = obj.GetType();
var properties = type.GetProperties();
var fields = type.GetFields();
Add(obj, properties, stringCase);
Add(obj, fields, stringCase);
return true;
}
private void Add(object obj, MemberInfo[] info, StringCase stringCase)
{
foreach (var item in info)
{
var notAddattributes = item.GetCustomAttributes(typeof(IgnoreAttribute), true);
if (notAddattributes.Length > 0)
{
continue;
}
string key;
var renameAttribute = item.GetCustomAttributes(typeof(ReNameAttribute), true);
if (renameAttribute.Length > 0)
{
key = ((ReNameAttribute)renameAttribute[0]).Name;
}
else
{
key = stringCase switch
{
StringCase.Snake => item.Name.ToSnakeCase(),
StringCase.Camel => item.Name.ToCamelCase(),
StringCase.Lower => item.Name.ToLower(),
_ => item.Name,
};
}
var value = item.MemberType switch
{
MemberTypes.Field => ((FieldInfo)item).GetValue(obj),
MemberTypes.Property => ((PropertyInfo)item).GetValue(obj),
_ => throw new NotImplementedException(),
};
if (value is null || string.IsNullOrEmpty(value.ToString()))
{
continue;
}
if (Exists(key))
{
_values[key] = value;
}
else
{
_values.Add(key, value);
}
}
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public object GetValue(string key)
{
_values.TryGetValue(key, out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public string GetStringValue(string key)
{
return GetValue(key)?.ToString();
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public double GetDoubleValue(string key)
{
double.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public int GetIntValue(string key)
{
int.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public DateTime GetDateTimeValue(string key)
{
DateTime.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public float GetFloatValue(string key)
{
float.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public decimal GetDecimalValue(string key)
{
decimal.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public byte GetByteValue(string key)
{
byte.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public char GetCharValue(string key)
{
char.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 根据参数名获取参数值
/// </summary>
/// <param name="key">参数名</param>
/// <returns>参数值</returns>
public bool GetBoolValue(string key)
{
bool.TryParse(GetStringValue(key), out var value);
return value;
}
/// <summary>
/// 是否存在指定参数名
/// </summary>
/// <param name="key">参数名</param>
/// <returns></returns>
public bool Exists(string key) => _values.ContainsKey(key);
/// <summary>
/// 将网关数据转成Xml格式数据
/// </summary>
/// <returns></returns>
public string ToXml()
{
if (_values.Count == 0)
{
return string.Empty;
}
var sb = new StringBuilder();
sb.Append("<xml>");
foreach (var item in _values)
{
if (item.Value is string)
{
sb.AppendFormat("<{0}><![CDATA[{1}]]></{0}>", item.Key, item.Value);
}
else
{
sb.AppendFormat("<{0}>{1}</{0}>", item.Key, item.Value);
}
}
sb.Append("</xml>");
return sb.ToString();
}
/// <summary>
/// 将Xml格式数据转换为网关数据
/// </summary>
/// <param name="xml">Xml数据</param>
/// <returns></returns>
public void FromXml(string xml)
{
try
{
Clear();
if (!string.IsNullOrEmpty(xml))
{
var xmlDoc = new XmlDocument()
{
XmlResolver = null
};
xmlDoc.LoadXml(xml);
var xmlElement = xmlDoc.DocumentElement;
var nodes = xmlElement.ChildNodes;
foreach (var item in nodes)
{
var xe = (XmlElement)item;
Add(xe.Name, xe.InnerText);
}
}
}
finally
{
Raw = xml;
}
}
/// <summary>
/// 将网关数据转换为Url格式数据
/// </summary>
/// <param name="isUrlEncode">是否需要url编码</param>
/// <returns></returns>
public string ToUrl(bool isUrlEncode = true)
{
return string.Join("&",
_values
.Select(a => $"{a.Key}={(isUrlEncode ? WebUtility.UrlEncode(a.Value.ToString()) : a.Value.ToString())}"));
}
/// <summary>
/// 将Url格式数据转换为网关数据
/// </summary>
/// <param name="url">url数据</param>
/// <param name="isUrlDecode">是否需要url解码</param>
/// <returns></returns>
public void FromUrl(string url, bool isUrlDecode = true)
{
try
{
Clear();
if (!string.IsNullOrEmpty(url))
{
var index = url.IndexOf('?');
if (index == 0)
{
url = url.Substring(index + 1);
}
var regex = new Regex(@"(^|&)?(\w+)=([^&]+)(&|$)?", RegexOptions.Compiled);
var mc = regex.Matches(url);
foreach (Match item in mc)
{
var value = item.Result("$3");
Add(item.Result("$2"), isUrlDecode ? WebUtility.UrlDecode(value) : value);
}
}
}
finally
{
Raw = url;
}
}
#if NETCOREAPP
/// <summary>
/// 将表单数据转换为网关数据
/// </summary>
/// <param name="form">表单</param>
/// <returns></returns>
public void FromForm(IFormCollection form)
{
try
{
Clear();
var allKeys = form.Keys;
foreach (var item in allKeys)
{
Add(item, form[item]);
}
}
catch { }
}
#endif
/// <summary>
/// 将键值对转换为网关数据
/// </summary>
/// <param name="nvc">键值对</param>
/// <returns></returns>
public void FromNameValueCollection(NameValueCollection nvc)
{
foreach (var item in nvc.AllKeys)
{
Add(item, nvc[item]);
}
}
/// <summary>
/// 将网关数据转换为表单数据
/// </summary>
/// <param name="url">请求地址</param>
/// <returns></returns>
public string ToForm(string url)
{
var html = new StringBuilder();
html.AppendLine("<body>");
html.AppendLine($"<form name='gateway' method='post' action ='{url}'>");
foreach (var item in _values)
{
html.AppendLine($"<input type='hidden' name='{item.Key}' value='{item.Value}'>");
}
html.AppendLine("</form>");
html.AppendLine("<script language='javascript' type='text/javascript'>");
html.AppendLine("document.gateway.submit();");
html.AppendLine("</script>");
html.AppendLine("</body>");
return html.ToString();
}
/// <summary>
/// 将网关数据转成Json格式数据
/// </summary>
/// <returns></returns>
public string ToJson()
{
return JsonConvert.SerializeObject(_values);
}
/// <summary>
/// 将Json格式数据转成网关数据
/// </summary>
/// <param name="json">json数据</param>
/// <returns></returns>
public void FromJson(string json)
{
try
{
Clear();
if (!string.IsNullOrEmpty(json))
{
var jObject = JObject.Parse(json);
foreach (var item in jObject)
{
if (item.Value.Type == JTokenType.Object)
{
Add(item.Key, item.Value.ToString(Newtonsoft.Json.Formatting.None));
}
else
{
Add(item.Key, item.Value.ToString());
}
}
}
}
finally
{
Raw = json;
}
}
/// <summary>
/// 将网关参数转为类型
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <param name="stringCase">字符串策略</param>
/// <returns></returns>
public T ToObject<T>(StringCase stringCase)
{
var type = typeof(T);
var obj = Activator.CreateInstance(type);
var properties = type.GetProperties();
foreach (var item in properties)
{
var renameAttribute = item.GetCustomAttributes(typeof(ReNameAttribute), true);
string key;
if (renameAttribute.Length > 0)
{
key = ((ReNameAttribute)renameAttribute[0]).Name;
}
else
{
key = stringCase switch
{
StringCase.Snake => item.Name.ToSnakeCase(),
StringCase.Camel => item.Name.ToCamelCase(),
StringCase.Lower => item.Name.ToLower(),
_ => item.Name
};
}
var value = GetStringValue(key);
if (value == null)
{
continue;
}
var propertyType = item.PropertyType;
if (propertyType.IsEnum)
{
item.SetValue(obj, Enum.Parse(propertyType, value));
}
else if (propertyType.IsGenericType)
{
propertyType = propertyType.GenericTypeArguments[0];
if (propertyType.IsEnum)
{
item.SetValue(obj, Enum.Parse(propertyType, value));
}
}
else
{
item.SetValue(obj, Convert.ChangeType(value, propertyType));
}
}
return (T)obj;
}
/// <summary>
/// 异步将网关参数转为类型
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <param name="stringCase">字符串策略</param>
/// <returns></returns>
public async Task<T> ToObjectAsync<T>(StringCase stringCase)
{
return await Task.Run(() => ToObject<T>(stringCase));
}
/// <summary>
/// 清空网关数据
/// </summary>
public void Clear()
{
_values.Clear();
}
/// <summary>
/// 移除指定参数
/// </summary>
/// <param name="key">参数名</param>
/// <returns></returns>
public bool Remove(string key)
{
return _values.Remove(key);
}
#endregion
}
}