You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

202 lines
6.9 KiB

using System;
using System.Web;
//正则
using System.Text.RegularExpressions;
using System.Security.Cryptography;
//泛型
using System.Collections.Generic;
// 字符相关
using System.Text;
namespace HttpProxyWorld
{
/**
* 生成签名类
*
* @version 3.0.0
* @author open.qq.com
* @copyright © 2012, Tencent Corporation. All rights reserved.
* @ History:
* 3.0.0 | coolinchen | 2013-1-11 11:11:11 | initialization
*/
public class SnsSigCheck
{
public SnsSigCheck()
{
}
/// <summary>
/// 生成签名
/// </summary>
/// <param name="method">请求方法 get/post </param>
/// <param name="url_path">url_path</param>
/// <param name="param">表单参数</param>
/// <param name="secret">密钥</param>
/// <returns>返回签名结果</returns>
//
static public string MakeSig(string method, string url_path, Dictionary<string, string>param, string secret)
{
string mk = MakeSource(method, url_path, param);
//使用SHA1的HMAC
HMAC hmac = HMACSHA1.Create();
hmac.Key = Encoding.UTF8.GetBytes(secret);
byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(mk));
//转为base64编码
string my_sign = Convert.ToBase64String(hash);
return my_sign;
}
static private string MakeSource(string method, string url_path, Dictionary<string, string> param)
{
string strs = method.ToUpper() + "&" + UrlEncode(url_path, Encoding.UTF8) + "&";
string query_string = "";
List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(param);
myList.Sort(delegate(KeyValuePair<string, string> s1, KeyValuePair<string, string> s2)
{
return s1.Key.CompareTo(s2.Key);
});
foreach (KeyValuePair<string, string> pair in myList)
{
query_string = query_string + pair.Key + "=" + pair.Value + "&";
}
query_string = query_string.Substring(0, query_string.Length - 1);
query_string = UrlEncode(query_string, Encoding.UTF8);
return strs + query_string;
}
/// <summary>
///解决HttpUtility.UrlEncode会将符号编码为小写英文的问题
/// </summary>
/// <param name="temp">待编码的字符串</param>
/// <param name="encoding">编码的方式</param>
/// <returns>返回编码结果</returns>
static public string UrlEncode(string temp, Encoding encoding)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < temp.Length; i++)
{
string t = temp[i].ToString();
string k;
switch (t)
{
case "'":
t = "%27";
builder.Append(t);
break;
case " ":
t = "%20";
builder.Append(t);
break;
case "(":
t = "%28";
builder.Append(t);
break;
case ")":
t = "%29";
builder.Append(t);
break;
case "!":
t = "%21";
builder.Append(t);
break;
case "*":
t = "%2A";
builder.Append(t);
break;
default:
k = HttpUtility.UrlEncode(t, encoding);
if (t == k)
{
builder.Append(t);
}
else
{
builder.Append(k.ToUpper());
}
break;
}
}
return builder.ToString();
}
/// <summary>
///验证回调发货URL的签名 (注意和普通的OpenAPI签名算法不一样, 详见
///http://wiki.open.qq.com/wiki/%E5%9B%9E%E8%B0%83%E5%8F%91%E8%B4%A7URL%E7%9A%84%E5%8D%8F%E8%AE%AE%E8%AF%B4%E6%98%8E_V3
/// </summary>
/// <param name="method">请求方法 get/post</param>
/// <param name="url_path">url_path</param>
/// <param name="param">腾讯调用发货回调URL携带的请求参数</param>
/// <param name="secret">密钥</param>
/// <param name="sig">腾讯调用发货回调URL时传递的签名</param>
/// <returns>签名校验结果</returns>
static public bool VerifySig(string method,string url_path, Dictionary<string, string> param,string secret,string sig)
{
// param无需传sig
if (param.ContainsKey("sig"))
{
param.Remove("sig");
}
Dictionary<string, string> new_param = new Dictionary<string, string>();
// 先使用专用的编码规则对value编码
foreach (string key in param.Keys)
{
new_param.Add(key, EncodeValue(param[key]));
}
// 再计算签名
string sig_new = MakeSig(method, url_path, new_param, secret);
return sig_new.Equals(sig);
}
/// <summary>
///回调发货URL专用的编码算法
///编码规则为:除了 0~9 a~z A~Z !*()之外其他字符按其ASCII码的十六进制加%进行表示,例如"-"编码为"%2D"
///详见 http://wiki.open.qq.com/wiki/%E5%9B%9E%E8%B0%83%E5%8F%91%E8%B4%A7URL%E7%9A%84%E5%8D%8F%E8%AE%AE%E8%AF%B4%E6%98%8E_V3
/// </summary>
/// <param name="value">待编码的字符串</param>
/// <returns>返回编码结果</returns>
static public string EncodeValue(string value)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < value.Length; i++)
{
if (Regex.IsMatch(value[i].ToString(), @"[a-zA-Z0-9!()*]"))
{
builder.Append(value[i].ToString());
}
else
{
//byte[] bt = new byte[1];
byte[] bt = Encoding.UTF8.GetBytes(value[i].ToString());//中文的话,一个汉字有三个字节
for (int k = 0; k < bt.Length; k++)
{
int ascii = (short)(bt[k]);//计算每个字节的ascii码值
builder.Append("%" + Convert.ToString(ascii, 16).ToUpper());
}
}
}
return builder.ToString();
}
}
}