2025-03-28 09:49:56 +08:00

552 lines
25 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
/// <summary>
/// 商业集团会员接口服务正式地址
/// </summary>
private const string ApiURL = "https://hy.zcgc.cn/api/open/do";
/// <summary>
/// 商业集团会员接口正式AppId
/// </summary>
private const string AppId = "AK202211100360169842";
/// <summary>
/// 商业集团会员接口正式AppSecret
/// </summary>
private const string AppSecret = "f26bfc607657ef286cc09397d0708c66";
#endregion
#region
///// <summary>
///// 商业集团会员接口服务地址
///// </summary>
//private const string ApiURL = "https://ms.cjene.cn/api/open/do";
///// <summary>
///// 商业集团会员接口AppId
///// </summary>
//private const string AppId = "AK202209070148347162";
///// <summary>
///// 商业集团会员接口AppSecret
///// </summary>
//private const string AppSecret = "0ae62dc278de2ada91808ac501e81171";
#endregion
#endregion
#region -> /coupon/getByMemberCode
/// <summary>
/// 浙江商业集团会员券查询接口(根据动态会员码查询) /coupon/getByMemberCode
/// </summary>
/// <param name="dynamicCode">动态券码</param>
/// <param name="orderCode">交易单号</param>
/// <param name="orderAmount">交易金额</param>
/// <param name="goodsTable">交易列表</param>
/// <returns></returns>
public static ZCGCResultModel<List<ZCGCCouponModel>> GetByMemberCode(string webServiceUrl, string storeCode, string dynamicCode, string orderCode, decimal orderAmount, string goodsTable)
{
//交易列表
JArray o_GoodsList = JsonConvert.DeserializeObject<JArray>(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<List<ZCGCCouponModel>> cm_Result = new ZCGCResultModel<List<ZCGCCouponModel>> { Success = false };
try
{
LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}");
LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}");
//调用接口获取交易结果
string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable);
cm_Result = JsonConvert.DeserializeObject<ZCGCResultModel<List<ZCGCCouponModel>>>(retString);
LogHelper.WriteServiceLog($"浙江商业集团会员可用券接口调用成功。接口返回值:{retString}");
}
catch (Exception ex)
{
LogHelper.WriteServiceLog($"浙江商业集团会员可用券接口调用失败:{ex.Message}");
}
return cm_Result;
}
#endregion
#region -> /coupon/getByCode
/// <summary>
/// 浙江商业集团会员券查询接口(根据动态券码查询) /coupon/getByCode
/// </summary>
/// <param name="dynamicCode">动态券码</param>
/// <param name="orderCode">交易单号</param>
/// <param name="orderAmount">交易金额</param>
/// <param name="goodsTable">交易列表</param>
/// <returns></returns>
public static ZCGCResultModel<ZCGCCouponModel> GetByCode(string webServiceUrl, string storeCode, string dynamicCode, string orderCode, decimal orderAmount, string goodsTable)
{
//交易列表
JArray o_GoodsList = JsonConvert.DeserializeObject<JArray>(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<ZCGCCouponModel> cm_Result = new ZCGCResultModel<ZCGCCouponModel> { Success = false };
try
{
LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}");
LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}");
//调用接口获取交易结果
string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable);
cm_Result = JsonConvert.DeserializeObject<ZCGCResultModel<ZCGCCouponModel>>(retString);
LogHelper.WriteServiceLog($"浙江商业集团会员券查询接口调用成功。接口返回值:{retString}");
}
catch (Exception ex)
{
LogHelper.WriteServiceLog($"浙江商业集团会员券查询接口调用失败:{ex.Message}");
}
return cm_Result;
}
#endregion
#region -> /coupon/immediateCost
/// <summary>
/// 浙江商业集团会员券核销接口/coupon/immediateCost
/// </summary>
/// <param name="couponCode">券编码</param>
/// <param name="orderCode">唯一交易单号</param>
/// <param name="orderAmount">交易金额</param>
/// <param name="goodsTable">商品列表</param>
/// <returns></returns>
public static ZCGCResultModel<ZCGCCouponModel> ImmediateCost(string webServiceUrl, string storeCode, string couponCode, string orderCode, decimal orderAmount, string goodsTable)
{
//交易列表
JArray o_GoodsList = JsonConvert.DeserializeObject<JArray>(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<ZCGCCouponModel> cm_Result = new ZCGCResultModel<ZCGCCouponModel> { Success = false };
try
{
LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}");
LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}");
//调用接口获取交易结果
string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable);
cm_Result = JsonConvert.DeserializeObject<ZCGCResultModel<ZCGCCouponModel>>(retString);
LogHelper.WriteServiceLog($"浙江商业集团会员券核销接口调用成功。接口返回值:{retString}");
}
catch (Exception ex)
{
LogHelper.WriteServiceLog($"浙江商业集团会员券核销接口调用失败:{ex.Message}");
}
return cm_Result;
}
#endregion
#region -> /coupon/undo
/// <summary>
/// 浙江商业集团会员券撤销接口/coupon/undo
/// </summary>
/// <param name="couponCode">券编码</param>
/// <returns></returns>
public static ZCGCResultModel<string> 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<string> cm_Result = new ZCGCResultModel<string> { Success = false };
try
{
LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}");
LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}");
//调用接口获取交易结果
string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable);
cm_Result = JsonConvert.DeserializeObject<ZCGCResultModel<string>>(retString);
LogHelper.WriteServiceLog($"浙江商业集团会员券撤销接口调用成功。接口返回值:{retString}");
}
catch (Exception ex)
{
LogHelper.WriteServiceLog($"浙江商业集团会员券撤销接口调用失败:{ex.Message}");
}
return cm_Result;
}
#endregion
#region -> /thirdOrder/sync
/// <summary>
/// 浙江商业集团会员订单同步接口/thirdOrder/sync
/// </summary>
/// <param name="webServiceUrl"></param>
/// <param name="storeCode">店铺ID</param>
/// <param name="userCode">会员编码</param>
/// <param name="orderCode">订单号</param>
/// <param name="orderDate">交易时间格式yyyy-MM-dd HH:mm:ss</param>
/// <param name="orderAmount">订单金额</param>
/// <param name="discountAmount">系统优惠金额</param>
/// <param name="couponAmount">券抵扣金额</param>
/// <param name="payInfo">付款明细</param>
/// <param name="couponInfo">券使用明细</param>
/// <param name="goodsTable">商品明细</param>
/// <returns></returns>
public static ZCGCResultModel<string> 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<JArray>(goodsTable);
//付款明细列表
JArray o_PayInfo = JsonConvert.DeserializeObject<JArray>(payInfo);
//优惠券信息
JArray o_CouponInfo = JsonConvert.DeserializeObject<JArray>(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<string> cm_Result = new ZCGCResultModel<string>
{
Success = false
};
try
{
LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}");
LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}");
//调用接口获取交易结果
string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable);
cm_Result = JsonConvert.DeserializeObject<ZCGCResultModel<string>>(retString);
LogHelper.WriteServiceLog($"浙江商业集团会员订单同步接口调用成功。接口返回值:{retString}");
}
catch (Exception ex)
{
LogHelper.WriteServiceLog($"浙江商业集团会员订单同步接口调用失败:{ex.Message}");
}
return cm_Result;
}
#endregion
#region -> /member/info
/// <summary>
/// 浙江商业集团会员信息查询接口/member/info
/// </summary>
/// <param name="dynamicCode">动态会员码(与会员手机号必传一个)</param>
/// <param name="phone">会员手机号(与会员动态码必传一个)</param>
/// <returns></returns>
public static ZCGCResultModel<ZCGCMemberInfoModel> 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<ZCGCMemberInfoModel> cm_Result = new ZCGCResultModel<ZCGCMemberInfoModel> { Success = false };
try
{
LogHelper.WriteServiceLog($"待发送的明文数据:{JsonConvert.SerializeObject(o_Data)}");
LogHelper.WriteServiceLog($"发送的加密报文:{str_PostData}");
//调用接口获取交易结果
string retString = SoapWSHelper.QuerySoapWebServiceString(webServiceUrl, "MobilePayProxy", hashtable);
cm_Result = JsonConvert.DeserializeObject<ZCGCResultModel<ZCGCMemberInfoModel>>(retString);
LogHelper.WriteServiceLog($"浙江商业集团会员信息查询接口调用成功。接口返回值:{retString}");
}
catch (Exception ex)
{
LogHelper.WriteServiceLog($"浙江商业集团会员信息查询接口调用失败:{ex.Message}");
}
return cm_Result;
}
#endregion
#region AES加密
/// <summary>
/// AES加密
/// </summary>
/// <param name="text">明文</param>
/// <param name="key">密钥,长度为16的字符串</param>
/// <param name="iv">偏移量,长度为16的字符串</param>
/// <param name="isHex">
/// <para>True输出Hex格式密文</para>
/// <para>False输出Base64格式密文</para>
/// </param>
/// <returns>密文</returns>
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解密
/// <summary>
/// AES解密
/// </summary>
/// <param name="text">密文</param>
/// <param name="key">密钥,长度为16的字符串</param>
/// <param name="iv">偏移量,长度为16的字符串</param>
/// <param name="isHex">
/// <para>True输入Hex格式密文</para>
/// <para>False输入Base64格式密文</para></param>
/// <returns>明文</returns>
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转码
/// <summary>
/// 从字符串转换到16进制表示的字符串
/// </summary>
/// <param name="bytes">需要转码的byte</param>
/// <returns>返回结果</returns>
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();
}
/// <summary>
/// 从16进制转换成utf编码的字符串
/// </summary>
/// <param name="hex">需要转码的hex</param>
/// <returns></returns>
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
}
}