签名校验方法:MD5Verify
1:首先需要解决参数排序一致问题,
2:参数全部转换位大写或者小写,
3:对象里面嵌套对象时,需要使用到递归
4:对象序列化
public static string MD5Sign(Object obj, string secretKey, List<string> ignoreProps = null)
{
try
{
if (obj == null)
throw new Exception("obj签名对象为空");
//首字母小写
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.Formatting = Formatting.Indented;
string jsonStr = JsonConvert.SerializeObject(obj, settings);
if (string.IsNullOrEmpty(jsonStr))
throw new Exception("obj序列化失败");
var dicParameters = GetParameters(jsonStr, ignoreProps);
if (dicParameters == null || dicParameters.Count <= 0)
throw new Exception("签名参数有误");
var signStr = string.Join("&", dicParameters.OrderBy(o => o.Key).Select(o => string.Format("{0}={1}", o.Key, o.Value)));
return EncryptUtil.MD5Hash(signStr + "&key=" + secretKey);
}
catch (Exception ex)
{
AppLog.Write(string.Format("调用接口【{0}/{1}】异常:{2}", "SignUtil", "MD5Sign", ex.Message), LogMessageType.Error, ex);
return null;
}
}
方法二:
private static Dictionary<string, string> GetParameters(string jsonStr, List<string> ignoreProps)
{
JObject jboj = JsonConvert.DeserializeObject<JObject>(jsonStr);
return GetParameters(jboj, ignoreProps);
}
方法三:
/// <summary>
/// 字典参数获取
/// </summary>
/// <param name="jsonStr"></param>
/// <param name="ignoreProps"></param>
/// <returns></returns>
private static Dictionary<string, string> GetParameters(JObject jboj, List<string> ignoreProps)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (KeyValuePair<string, JToken> item in jboj)
{
//剔除忽略属性
if (ignoreProps != null && ignoreProps.Where(o => item.Key.Equals(o)).Count() > 0)
{
continue;
}
JToken jToken = item.Value;
var jTokenType = jToken.Type;
string value = string.Empty;
//value = JsonConvert.SerializeObject(item.Value);
//对象和数组单独处理
if (jTokenType == JTokenType.Object)
{
value = JsonConvert.SerializeObject(item.Value);
}
else if (jTokenType == JTokenType.Array)
{
value = ArrayToString(item.Value);
}
else if (jTokenType == JTokenType.Float)
{
//value = JsonConvert.SerializeObject(String.Format("{0:F}", item.Value.ToString()));;
string valueset = JsonConvert.SerializeObject(item.Value);
value = Convert.ToDecimal(valueset).ToString("0.00####");
}
else
{
value = item.Value.ToString();
}
//bool true和false首字母会转大写
if (value == "False" || value == "True")
{
value = value.ToLower();
}
dic.Add(item.Key, value);
}
dic.Remove("Sign");
dic.Remove("sign");
return dic;
}
方法四:
private static string ArrayToString(JToken jToken)
{
List<string> list = new List<string>();
Dictionary<string, string> dicParameters = new Dictionary<string, string>();
StringBuilder signStr = new StringBuilder();
foreach (var item in jToken)
{
signStr.Append("{");
dicParameters = GetParameters(item as JObject, null);
if (dicParameters == null || dicParameters.Count <= 0)
throw new Exception("签名参数有误");
signStr.Append(string.Join("&", dicParameters.OrderBy(o => o.Key).Select(o => string.Format("{0}={1}", o.Key, o.Value))));
signStr.Append("}");
}
if (dicParameters == null || dicParameters.Count <= 0)
throw new Exception("签名参数有误");
//var signStr = string.Join("&", dicParameters.OrderBy(o => o.Key).Select(o => string.Format("{0}={1}", o.Key, o.Value)));
return "[" + signStr + "]";
}