接口文件

This commit is contained in:
“wanyongkang”
2024-04-10 13:55:27 +08:00
parent fff6bee06a
commit ed3b2c653e
3190 changed files with 268248 additions and 1 deletions

View File

@@ -0,0 +1,14 @@
using System;
using System.Reflection;
namespace Alipay.AopSdk.Core.Parser
{
public class AopAttribute
{
public string ItemName { get; set; }
public Type ItemType { get; set; }
public string ListName { get; set; }
public Type ListType { get; set; }
public MethodInfo Method { get; set; }
}
}

View File

@@ -0,0 +1,263 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Alipay.AopSdk.Core.Util;
using Newtonsoft.Json;
namespace Alipay.AopSdk.Core.Parser
{
/// <summary>
/// AOP JSON响应通用解释器。
/// </summary>
public class AopJsonParser<T> : IAopParser<T> where T : AopResponse
{
private static readonly Dictionary<string, Dictionary<string, AopAttribute>> attrs =
new Dictionary<string, Dictionary<string, AopAttribute>>();
protected static readonly DAopConvert AopJsonConvert = delegate(IAopReader reader, Type type)
{
object rsp = null;
var pas = GetAopAttributes(type);
var em = pas.GetEnumerator();
while (em.MoveNext())
{
var kvp = em.Current;
var ta = kvp.Value;
var itemName = ta.ItemName;
var listName = ta.ListName;
if (!reader.HasReturnField(itemName) && (string.IsNullOrEmpty(listName) || !reader.HasReturnField(listName)))
continue;
object value = null;
if (ta.ListType != null)
{
value = reader.GetListObjects(listName, itemName, ta.ListType, AopJsonConvert);
}
else
{
if (typeof(string) == ta.ItemType)
{
var tmp = reader.GetPrimitiveObject(itemName);
if (tmp != null)
value = tmp.ToString();
}
else if (typeof(long) == ta.ItemType)
{
var tmp = reader.GetPrimitiveObject(itemName);
if (tmp != null)
value = ((IConvertible) tmp).ToInt64(null);
}
else if (typeof(bool) == ta.ItemType)
{
value = reader.GetPrimitiveObject(itemName);
}
else
{
value = reader.GetReferenceObject(itemName, ta.ItemType, AopJsonConvert);
}
}
if (value != null)
{
if (rsp == null)
rsp = Activator.CreateInstance(type);
ta.Method.Invoke(rsp, new[] {value});
}
}
return rsp;
};
public string EncryptSourceData(IAopRequest<T> request, string body, string encryptType, string encryptKey,
string charset)
{
if (!"AES".Equals(encryptType))
throw new AopException("API only support AES!");
var item = parseEncryptData(request, body);
var bodyIndexContent = body.Substring(0, item.startIndex);
var bodyEndexContent = body.Substring(item.endIndex);
//TODO 解密逻辑
var bizContent = AlipayEncrypt.AesDencrypt(encryptKey, item.encryptContent, charset);
return bodyIndexContent + bizContent + bodyEndexContent;
}
private static Dictionary<string, AopAttribute> GetAopAttributes(Type type)
{
Dictionary<string, AopAttribute> tas = null;
var inc = attrs.TryGetValue(type.FullName, out tas);
if (inc && tas != null) // 从缓存中获取类属性元数据
return tas;
tas = new Dictionary<string, AopAttribute>();
var pis = type.GetProperties();
foreach (var pi in pis)
{
var ta = new AopAttribute();
ta.Method = pi.GetSetMethod();
// 获取对象属性名称
var xeas = pi.GetCustomAttributes(typeof(JsonPropertyAttribute), true) as JsonPropertyAttribute[];
if (xeas != null && xeas.Length > 0)
ta.ItemName = xeas[0].PropertyName;
// 获取属性类型
if (pi.PropertyType.IsGenericType)
{
var types = pi.PropertyType.GetGenericArguments();
ta.ListType = types[0];
}
else
{
ta.ItemType = pi.PropertyType;
}
tas.Add(pi.Name + ta.ItemType + ta.ListType, ta);
}
attrs[type.FullName] = tas;
return tas;
}
private static string GetSign(string body)
{
var json = JsonConvert.DeserializeObject<IDictionary>(body);
return (string) json["sign"];
}
private static string GetSignSourceData(IAopRequest<T> request, string body)
{
var rootNode = request.GetApiName().Replace(".", "_") + AlipayConstants.RESPONSE_SUFFIX;
var errorRootNode = AlipayConstants.ERROR_RESPONSE;
var indexOfRootNode = body.IndexOf(rootNode);
var indexOfErrorRoot = body.IndexOf(errorRootNode);
string result = null;
if (indexOfRootNode > 0)
result = ParseSignSourceData(body, rootNode, indexOfRootNode);
else if (indexOfErrorRoot > 0)
result = ParseSignSourceData(body, errorRootNode, indexOfErrorRoot);
return result;
}
private static string ParseSignSourceData(string body, string rootNode, int indexOfRootNode)
{
var signDataStartIndex = indexOfRootNode + rootNode.Length + 2;
var indexOfSign = body.IndexOf("\"" + AlipayConstants.SIGN + "\"");
if (indexOfSign < 0)
return null;
var signDataEndIndex = indexOfSign - 1;
var length = signDataEndIndex - signDataStartIndex;
return body.Substring(signDataStartIndex, length);
}
/// <summary>
/// 解析加密节点
/// </summary>
/// <param name="request"></param>
/// <param name="body"></param>
/// <returns></returns>
private static EncryptParseItem parseEncryptData(IAopRequest<T> request, string body)
{
var rootNode = request.GetApiName().Replace(".", "_") + AlipayConstants.RESPONSE_SUFFIX;
var errorRootNode = AlipayConstants.ERROR_RESPONSE;
var indexOfRootNode = body.IndexOf(rootNode);
var indexOfErrorRoot = body.IndexOf(errorRootNode);
EncryptParseItem result = null;
if (indexOfRootNode > 0)
result = ParseEncryptItem(body, rootNode, indexOfRootNode);
else if (indexOfErrorRoot > 0)
result = ParseEncryptItem(body, errorRootNode, indexOfErrorRoot);
return result;
}
private static EncryptParseItem ParseEncryptItem(string body, string rootNode, int indexOfRootNode)
{
var signDataStartIndex = indexOfRootNode + rootNode.Length + 2;
var indexOfSign = body.IndexOf("\"" + AlipayConstants.SIGN + "\"");
var signDataEndIndex = indexOfSign - 1;
if (signDataEndIndex < 0)
signDataEndIndex = body.Length - 1;
var length = signDataEndIndex - signDataStartIndex;
var encyptContent = body.Substring(signDataStartIndex + 1, length - 2);
var item = new EncryptParseItem();
item.encryptContent = encyptContent;
item.startIndex = signDataStartIndex;
item.endIndex = signDataEndIndex;
return item;
}
#region IAopParser<T> Members
public T Parse(string body, string charset)
{
T rsp = null;
IDictionary json = null;
if (!body.StartsWith("<form") && !body.StartsWith("http"))
{
json=JsonConvert.DeserializeObject<IDictionary>(body);
}
if (json != null)
{
// 忽略根节点的名称
foreach (var key in json.Keys)
{
rsp = JsonConvert.DeserializeObject<T>(json[key].ToString());
if (rsp != null)
break;
}
}
if (rsp == null)
rsp = Activator.CreateInstance<T>();
rsp.Body = body;
return rsp;
}
public SignItem GetSignItem(IAopRequest<T> request, string responseBody)
{
if (string.IsNullOrEmpty(responseBody))
return null;
var signItem = new SignItem();
var sign = GetSign(responseBody);
signItem.Sign = sign;
var signSourceData = GetSignSourceData(request, responseBody);
signItem.SignSourceDate = signSourceData;
return signItem;
}
#endregion
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Alipay.AopSdk.Core.Parser
{
/// <summary>
/// AOP JSON响应通用读取器。
/// </summary>
public class AopJsonReader : IAopReader
{
private readonly IDictionary json;
public AopJsonReader(IDictionary json)
{
this.json = json;
}
public bool HasReturnField(object name)
{
return json.Contains(name);
}
public object GetPrimitiveObject(object name)
{
return json[name];
}
public object GetReferenceObject(object name, Type type, DAopConvert convert)
{
var dict = json[name] as IDictionary;
if (dict != null && dict.Count > 0)
return convert(new AopJsonReader(dict), type);
return null;
}
public IList GetListObjects(string listName, string itemName, Type type, DAopConvert convert)
{
IList listObjs = null;
var jsonObject = json[listName];
IList jsonList = null;
if (jsonObject is IList)
{
jsonList = jsonObject as IList;
}
else if (jsonObject is IDictionary)
{
var jsonMap = jsonObject as IDictionary;
if (jsonMap != null && jsonMap.Count > 0)
{
var itemTmp = jsonMap[itemName];
if (itemTmp == null && listName != null)
itemTmp = jsonMap[listName.Substring(0, listName.Length - 1)];
if (itemTmp is IList)
jsonList = itemTmp as IList;
}
}
if (jsonList != null && jsonList.Count > 0)
{
var listType = typeof(List<>).MakeGenericType(type);
listObjs = Activator.CreateInstance(listType) as IList;
foreach (var item in jsonList)
if (typeof(IDictionary).IsAssignableFrom(item.GetType())) // object
{
var subMap = item as IDictionary;
var subObj = convert(new AopJsonReader(subMap), type);
if (subObj != null)
listObjs.Add(subObj);
}
else if (typeof(IList).IsAssignableFrom(item.GetType())) // list/array
{
// TODO not support yet
}
else if (typeof(long).IsAssignableFrom(type))
{
listObjs.Add((long) item);
}
else if (typeof(int).IsAssignableFrom(type))
{
listObjs.Add((int) item);
}
else if (typeof(double).IsAssignableFrom(type))
{
listObjs.Add((double) item);
}
else // boolean, string, null
{
listObjs.Add(item);
}
}
return listObjs;
}
}
}

View File

@@ -0,0 +1,19 @@
using Newtonsoft.Json;
namespace Alipay.AopSdk.Core.Parser
{
public class AopModelParser
{
/// <summary>
/// Json序列化AopObject对象
/// </summary>
/// <param name="res"></param>
/// <returns></returns>
public string SerializeAopObject(AopObject res)
{
JsonSerializerSettings jsetting = new JsonSerializerSettings();
jsetting.NullValueHandling = NullValueHandling.Ignore;
return JsonConvert.SerializeObject(res,Formatting.None,jsetting);
}
}
}

View File

@@ -0,0 +1,195 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Alipay.AopSdk.Core.Util;
namespace Alipay.AopSdk.Core.Parser
{
/// <summary>
/// AOP XML响应通用解释器。
/// </summary>
public class AopXmlParser<T> : IAopParser<T> where T : AopResponse
{
private static readonly Regex regex = new Regex("<(\\w+?)[ >]", RegexOptions.Compiled);
private static readonly Dictionary<string, XmlSerializer> parsers = new Dictionary<string, XmlSerializer>();
public string EncryptSourceData(IAopRequest<T> request, string body, string encryptType, string encryptKey,
string charset)
{
var item = ParseEncryptData(request, body);
var bodyIndexContent = body.Substring(0, item.startIndex);
var bodyEndContent = body.Substring(item.endIndex);
var encryptContent = AlipayEncrypt.AesDencrypt(encryptKey, item.encryptContent, charset);
return bodyIndexContent + encryptContent + bodyEndContent;
}
/// <summary>
/// 获取XML响应的根节点名称
/// </summary>
private string GetRootElement(string body)
{
var match = regex.Match(body);
if (match.Success)
return match.Groups[1].ToString();
throw new AopException("Invalid XML response format!");
}
private static string GetSign(string body)
{
var signNodeName = "<" + AlipayConstants.SIGN + ">";
var signEndNodeName = "</" + AlipayConstants.SIGN + ">";
var indexOfSignNode = body.IndexOf(signNodeName);
var indexOfSignEndNode = body.IndexOf(signEndNodeName);
if (indexOfSignNode < 0 || indexOfSignEndNode < 0)
return null;
// 签名
var startPos = indexOfSignNode + signNodeName.Length;
return body.Substring(startPos, indexOfSignEndNode - startPos);
}
private static string GetSignSourceData(IAopRequest<T> request, string body)
{
var rootNode = request.GetApiName().Replace(".", "_") + AlipayConstants.RESPONSE_SUFFIX;
var errorRootNode = AlipayConstants.ERROR_RESPONSE;
var indexOfRootNode = body.IndexOf(rootNode);
var indexOfErrorRoot = body.IndexOf(errorRootNode);
string result = null;
if (indexOfRootNode > 0)
result = ParseSignSourceData(body, rootNode, indexOfRootNode);
else if (indexOfErrorRoot > 0)
result = ParseSignSourceData(body, errorRootNode, indexOfErrorRoot);
return result;
}
private static string ParseSignSourceData(string body, string rootNode, int indexOfRootNode)
{
// 第一个字母+长度+>
var signDataStartIndex = indexOfRootNode + rootNode.Length + 1;
var indexOfSign = body.IndexOf("<" + AlipayConstants.SIGN);
if (indexOfSign < 0)
return null;
// 签名前减去
var signDataEndIndex = indexOfSign;
return body.Substring(signDataStartIndex, signDataEndIndex - signDataStartIndex);
}
private static EncryptParseItem ParseEncryptData(IAopRequest<T> request, string body)
{
var rootNode = request.GetApiName().Replace(".", "_") + AlipayConstants.RESPONSE_SUFFIX;
var errorRootNode = AlipayConstants.ERROR_RESPONSE;
var indexOfRootNode = body.IndexOf(rootNode);
var indexOfErrorRoot = body.IndexOf(errorRootNode);
EncryptParseItem result = null;
if (indexOfRootNode > 0)
result = ParseEncryptItem(body, rootNode, indexOfRootNode);
else if (indexOfErrorRoot > 0)
result = ParseEncryptItem(body, errorRootNode, indexOfErrorRoot);
return result;
}
private static EncryptParseItem ParseEncryptItem(string body, string rootNode, int indexOfRootNode)
{
// 第一个字母+长度+>
var signDataStartIndex = indexOfRootNode + rootNode.Length + 1;
var xmlStartNode = "<" + AlipayConstants.ENCRYPT_NODE_NAME + ">";
var xmlEndNode = "</" + AlipayConstants.ENCRYPT_NODE_NAME + ">";
var indexOfEncryptNode = body.IndexOf(xmlEndNode);
if (indexOfEncryptNode < 0)
{
var item = new EncryptParseItem();
item.encryptContent = null;
item.startIndex = 0;
item.endIndex = 0;
return item;
}
var startIndex = signDataStartIndex + xmlStartNode.Length;
var bizLen = indexOfEncryptNode - startIndex;
var encryptBizContent = body.Substring(startIndex, bizLen);
var item2 = new EncryptParseItem();
item2.encryptContent = encryptBizContent;
item2.startIndex = signDataStartIndex;
item2.endIndex = indexOfEncryptNode + xmlEndNode.Length;
return item2;
}
#region IAopParser<T> Members
public T Parse(string body, string charset)
{
XmlSerializer serializer = null;
var rootTagName = GetRootElement(body);
var inc = parsers.TryGetValue(rootTagName, out serializer);
if (!inc || serializer == null)
{
var rootAttrs = new XmlAttributes();
rootAttrs.XmlRoot = new XmlRootAttribute(rootTagName);
var attrOvrs = new XmlAttributeOverrides();
attrOvrs.Add(typeof(T), rootAttrs);
serializer = new XmlSerializer(typeof(T), attrOvrs);
parsers[rootTagName] = serializer;
}
object obj = null;
Encoding encoding = null;
if (string.IsNullOrEmpty(charset))
encoding = Encoding.UTF8;
else
encoding = Encoding.GetEncoding(charset);
using (Stream stream = new MemoryStream(encoding.GetBytes(body)))
{
obj = serializer.Deserialize(stream);
}
var rsp = (T) obj;
if (rsp != null)
rsp.Body = body;
return rsp;
}
public SignItem GetSignItem(IAopRequest<T> request, string reponseBody)
{
if (string.IsNullOrEmpty(reponseBody))
return null;
var signItem = new SignItem();
var sign = GetSign(reponseBody);
signItem.Sign = sign;
var signSourceData = GetSignSourceData(request, reponseBody);
signItem.SignSourceDate = signSourceData;
return signItem;
}
#endregion
}
}

View File

@@ -0,0 +1,9 @@
namespace Alipay.AopSdk.Core.Parser
{
internal class EncryptParseItem
{
public string encryptContent;
public int endIndex;
public int startIndex;
}
}

View File

@@ -0,0 +1,36 @@
namespace Alipay.AopSdk.Core.Parser
{
/// <summary>
/// AOP API响应解释器接口。响应格式可以是XML, JSON等等。
/// </summary>
/// <typeparam name="T">领域对象</typeparam>
public interface IAopParser<T> where T : AopResponse
{
/// <summary>
/// 把响应字符串解释成相应的领域对象。
/// </summary>
/// <param name="body">响应字符串</param>
/// <returns>领域对象</returns>
T Parse(string body, string charset);
/// <summary>
/// 解析签名内容
/// </summary>
/// <param name="request"></param>
/// <param name="responseBody"></param>
/// <returns></returns>
SignItem GetSignItem(IAopRequest<T> request, string responseBody);
/// <summary>
/// 将响应串解密
/// </summary>
/// <param name="request"></param>
/// <param name="body"></param>
/// <param name="encryptType"></param>
/// <param name="encryptKey"></param>
/// <param name="charset"></param>
/// <returns></returns>
string EncryptSourceData(IAopRequest<T> request, string body, string encryptType, string encryptKey, string charset);
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections;
namespace Alipay.AopSdk.Core.Parser
{
public delegate object DAopConvert(IAopReader reader, Type type);
/// <summary>
/// AOP API响应读取器接口。响应格式可以是XML, JSON等等。
/// </summary>
public interface IAopReader
{
/// <summary>
/// 判断响应中是否包含指定的属性。
/// </summary>
/// <param name="name">属性名称</param>
/// <returns>true/false</returns>
bool HasReturnField(object name);
/// <summary>
/// 获取值类型属性的值。
/// </summary>
/// <param name="name">属性名称</param>
/// <returns>值对象</returns>
object GetPrimitiveObject(object name);
/// <summary>
/// 获取引用类型的值。
/// </summary>
/// <param name="name">属性名称</param>
/// <param name="type">引用类型</param>
/// <param name="convert">转换器</param>
/// <returns>引用对象</returns>
object GetReferenceObject(object name, Type type, DAopConvert convert);
/// <summary>
/// 获取列表类型的值。
/// </summary>
/// <param name="listName">列表属性名称</param>
/// <param name="itemName">列表项名称</param>
/// <param name="type">引用类型</param>
/// <param name="convert">转换器</param>
/// <returns>列表对象</returns>
IList GetListObjects(string listName, string itemName, Type type, DAopConvert convert);
}
}