using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using WebService.SDK.PayCommon; namespace WebService.SDK.CCBPay { public class CCBPayAPI { /// /// 建设银行被扫交易接口 /// /// 接口配置 /// 平台商户信息 /// 用户付款授权码 /// 商户交易订单号 /// 交易金额(元) /// public static Model.CCBPayResultModel ScanPay(CCBPayConfig payConfig, MobilePayConfig.PayMerchant merchantInfo, string authCode, string merchantOrderCode, string payAmount) { return ScanPay(payConfig, merchantInfo, authCode, merchantOrderCode, payAmount, null); } /// /// 建设银行被扫交易接口 /// /// 接口配置 /// 平台商户信息 /// 用户付款授权码 /// 商户交易订单号 /// 交易金额(元) /// public static Model.CCBPayResultModel ScanPay(CCBPayConfig payConfig, MobilePayConfig.PayMerchant merchantInfo, string authCode, string merchantOrderCode, string payAmount, List goodsDetails) { if (payConfig == null) { return default(Model.CCBPayResultModel); } if (merchantInfo == null || string.IsNullOrWhiteSpace(merchantInfo.MerchantCode) || string.IsNullOrWhiteSpace(merchantInfo.MerchantKey) || string.IsNullOrWhiteSpace(merchantInfo.MerchantPosCode)) { return default(Model.CCBPayResultModel); } if (!decimal.TryParse(payAmount, out decimal _PayAmount) || _PayAmount <= 0) { return default(Model.CCBPayResultModel); } Dictionary _ApiDictionary = new Dictionary { //{ "MERCHANTID", merchantInfo.MerchantCode },//平台商户号 //{ "POSID", merchantInfo.MerchantPosCode },//柜台号 //{ "BRANCHID", payConfig.Organization },//分行号 //{ "TERMNO1", "" },//终端编号1 //{ "TERMNO2", "" }, //终端编号2 { "MERFLAG", "1" },//商户类型 { "ORDERID", merchantOrderCode },//订单号 { "QRCODE", authCode},//用户付款码 { "AMOUNT", payAmount },//交易金额 { "TXCODE", "PAY100" }//接口名称,固定:PAY100 }; if (goodsDetails != null) { for (int i = 0; i < goodsDetails.Count; i++) { goodsDetails[i].quantity = (int)goodsDetails[i].quantity; goodsDetails[i].price = decimal.Parse(goodsDetails[i].price.ToString("F2")); if (string.IsNullOrWhiteSpace(goodsDetails[i].goods_name)) { goodsDetails[i].goods_name = goodsDetails[i].goods_id; } } _ApiDictionary.Add("goods_detail_ali", JsonConvert.SerializeObject(goodsDetails));//支付宝优惠券商品参数 } LogHelper.WriteReceiveLog("支付反扫-传第三方参数:" + _ApiDictionary.Select(pair => pair.Key + "=" + pair.Value). DefaultIfEmpty("").Aggregate((a, b) => a + "&" + b)); //测试用日志记录 LogHelper.WriteSendLog("支付调用的服务地址" + payConfig.ScanURL); return JsonConvert.DeserializeObject( CommonHelper.HttpUrlPost($"MERCHANTID={merchantInfo.MerchantCode}" + $"&POSID={merchantInfo.MerchantPosCode}&BRANCHID={payConfig.Organization}" + $"&ccbParam={ApiParamSign(_ApiDictionary, merchantInfo.MerchantKey)}", payConfig.ScanURL, "application/x-www-form-urlencoded", payConfig.PlatformTimeout)); } /// /// 建设银行交易查询接口 /// /// 接口配置 /// 平台商户信息 /// 商户交易订单号 /// 平台交易订单号 /// 交易金额 /// 累计查询次数 /// public static Model.CCBPayResultModel QueryPay(CCBPayConfig payConfig, MobilePayConfig.PayMerchant merchantInfo, string merchantOrderCode, string platformOrderCode, string payType, int queryCount) { if (payConfig == null) { return default(Model.CCBPayResultModel); } if (merchantInfo == null || string.IsNullOrWhiteSpace(merchantInfo.MerchantCode) || string.IsNullOrWhiteSpace(merchantInfo.MerchantKey) || string.IsNullOrWhiteSpace(merchantInfo.MerchantPosCode)) { return default(Model.CCBPayResultModel); } int QRCodeType = 2; switch (payType.ToUpper()) { case "WECHAT": QRCodeType = 2; break; case "ALIPAY": QRCodeType = 3; break; case "UNIONPAY": QRCodeType = 4; break; } Dictionary _ApiDictionary = new Dictionary { //{ "MERCHANTID", merchantInfo.MerchantCode },//平台商户号 //{ "POSID", merchantInfo.MerchantPosCode },//柜台号 //{ "BRANCHID", payConfig.Organization },//分行号 //{ "TERMNO1", "" },//终端编号1 //{ "TERMNO2", "" }, //终端编号2 { "MERFLAG", "1" },//商户类型 { "ORDERID", merchantOrderCode },//订单号 { "QRYTIME", queryCount.ToString() },//查询次数 { "QRCODETYPE", QRCodeType.ToString() },//二维码类型 { "TXCODE", "PAY101" } }; LogHelper.WriteReceiveLog("支付查询-传第三方参数:" + _ApiDictionary.Select(pair => pair.Key + "=" + pair.Value). DefaultIfEmpty("").Aggregate((a, b) => a + "&" + b)); return JsonConvert.DeserializeObject( CommonHelper.HttpUrlPost($"MERCHANTID={merchantInfo.MerchantCode}" + $"&POSID={merchantInfo.MerchantPosCode}&BRANCHID={payConfig.Organization}" + $"&ccbParam={ApiParamSign(_ApiDictionary, merchantInfo.MerchantKey)}", payConfig.ScanURL, "application/x-www-form-urlencoded", payConfig.PlatformTimeout)); } /// /// 建设银行交易退款接口 /// /// 接口配置 /// 平台商户信息 /// 平台交易订单号 /// 商户交易订单号 /// 退款订单号 /// 退款金额 /// public static Model.CCBRefundModel RefundPay(CCBPayConfig payConfig, MobilePayConfig.PayMerchant merchantInfo, string platformOrderCode, string merchantOrderCode, string refundOrderCode, string payAmount) { if (payConfig == null) { return default(Model.CCBRefundModel); } if (merchantInfo == null || string.IsNullOrWhiteSpace(merchantInfo.MerchantCode)) { return default(Model.CCBRefundModel); } if (!decimal.TryParse(payAmount, out decimal _PayAmount) || _PayAmount <= 0) { return default(Model.CCBRefundModel); } Dictionary _ApiDictionary = new Dictionary { { "CUST_ID", merchantInfo.MerchantCode },//建设银行平台商户号 { "ORDER", merchantOrderCode },//原商户订单号 { "MONEY", _PayAmount.ToString() } //退款款交易金额 }; string str_Refund = $"{merchantInfo.MerchantCode}&{merchantOrderCode}&{_PayAmount.ToString()}"; _ApiDictionary.Add("fundParams", Encry(str_Refund, "503252CD487D3B0ADA6CD0A42EF28CF8")); LogHelper.WriteReceiveLog("支付退款-传第三方参数:" + _ApiDictionary.Select(pair => pair.Key + "=" + pair.Value). DefaultIfEmpty("").Aggregate((a, b) => a + "&" + b)); //测试用日志记录 LogHelper.WriteSendLog("退款调用的服务地址" + payConfig.PayRefundURL); return JsonConvert.DeserializeObject(CommonHelper.HttpUrlPost( $"fundParams={System.Web.HttpUtility.UrlEncode(Encry(str_Refund, "503252CD487D3B0ADA6CD0A42EF28CF8"))}", payConfig.PayRefundURL, "application/x-www-form-urlencoded", payConfig.PlatformTimeout, Encoding.Default, false)); } /// /// 建设银行支付平台参数签名 /// /// 待签名参数集 /// 签名密钥 /// private static string ApiParamSign(Dictionary signParm, string mchKey) { try { //拼接待签名参数字符串 string parameter = signParm.Select(pair => $"{pair.Key}={pair.Value}"). DefaultIfEmpty("").Aggregate((a, b) => $"{a}&{b}"); return new CCB_B2CPay_Util.CCBPayUtil().makeCCBParam(parameter, mchKey); } catch { return ""; } } /// /// 建设银行参数签名加密 /// /// 待加密字符串 /// 密钥 /// private static string CCBDESEncrypt(string encryptString, string sKey) { byte[] byKey = null; byte[] IV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; try { byKey = Encoding.UTF8.GetBytes(sKey.Substring(0, 8)); DESCryptoServiceProvider des = new DESCryptoServiceProvider(); des.Mode = CipherMode.ECB; byte[] inputByteArray = Encoding.GetEncoding("utf-16be").GetBytes(encryptString); MemoryStream ms = new MemoryStream(); // byte[] bytes = new byte[inputByteArray.Length + 2]; List bytes = new List(); bytes.Add(0xfe); bytes.Add(0xff); bytes.AddRange(inputByteArray.ToList()); CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write); cs.Write(bytes.ToArray(), 0, bytes.Count); cs.FlushFinalBlock(); var resultStr = Convert.ToBase64String(ms.ToArray()); int count = resultStr.Length / 76; count += resultStr.Length % 76 > 0 ? 1 : 0; StringBuilder result = new StringBuilder(); for (int i = 0; i < count; i++) { if (resultStr.Length > (i + 1) * 76) result.Append(resultStr.Substring(i * 76, 76) + Environment.NewLine);//此处不能撤销换行 else result.Append(resultStr.Substring(i * 76, resultStr.Length - i * 76)); } return result.ToString().Replace("+", ","); } catch (Exception ex) { throw ex; } } /// AES加密 /// 明文 /// 密钥,长度为16的字符串 s /// 密文 public static string Encry(string text, string key) { string iv = key; if (key.Length > 16) { // IV为商户MD5密钥后16位 iv = key.Substring(key.Length - 16); // RES的KEY 为商户MD5密钥的前16位 key = key.Substring(0, 16); } return EncodeAES(text, key, iv); } /// AES加密 /// 明文 /// 密钥,长度为16的字符串 /// 偏移量,长度为16的字符串 /// 密文 public static string EncodeAES(string text, string key, string iv) { RijndaelManaged rijndaelCipher = new RijndaelManaged(); rijndaelCipher.Mode = CipherMode.CBC; rijndaelCipher.Padding = PaddingMode.PKCS7; rijndaelCipher.KeySize = 128; rijndaelCipher.BlockSize = 128; byte[] pwdBytes = System.Text.Encoding.UTF8.GetBytes(key); byte[] keyBytes = new byte[16]; int len = pwdBytes.Length; if (len > keyBytes.Length) len = keyBytes.Length; System.Array.Copy(pwdBytes, keyBytes, len); rijndaelCipher.Key = keyBytes; rijndaelCipher.IV = Encoding.UTF8.GetBytes(iv); ICryptoTransform transform = rijndaelCipher.CreateEncryptor(); byte[] plainText = Encoding.UTF8.GetBytes(text); byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length); return Convert.ToBase64String(cipherBytes); } /// AES解密 /// 密文 /// 密钥,长度为16的字符串 /// 偏移量,长度为16的字符串 /// 明文 public static string DecodeAES(string text, string key, string iv) { RijndaelManaged rijndaelCipher = new RijndaelManaged(); rijndaelCipher.Mode = CipherMode.CBC; rijndaelCipher.Padding = PaddingMode.PKCS7; rijndaelCipher.KeySize = 128; rijndaelCipher.BlockSize = 128; byte[] encryptedData = Convert.FromBase64String(text); byte[] pwdBytes = System.Text.Encoding.UTF8.GetBytes(key); byte[] keyBytes = new byte[16]; int len = pwdBytes.Length; if (len > keyBytes.Length) len = keyBytes.Length; System.Array.Copy(pwdBytes, keyBytes, len); rijndaelCipher.Key = keyBytes; rijndaelCipher.IV = Encoding.UTF8.GetBytes(iv); ICryptoTransform transform = rijndaelCipher.CreateDecryptor(); byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length); return Encoding.UTF8.GetString(plainText); } } }