要求

    1. 首先,排除sign参数之外,将其它参数(空值除外)按名称进行字母排序,并和它的取值一起组成name=value样式的字符串,然后用&把它们拼装为一个大字符串,对于嵌套的参数,嵌套的参数列表也需按照字母排序进行拼装。
      a) 比如,要传递下列参数
      i.version=1.0.0
      ii.return_code=0
      iii.拼装之后的字符串为:return_code=0&version=1.0.0
      b) 比如,要传递下列参数
      i.a=1
      ii.b={“d”:”3”,”c”:”2”}
      iii.拼装之后的字符串为:a=1&b=c=2&d=3
      c)比如,要传递下列参数
      i.a=1
      ii.b=[{“d”:”3”,”c”:”2”},{“d”:”5”,”c”:”4”}]
      iii.拼装之后的字符串为:a=1&b=c=2&d=3&c=4&d=5
      d)比如,要传递下列参数
      i.a=1
      ii.b=[“2”,”3”]
      iii.拼装之后的字符串为:a=1&b=2&3
      e)比如,要传递下列参数
      i.a=1
      ii.b=[[{“d1”:”1”,”c1”:”2”},{“d2”:”3”,”c2”:”4”}],[{“d3”:”5”,”c3”:”6”},{“d4”:”7”,”c4”:”8”}]]
      iii.拼装之后的字符串为:a=1&b=c1=2&d1=1&c2=4&d2=3&c3=6&d3=5&c4=8&d4=7
    2. 在上述拼装之后的字符串后面直接拼装accesskey的值。
      a)比如,上述参数return_code=0&version=1.0.0,假设accesskey是123456789ABCDEF,拼装以后,成为下述字符串:
      b)return_code=0&version=1.0.0123456789ABCDEF
    3. 对上述第2步得到的字符串,进行MD5运算(32位大写),得到sign
    1. using Newtonsoft.Json;
    2. using Newtonsoft.Json.Linq;
    3. using System.Security.Cryptography;
    4. using System.Text;
    5. namespace Demo
    6. {
    7. public class SignUtils
    8. {
    9. private static readonly JsonSerializerSettings jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Include };
    10. public static string GetToBeSign(SortedDictionary<string, object> dictionary)
    11. {
    12. var json = JsonConvert.SerializeObject(dictionary, jSetting);
    13. var jobj = JsonConvert.DeserializeObject<JObject>(json);
    14. return GetToBeSign(jobj);
    15. }
    16. public static string GetToBeSign(string json)
    17. {
    18. var jobj = JsonConvert.DeserializeObject<JObject>(json);
    19. return GetToBeSign(jobj);
    20. }
    21. public static string GetToBeSign(JObject jobj)
    22. {
    23. var _dictionary = new SortedDictionary<string, string>();
    24. foreach (var item in jobj)
    25. {
    26. if (item.Value == null || "".Equals(item.Value) || "".Equals(item.Value.ToString()) || "sign".Equals(item.Key) || "mac".Equals(item.Key))
    27. {
    28. continue;
    29. }
    30. var value = item.Value.ToString();
    31. if (item.Value.GetType() == typeof(JObject))
    32. {
    33. value = GetToBeSign(value);
    34. }
    35. else if (item.Value.GetType() == typeof(JArray))
    36. {
    37. value = GetJsonArrayStr(value);
    38. }
    39. _dictionary.Add(item.Key, value);
    40. }
    41. var values = _dictionary.OrderBy(o => o.Key)
    42. .Select(s => $"{s.Key}={s.Value}");
    43. return string.Join("&", values);
    44. }
    45. public static string GetJsonArrayStr(string jarrstr)
    46. {
    47. var jarr = JsonConvert.DeserializeObject<JArray>(jarrstr);
    48. return GetJsonArrayStr(jarr);
    49. }
    50. public static string GetJsonArrayStr(JArray jarr)
    51. {
    52. var values = new List<string>();
    53. foreach (var item in jarr)
    54. {
    55. var value = item.ToString();
    56. if (item.GetType() == typeof(JObject))
    57. {
    58. value = GetToBeSign(item.ToString());
    59. }
    60. else if (item.GetType() == typeof(JArray))
    61. {
    62. value = GetJsonArrayStr(item as JArray);
    63. }
    64. values.Add(value);
    65. }
    66. return string.Join("&", values);
    67. }
    68. /// <summary>
    69. /// 使用 MD5 对输入字符串进行加密
    70. /// </summary>
    71. /// <param name="inputString">需要加密的字符串</param>
    72. /// <param name="charset">编码格式</param>
    73. /// <returns>返回加密后的字符串</returns>
    74. private static string ConvertToMD5(string inputString, string charset = null)
    75. {
    76. if (string.IsNullOrEmpty(charset))
    77. {
    78. charset = "utf-8";
    79. }
    80. MD5 md5Hash = MD5.Create();
    81. byte[] bytes = md5Hash.ComputeHash(Encoding.GetEncoding(charset).GetBytes(inputString));
    82. StringBuilder result = new StringBuilder();
    83. foreach (byte b in bytes)
    84. {
    85. result.Append(b.ToString("x2"));
    86. }
    87. return result.ToString();
    88. }
    89. public static string Sign(string json, string key)
    90. {
    91. var tobesign = $"{GetToBeSign(json)}{key}";
    92. var sign = ConvertToMD5(tobesign).ToUpper();
    93. return sign;
    94. }
    95. public static string Sign(SortedDictionary<string, object> dictionary, string key)
    96. {
    97. var tobesign = $"{GetToBeSign(dictionary)}{key}";
    98. var sign = ConvertToMD5(tobesign).ToUpper();
    99. return sign;
    100. }
    101. public static bool CheckSign(string json, string key)
    102. {
    103. var param = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
    104. var ispassed = param.TryGetValue("sign", out object originsign);
    105. if (!ispassed) { return !ispassed; }
    106. var tobesign = $"{GetToBeSign(json)}{key}";
    107. var sign = ConvertToMD5(tobesign).ToUpper();
    108. return originsign.ToString() == sign;
    109. }
    110. }
    111. }