|
|
@@ -0,0 +1,231 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
+using System.Net;
|
|
|
+using System.Text;
|
|
|
+using Library;
|
|
|
+using LitJson;
|
|
|
+using MySystem.Entity.UnionPay;
|
|
|
+using Org.BouncyCastle.Crypto.Digests;
|
|
|
+using Org.BouncyCastle.Crypto.Macs;
|
|
|
+using Org.BouncyCastle.Crypto.Parameters;
|
|
|
+
|
|
|
+namespace MySystem.Util.UnionPay
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 银联支付基础类
|
|
|
+ /// </summary>
|
|
|
+ public class UnionPayBase
|
|
|
+ {
|
|
|
+ // 测试环境
|
|
|
+ protected string UnionPayRequestUrl = "https://t-uts.lepass.cn";
|
|
|
+ protected string UnionPayAppId = "test_app_id";
|
|
|
+ protected string UnionPayAppSecret = "test_app_secret";
|
|
|
+ protected string UnionPayPublicKey = "";
|
|
|
+
|
|
|
+ // 生产环境
|
|
|
+ // protected string UnionPayRequestUrl = "https://uts.leshuazf.com";
|
|
|
+ // protected string UnionPayAppId = "prod_app_id";
|
|
|
+ // protected string UnionPayAppSecret = "prod_app_secret";
|
|
|
+ // protected string UnionPayPublicKey = "";
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 创建银联请求对象
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="T">业务数据类型</typeparam>
|
|
|
+ /// <param name="agentId">服务商编号</param>
|
|
|
+ /// <param name="currentAgentId">当前代理商编号</param>
|
|
|
+ /// <param name="businessData">业务数据</param>
|
|
|
+ /// <param name="useSM3">是否使用国密验签</param>
|
|
|
+ /// <returns>银联请求对象</returns>
|
|
|
+ protected UnionPayRequest<T> CreateRequest<T>(string agentId, string currentAgentId, T businessData, bool useSM3 = true)
|
|
|
+ {
|
|
|
+ // 创建请求对象
|
|
|
+ var request = new UnionPayRequest<T>
|
|
|
+ {
|
|
|
+ agentId = agentId,
|
|
|
+ currentAgentId = currentAgentId,
|
|
|
+ algorithm = useSM3,
|
|
|
+ data = businessData
|
|
|
+ };
|
|
|
+
|
|
|
+ // 序列化业务数据
|
|
|
+ string dataJson = Newtonsoft.Json.JsonConvert.SerializeObject(businessData);
|
|
|
+
|
|
|
+ // 根据算法生成签名
|
|
|
+ request.sign = GenerateSignatureByAlgorithm(dataJson, useSM3);
|
|
|
+
|
|
|
+ return request;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 根据算法生成签名
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="data">待签名数据</param>
|
|
|
+ /// <param name="useSM3">是否使用国密验签</param>
|
|
|
+ /// <returns>签名字符串</returns>
|
|
|
+ protected string GenerateSignatureByAlgorithm(string data, bool useSM3 = true)
|
|
|
+ {
|
|
|
+ if (useSM3)
|
|
|
+ {
|
|
|
+ // 使用国密SM3算法
|
|
|
+ return SM3Encrypt(UnionPayAppSecret, data);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 使用MD5算法
|
|
|
+ return MD5Encrypt(UnionPayAppSecret, data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 国密验签,推荐使用
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key">密钥</param>
|
|
|
+ /// <param name="srcData">待加密数据</param>
|
|
|
+ /// <returns>加密后的字符串</returns>
|
|
|
+ protected static string SM3Encrypt(string key, string srcData)
|
|
|
+ {
|
|
|
+ LogHelper.Instance.WriteLog("SM3Encrypt,待加密数据:" + srcData, "银联SM3加密", true);
|
|
|
+ byte[] result = Hmac(key, srcData);
|
|
|
+ return Convert.ToBase64String(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// HMAC计算
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key">密钥</param>
|
|
|
+ /// <param name="srcData">源数据</param>
|
|
|
+ /// <returns>计算结果</returns>
|
|
|
+ private static byte[] Hmac(byte[] key, byte[] srcData)
|
|
|
+ {
|
|
|
+ KeyParameter keyParameter = new KeyParameter(key);
|
|
|
+ SM3Digest digest = new SM3Digest();
|
|
|
+ HMac mac = new HMac(digest);
|
|
|
+ mac.Init(keyParameter);
|
|
|
+ mac.BlockUpdate(srcData, 0, srcData.Length);
|
|
|
+ byte[] result = new byte[mac.GetMacSize()];
|
|
|
+ mac.DoFinal(result, 0);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// HMAC计算
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key">密钥</param>
|
|
|
+ /// <param name="srcData">源数据</param>
|
|
|
+ /// <returns>计算结果</returns>
|
|
|
+ private static byte[] Hmac(string key, string srcData)
|
|
|
+ {
|
|
|
+ return Hmac(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(srcData));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// MD5验签
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key">密钥</param>
|
|
|
+ /// <param name="srcData">待加密数据</param>
|
|
|
+ /// <returns>加密后的字符串</returns>
|
|
|
+ protected static string MD5Encrypt(string key, string srcData)
|
|
|
+ {
|
|
|
+ LogHelper.Instance.WriteLog("MD5Encrypt,待加密数据:" + srcData, "银联MD5加密", true);
|
|
|
+ string signStr = key + srcData;
|
|
|
+ using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
|
|
|
+ {
|
|
|
+ byte[] inputBytes = Encoding.UTF8.GetBytes(signStr);
|
|
|
+ byte[] hashBytes = md5.ComputeHash(inputBytes);
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ for (int i = 0; i < hashBytes.Length; i++)
|
|
|
+ {
|
|
|
+ sb.Append(hashBytes[i].ToString("X2"));
|
|
|
+ }
|
|
|
+ return sb.ToString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 发送HTTP POST请求
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="postUrl">请求地址</param>
|
|
|
+ /// <param name="paramData">请求参数</param>
|
|
|
+ /// <param name="headers">请求头</param>
|
|
|
+ /// <returns>响应结果</returns>
|
|
|
+ protected string PostWebRequest(string postUrl, string paramData, Dictionary<string, string> headers)
|
|
|
+ {
|
|
|
+ string ret = string.Empty;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ string logString = "";
|
|
|
+ logString += "\n" + DateTime.Now.ToString();
|
|
|
+ logString += "\n" + postUrl;
|
|
|
+ logString += "\n" + paramData;
|
|
|
+ byte[] postData = System.Text.Encoding.UTF8.GetBytes(paramData);
|
|
|
+
|
|
|
+ System.Net.HttpWebRequest request = System.Net.WebRequest.Create(postUrl) as System.Net.HttpWebRequest;
|
|
|
+ System.Text.Encoding myEncoding = System.Text.Encoding.UTF8;
|
|
|
+ request.Method = "POST";
|
|
|
+ request.KeepAlive = false;
|
|
|
+ request.AllowAutoRedirect = true;
|
|
|
+ request.ContentType = "application/json";
|
|
|
+ foreach (string key in headers.Keys)
|
|
|
+ {
|
|
|
+ if (key != "Content-Type")
|
|
|
+ {
|
|
|
+ request.Headers.Add(key, headers[key]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ request.ContentType = headers[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
|
|
|
+ request.ContentLength = postData.Length;
|
|
|
+
|
|
|
+ using (System.IO.Stream outputStream = request.GetRequestStream())
|
|
|
+ {
|
|
|
+ outputStream.Write(postData, 0, postData.Length);
|
|
|
+ outputStream.Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ using (System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse)
|
|
|
+ {
|
|
|
+ using (System.IO.Stream responseStream = response.GetResponseStream())
|
|
|
+ {
|
|
|
+ using (System.IO.StreamReader reader = new System.IO.StreamReader(responseStream, System.Text.Encoding.UTF8))
|
|
|
+ {
|
|
|
+ ret = reader.ReadToEnd();
|
|
|
+ logString += "\n" + ret;
|
|
|
+ LogHelper.Instance.WriteLog(logString, "请求联合收单API日志", true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (System.Net.WebException ex)
|
|
|
+ {
|
|
|
+ if (ex.Response != null)
|
|
|
+ {
|
|
|
+ using (System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)ex.Response)
|
|
|
+ {
|
|
|
+ using (System.IO.Stream stream = response.GetResponseStream())
|
|
|
+ {
|
|
|
+ using (System.IO.StreamReader reader = new System.IO.StreamReader(stream, System.Text.Encoding.UTF8))
|
|
|
+ {
|
|
|
+ string errorMsg = reader.ReadToEnd();
|
|
|
+ LogHelper.Instance.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString() + "\r\n" + errorMsg, "请求联合收单API异常", true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LogHelper.Instance.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "请求联合收单API异常", true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.Instance.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "请求联合收单API异常", true);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|