| ApiTools.Application/ApiTools.Application.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Application/ChannelWallets/Commands/ChannelWalletCommandHandler.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Core/ApiTools.Core.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Core/Models/ChannelWallets/Commands/TestNongYePayCommand.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Core/Utils/NongYePayUtils/Models/NongYePayBaseRequest.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Core/Utils/NongYePayUtils/Models/NongYePayGetBalanceRequest.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Core/Utils/NongYePayUtils/NongYePayOptions.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Core/Utils/NongYePayUtils/NongYePayUtils.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Core/Utils/StringUtils/StringUtils.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Web.Entry/Startup.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| ApiTools.Web.Entry/appsettings.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
ApiTools.Application/ApiTools.Application.xml
@@ -165,6 +165,14 @@ <param name="cancellationToken"></param> <returns></returns> </member> <member name="M:ApiTools.Application.ChannelWalletCommandHandler.Handle(ApiTools.Core.TestNongYePayCommand,System.Threading.CancellationToken)"> <summary> 测试农业银行接口 </summary> <param name="request"></param> <param name="cancellationToken"></param> <returns></returns> </member> <member name="T:ApiTools.Application.ChannelWalletQueryHandler"> <summary> 查询渠道钱包交易详情 ApiTools.Application/ChannelWallets/Commands/ChannelWalletCommandHandler.cs
@@ -19,15 +19,18 @@ IDistributedLockProvider distributedLockProvider, ChannelWalletRepository channelWalletRepository, ChannelWalletTransactionRepository channelWalletTransactionRepository, ChannelWalletService channelWalletService ChannelWalletService channelWalletService, NongYePayUtils nongYePayUtils ) : IRequestHandler<SaveChannelPingAnPayWalletCommand, SaveChannelPingAnPayWalletCommandResult>, IRequestHandler<SubmitChannelWalletTransferCommand, SubmitChannelWalletTransferCommandResult> IRequestHandler<SubmitChannelWalletTransferCommand, SubmitChannelWalletTransferCommandResult>, IRequestHandler<TestNongYePayCommand, bool> { private readonly IDistributedLockProvider distributedLockProvider = distributedLockProvider; private readonly ChannelWalletRepository channelWalletRepository = channelWalletRepository; private readonly ChannelWalletTransactionRepository channelWalletTransactionRepository = channelWalletTransactionRepository; private readonly ChannelWalletService channelWalletService = channelWalletService; private readonly NongYePayUtils nongYePayUtils = nongYePayUtils; /// <summary> /// 保存渠道平安银行钱包 @@ -171,5 +174,25 @@ FailReason = transaction.FailReason, }; } /// <summary> /// 测试农业银行接口 /// </summary> /// <param name="request"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task<bool> Handle(TestNongYePayCommand request, CancellationToken cancellationToken) { var res = await nongYePayUtils.GetBalance(new Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceRequest { Cmp = new Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceRequestCmp { AccountNo = "314101046433493", CurrencyCode = "01", ProvinceCode = "14" } }); return true; } } } ApiTools.Core/ApiTools.Core.xml
@@ -2473,6 +2473,11 @@ 查询到的订单状态为FAIL失败或REFUND退票时,返回具体的原因。 </summary> </member> <member name="T:ApiTools.Core.TestNongYePayCommand"> <summary> 测试农业银行接口 </summary> </member> <member name="T:ApiTools.Core.GetChannelPingAnPayWalletQuery"> <summary> 查询渠道平安银行钱包 @@ -4937,6 +4942,231 @@ </summary> <returns></returns> </member> <member name="T:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest"> <summary> 农业银行支付基础请求 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.TransCode"> <summary> 交易码 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.CorpNo"> <summary> 客户号 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.OpNo"> <summary> 操作员ID(空节点,ICT自动补充) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.AuthNo"> <summary> 认证码(空节点,ICT自动补充) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.ChannelType"> <summary> 渠道标识 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.ProductID"> <summary> 产品标识 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.ReqDate"> <summary> 请求日期(YYYYMMDD) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.ReqTime"> <summary> 请求时间(HHMMSS) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.ReqSeqNo"> <summary> 请求流水号(全局唯一) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseRequest.Sign"> <summary> 数字签名(空节点,ICT自动补充) </summary> </member> <member name="T:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse"> <summary> 农业银行支付基础回调 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.TransCode"> <summary> 交易码 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.RespSource"> <summary> 返回来源(0=成功) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.RespSeqNo"> <summary> 应答流水号 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.RespCode"> <summary> 返回码(0000=受理成功) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.RespInfo"> <summary> 返回信息 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.RxtInfo"> <summary> 扩展信息 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.RespDate"> <summary> 应答日期 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.RespTime"> <summary> 应答时间 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.FileFlag"> <summary> 文件标识 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.Cmp"> <summary> </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponse.Cme"> <summary> </summary> </member> <member name="T:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponseCme"> <summary> 农业银行支付基础回调 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponseCme.RecordNum"> <summary> 记录数(行) </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponseCme.FieldNum"> <summary> 字段数(列) </summary> </member> <member name="T:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponseCmp"> <summary> 农业银行支付基础回调 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponseCmp.BatFileName"> <summary> 文件名 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayBaseResponseCmp.RespPrvData"> <summary> 私有数据区 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceRequest.Cmp"> <summary> 业务数据 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceRequestCmp.ProvinceCode"> <summary> 省市代码 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceRequestCmp.AccountNo"> <summary> 查询账号 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceRequestCmp.CurrencyCode"> <summary> 货币码 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseCorp.DbAccName"> <summary> 借方户名 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.Bal"> <summary> 账户余额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.AvailBal"> <summary> 账户可用余额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.FrzAmt"> <summary> 冻结金额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.FrzBal"> <summary> 冻结余额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.ValUDLmt"> <summary> 不定期可用限额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.ValMonthLmt"> <summary> 月可用限额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.ValDayLmt"> <summary> 日可用限额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.LastAvailBal"> <summary> 昨日可用余额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.LastBal"> <summary> 昨日余额 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.AccType"> <summary> 账户类型 </summary> </member> <member name="P:ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceResponseAcc.AccSts"> <summary> 账户状态 </summary> </member> <member name="T:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenRequest"> <summary> 微信小程序获取接口调用凭据 @@ -5057,6 +5287,42 @@ </summary> <returns></returns> </member> <member name="P:ApiTools.Core.NongYePayOptions.Ip"> <summary> ICT IP地址 </summary> </member> <member name="P:ApiTools.Core.NongYePayOptions.Port"> <summary> ICP 端口 </summary> </member> <member name="P:ApiTools.Core.NongYePayOptions.CorpNo"> <summary> 客户号 </summary> </member> <member name="M:ApiTools.Core.NongYePayUtils.GetBalance(ApiTools.Core.Utils.NongYePayUtils.Models.NongYePayGetBalanceRequest)"> <summary> 查询账户余额 </summary> <returns>余额信息</returns> </member> <member name="M:ApiTools.Core.NongYePayUtils.SerializeRequest``1(``0)"> <summary> 泛型请求类转XML </summary> </member> <member name="M:ApiTools.Core.NongYePayUtils.DeserializeResponse``1(System.String)"> <summary> XML转泛型应答类 </summary> </member> <member name="M:ApiTools.Core.NongYePayUtils.SendRequest(System.String)"> <summary> 发送请求并接收应答 </summary> </member> <member name="T:ApiTools.Core.PasswordUtils"> <summary> 密码工具 ApiTools.Core/Models/ChannelWallets/Commands/TestNongYePayCommand.cs
New file @@ -0,0 +1,17 @@ using MediatR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ApiTools.Core { /// <summary> /// 测试农业银行接口 /// </summary> [Resource([EnumResourceController.UserServerChannelWallet])] public class TestNongYePayCommand : IRequest<bool> { } } ApiTools.Core/Utils/NongYePayUtils/Models/NongYePayBaseRequest.cs
New file @@ -0,0 +1,180 @@ using Org.BouncyCastle.Ocsp; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Serialization; namespace ApiTools.Core.Utils.NongYePayUtils.Models { /// <summary> /// 农业银行支付基础请求 /// </summary> [XmlRoot("ap")] public abstract class NongYePayBaseRequest { /// <summary> /// 交易码 /// </summary> [XmlElement("CCTransCode")] public string TransCode { get; set; } /// <summary> /// 客户号 /// </summary> [XmlElement("CorpNo")] public string CorpNo { get; set; } /// <summary> /// 操作员ID(空节点,ICT自动补充) /// </summary> [XmlElement("OpNo")] public string OpNo { get; set; } /// <summary> /// 认证码(空节点,ICT自动补充) /// </summary> [XmlElement("AuthNo")] public string AuthNo { get; set; } /// <summary> /// 渠道标识 /// </summary> [XmlElement("ChannelType")] public string ChannelType { get; set; } /// <summary> /// 产品标识 /// </summary> [XmlElement("ProductID")] public string ProductID { get; set; } /// <summary> /// 请求日期(YYYYMMDD) /// </summary> [XmlElement("ReqDate")] public string ReqDate { get; set; } /// <summary> /// 请求时间(HHMMSS) /// </summary> [XmlElement("ReqTime")] public string ReqTime { get; set; } /// <summary> /// 请求流水号(全局唯一) /// </summary> [XmlElement("ReqSeqNo")] public string ReqSeqNo { get; set; } /// <summary> /// 数字签名(空节点,ICT自动补充) /// </summary> [XmlElement("Sign")] public string Sign { get; set; } } /// <summary> /// 农业银行支付基础回调 /// </summary> [XmlRoot("ap")] public abstract class NongYePayBaseResponse { /// <summary> /// 交易码 /// </summary> [XmlElement("CCTransCode")] public string TransCode { get; set; } /// <summary> /// 返回来源(0=成功) /// </summary> [XmlElement("RespSource")] public string RespSource { get; set; } /// <summary> /// 应答流水号 /// </summary> [XmlElement("RespSeqNo")] public string RespSeqNo { get; set; } /// <summary> /// 返回码(0000=受理成功) /// </summary> [XmlElement("RespCode")] public string RespCode { get; set; } /// <summary> /// 返回信息 /// </summary> [XmlElement("RespInfo")] public string RespInfo { get; set; } /// <summary> /// 扩展信息 /// </summary> [XmlElement("RxtInfo")] public string RxtInfo { get; set; } /// <summary> /// 应答日期 /// </summary> [XmlElement("RespDate")] public string RespDate { get; set; } /// <summary> /// 应答时间 /// </summary> [XmlElement("RespTime")] public string RespTime { get; set; } /// <summary> /// 文件标识 /// </summary> [XmlElement("FileFlag")] public string FileFlag { get; set; } /// <summary> /// /// </summary> public NongYePayBaseResponseCmp Cmp { get; set; } /// <summary> /// /// </summary> public NongYePayBaseResponseCme Cme { get; set; } } /// <summary> /// 农业银行支付基础回调 /// </summary> public class NongYePayBaseResponseCme { /// <summary> /// 记录数(行) /// </summary> public string RecordNum { get; set; } /// <summary> /// 字段数(列) /// </summary> public string FieldNum { get; set; } } /// <summary> /// 农业银行支付基础回调 /// </summary> public class NongYePayBaseResponseCmp { /// <summary> /// 文件名 /// </summary> public string BatFileName { get; set; } /// <summary> /// 私有数据区 /// </summary> public string RespPrvData { get; set; } } } ApiTools.Core/Utils/NongYePayUtils/Models/NongYePayGetBalanceRequest.cs
New file @@ -0,0 +1,137 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Serialization; namespace ApiTools.Core.Utils.NongYePayUtils.Models { [XmlRoot("ap")] public class NongYePayGetBalanceRequest : NongYePayBaseRequest { public NongYePayGetBalanceRequest() { TransCode = "CQRA06"; } /// <summary> /// 业务数据 /// </summary> [XmlElement("Cmp")] public NongYePayGetBalanceRequestCmp Cmp { get; set; } } public class NongYePayGetBalanceRequestCmp { /// <summary> /// 省市代码 /// </summary> [XmlElement("DbProv")] public string ProvinceCode { get; set; } /// <summary> /// 查询账号 /// </summary> [XmlElement("DbAccNo")] public string AccountNo { get; set; } /// <summary> /// 货币码 /// </summary> [XmlElement("DbCur")] public string CurrencyCode { get; set; } } [XmlRoot("ap")] public class NongYePayGetBalanceResponse : NongYePayBaseResponse { [XmlElement("Acc")] public NongYePayGetBalanceResponseAcc Acc { get; set; } [XmlElement("Corp")] public NongYePayGetBalanceResponseCorp Corp { get; set; } } public class NongYePayGetBalanceResponseCorp { /// <summary> /// 借方户名 /// </summary> [XmlElement("DbAccName")] public string DbAccName { get; set; } [XmlElement("UseState")] public string UseState { get; set; } } public class NongYePayGetBalanceResponseAcc { /// <summary> /// 账户余额 /// </summary> [XmlElement("Bal")] public string Bal { get; set; } /// <summary> /// 账户可用余额 /// </summary> [XmlElement("AvailBal")] public string AvailBal { get; set; } /// <summary> /// 冻结金额 /// </summary> [XmlElement("FrzAmt")] public string FrzAmt { get; set; } /// <summary> /// 冻结余额 /// </summary> [XmlElement("FrzBal")] public string FrzBal { get; set; } /// <summary> /// 不定期可用限额 /// </summary> [XmlElement("ValUDLmt")] public string ValUDLmt { get; set; } /// <summary> /// 月可用限额 /// </summary> [XmlElement("ValMonthLmt")] public string ValMonthLmt { get; set; } /// <summary> /// 日可用限额 /// </summary> [XmlElement("ValDayLmt")] public string ValDayLmt { get; set; } /// <summary> /// 昨日可用余额 /// </summary> [XmlElement("LastAvailBal")] public string LastAvailBal { get; set; } /// <summary> /// 昨日余额 /// </summary> [XmlElement("LastBal")] public string LastBal { get; set; } /// <summary> /// 账户类型 /// </summary> [XmlElement("AccType")] public string AccType { get; set; } /// <summary> /// 账户状态 /// </summary> [XmlElement("AccSts")] public string AccSts { get; set; } } } ApiTools.Core/Utils/NongYePayUtils/NongYePayOptions.cs
New file @@ -0,0 +1,26 @@ using Furion.ConfigurableOptions; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ApiTools.Core { public class NongYePayOptions : IConfigurableOptions { /// <summary> /// ICT IP地址 /// </summary> public string Ip { get; set; } /// <summary> /// ICP 端口 /// </summary> public int Port { get; set; } /// <summary> /// 客户号 /// </summary> public string CorpNo { get; set; } } } ApiTools.Core/Utils/NongYePayUtils/NongYePayUtils.cs
New file @@ -0,0 +1,181 @@ using Aop.Api.Domain; using ApiTools.Core.Utils.NongYePayUtils.Models; using Furion; using Furion.DatabaseAccessor; using Furion.DependencyInjection; using Furion.DistributedIDGenerator; using Furion.FriendlyException; using Microsoft.Extensions.Options; using NetTopologySuite.Algorithm; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; namespace ApiTools.Core { public class NongYePayUtils( IOptions<NongYePayOptions> options, IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog ) : ITransient { private readonly IOptions<NongYePayOptions> options = options; private readonly IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog = repThreeResourceLog; /// <summary> /// 查询账户余额 /// </summary> /// <returns>余额信息</returns> public Task<NongYePayGetBalanceResponse> GetBalance(NongYePayGetBalanceRequest request) { return Send<NongYePayGetBalanceRequest, NongYePayGetBalanceResponse>(request); } private async Task<TResponse> Send<TRequest, TResponse>(TRequest request) where TRequest : NongYePayBaseRequest where TResponse : NongYePayBaseResponse { var logier = JwtUtils.GetCurrentLogier(); var now = DateTime.Now; var random = StringUtils.GenerateRandomString(6); request.CorpNo = options.Value.CorpNo; request.ReqDate = now.ToString("yyyyMMdd"); request.ReqTime = now.ToString("HHmmss"); request.ReqSeqNo = $"{now:yyyyMMddHHmmssfff}{random}"; request.ChannelType = "ERP"; request.ProductID = "ICC"; string requestXml = SerializeRequest(request); var log = new ThreeResourceLog { CreatedTime = DateTimeOffset.Now, Id = IDGen.NextID(), TraceId = App.GetTraceId(), Method = EnumResourceMethod.Post, Domain = $"{options.Value.Ip}:{options.Value.Port}", Path = request.TransCode, CreatedUserId = logier?.Id, CreatedChannelId = logier?.ChannelId, Request = request.ToJson(), }; await repThreeResourceLog.InsertNowAsync(log); var stopwatch = Stopwatch.StartNew(); var responseXml = await SendRequest(requestXml); stopwatch.Stop(); var response = DeserializeResponse<TResponse>(responseXml); log.UpdatedTime = DateTimeOffset.Now; log.Response = responseXml; log.IsSuccess = response.RespSource == "0"; log.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds; await repThreeResourceLog.UpdateNowAsync(log); if (!log.IsSuccess) throw Oops.Oh(EnumErrorCodeType.s510, $"农行接口异常:{response.RespInfo}"); return response; } /// <summary> /// 泛型请求类转XML /// </summary> private string SerializeRequest<T>(T request) { var serializer = new XmlSerializer(typeof(T)); var ns = new XmlSerializerNamespaces(); ns.Add("", ""); var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = false, Encoding = Encoding.UTF8 }; using var stream = new MemoryStream(); using var writer = XmlWriter.Create(stream, settings); serializer.Serialize(writer, request, ns); // 转换为GBK编码 stream.Position = 0; using var reader = new StreamReader(stream, Encoding.UTF8); string utf8Xml = reader.ReadToEnd(); return Encoding.GetEncoding("GBK").GetString(Encoding.GetEncoding("GBK").GetBytes(utf8Xml)); } /// <summary> /// XML转泛型应答类 /// </summary> private T DeserializeResponse<T>(string gbkXml) { var serializer = new XmlSerializer(typeof(T)); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(gbkXml)); return (T)serializer.Deserialize(stream); } /// <summary> /// 发送请求并接收应答 /// </summary> private async Task<string> SendRequest(string requestXml) { byte[] requestBytes = Encoding.GetEncoding("GBK").GetBytes(requestXml); // 2. 构建7字节包头(加密标志0 + 数据长度,右补空格) byte[] header = new byte[7]; header[0] = 0x30; // 加密标志:0(ASCII码) string requestLengthStr = requestBytes.Length.ToString().PadRight(6, ' '); // 后6字节:长度右补空格 Buffer.BlockCopy(Encoding.ASCII.GetBytes(requestLengthStr), 0, header, 1, 6); // 3. 合并包头+数据包 byte[] sendData = new byte[header.Length + requestBytes.Length]; Buffer.BlockCopy(header, 0, sendData, 0, header.Length); Buffer.BlockCopy(requestBytes, 0, sendData, header.Length, requestBytes.Length); // 4. Socket发送(带超时) using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.SendTimeout = (int)TimeSpan.FromMinutes(5).TotalMilliseconds; socket.ReceiveTimeout = (int)TimeSpan.FromMinutes(5).TotalMilliseconds; try { await socket.ConnectAsync(options.Value.Ip, options.Value.Port); await socket.SendAsync(sendData); // 接收包头 byte[] responseHeader = new byte[7]; int headerLen = socket.Receive(responseHeader); if (headerLen != 7) throw Oops.Oh(EnumErrorCodeType.s510, "接收包头失败"); // 解析数据长度 string lengthStr = Encoding.ASCII.GetString(responseHeader, 1, 6).Trim(); if (!int.TryParse(lengthStr, out int dataLength)) throw Oops.Oh(EnumErrorCodeType.s510, $"解析数据长度失败:{lengthStr}"); // 接收数据包 byte[] responseBytes = new byte[dataLength]; int receivedLen = 0; while (receivedLen < dataLength) { int len = socket.Receive(responseBytes, receivedLen, dataLength - receivedLen, SocketFlags.None); receivedLen += len; } // 转换为GBK XML var responseXml = Encoding.GetEncoding("GBK").GetString(responseBytes); if (responseXml.IsNull()) { throw Oops.Oh(EnumErrorCodeType.s510, "未收到应答"); } return responseXml; } finally { socket.Dispose(); } } } } ApiTools.Core/Utils/StringUtils/StringUtils.cs
@@ -166,5 +166,6 @@ } return result.ToString(); } } } ApiTools.Web.Entry/Startup.cs
@@ -27,7 +27,8 @@ services.AddConfigurableOptions<WxmpOptions>(); services.AddConfigurableOptions<WeChatPayOptions>(); services.AddConfigurableOptions<AlipayOptions>(); services.AddConfigurableOptions<PingAnPayOptions>(); services.AddConfigurableOptions<PingAnPayOptions>(); services.AddConfigurableOptions<NongYePayOptions>(); services.AddConfigurableOptions<ChengLiYeSmsOptions>(); services.AddConfigurableOptions<AliyunOptions>(); services.AddConfigurableOptions<BaiduOptions>(); ApiTools.Web.Entry/appsettings.json
@@ -96,6 +96,11 @@ "PingAnPay": { "MrChCode": "0040107980000NBCS000" }, "NongYePay": { "Ip": "183.242.60.51", "Port": 14028, "CorpNo": "14314153600000025" }, "ChengLiYeSms": { "UserName": "nbcsxx", "Password": "8af9s7",