企业微信新更新了一个收银台 ,我们代开发应用需要调用创建收款订单接口
企业微信文档地址 签名算法 - 接口文档 - 企业微信开发者中心
下面直接上代码(适用于复杂JSON结构的API请求)
/// <summary>
/// 生成企业微信sig
/// </summary>
/// <param name="json">发起请求的json体</param>
/// <param name="jmKey">收银台加密的key</param>
/// <returns></returns>
private string GenerateSignature(string json, string jmKey)
{
var jsonObject = JObject.Parse(json);
var parameters = new List<string>();
foreach (var property in jsonObject.Properties())
{
if (property.Name != "sig") // 排除指定字段
{
if (property.Value.Type == JTokenType.Object || property.Value.Type == JTokenType.Array)
{
// 处理嵌套对象和数组
var nestedParameters = GetNestedParameters(property.Name, property.Value);
parameters.AddRange(nestedParameters);
}
else
{
parameters.Add($"{property.Name}={property.Value.ToString()}");
}
}
}
// 按照字典序排序参数
parameters.Sort(StringComparer.Ordinal);
// 将参数连接成字符串
string parameterString = string.Join("&", parameters);
var sig = HA256Encode(parameterString, jmKey);
return sig;
}
private List<string> GetNestedParameters(string parentKey, JToken token)
{
var parameters = new List<string>();
if (token.Type == JTokenType.Object)
{
foreach (var property in token.Children<JProperty>())
{
if (property.Value.Type == JTokenType.Object || property.Value.Type == JTokenType.Array)
{
var nestedParameters = GetNestedParameters($"{property.Name}", property.Value);
parameters.AddRange(nestedParameters);
}
else
{
parameters.Add($"{property.Name}={property.Value.ToString()}");
}
}
}
else if (token.Type == JTokenType.Array)
{
int index = 0;
foreach (var item in token.Children())
{
var nestedParameters = GetNestedParameters($"{parentKey}[{index}]", item);
parameters.AddRange(nestedParameters);
index++;
}
}
return parameters;
}
private string HA256Encode(string stringA, string secret)
{
using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
{
byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringA));
string base64Encoded = Convert.ToBase64String(hashBytes);
return base64Encoded;
}
}
调用这样写
//生成签名
var createSig = GenerateSignature(需要POST的Json, 服务商的支付密钥);
还需要注意一个 请求参数ts 时间戳用utc时间
/// <summary>
/// 生成ts时间戳
/// </summary>
/// <returns></returns>
private long GetUnixTimestamp()
{
DateTime utcNow = DateTime.UtcNow;
DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeSpan timeSpan = utcNow - unixEpoch;
return Convert.ToInt64(timeSpan.TotalSeconds);
}