using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; namespace libEShangPB { internal class ZJZCGCMemberHelper { #region 接口参数 #region 正式参数 /// /// 商业集团会员接口服务正式地址 /// private const string ApiURL = "https://hy.zcgc.cn/api/open/do"; /// /// 商业集团会员接口正式AppId /// private const string AppId = "AK202211100360169842"; /// /// 商业集团会员接口正式AppSecret /// private const string AppSecret = "f26bfc607657ef286cc09397d0708c66"; #endregion #region 测试参数 ///// ///// 商业集团会员接口服务地址 ///// //private const string ApiURL = "https://ms.cjene.cn/api/open/do"; ///// ///// 商业集团会员接口AppId ///// //private const string AppId = "AK202209070148347162"; ///// ///// 商业集团会员接口AppSecret ///// //private const string AppSecret = "0ae62dc278de2ada91808ac501e81171"; #endregion #endregion #region 方法 -> 浙江商业集团会员券查询接口(根据动态会员码查询) /coupon/getByMemberCode /// /// 浙江商业集团会员券查询接口(根据动态会员码查询) /coupon/getByMemberCode /// /// 动态券码 /// 交易单号 /// 交易金额 /// 交易列表 /// public static ZCGCResultModel> GetByMemberCode(string webServiceUrl, string storeCode, string dynamicCode, string orderCode, decimal orderAmount, string goodsTable) { //交易列表 JArray o_GoodsList = JsonConvert.DeserializeObject(goodsTable); //接口参数内容 object o_Data = new { timestamp = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds,//13位时间戳 dynamicCode = dynamicCode,//待核销券码 storeCode = storeCode,//会员系统店铺编号 orderAmount = orderAmount.ToString(),//交易金额 orderno = orderCode,//订单号 discountAmount = "0",//折扣金额 goodsList = o_GoodsList,//商品列表 extParam = new { }//扩展字段 }; //发送的接口数据 object o_Temp = new { appid = AppId, data = AESEncrypt(JsonConvert.SerializeObject(o_Data), AppSecret, "", true)//AES加密后的数据内容 }; string str_PostData = JsonConvert.SerializeObject(o_Temp); Hashtable hashtable = new Hashtable { { "requestURL", ApiURL+"/coupon/getByMemberCode" }, { "postData", str_PostData }, { "contentType", "application/json" } }; ZCGCResultModel> cm_Result = new ZCGCResultModel> { Success = false }; try { LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}"); LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}"); //调用接口获取交易结果 string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable); cm_Result = JsonConvert.DeserializeObject>>(retString); LogHelper.WriteServiceLog($"浙江商业集团会员可用券接口调用成功。接口返回值:{retString}"); } catch (Exception ex) { LogHelper.WriteServiceLog($"浙江商业集团会员可用券接口调用失败:{ex.Message}"); } return cm_Result; } #endregion #region 方法 -> 浙江商业集团会员券查询接口(根据动态券码查询) /coupon/getByCode /// /// 浙江商业集团会员券查询接口(根据动态券码查询) /coupon/getByCode /// /// 动态券码 /// 交易单号 /// 交易金额 /// 交易列表 /// public static ZCGCResultModel GetByCode(string webServiceUrl, string storeCode, string dynamicCode, string orderCode, decimal orderAmount, string goodsTable) { //交易列表 JArray o_GoodsList = JsonConvert.DeserializeObject(goodsTable); //接口参数内容 object o_Data = new { timestamp = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds,//13位时间戳 dynamicCode = dynamicCode,//待核销券码 storeCode = storeCode,//会员系统店铺编号 orderAmount = orderAmount.ToString(),//交易金额 orderno = orderCode,//订单号 discountAmount = "0",//折扣金额 goodsList = o_GoodsList,//商品列表 extParam = new { }//扩展字段 }; //发送的接口数据 object o_Temp = new { appid = AppId, data = AESEncrypt(JsonConvert.SerializeObject(o_Data), AppSecret, "", true)//AES加密后的数据内容 }; string str_PostData = JsonConvert.SerializeObject(o_Temp); Hashtable hashtable = new Hashtable { { "requestURL", ApiURL+"/coupon/getByCode" }, { "postData", str_PostData }, { "contentType", "application/json" } }; ZCGCResultModel cm_Result = new ZCGCResultModel { Success = false }; try { LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}"); LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}"); //调用接口获取交易结果 string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable); cm_Result = JsonConvert.DeserializeObject>(retString); LogHelper.WriteServiceLog($"浙江商业集团会员券查询接口调用成功。接口返回值:{retString}"); } catch (Exception ex) { LogHelper.WriteServiceLog($"浙江商业集团会员券查询接口调用失败:{ex.Message}"); } return cm_Result; } #endregion #region 方法 -> 浙江商业集团会员券核销接口/coupon/immediateCost /// /// 浙江商业集团会员券核销接口/coupon/immediateCost /// /// 券编码 /// 唯一交易单号 /// 交易金额 /// 商品列表 /// public static ZCGCResultModel ImmediateCost(string webServiceUrl, string storeCode, string couponCode, string orderCode, decimal orderAmount, string goodsTable) { //交易列表 JArray o_GoodsList = JsonConvert.DeserializeObject(goodsTable); //接口参数内容 object o_Data = new { timestamp = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds,//13位时间戳 couponCode = couponCode,//待核销券码 storeCode = storeCode,//会员系统店铺编号 orderAmount = orderAmount.ToString(),//交易金额 orderno = orderCode,//订单号 discountAmount = "0",//折扣金额 goodsList = o_GoodsList,//商品列表 extParam = new { }//扩展字段 }; //发送的接口数据 object o_Temp = new { appid = AppId, data = AESEncrypt(JsonConvert.SerializeObject(o_Data), AppSecret, "", true)//AES加密后的数据内容 }; string str_PostData = JsonConvert.SerializeObject(o_Temp); Hashtable hashtable = new Hashtable { { "requestURL", ApiURL+"/coupon/immediateCost" }, { "postData", str_PostData }, { "contentType", "application/json" } }; ZCGCResultModel cm_Result = new ZCGCResultModel { Success = false }; try { LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}"); LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}"); //调用接口获取交易结果 string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable); cm_Result = JsonConvert.DeserializeObject>(retString); LogHelper.WriteServiceLog($"浙江商业集团会员券核销接口调用成功。接口返回值:{retString}"); } catch (Exception ex) { LogHelper.WriteServiceLog($"浙江商业集团会员券核销接口调用失败:{ex.Message}"); } return cm_Result; } #endregion #region 方法 -> 浙江商业集团会员券撤销接口/coupon/undo /// /// 浙江商业集团会员券撤销接口/coupon/undo /// /// 券编码 /// public static ZCGCResultModel Undo(string webServiceUrl, string couponCode) { //接口参数内容 object o_Data = new { timestamp = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds,//13位时间戳 undoType = 2,//撤销类型,固定值 2:撤销核销 coupon = new string[] { couponCode },//待撤销券码 extParam = new { }//扩展字段 }; //发送的接口数据 object o_Temp = new { appid = AppId, data = AESEncrypt(JsonConvert.SerializeObject(o_Data), AppSecret, "", true)//AES加密后的数据内容 }; string str_PostData = JsonConvert.SerializeObject(o_Temp); Hashtable hashtable = new Hashtable { { "requestURL", ApiURL+"/coupon/undo" }, { "postData", str_PostData }, { "contentType", "application/json" } }; ZCGCResultModel cm_Result = new ZCGCResultModel { Success = false }; try { LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}"); LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}"); //调用接口获取交易结果 string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable); cm_Result = JsonConvert.DeserializeObject>(retString); LogHelper.WriteServiceLog($"浙江商业集团会员券撤销接口调用成功。接口返回值:{retString}"); } catch (Exception ex) { LogHelper.WriteServiceLog($"浙江商业集团会员券撤销接口调用失败:{ex.Message}"); } return cm_Result; } #endregion #region 方法 -> 浙江商业集团会员订单同步接口/thirdOrder/sync /// /// 浙江商业集团会员订单同步接口/thirdOrder/sync /// /// /// 店铺ID /// 会员编码 /// 订单号 /// 交易时间(格式:yyyy-MM-dd HH:mm:ss) /// 订单金额 /// 系统优惠金额 /// 券抵扣金额 /// 付款明细 /// 券使用明细 /// 商品明细 /// public static ZCGCResultModel ThirdOrderSync(string webServiceUrl, string storeCode, string userCode, string orderCode, string orderDate, decimal orderAmount, decimal discountAmount, decimal couponAmount, string payInfo, string couponInfo, string goodsTable) { //交易列表 JArray o_GoodsList = JsonConvert.DeserializeObject(goodsTable); //付款明细列表 JArray o_PayInfo = JsonConvert.DeserializeObject(payInfo); //优惠券信息 JArray o_CouponInfo = JsonConvert.DeserializeObject(couponInfo); //接口参数内容 object o_Data = new { timestamp = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds,//13位时间戳 userCode = userCode,//待核销券码 orderno = orderCode,//订单号 storeCode = storeCode,//会员系统店铺编号 orderPayAmount = (orderAmount - couponAmount).ToString("F2"),//订单实付金额 originalDiscountAmount = discountAmount.ToString("F2"),//系统优惠金额 discountAmount = couponAmount.ToString("F2"),//券抵扣金额 orderTime = orderDate,//交易时间 goodsList = o_GoodsList,//商品列表 payInfo = o_PayInfo,//付款明细 couponInfo = o_CouponInfo,//券明细 extParam = new { }//扩展字段 }; //发送的接口数据 object o_Temp = new { appid = AppId, operation = 0, data = AESEncrypt(JsonConvert.SerializeObject(o_Data), AppSecret, "", true)//AES加密后的数据内容 }; string str_PostData = JsonConvert.SerializeObject(o_Temp); Hashtable hashtable = new Hashtable { { "requestURL", ApiURL+"/thirdOrder/sync" }, { "postData", str_PostData }, { "contentType", "application/json" } }; ZCGCResultModel cm_Result = new ZCGCResultModel { Success = false }; try { LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}"); LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}"); //调用接口获取交易结果 string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable); cm_Result = JsonConvert.DeserializeObject>(retString); LogHelper.WriteServiceLog($"浙江商业集团会员订单同步接口调用成功。接口返回值:{retString}"); } catch (Exception ex) { LogHelper.WriteServiceLog($"浙江商业集团会员订单同步接口调用失败:{ex.Message}"); } return cm_Result; } #endregion #region 方法 -> 浙江商业集团会员信息查询接口/member/info /// /// 浙江商业集团会员信息查询接口/member/info /// /// 动态会员码(与会员手机号必传一个) /// 会员手机号(与会员动态码必传一个) /// public static ZCGCResultModel MemberInfo(string webServiceUrl, string dynamicCode, string phone) { // https://hywx.zcgc.cn/api/open/do/member/info //接口参数内容 object o_Data = null; if (!string.IsNullOrWhiteSpace(dynamicCode)) { //通过动态会员码查询 o_Data = new { timestamp = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds,//13位时间戳 dynamicCode = dynamicCode,//会员动态码 extParam = new { }//扩展字段 }; } else { //通过会员手机号查询 o_Data = new { timestamp = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds,//13位时间戳 phone = phone,//会员手机号 extParam = new { }//扩展字段 }; } //发送的接口数据 object o_Temp = new { appid = AppId, data = AESEncrypt(JsonConvert.SerializeObject(o_Data), AppSecret, "", true)//AES加密后的数据内容 }; string str_PostData = JsonConvert.SerializeObject(o_Temp); Hashtable hashtable = new Hashtable { { "requestURL", ApiURL+"/member/info" }, { "postData", str_PostData }, { "contentType", "application/json" } }; ZCGCResultModel cm_Result = new ZCGCResultModel { Success = false }; try { LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}"); LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}"); //调用接口获取交易结果 string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable); cm_Result = JsonConvert.DeserializeObject>(retString); LogHelper.WriteServiceLog($"浙江商业集团会员信息查询接口调用成功。接口返回值:{retString}"); } catch (Exception ex) { LogHelper.WriteServiceLog($"浙江商业集团会员信息查询接口调用失败:{ex.Message}"); } return cm_Result; } #endregion #region AES加密 /// /// AES加密 /// /// 明文 /// 密钥,长度为16的字符串 /// 偏移量,长度为16的字符串 /// /// True:输出Hex格式密文 /// False:输出Base64格式密文 /// /// 密文 public static string AESEncrypt(string text, string key, string iv = "", bool isHex = false) { if (key.Length > 16) { key = key.Substring(0, 16); } //密码转换Byte数据 byte[] pwdBytes = Encoding.UTF8.GetBytes(key); //使用加密后的密钥对数据进行AES加密 AesManaged rijndaelCipher = new AesManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7, KeySize = 128, BlockSize = 128, Key = pwdBytes }; if (!string.IsNullOrWhiteSpace(iv)) { byte[] ivBytes = Encoding.UTF8.GetBytes(iv); rijndaelCipher.IV = ivBytes;//需要IV的启用这两句 } ICryptoTransform transform = rijndaelCipher.CreateEncryptor(); byte[] plainText = Encoding.UTF8.GetBytes(text); byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length); if (isHex) return ToHex(cipherBytes);//输出为hex即启用此句,注释上一句 else return Convert.ToBase64String(cipherBytes);//输出为Base64即启用此句,注释下一句 } #endregion #region AES解密 /// /// AES解密 /// /// 密文 /// 密钥,长度为16的字符串 /// 偏移量,长度为16的字符串 /// /// True:输入Hex格式密文 /// False:输入Base64格式密文 /// 明文 public static string AESDecrypt(string text, string key, string iv = "", bool isHex = false) { if (key.Length > 16) { key = key.Substring(0, 16); } byte[] pwdBytes = Encoding.UTF8.GetBytes(key); AesManaged rijndaelCipher = new AesManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7, KeySize = 128, BlockSize = 128, Key = pwdBytes }; if (!string.IsNullOrWhiteSpace(iv)) { byte[] ivBytes = Encoding.UTF8.GetBytes(iv); rijndaelCipher.IV = ivBytes;//需要IV的启用这两句 } byte[] encryptedData; if (isHex) encryptedData = UnHex(text);//输出为hex即启用此句,注释上一句 else encryptedData = Convert.FromBase64String(text);//输出为Base64即启用此句,注释下一句 ICryptoTransform transform = rijndaelCipher.CreateDecryptor(); byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length); return Encoding.UTF8.GetString(plainText); } #endregion #region Hex与byte转码 /// /// 从字符串转换到16进制表示的字符串 /// /// 需要转码的byte /// 返回结果 private static string ToHex(byte[] bytes) { string str = string.Empty; if (bytes != null || bytes.Length > 0) { for (int i = 0; i < bytes.Length; i++) { str += string.Format("{0:X2}", bytes[i]); } } return str.ToLower(); } /// /// 从16进制转换成utf编码的字符串 /// /// 需要转码的hex /// public static byte[] UnHex(string hex) { if (hex == null) throw new ArgumentNullException("hex"); hex = hex.Replace(",", ""); hex = hex.Replace("\n", ""); hex = hex.Replace("\\", ""); hex = hex.Replace(" ", ""); if (hex.Length % 2 != 0) { hex += "20";//空格 throw new ArgumentException("hex is not a valid number!", "hex"); } // 需要将 hex 转换成 byte 数组。 byte[] bytes = new byte[hex.Length / 2]; for (int i = 0; i < bytes.Length; i++) { try { // 每两个字符是一个 byte。 bytes[i] = byte.Parse(hex.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); } catch { // Rethrow an exception with custom message. throw new ArgumentException("hex is not a valid hex number!", "hex"); } } return bytes; } #endregion } }