背景
最近在对接腾讯会议这块,前期磕磕绊绊算走过来。对接到会议事件(webhook)这块死活验签不通过。打日志发现,C#的生成的签名和腾讯返回的签名是不一样呢,首先确认了一下token是不是一样的,确认token是完全一样的。最终没办法拿到java的示例跑一下看看。哇塞!为什么和服务器生成一毛一样。(暗自窃喜)这个肯定是C#的代码示例有问题。向腾讯那边的人反馈,他确认后,让我提交工单,让腾讯那边的改一下就行。万万没想到,这个客服只会让我确认两个问题,
- 时间戳必须在计算机的五分钟内(这个根本不可能,验签工作时我做的,我压根没有判断有没有小于五分钟)
- token是不是一致(这个在上诉中已经确认,肯定一样的)
刚好我今天腾出空来,好好看看这个是什么问题
排查问题
根据腾讯文档上的签名生成规则来分析。
在这个四个步骤里面,按照字典排序最有可能出现问题。没明确表示是按照哪种算法排序。
然后我就把断点打在这里看数组:
java代码
C#代码
发现了两块代码中token和data的顺序并不一样。
现在问题已经明确是C#的排序和java的字符串排序不一样导致
解决办法
把这块代码
string[] arr = { token, timestamp, nonce, data };
Array.Sort(arr);
替换成如下代码
var arr = new List<string> { token, timestamp, nonce, data };
arr.Sort(string.CompareOrdinal);
完整代码示例:
public static string CalSignature(string token, string timestamp, string nonce, string data)
{
var arr = new List<string> { token, timestamp, nonce, data };
arr.Sort(string.CompareOrdinal);
var toSign = new StringBuilder();
for (int i = 0; i < arr.Count; i++)
{
toSign.Append(arr[i]);
}
var buffer = Encoding.UTF8.GetBytes(toSign.ToString());
var signData = SHA1.Create().ComputeHash(buffer);
var sb = new StringBuilder();
foreach (var t in signData)
{
sb.Append(t.ToString("x2"));
}
return sb.ToString();
}
后续
事情解决完了,我还把相关的解决思路。发给腾讯客服了,客服没有道歉,只说会把情况反应到技术上。这么人性的客服那肯定一星好评送上是吧