--
MD5Util:
using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; namespace dotNetRsa客户端 { public class MD5Util { /// <summary> /// mdh5 hash, UTF8 , 16进制表示,去除 "-" 符号,大写 /// </summary> /// <param name="sArray"></param> /// <returns></returns> public static string GetMD5(string sArray,string charset) { Encoding enc = Encoding.GetEncoding(charset); byte[] sourceBytes = enc.GetBytes(sArray); MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); byte[] hashedBytes = md5.ComputeHash(sourceBytes); string str16 = BitConverter.ToString(hashedBytes); string rst = str16.Replace("-", "").ToUpper(); return rst; } } }
--
Utils:
using System; using System.Collections.Generic; using System.Text; using System.Web; namespace dotNetRsa客户端 { public class Utils { public static string UrlEncode(string temp, string charset ) { Encoding encoding = Encoding.GetEncoding(charset); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < temp.Length; i++) { string t = temp[i].ToString(); string k = HttpUtility.UrlEncode(t, encoding); if (t == k) { stringBuilder.Append(t); } else { stringBuilder.Append(k.ToUpper()); } } return stringBuilder.ToString(); } } }
--
RequestHandlerB:
--
using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.Web; using System.Xml; namespace dotNetRsa客户端 { /// <summary> /// 能处理请求报文和响应报文 /// </summary> public class RequestHandlerB { /// <summary> /// 原始内容 /// </summary> protected string content; public RequestHandlerB() { parameters = new Hashtable(); // this.httpContext = httpContext; } /// <summary> /// 网关url地址 /// </summary> private string gateUrl; /// <summary> /// 密钥 /// </summary> private string key; /// <summary> /// 请求的参数 /// </summary> protected Hashtable parameters; /// <summary> /// debug信息 /// </summary> private string debugInfo; /// <summary> /// 初始化函数 /// </summary> public virtual void init() { //nothing to do } /// <summary> /// 获取入口地址,不包含参数值 /// </summary> /// <returns></returns> public String getGateUrl() { return gateUrl; } /// <summary> /// 设置入口地址,不包含参数值 /// </summary> /// <param name="gateUrl">入口地址</param> public void setGateUrl(String gateUrl) { this.gateUrl = gateUrl; } /// <summary> /// 获取密钥 /// </summary> /// <returns></returns> public String getKey() { return key; } /// <summary> /// 设置密钥 /// </summary> /// <param name="key">密钥字符串</param> public void setKey(string key) { this.key = key; } /// <summary> /// 获取带参数的请求URL /// </summary> /// <returns></returns> public virtual string getRequestURL() { this.createSign(); StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "key".CompareTo(k) != 0) { sb.Append(k + "=" + Utils.UrlEncode(v, getCharset()) + "&"); } } //去掉最后一个& if (sb.Length > 0) { sb.Remove(sb.Length - 1, 1); } return this.getGateUrl() + "?" + sb.ToString(); } /// <summary> ///创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 /// </summary> public virtual void createSign() { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { sb.Append(k + "=" + v + "&"); } } sb.Append("key=" + this.getKey()); string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper(); this.setParameter("sign", sign); //debug信息 this.setDebugInfo(sb.ToString() + " => sign:" + sign); } /// <summary> /// 没有KEY的拼接和MD5 HASH 签名 /// </summary> public virtual void createSignWithoutKey() { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { sb.Append(k + "=" + v + "&"); } } string rst = sb.ToString(); rst = rst.TrimEnd('&'); // sb.Append("key=" + this.getKey()); string sign = MD5Util.GetMD5(rst, getCharset()).ToUpper(); this.setParameter("sign", sign); //debug信息 this.setDebugInfo(sb.ToString() + " => sign:" + sign); } /// <summary> /// 获取参数值 /// </summary> /// <param name="parameter">参数名</param> /// <returns></returns> public string getParameter(string parameter) { string s = (string)parameters[parameter]; return (null == s) ? "" : s; } /// <summary> /// 设置参数值 /// </summary> /// <param name="parameter">参数名</param> /// <param name="parameterValue">参数值</param> public void setParameter(string parameter, string parameterValue) { if (parameter != null && parameter != "") { if (parameters.Contains(parameter)) { parameters.Remove(parameter); } parameters.Add(parameter, parameterValue); } } /// <summary> /// 获取debug信息 /// </summary> /// <returns></returns> public String getDebugInfo() { return debugInfo; } /// <summary> /// 设置debug信息 /// </summary> /// <param name="debugInfo"></param> public void setDebugInfo(String debugInfo) { this.debugInfo = debugInfo; } /// <summary> /// 获取所有参数 /// </summary> /// <returns></returns> public Hashtable getAllParameters() { return this.parameters; } /// <summary> /// 获取编码 /// </summary> /// <returns></returns> protected virtual string getCharset() { //return this.httpContext.Request.ContentEncoding.BodyName; return "utf-8"; } public virtual void createSignMCH() { /* 1.进件接口用 用的是dataSign,不是sign 2.拼接key时,不需要&key= */ StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { sb.Append(k + "=" + v + "&"); } } string sighStr = sb.ToString(); sighStr = sighStr.TrimEnd('&'); sighStr += this.getKey();//和支付接口不同 string sign = MD5Util.GetMD5(sighStr, getCharset()).ToLower(); this.setParameter("dataSign", sign); //debug信息 this.setDebugInfo(sb.ToString() + " => dataSign:" + sign); } //创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 //public string createSign2() //{ // StringBuilder sb = new StringBuilder(); // ArrayList akeys = new ArrayList(parameters.Keys); // akeys.Sort(); // foreach (string k in akeys) // { // string v = (string)parameters[k]; // if (null != v && "".CompareTo(v) != 0 // && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) // { // sb.Append(k + "=" + v + "&"); // } // } // sb.Append("key=" + this.getKey()); // string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper(); // this.setParameter("sign", sign); // return sign; //} //输出XML public string parseXML() { StringBuilder sb = new StringBuilder(); sb.Append("<xml>"); foreach (string k in parameters.Keys) { string v = (string)parameters[k]; if (Regex.IsMatch(v, @"^[0-9.]$")) { sb.Append("<" + k + ">" + v + "</" + k + ">"); } else { sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">"); } } sb.Append("</xml>"); return sb.ToString(); } /// <summary> /// 设置返回内容 /// </summary> /// <param name="content">XML内容</param> public virtual void setContent(string content) { this.content = content; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.XmlResolver = null;//2018-12-3 xmlDoc.LoadXml(content); XmlNode root = xmlDoc.SelectSingleNode("xml"); XmlNodeList xnl = root.ChildNodes; foreach (XmlNode xnf in xnl) { this.setParameter(xnf.Name, xnf.InnerText); } } /// <summary> /// 是否平台签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 /// </summary> /// <returns></returns> public virtual Boolean isTenpaySign() { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = (string)parameters[k]; if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) { sb.Append(k + "=" + v + "&"); } } sb.Append("key=" + this.getKey()); string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper(); //debug信息 this.setDebugInfo(sb.ToString() + " => sign:" + sign); return getParameter("sign").Equals(sign); } } }
--
xml root 为"xml"。
使用,签名:
RequestHandlerB rb = new RequestHandlerB(); rb.setKey("1111111111111111XXXXXXXXXXXXX"); //设置KEY rb.setParameter("custno", "11111"); rb.setParameter("shopname", "2222"); rb.setParameter("type", "333"); rb.setParameter("serialno", "141111"); rb.createSign(); //签名 string xmlb = rb.parseXML(); // 转XML
验证签名
RequestHandlerB rb2 = new RequestHandlerB(); rb2.setKey("1111111111111111XXXXXXXXXXXXX"); rb2.setContent(xmlb); bool isvalid = rb2.isTenpaySign();
--