【发布时间】:2011-09-23 16:29:21
【问题描述】:
我正在实施托管结帐,托管结帐应该将用户重定向回我的网站,以便我可以显示自定义收据页面。
这是我要返回的示例查询字符串:
trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed= 0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref2=&ref3=& &hashValue=33dacf84682470f267b2cc6d528b1594
为了验证请求,我应该从查询字符串的末尾删除&hashValue=f3cf58ef0fd363e0c2241938b04f1068,然后附加一个键。然后我对整个字符串进行 MD5 哈希,结果应该是33dacf84682470f267b2cc6d528b1594,和原来的一样。
这很容易,只是一些字段对我造成了问题。这是我使用的代码(取自一个虚拟应用程序,因此您可以忽略一些错误的编码):
// Split up the query string parameters
string[] parameters = GetQueryString().Split(new[] { "&" }, StringSplitOptions.None);
var querySet = new List<string>();
// Rebuild the query string, encoding the values.
foreach (string s in parameters)
{
// Every field that contains a "." will need to be encoded except for trnAmount
querySet.Add(param.Contains("trnAmount") ? param : UrlEncodeToUpper(param));
}
// Create the querystring without the hashValue, we need to calculate our hash without it.
string qs = string.Join("&", querySet.ToArray());
qs = qs.Substring(0, qs.IndexOf("&hashValue"));
qs = qs + "fb76124fea73488fa11995dfa4cbe89b";
var encoding = new UTF8Encoding();
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(encoding.GetBytes(qs));
var calculatedHash = BitConverter.ToString(hash).Replace("-", String.Empty).ToLower();
这是我使用的 UrlEncode 方法。
private static string UrlEncodeToUpper(string value)
{
// Convert their encoding into uppercase so we can do our hash
value = Regex.Replace(value, "(%[0-9af][0-9a-f])", c => c.Value.ToUpper());
// Encode the characters that they missed
value = value.Replace("-", "%2D").Replace(".", "%2E").Replace("_", "%5F");
return value;
}
这一切都有效(直到有人输入了我没有考虑过的角色),除了这似乎比它应该的更复杂。我知道我不是唯一一个必须将这个 HCO 实现到 ASP.NET 应用程序中的人,所以我认为简单的验证不应该这么复杂。
我错过了一种更简单的方法吗?必须遍历字段,对其中一些进行编码,同时跳过其他字段,将它们的编码转换为大写,然后选择性地替换字符似乎有点……奇怪。
【问题讨论】:
-
是的,一个 GET 请求会改变状态...最好希望 Google 有足够的钱来支付它将从您的网站上购买的所有东西!
-
@Blindy,改变状态?此请求不会更改任何内容。我们只是向将要通过身份验证的用户显示收据。
-
你可以发帖而不是使用查询字符串吗?
-
GetQueryString()是做什么的? -
@Jacob,在生产站点中它只是调用 HttpContext.Current.Request.QueryString,在我的小虚拟应用程序中它只是调用那个确切的字符串。