AopXmlParser.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Text;
  4. using System.Text.RegularExpressions;
  5. using System.Xml.Serialization;
  6. using Aop.Api.Request;
  7. namespace Aop.Api.Parser
  8. {
  9. /// <summary>
  10. /// AOP XML响应通用解释器。
  11. /// </summary>
  12. public class AopXmlParser<T> : IAopParser<T> where T : AopResponse
  13. {
  14. private static Regex regex = new Regex("<(\\w+?)[ >]", RegexOptions.Compiled);
  15. private static Dictionary<string, XmlSerializer> parsers = new Dictionary<string, XmlSerializer>();
  16. #region IAopParser<T> Members
  17. public T Parse(string body, string charset)
  18. {
  19. XmlSerializer serializer = null;
  20. string rootTagName = GetRootElement(body);
  21. bool inc = parsers.TryGetValue(rootTagName, out serializer);
  22. if (!inc || serializer == null)
  23. {
  24. XmlAttributes rootAttrs = new XmlAttributes();
  25. rootAttrs.XmlRoot = new XmlRootAttribute(rootTagName);
  26. XmlAttributeOverrides attrOvrs = new XmlAttributeOverrides();
  27. attrOvrs.Add(typeof(T), rootAttrs);
  28. serializer = new XmlSerializer(typeof(T), attrOvrs);
  29. parsers[rootTagName] = serializer;
  30. }
  31. object obj = null;
  32. Encoding encoding = null;
  33. if (string.IsNullOrEmpty(charset))
  34. {
  35. encoding = Encoding.UTF8;
  36. }
  37. else
  38. {
  39. encoding = Encoding.GetEncoding(charset);
  40. }
  41. using (Stream stream = new MemoryStream(encoding.GetBytes(body)))
  42. {
  43. obj = serializer.Deserialize(stream);
  44. }
  45. T rsp = (T)obj;
  46. if (rsp != null)
  47. {
  48. rsp.Body = body;
  49. }
  50. return rsp;
  51. }
  52. public SignItem GetSignItem(IAopRequest<T> request, T response)
  53. {
  54. string body = response.Body;
  55. if (string.IsNullOrEmpty(body))
  56. {
  57. return null;
  58. }
  59. SignItem signItem = new SignItem();
  60. string sign = GetSign(body);
  61. signItem.Sign = sign;
  62. string signSourceData = GetSignSourceData(request, body);
  63. signItem.SignSourceDate = signSourceData;
  64. return signItem;
  65. }
  66. #endregion
  67. /// <summary>
  68. /// 获取XML响应的根节点名称
  69. /// </summary>
  70. private string GetRootElement(string body)
  71. {
  72. Match match = regex.Match(body);
  73. if (match.Success)
  74. {
  75. return match.Groups[1].ToString();
  76. }
  77. else
  78. {
  79. throw new AopException("Invalid XML response format!");
  80. }
  81. }
  82. private static string GetSign(string body)
  83. {
  84. string signNodeName = "<" + AlipayConstants.SIGN + ">";
  85. string signEndNodeName = "</" + AlipayConstants.SIGN + ">";
  86. int indexOfSignNode = body.IndexOf(signNodeName);
  87. int indexOfSignEndNode = body.IndexOf(signEndNodeName);
  88. if (indexOfSignNode < 0 || indexOfSignEndNode < 0)
  89. {
  90. return null;
  91. }
  92. // 签名
  93. int startPos = indexOfSignNode + signNodeName.Length;
  94. return body.Substring(startPos, indexOfSignEndNode - startPos);
  95. }
  96. private static string GetSignSourceData(IAopRequest<T> request, string body)
  97. {
  98. string rootNode = request.GetApiName().Replace(".", "_") + AlipayConstants.RESPONSE_SUFFIX;
  99. string errorRootNode = AlipayConstants.ERROR_RESPONSE;
  100. int indexOfRootNode = body.IndexOf(rootNode);
  101. int indexOfErrorRoot = body.IndexOf(errorRootNode);
  102. string result = null;
  103. if (indexOfRootNode > 0)
  104. {
  105. result = ParseSignSourceData(body, rootNode, indexOfRootNode);
  106. }
  107. else if (indexOfErrorRoot > 0)
  108. {
  109. result = ParseSignSourceData(body, errorRootNode, indexOfErrorRoot);
  110. }
  111. return result;
  112. }
  113. private static string ParseSignSourceData(string body, string rootNode, int indexOfRootNode)
  114. {
  115. // 第一个字母+长度+>
  116. int signDataStartIndex = indexOfRootNode + rootNode.Length + 1;
  117. int indexOfSign = body.IndexOf("<" + AlipayConstants.SIGN);
  118. if (indexOfSign < 0)
  119. {
  120. return null;
  121. }
  122. // 签名前减去
  123. int signDataEndIndex = indexOfSign;
  124. return body.Substring(signDataStartIndex, signDataEndIndex - signDataStartIndex);
  125. }
  126. }
  127. }