WX-Game1/Assets/Scripts/SignUtil.cs

93 lines
3.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
public static class SignUtil
{
public static string LastPlainText { get; private set; } = "";
public static string GetSign(Dictionary<string, string> parameters, string secret)
{
// 排序并拼接
var sorted = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
sorted.Remove("sign"); // sign 不参与
StringBuilder sb = new StringBuilder();
foreach (var kv in sorted)
sb.Append(kv.Key).Append(kv.Value);
sb.Append(secret);
// MD5 小写
using var md5 = System.Security.Cryptography.MD5.Create();
byte[] input = Encoding.UTF8.GetBytes(sb.ToString());
byte[] hash = md5.ComputeHash(input);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
public static string GetSign(IDictionary<string, object> parameters, string secret)
{
// 拷贝并排除 sign
var dict = parameters
.Where(kv => !string.Equals(kv.Key, "sign", StringComparison.Ordinal))
.ToDictionary(kv => kv.Key, kv => kv.Value);
// 按 key ASCII 排序(等同 PHP 的 ksort
var ordered = dict.OrderBy(k => k.Key, StringComparer.Ordinal);
// 拼接 key + value
var sb = new StringBuilder();
foreach (var kv in ordered)
{
string v = ToFlatString(kv.Value);
sb.Append(kv.Key).Append(v);
}
// // 追加 AppSecret
sb.Append(secret);
// 记录签名原文,便于排错
LastPlainText = sb.ToString();
Debug.Log(LastPlainText);
// MD5 小写32位
using var md5 = MD5.Create();
var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(LastPlainText));
return BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant();
}
// 将值转成“紧凑字符串”,数组按紧凑 JSON无空格序列化
private static string ToFlatString(object val)
{
if (val == null) return "";
switch (val)
{
case string s: return s;
case bool b: return b ? "true" : "false";
case Array a: return JsonArrayCompact(a);
case IList<object> l: return JsonArrayCompact(l.ToArray());
default:
if (val is IFormattable f)
return f.ToString(null, System.Globalization.CultureInfo.InvariantCulture);
return val.ToString();
}
}
private static string JsonArrayCompact(Array arr)
{
var parts = new List<string>(arr.Length);
foreach (var x in arr)
{
if (x == null) { parts.Add("null"); continue; }
if (x is string s) parts.Add($"\"{Escape(s)}\"");
else if (x is bool b) parts.Add(b ? "true" : "false");
else if (x is IFormattable f) parts.Add(f.ToString(null, System.Globalization.CultureInfo.InvariantCulture));
else parts.Add($"\"{Escape(x.ToString())}\"");
}
return "[" + string.Join(",", parts) + "]";
}
private static string Escape(string s) => s.Replace("\\", "\\\\").Replace("\"", "\\\"");
}