From a6e5a2e630a4a1dcfd9def94c20bde6bec89f96f Mon Sep 17 00:00:00 2001
From: sunpengfei <i@angelzzz.com>
Date: 星期二, 30 九月 2025 16:01:25 +0800
Subject: [PATCH] 添加项目文件。
---
ApiTools.Core/Utils/AlipayUtils/AlipayUtils.cs | 293
ApiTools.Core/Utils/DbUtils/SaveDataCommand.cs | 20
ApiTools.Core/DbContextLocators/LogDbContextLocator.cs | 16
ApiTools.Core/Utils/LogUtils/LogServiceComponent.cs | 34
ApiTools.Core/Utils/SmsUtils/Models/SendSmsModel.cs | 39
ApiTools.Database.Migrations/Migrations/DefaultDbContextModelSnapshot.cs | 656 +
ApiTools.Core/Entities/SmsUtils/SmsLog.cs | 85
ApiTools.Core/Models/Auths/Commands/UpdatePhoneNumberVerifyCodeCommand.cs | 24
ApiTools.Core/Utils/PasswordUtils/PasswordUtils.cs | 47
ApiTools.Core/Entities/SmsUtils/SmsSetting.cs | 60
ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityBackResult.cs | 78
ApiTools.Core/Utils/ResourceUtils/ResourceServiceAttribute.cs | 100
ApiTools.Core/Utils/StringUtils/StringUtils.cs | 170
ApiTools.Core/Utils/WxmpUtils/WxmpGetAccessTokenRequest.cs | 50
ApiTools.Application/ApiTools.Application.xml | 228
ApiTools.Core/Enums/Resources/EnumResourceController.cs | 61
ApiTools.Core/Utils/WxmpUtils/WxmpUtils.cs | 128
ApiTools.Core/Entities/Resource.cs | 145
ApiTools.Application/Auths/Commands/VerifyCodeCommandHandler.cs | 54
ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsSubmitRequest.cs | 99
ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResultProvider.cs | 170
ApiTools.Core/Entities/LogRecords/ExceptionLog.cs | 37
ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayEcommerceFundBalance.cs | 69
ApiTools.Core/Enums/EnumUserErrorCodeType.cs | 46
ApiTools.sln | 49
ApiTools.Core/Utils/AliyunUtils/AliyunOSSUtils.cs | 144
ApiTools.Web.Entry/appsettings.json | 153
ApiTools.Core/Utils/BaiduUtils/OcrResult.cs | 26
ApiTools.Core/Utils/SmsUtils/Services/ISmsService.cs | 24
ApiTools.Core/Enums/Users/EnumUserType.cs | 23
ApiTools.Core/Enums/Users/EnumUserStatus.cs | 23
ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityFrontResult.cs | 100
ApiTools.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs | 57
ApiTools.Core/Models/SmsUtils/Commands/SmsAliyunNotifyCommand.cs | 82
ApiTools.Database.Migrations/Migrations/20250930032645_Init.cs | 255
ApiTools.Core/Entities/LogRecords/ConsoleLog.cs | 57
ApiTools.Core/Entities/LogRecords/DbAuditLog.cs | 42
ApiTools.Core/Utils/AliyunUtils/AliyunOSSUploadResult.cs | 24
ApiTools.Core/Enums/EnumPagedListOrder.cs | 23
ApiTools.Core/Models/SmsUtils/Queries/GetSmsLogsQuery.cs | 162
ApiTools.Application/SmsUtils/Queries/GetSmsSettingQueryHandler.cs | 88
ApiTools.Core/Models/SmsUtils/Commands/SaveSmsSettingCommand.cs | 72
ApiTools.Core/Models/SmsUtils/Queries/GetSmsSettingQuery.cs | 80
ApiTools.Core/Enums/Users/EnumUserGender.cs | 23
ApiTools.Core/settings.json | 54
ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayPartnerTransferBatches.cs | 171
ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountStopPaymentDetailsRequest.cs | 88
ApiTools.Core/Utils/DateTimeUtils/DateTimeRange.cs | 23
ApiTools.Core/Utils/DbUtils/DeleteDataCommand.cs | 24
ApiTools.Core/Models/Auths/Commands/SmsLoginCommand.cs | 37
ApiTools.Core/Enums/LogRecords/EnumConsoleLogAccess.cs | 23
ApiTools.Core/Utils/ExcelUtils/ExcelUtils.cs | 100
ApiTools.Core/Utils/PingAnPayUtils/Models/SingleOrBatchReceiptPDFMergeDownloadNewRequest.cs | 98
ApiTools.Core/Models/ChannelUsers/Commands/SaveChannelUserCommand.cs | 54
ApiTools.Core/Models/SmsUtils/Commands/SendSmsCommand.cs | 44
ApiTools.Core/Utils/JwtUtils/JwtUtils.cs | 141
ApiTools.Core/Utils/WeChatPayUtils/WeChatPayOptions.cs | 35
ApiTools.Core/Entities/LogRecords/QueueLog.cs | 43
ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.cs | 229
ApiTools.Application/SmsUtils/Commands/SaveSmsSettingCommandHandler.cs | 56
ApiTools.Core/Utils/CollectionUtils/CollectionUtils.cs | 73
ApiTools.Core/Utils/ResourceUtils/ResourceHttpUtils.cs | 174
ApiTools.Core/Utils/SmsUtils/Models/SendVerifyCodeModel.cs | 28
ApiTools.Core/Entities/ScheduleJobs/ScheduleJobTrigger.cs | 129
ApiTools.Core/Enums/SmsUtils/EnumSmsTemplateCode.cs | 40
ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.Designer.cs | 659 +
ApiTools.Core/Utils/JsonUtils/JsonUtils.cs | 32
ApiTools.Core/Enums/EnumErrorCodeType.cs | 59
ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountDayHistoryTransactionDetailsRequest.cs | 386
ApiTools.EntityFramework.Core/Startup.cs | 18
ApiTools.Core/Utils/SmsUtils/Models/CheckVerifyCodeModel.cs | 30
ApiTools.Core/Models/Channels/Commands/SaveChannelCommand.cs | 30
ApiTools.Web.Entry/Startup.cs | 134
ApiTools.Core/Utils/AlipayUtils/AlipayOptions.cs | 25
ApiTools.Core/Models/SmsUtils/Commands/SmsChengLiYeNotifyCommand.cs | 76
ApiTools.Core/Models/Auths/Queries/GetAliyunOSSAcsQuery.cs | 30
ApiTools.Core/Utils/SmsUtils/Models/SmsResponse.cs | 31
ApiTools.Core/Entities/CommonEntity.cs | 72
ApiTools.Core/Entities/LogRecords/ResourceLog.cs | 75
ApiTools.EntityFramework.Core/ApiTools.EntityFramework.Core.csproj | 12
ApiTools.Core/Entities/LogRecords/ThreeResourceLog.cs | 74
ApiTools.Core/Utils/BaiduUtils/BaiduOcrUtils.cs | 157
ApiTools.Application/Channels/Commands/ChannelCommandHandler.cs | 30
ApiTools.Core/Enums/SmsUtils/EnumSmsStatus.cs | 31
ApiTools.Core/Utils/EventBusUtils/EventBusServiceComponent.cs | 43
ApiTools.Core/Utils/BaiduUtils/BaiduOcrBusinessLicenseResult.cs | 90
ApiTools.Core/Utils/JwtUtils/CurrentLogier.cs | 66
ApiTools.Core/Enums/EnumValidationTypes.cs | 37
ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.cs | 168
ApiTools.Web.Entry/Program.cs | 1
ApiTools.Core/Models/Channels/Queries/GetChannelsQuery.cs | 50
ApiTools.Application/ChannelUsers/Commands/ChannelUserCommandHandler.cs | 56
ApiTools.Core/Entities/Users/User.cs | 100
ApiTools.Core/Utils/PingAnPayUtils/Models/StopPaymentAndSettlementAccountsRequest.cs | 89
ApiTools.Core/Entities/Users/Channel.cs | 30
ApiTools.Core/Utils/EnumUtils/EnumUtils.cs | 115
ApiTools.Core/Utils/WxmpUtils/WxmpSnsJscode2sessionResponse.cs | 17
ApiTools.Core/Enums/Resources/EnumResourceMethod.cs | 35
ApiTools.Core/Utils/EnumUtils/EnumModel.cs | 72
ApiTools.Core/Utils/ConsoleLogUtils/DatabaseLoggingWriter.cs | 64
ApiTools.Core/Utils/SmsUtils/Services/ChengLiYeSmsService.cs | 76
ApiTools.Core/Utils/PingAnPayUtils/Models/SameDayHistoryReceiptDataQueryRequest.cs | 231
ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.cs | 29
ApiTools.Core/Interfaces/IPhysicalDeletion.cs | 15
ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/IResourceHttpProvider.cs | 31
ApiTools.Core/Enums/Resources/EnumResourceService.cs | 41
ApiTools.Core/Utils/ConsulUtils/ConsulApplicationComponent.cs | 62
ApiTools.Core/Utils/ExceptionLogUtils/LogExceptionHandler.cs | 53
ApiTools.Core/Utils/WeChatPayUtils/WeChatPayUtils.cs | 274
ApiTools.Core/Utils/XmlDocUtils/XmlDocUtils.cs | 193
ApiTools.Core/Models/Auths/Commands/ChangePhoneNumberCommand.cs | 29
ApiTools.Core/Utils/ResourceUtils/ResourceModel.cs | 136
ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/DefaultResourceHttpProvider.cs | 83
ApiTools.Core/Utils/XmlDocUtils/XmlDoc.cs | 52
ApiTools.Core/Utils/BaiduUtils/BaiduOcrResultWord.cs | 57
ApiTools.Core/Utils/EventBusUtils/RabbitMQEventSourceStorer.cs | 139
ApiTools.Core/Utils/SmsUtils/Services/AliyunSmsService.cs | 140
ApiTools.Database.Migrations/ApiTools.Database.Migrations.csproj | 12
ApiTools.Core/Models/Auths/Commands/SendLoginOrRegisterVerifyCodeCommand.cs | 24
ApiTools.Core/Utils/DbUtils/SelectQuery.cs | 40
ApiTools.Core/Interfaces/IDbAuditLogIgnore.cs | 12
ApiTools.Core/Utils/ResourceUtils/ResourceActionFilter.cs | 90
ApiTools.Core/Utils/PingAnPayUtils/Models/SingleDataQueryRequest.cs | 487 +
ApiTools.Core/Utils/PingAnPayUtils/PingAnPayUtils.cs | 233
ApiTools.Core/Utils/WxmpUtils/WxmpOptions.cs | 45
ApiTools.Application/Auths/Queries/GetAliyunOSSAcsQueryHandler.cs | 27
ApiTools.Core/Utils/BaiduUtils/BaiduOptions.cs | 36
ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsOptions.cs | 37
ApiTools.Web.Entry/Properties/launchSettings.json | 31
ApiTools.Core/Utils/AliyunUtils/AliyunOptions.cs | 65
ApiTools.Core/Utils/PingAnPayUtils/Models/SingleApplicationSuspensionPaymentRequest.cs | 241
ApiTools.Core/Utils/PingAnPayUtils/PingAnPayOptions.cs | 17
ApiTools.Core/Utils/ScheduleUtils/DbJobPersistence.cs | 121
ApiTools.Core/Enums/Users/EnumClientType.cs | 31
ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayRequest.cs | 44
ApiTools.Core/Utils/DateTimeUtils/DateTimeUtils.cs | 241
ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.Designer.cs | 452 +
ApiTools.Web.Entry/appsettings.Development.json | 10
ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseRequest.cs | 44
ApiTools.Core/Utils/ResourceUtils/CustomResponseAttribute.cs | 15
ApiTools.Core/Utils/ResourceUtils/ResourceUtils.cs | 358
ApiTools.Core/Utils/DbUtils/PagedListQuery.cs | 119
ApiTools.Core/Utils/ConsoleLogUtils/ConsoleLogUtils.cs | 13
ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseResponse.cs | 26
ApiTools.Core/Enums/LogRecords/EnumDbAuditOperate.cs | 27
ApiTools.Core/Utils/PingAnPayUtils/Models/CorAcctBalanceQueryRequest.cs | 172
ApiTools.Core/ApiTools.Core.csproj | 40
ApiTools.Core/Utils/ResourceUtils/BuildDynamicControllersHostedService.cs | 23
ApiTools.Application/Auths/Commands/LoginCommandHandler.cs | 108
ApiTools.Core/Enums/SmsUtils/EnumSmsAccess.cs | 27
ApiTools.Core/Utils/DistributedCacheUtils/DistributedCacheServiceComponent.cs | 23
ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/SystemUserResourceHttpProvider.cs | 89
ApiTools.Core/Utils/SmsUtils/SmsUtils.cs | 305
ApiTools.Core/Enums/LogRecords/EnumLogLevel.cs | 39
ApiTools.Application/SmsUtils/Commands/SendSmsCommandHandler.cs | 53
ApiTools.Core/Entities/LogRecords/ScheduleJobTriggerTimeline.cs | 67
ApiTools.Core/Enums/EnumQueueAccess.cs | 19
ApiTools.Core/Utils/DbUtils/DbUtils.cs | 611 +
ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs | 109
ApiTools.EntityFramework.Core/DbContexts/DefaultDbContext.cs | 40
ApiTools.Core/Entities/ScheduleJobs/ScheduleJobDetail.cs | 56
ApiTools.Core/Utils/XmlDocUtils/XmlDocBuildHostedService.cs | 23
ApiTools.Core/Models/ChannelUsers/Queries/GetChannelUsersQuery.cs | 74
ApiTools.Core/Utils/JwtUtils/JwtHandler.cs | 88
ApiTools.Core/Entities/SmsUtils/SmsSettingAccess.cs | 46
ApiTools.Core/Interfaces/IIsDisabled.cs | 19
ApiTools.Core/Utils/PingAnPayUtils/Models/HistoryBalanceQueryRequest.cs | 131
ApiTools.Core/Utils/JsonUtils/JsonSerializerProvider.cs | 63
ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResult.cs | 93
ApiTools.Core/Utils/DbUtils/SetIsDisabledCommand.cs | 27
ApiTools.Application/ApiTools.Application.csproj | 19
ApiTools.Core/Utils/SwaggerUtils/EnumSchemaFilter.cs | 29
ApiTools.Database.Migrations/REDEME.MD | 21
ApiTools.Application/ChannelUsers/Queries/GetChannelUsersQueryHandler.cs | 33
ApiTools.Application/Channels/Queries/ChannelQueryHandler.cs | 37
ApiTools.Core/Utils/JsonUtils/EmptyStringToNullConverter.cs | 28
ApiTools.Database.Migrations/Migrations/LogDb/LogDbContextModelSnapshot.cs | 449 +
ApiTools.Core/Interfaces/ITreeData.cs | 42
ApiTools.Core/Utils/ConsulUtils/ConsulServiceComponent.cs | 23
ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.Designer.cs | 656 +
ApiTools.EntityFramework.Core/DbContexts/LogDbContext.cs | 42
ApiTools.Application/SmsUtils/Commands/SmsChengLiYeNotifyCommandHandler.cs | 92
ApiTools.Core/Models/Auths/Commands/PasswordLoginCommand.cs | 70
ApiTools.Core/ApiTools.Core.xml | 6554 +++++++++++++++
ApiTools.Application/SmsUtils/Commands/SmsAliyunNotifyCommandHandler.cs | 88
ApiTools.Web.Entry/ApiTools.Web.Entry.csproj | 30
ApiTools.Core/Utils/PingAnPayUtils/Models/CorSingleTransferQueryRequest.cs | 225
ApiTools.Core/Models/SmsUtils/Commands/CheckVerifyCodeSmsCommand.cs | 31
ApiTools.Database.Migrations/Migrations/20250930032645_Init.Designer.cs | 515 +
189 files changed, 24,742 insertions(+), 0 deletions(-)
diff --git a/ApiTools.Application/ApiTools.Application.csproj b/ApiTools.Application/ApiTools.Application.csproj
new file mode 100644
index 0000000..4c7484c
--- /dev/null
+++ b/ApiTools.Application/ApiTools.Application.csproj
@@ -0,0 +1,19 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+
+ <PropertyGroup>
+ <TargetFramework>net9.0</TargetFramework>
+ <NoWarn>1701;1702;1591</NoWarn>
+ <DocumentationFile>ApiTools.Application.xml</DocumentationFile>
+ <ImplicitUsings>enable</ImplicitUsings>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <None Remove="ApiTools.Application.xml" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\ApiTools.Core\ApiTools.Core.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/ApiTools.Application/ApiTools.Application.xml b/ApiTools.Application/ApiTools.Application.xml
new file mode 100644
index 0000000..f18a0cb
--- /dev/null
+++ b/ApiTools.Application/ApiTools.Application.xml
@@ -0,0 +1,228 @@
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>ApiTools.Application</name>
+ </assembly>
+ <members>
+ <member name="T:ApiTools.UserServer.Application.LoginCommandHandler">
+ <summary>
+ 鐧诲綍鍛戒护澶勭悊鍣�
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.LoginCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.User},ApiTools.Core.SmsUtils)">
+ <summary>
+ 鐧诲綍鍛戒护澶勭悊鍣�
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.LoginCommandHandler.Handle(ApiTools.Core.PasswordLoginCommand,System.Threading.CancellationToken)">
+ <summary>
+ 瀵嗙爜鐧诲綍
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.LoginCommandHandler.Handle(ApiTools.Core.SmsLoginCommand,System.Threading.CancellationToken)">
+ <summary>
+ 鐭俊鐧诲綍
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.LoginCommandHandler.Handle(ApiTools.Core.ChangePhoneNumberCommand,System.Threading.CancellationToken)">
+ <summary>
+ 鏇存崲鎵嬫満鍙�
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.UserServer.Application.VerifyCodeCommandHandler">
+ <summary>
+ 楠岃瘉鐮佸懡浠ゅ鐞嗗櫒
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.VerifyCodeCommandHandler.#ctor(ApiTools.Core.SmsUtils)">
+ <summary>
+ 楠岃瘉鐮佸懡浠ゅ鐞嗗櫒
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.VerifyCodeCommandHandler.Handle(ApiTools.Core.SendLoginOrRegisterVerifyCodeCommand,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�佺櫥褰曟垨娉ㄥ唽鐭俊
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.VerifyCodeCommandHandler.Handle(ApiTools.Core.UpdatePhoneNumberVerifyCodeCommand,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�佹洿鎹㈡墜鏈哄彿鐭俊
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.UserServer.Application.GetAliyunOSSAcsQueryHandler">
+ <summary>
+ 鑾峰彇闃块噷浜慜SS鎺堟潈淇℃伅
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.GetAliyunOSSAcsQueryHandler.Handle(ApiTools.Core.GetAliyunOSSAcsQuery,System.Threading.CancellationToken)">
+ <inheritdoc/>
+ </member>
+ <member name="T:ApiTools.UserServer.Application.ChannelCommandHandler">
+ <summary>
+ 淇濆瓨娓犻亾
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.ChannelCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.Channel})">
+ <summary>
+ 淇濆瓨娓犻亾
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.ChannelCommandHandler.Handle(ApiTools.Core.SaveChannelCommand,System.Threading.CancellationToken)">
+ <summary>
+ 淇濆瓨娓犻亾
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.UserServer.Application.ChannelQueryHandler">
+ <summary>
+ 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.ChannelQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.Channel})">
+ <summary>
+ 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.ChannelQueryHandler.Handle(ApiTools.Core.GetChannelsQuery,System.Threading.CancellationToken)">
+ <summary>
+ 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.UserServer.Application.ChannelUserCommandHandler">
+ <summary>
+ 淇濆瓨娓犻亾鐢ㄦ埛
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.ChannelUserCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.User})">
+ <summary>
+ 淇濆瓨娓犻亾鐢ㄦ埛
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.ChannelUserCommandHandler.Handle(ApiTools.Core.SaveChannelUserCommand,System.Threading.CancellationToken)">
+ <summary>
+ 淇濆瓨娓犻亾鐢ㄦ埛
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.UserServer.Application.GetChannelUsersQueryHandler">
+ <summary>
+ 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="M:ApiTools.UserServer.Application.GetChannelUsersQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.User})">
+ <summary>
+ 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="T:ApiTools.CommonServer.Application.SaveSmsSettingCommandHandler">
+ <summary>
+ 淇濆瓨鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.SaveSmsSettingCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.SmsSetting})">
+ <summary>
+ 淇濆瓨鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.SaveSmsSettingCommandHandler.Handle(ApiTools.Core.SaveSmsSettingCommand,System.Threading.CancellationToken)">
+ <summary>
+ 淇濆瓨鐭俊閰嶇疆
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.CommonServer.Application.SmsAliyunNotifyCommandHandler">
+ <summary>
+ 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.SmsAliyunNotifyCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.SmsSetting},Furion.DatabaseAccessor.IRepository{ApiTools.Core.SmsLog},ApiTools.Core.SmsUtils)">
+ <summary>
+ 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.SmsAliyunNotifyCommandHandler.Handle(ApiTools.Core.SmsAliyunNotifyCommand,System.Threading.CancellationToken)">
+ <summary>
+ 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.CommonServer.Application.SmsChengLiYeNotifyCommandHandler">
+ <summary>
+ 璇氱珛涓氱煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.SmsChengLiYeNotifyCommandHandler.#ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor,Furion.DatabaseAccessor.IRepository{ApiTools.Core.SmsSetting},Furion.DatabaseAccessor.IRepository{ApiTools.Core.SmsLog},ApiTools.Core.SmsUtils)">
+ <summary>
+ 璇氱珛涓氱煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.SmsChengLiYeNotifyCommandHandler.Handle(ApiTools.Core.SmsChengLiYeNotifyCommand,System.Threading.CancellationToken)">
+ <summary>
+ 璇氱珛涓氱煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.CommonServer.Application.GetSmsSettingQueryHandler">
+ <summary>
+ 鏌ヨ鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.GetSmsSettingQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{ApiTools.Core.SmsSetting},Furion.DatabaseAccessor.IRepository{ApiTools.Core.SmsLog})">
+ <summary>
+ 鏌ヨ鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="M:ApiTools.CommonServer.Application.GetSmsSettingQueryHandler.Handle(ApiTools.Core.GetSmsSettingQuery,System.Threading.CancellationToken)">
+ <summary>
+ 鏌ヨ鐭俊閰嶇疆
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Application.SendSmsCommandHandler.Handle(ApiTools.Core.SendSmsCommand,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�佺煭淇�
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Application.SendSmsCommandHandler.Handle(ApiTools.Core.CheckVerifyCodeSmsCommand,System.Threading.CancellationToken)">
+ <summary>
+ 鏍¢獙楠岃瘉鐮�
+ </summary>
+ <param name="request"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ </members>
+</doc>
diff --git a/ApiTools.Application/Auths/Commands/LoginCommandHandler.cs b/ApiTools.Application/Auths/Commands/LoginCommandHandler.cs
new file mode 100644
index 0000000..73a6124
--- /dev/null
+++ b/ApiTools.Application/Auths/Commands/LoginCommandHandler.cs
@@ -0,0 +1,108 @@
+锘縰sing Azure.Core;
+using ApiTools.Core;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.FriendlyException;
+using Mapster;
+using MediatR;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.UserServer.Application
+{
+ /// <summary>
+ /// 鐧诲綍鍛戒护澶勭悊鍣�
+ /// </summary>
+ public class LoginCommandHandler(
+ IRepository<User> rep,
+ SmsUtils smsUtils) :
+ IRequestHandler<PasswordLoginCommand, LoginCommandCallback>,
+ IRequestHandler<SmsLoginCommand, LoginCommandCallback>,
+ IRequestHandler<ChangePhoneNumberCommand, bool>
+ {
+ private readonly IRepository<User> rep = rep;
+ private readonly SmsUtils smsUtils = smsUtils;
+
+ /// <summary>
+ /// 瀵嗙爜鐧诲綍
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<LoginCommandCallback> Handle(PasswordLoginCommand request, CancellationToken cancellationToken)
+ {
+ var user = await rep.AsQueryable().AsNoTracking()
+ .Where(it => it.UserName == request.UserName && it.Type == request.Type)
+ .FirstOrDefaultAsync(cancellationToken);
+ var supplierPassword = App.GetConfig<string>("SupplierPassword");
+ if (user == null || !request.Password.CheckPassword(user.Password))
+ throw Oops.Oh(EnumUserErrorCodeType.u1000);
+ if (user.Status == EnumUserStatus.Disabled)
+ throw Oops.Oh(EnumUserErrorCodeType.u1001);
+ return user.GetCurrentLogier(request.ClientType);
+ }
+
+ /// <summary>
+ /// 鐭俊鐧诲綍
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<LoginCommandCallback> Handle(SmsLoginCommand request, CancellationToken cancellationToken)
+ {
+ await smsUtils.CheckVerifyCode(new CheckVerifyCodeModel
+ {
+ PhoneNumber = request.PhoneNumber,
+ VerifyCode = request.VerifyCode,
+ TemplateCode = EnumSmsTemplateCode.LoginOrRegister
+ });
+ var user = await rep.AsQueryable().AsNoTracking()
+ .Where(it => it.UserName == request.PhoneNumber && it.Type == request.Type)
+ .FirstOrDefaultAsync(cancellationToken);
+ if (user == null)
+ throw Oops.Oh(EnumUserErrorCodeType.u1000);
+ if (user.Status == EnumUserStatus.Disabled)
+ throw Oops.Oh(EnumUserErrorCodeType.u1001);
+ return user.GetCurrentLogier(request.ClientType);
+ }
+
+ /// <summary>
+ /// 鏇存崲鎵嬫満鍙�
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<bool> Handle(ChangePhoneNumberCommand request, CancellationToken cancellationToken)
+ {
+ await smsUtils.CheckVerifyCode(new CheckVerifyCodeModel
+ {
+ PhoneNumber = request.PhoneNumber,
+ VerifyCode = request.VerifyCode,
+ TemplateCode = EnumSmsTemplateCode.UpdateUserPhoneNumber
+ });
+ var logier = JwtUtils.GetCurrentLogier();
+ var user = await rep.AsQueryable()
+ .FirstOrDefaultAsync(it => it.Id == logier.Id);
+ if (user == null)
+ throw Oops.Oh(EnumErrorCodeType.s404, "褰撳墠璐﹀彿涓嶅瓨鍦�");
+
+ var exist = await rep.AsQueryable()
+ .Where(it => it.Type == logier.Type && it.PhoneNumber == request.PhoneNumber && it.Id != user.Id)
+ .AnyAsync(cancellationToken);
+ if (exist) throw Oops.Oh(EnumUserErrorCodeType.u1010);
+
+ user.UserName = request.PhoneNumber;
+ user.PhoneNumber = request.PhoneNumber;
+ user.IsCheckPhoneNumber = true;
+ return true;
+ }
+ }
+}
diff --git a/ApiTools.Application/Auths/Commands/VerifyCodeCommandHandler.cs b/ApiTools.Application/Auths/Commands/VerifyCodeCommandHandler.cs
new file mode 100644
index 0000000..b9a0853
--- /dev/null
+++ b/ApiTools.Application/Auths/Commands/VerifyCodeCommandHandler.cs
@@ -0,0 +1,54 @@
+锘縰sing ApiTools.Core;
+using Furion.DatabaseAccessor;
+using Mapster;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.UserServer.Application
+{
+ /// <summary>
+ /// 楠岃瘉鐮佸懡浠ゅ鐞嗗櫒
+ /// </summary>
+ public class VerifyCodeCommandHandler(
+ SmsUtils smsUtils
+ ) :
+ IRequestHandler<SendLoginOrRegisterVerifyCodeCommand, Guid>,
+ IRequestHandler<UpdatePhoneNumberVerifyCodeCommand, Guid>
+ {
+ private readonly SmsUtils smsUtils = smsUtils;
+
+ /// <summary>
+ /// 鍙戦�佺櫥褰曟垨娉ㄥ唽鐭俊
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public Task<Guid> Handle(SendLoginOrRegisterVerifyCodeCommand request, CancellationToken cancellationToken)
+ {
+ return smsUtils.SendVerifyCode(new SendVerifyCodeModel
+ {
+ PhoneNumber = request.PhoneNumber,
+ TemplateCode = EnumSmsTemplateCode.LoginOrRegister
+ });
+ }
+
+ /// <summary>
+ /// 鍙戦�佹洿鎹㈡墜鏈哄彿鐭俊
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public Task<Guid> Handle(UpdatePhoneNumberVerifyCodeCommand request, CancellationToken cancellationToken)
+ {
+ return smsUtils.SendVerifyCode(new SendVerifyCodeModel
+ {
+ PhoneNumber = request.PhoneNumber,
+ TemplateCode = EnumSmsTemplateCode.UpdateUserPhoneNumber
+ });
+ }
+ }
+}
diff --git a/ApiTools.Application/Auths/Queries/GetAliyunOSSAcsQueryHandler.cs b/ApiTools.Application/Auths/Queries/GetAliyunOSSAcsQueryHandler.cs
new file mode 100644
index 0000000..b77cc87
--- /dev/null
+++ b/ApiTools.Application/Auths/Queries/GetAliyunOSSAcsQueryHandler.cs
@@ -0,0 +1,27 @@
+锘縰sing Aliyun.Acs.Core;
+using Aliyun.Acs.Core.Auth.Sts;
+using Aliyun.Acs.Core.Http;
+using Aliyun.Acs.Core.Profile;
+using ApiTools.Core;
+using Furion;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.UserServer.Application
+{
+ /// <summary>
+ /// 鑾峰彇闃块噷浜慜SS鎺堟潈淇℃伅
+ /// </summary>
+ public class GetAliyunOSSAcsQueryHandler : IRequestHandler<GetAliyunOSSAcsQuery, GetAliyunOSSAcsQueryResult>
+ {
+ /// <inheritdoc/>
+ public Task<GetAliyunOSSAcsQueryResult> Handle(GetAliyunOSSAcsQuery request, CancellationToken cancellationToken)
+ {
+ return Task.FromResult(AliyunOSSUtils.GetOSSAcs());
+ }
+ }
+}
diff --git a/ApiTools.Application/ChannelUsers/Commands/ChannelUserCommandHandler.cs b/ApiTools.Application/ChannelUsers/Commands/ChannelUserCommandHandler.cs
new file mode 100644
index 0000000..b944704
--- /dev/null
+++ b/ApiTools.Application/ChannelUsers/Commands/ChannelUserCommandHandler.cs
@@ -0,0 +1,56 @@
+锘縰sing ApiTools.Core;
+using Furion.DatabaseAccessor;
+using Mapster;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.UserServer.Application
+{
+ /// <summary>
+ /// 淇濆瓨娓犻亾鐢ㄦ埛
+ /// </summary>
+ public class ChannelUserCommandHandler(
+ IRepository<User> rep
+ ) :
+ IRequestHandler<SaveChannelUserCommand, Guid>
+ {
+ private readonly IRepository<User> rep = rep;
+
+ /// <summary>
+ /// 淇濆瓨娓犻亾鐢ㄦ埛
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<Guid> Handle(SaveChannelUserCommand request, CancellationToken cancellationToken)
+ {
+ var entity = await request.SaveData<User, SaveChannelUserCommand>(
+ q =>
+ {
+ return rep.AsQueryable()
+ .Where(it =>
+ it.Type == EnumUserType.Channel
+ && it.ChannelId == request.ChannelId);
+ },
+ it =>
+ it.Type == EnumUserType.Channel
+ && it.ChannelId == request.ChannelId
+ && it.UserName == request.UserName
+ && it.Id != request.Id,
+ entity =>
+ {
+ if (request.Id == null)
+ {
+ entity.Type = EnumUserType.Channel;
+ }
+ request.Adapt(entity);
+ });
+ return entity.Id;
+ }
+ }
+}
diff --git a/ApiTools.Application/ChannelUsers/Queries/GetChannelUsersQueryHandler.cs b/ApiTools.Application/ChannelUsers/Queries/GetChannelUsersQueryHandler.cs
new file mode 100644
index 0000000..39acd37
--- /dev/null
+++ b/ApiTools.Application/ChannelUsers/Queries/GetChannelUsersQueryHandler.cs
@@ -0,0 +1,33 @@
+锘縰sing ApiTools.Core;
+using Furion.DatabaseAccessor;
+using Mapster;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.UserServer.Application
+{
+ /// <summary>
+ /// 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ public class GetChannelUsersQueryHandler(
+ IRepository<User> rep
+ ) :
+ IRequestHandler<GetChannelUsersQuery, GetChannelUsersQueryResult>
+ {
+ private readonly IRepository<User> rep = rep;
+
+ public Task<GetChannelUsersQueryResult> Handle(GetChannelUsersQuery request, CancellationToken cancellationToken)
+ {
+ var q = rep.AsQueryable().AsNoTracking()
+ .Where(it => it.Type == EnumUserType.Channel)
+ .ProjectToType<GetChannelUsersQueryResultItem>();
+ return request.PageModel.GetPagedListAsync<GetChannelUsersQueryResult, GetChannelUsersQueryResultItem>(q, cancellationToken);
+ }
+ }
+}
diff --git a/ApiTools.Application/Channels/Commands/ChannelCommandHandler.cs b/ApiTools.Application/Channels/Commands/ChannelCommandHandler.cs
new file mode 100644
index 0000000..1300543
--- /dev/null
+++ b/ApiTools.Application/Channels/Commands/ChannelCommandHandler.cs
@@ -0,0 +1,30 @@
+锘縰sing ApiTools.Core;
+using Furion.DatabaseAccessor;
+using MediatR;
+
+namespace ApiTools.UserServer.Application
+{
+ /// <summary>
+ /// 淇濆瓨娓犻亾
+ /// </summary>
+ [Resource([EnumResourceController.UserServerChannel])]
+ public class ChannelCommandHandler(
+ IRepository<Channel> rep
+ ) :
+ IRequestHandler<SaveChannelCommand, Guid>
+ {
+ private readonly IRepository<Channel> rep = rep;
+
+ /// <summary>
+ /// 淇濆瓨娓犻亾
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<Guid> Handle(SaveChannelCommand request, CancellationToken cancellationToken)
+ {
+ var entity = await request.SaveData<Channel, SaveChannelCommand>();
+ return entity.Id;
+ }
+ }
+}
diff --git a/ApiTools.Application/Channels/Queries/ChannelQueryHandler.cs b/ApiTools.Application/Channels/Queries/ChannelQueryHandler.cs
new file mode 100644
index 0000000..18e187b
--- /dev/null
+++ b/ApiTools.Application/Channels/Queries/ChannelQueryHandler.cs
@@ -0,0 +1,37 @@
+锘縰sing ApiTools.Core;
+using Furion.DatabaseAccessor;
+using Mapster;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.UserServer.Application
+{
+ /// <summary>
+ /// 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ public class ChannelQueryHandler(
+ IRepository<Channel> rep
+ ) :
+ IRequestHandler<GetChannelsQuery, GetChannelsQueryResult>
+ {
+ private readonly IRepository<Channel> rep = rep;
+
+ /// <summary>
+ /// 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public Task<GetChannelsQueryResult> Handle(GetChannelsQuery request, CancellationToken cancellationToken)
+ {
+ var q = rep.AsQueryable().AsNoTracking()
+ .ProjectToType<GetChannelsQueryResultItem>();
+ return request.PageModel.GetPagedListAsync<GetChannelsQueryResult, GetChannelsQueryResultItem>(q, cancellationToken);
+ }
+ }
+}
diff --git a/ApiTools.Application/SmsUtils/Commands/SaveSmsSettingCommandHandler.cs b/ApiTools.Application/SmsUtils/Commands/SaveSmsSettingCommandHandler.cs
new file mode 100644
index 0000000..8bc6a9e
--- /dev/null
+++ b/ApiTools.Application/SmsUtils/Commands/SaveSmsSettingCommandHandler.cs
@@ -0,0 +1,56 @@
+锘縰sing ApiTools.Core;
+using Furion.DatabaseAccessor;
+using Mapster;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.CommonServer.Application
+{
+ /// <summary>
+ /// 淇濆瓨鐭俊閰嶇疆
+ /// </summary>
+ public class SaveSmsSettingCommandHandler(
+ IRepository<SmsSetting> rep
+ ) :
+ IRequestHandler<SaveSmsSettingCommand, Guid>
+ {
+ private readonly IRepository<SmsSetting> rep = rep;
+
+ /// <summary>
+ /// 淇濆瓨鐭俊閰嶇疆
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<Guid> Handle(SaveSmsSettingCommand request, CancellationToken cancellationToken)
+ {
+ var logier = JwtUtils.GetCurrentLogier();
+ var entity = await rep.AsQueryable()
+ .Include(it => it.Accesses)
+ .Where(it => it.ChannelId == logier.ChannelId)
+ .FirstOrDefaultAsync();
+ var add = false;
+ if (entity == null)
+ {
+ entity = new SmsSetting();
+ entity.ChannelId = logier.ChannelId;
+ add = true;
+ }
+ request.Adapt(entity);
+ if (add)
+ {
+ await rep.InsertAsync(entity);
+ }
+ else
+ {
+ await rep.UpdateAsync(entity);
+ }
+ return entity.Id;
+ }
+ }
+}
diff --git a/ApiTools.Application/SmsUtils/Commands/SendSmsCommandHandler.cs b/ApiTools.Application/SmsUtils/Commands/SendSmsCommandHandler.cs
new file mode 100644
index 0000000..5e84ea7
--- /dev/null
+++ b/ApiTools.Application/SmsUtils/Commands/SendSmsCommandHandler.cs
@@ -0,0 +1,53 @@
+锘縰sing ApiTools.Core;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Application
+{
+ public class SendSmsCommandHandler(
+ SmsUtils utils
+ ) :
+ IRequestHandler<SendSmsCommand, Guid>,
+ IRequestHandler<CheckVerifyCodeSmsCommand, bool>
+ {
+ private readonly SmsUtils utils = utils;
+
+ /// <summary>
+ /// 鍙戦�佺煭淇�
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<Guid> Handle(SendSmsCommand request, CancellationToken cancellationToken)
+ {
+ return await utils.Send(new SendSmsModel
+ {
+ PhoneNumber = request.PhoneNumber,
+ TemplateCode = request.TemplateCode,
+ Expiry = request.Expiry,
+ ChannelCreatedUserId = request.ChannelCreatedUserId
+ }, request.TemplateParam, cancellationToken);
+ }
+
+ /// <summary>
+ /// 鏍¢獙楠岃瘉鐮�
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<bool> Handle(CheckVerifyCodeSmsCommand request, CancellationToken cancellationToken)
+ {
+ await utils.CheckVerifyCode(new CheckVerifyCodeModel
+ {
+ PhoneNumber = request.PhoneNumber,
+ TemplateCode = request.TemplateCode,
+ VerifyCode = request.VerifyCode,
+ }, cancellationToken);
+ return true;
+ }
+ }
+}
diff --git a/ApiTools.Application/SmsUtils/Commands/SmsAliyunNotifyCommandHandler.cs b/ApiTools.Application/SmsUtils/Commands/SmsAliyunNotifyCommandHandler.cs
new file mode 100644
index 0000000..ab7383e
--- /dev/null
+++ b/ApiTools.Application/SmsUtils/Commands/SmsAliyunNotifyCommandHandler.cs
@@ -0,0 +1,88 @@
+锘縰sing ApiTools.Core;
+using Furion.DatabaseAccessor;
+using MediatR;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.CommonServer.Application
+{
+ /// <summary>
+ /// 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ /// </summary>
+ public class SmsAliyunNotifyCommandHandler(
+ IRepository<SmsSetting> repSmsSetting,
+ IRepository<SmsLog> repSmsLog,
+ ApiTools.Core.SmsUtils smsUtils
+ )
+ : IRequestHandler<SmsAliyunNotifyCommand, SmsAliyunNotifyCommandResult>
+ {
+ private readonly IRepository<SmsSetting> repSmsSetting = repSmsSetting;
+ private readonly IRepository<SmsLog> repSmsLog = repSmsLog;
+ private readonly Core.SmsUtils smsUtils = smsUtils;
+
+ /// <summary>
+ /// 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<SmsAliyunNotifyCommandResult> Handle(SmsAliyunNotifyCommand request, CancellationToken cancellationToken)
+ {
+ var templateCodes = await EnumUtils.GetModel<EnumSmsTemplateCode>();
+ var msgIds = request.DistinctSelect(it => it.BizId.ToString());
+ var entities = await repSmsLog.AsQueryable()
+ .Where(it =>
+ it.Access == EnumSmsAccess.AliyunSms
+ && msgIds.Contains(it.RequestId)
+ && it.Status == EnumSmsStatus.InProcess)
+ .ToListAsync();
+ var channelIds = entities.DistinctSelect(it => it.ChannelId.HasValue, it => it.ChannelId.Value);
+ var settings = await repSmsSetting.AsQueryable().AsNoTracking()
+ .Include(it => it.Accesses)
+ .Where(it => it.ChannelId.HasValue && channelIds.Contains(it.ChannelId.Value))
+ .ToListAsync();
+ foreach (var entity in entities)
+ {
+ var report = request.FirstOrDefault(it => it.BizId.ToString() == entity.RequestId);
+ if (report != null)
+ {
+ entity.Status = report.Success
+ ? EnumSmsStatus.Success
+ : EnumSmsStatus.Fail;
+ entity.Code = report.ErrCode;
+ entity.Message = report.ErrMsg;
+ await repSmsLog.UpdateNowAsync(entity);
+
+ if (entity.Status == EnumSmsStatus.Fail)
+ {
+ var templateCode = templateCodes.Items.FirstOrDefault(it => it.Name == entity.TemplateCode)?.Enum;
+ if (templateCode.HasValue)
+ {
+ var templateParam = entity.TemplateParam.IsNotNull()
+ ? JObject.Parse(entity.TemplateParam)
+ : null;
+ var setting = settings.FirstOrDefault(it => it.ChannelId == entity.ChannelId);
+ await smsUtils.Send(setting, entity, new SendSmsModel
+ {
+ PhoneNumber = entity.PhoneNumber,
+ TemplateCode = templateCode.Value,
+ Expiry = entity.Expiry,
+ }, templateParam, cancellationToken);
+ }
+ }
+ }
+ }
+ return new SmsAliyunNotifyCommandResult
+ {
+ Code = 0,
+ Msg = " 鎴愬姛"
+ };
+ }
+ }
+}
diff --git a/ApiTools.Application/SmsUtils/Commands/SmsChengLiYeNotifyCommandHandler.cs b/ApiTools.Application/SmsUtils/Commands/SmsChengLiYeNotifyCommandHandler.cs
new file mode 100644
index 0000000..ccb1e2f
--- /dev/null
+++ b/ApiTools.Application/SmsUtils/Commands/SmsChengLiYeNotifyCommandHandler.cs
@@ -0,0 +1,92 @@
+锘縰sing Baidu.Aip.BodyAnalysis;
+using ApiTools.Core;
+using Furion.DatabaseAccessor;
+using Furion.HttpRemote;
+using MediatR;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.CommonServer.Application
+{
+ /// <summary>
+ /// 璇氱珛涓氱煭淇″钩鍙板洖浼犻�氱煡
+ /// </summary>
+ public class SmsChengLiYeNotifyCommandHandler(
+ IHttpContextAccessor httpContextAccessor,
+ IRepository<SmsSetting> repSmsSetting,
+ IRepository<SmsLog> repSmsLog,
+ ApiTools.Core.SmsUtils smsUtils
+ ) :
+ IRequestHandler<SmsChengLiYeNotifyCommand, bool>
+ {
+ private readonly IHttpContextAccessor httpContextAccessor = httpContextAccessor;
+ private readonly IRepository<SmsSetting> repSmsSetting = repSmsSetting;
+ private readonly IRepository<SmsLog> repSmsLog = repSmsLog;
+ private readonly ApiTools.Core.SmsUtils smsUtils = smsUtils;
+
+ /// <summary>
+ /// 璇氱珛涓氱煭淇″钩鍙板洖浼犻�氱煡
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<bool> Handle(SmsChengLiYeNotifyCommand request, CancellationToken cancellationToken)
+ {
+ if (request.MsgReports.IsNotNull())
+ {
+ var templateCodes = await EnumUtils.GetModel<EnumSmsTemplateCode>();
+ var msgIds = request.MsgReports.DistinctSelect(it => it.Msgid.ToString());
+ var entities = await repSmsLog.AsQueryable()
+ .Where(it =>
+ it.Access == EnumSmsAccess.ChengLiYe
+ && msgIds.Contains(it.RequestId)
+ && it.Status == EnumSmsStatus.InProcess)
+ .ToListAsync();
+ var channelIds = entities.DistinctSelect(it => it.ChannelId.HasValue, it => it.ChannelId.Value);
+ var settings = await repSmsSetting.AsQueryable().AsNoTracking()
+ .Include(it => it.Accesses)
+ .Where(it => it.ChannelId.HasValue && channelIds.Contains(it.ChannelId.Value))
+ .ToListAsync();
+ foreach (var entity in entities)
+ {
+ var report = request.MsgReports.FirstOrDefault(it => it.Msgid.ToString() == entity.RequestId);
+ if (report != null)
+ {
+ entity.Status = report.Status == "DELIVRD"
+ ? EnumSmsStatus.Success
+ : EnumSmsStatus.Fail;
+ entity.Code = report.Status;
+ entity.Message = report.StatusDes;
+ await repSmsLog.UpdateNowAsync(entity);
+
+ if (entity.Status == EnumSmsStatus.Fail)
+ {
+ var templateCode = templateCodes.Items.FirstOrDefault(it => it.Name == entity.TemplateCode)?.Enum;
+ if (templateCode.HasValue)
+ {
+ var templateParam = entity.TemplateParam.IsNotNull()
+ ? JObject.Parse(entity.TemplateParam)
+ : null;
+ var setting = settings.FirstOrDefault(it => it.ChannelId == entity.ChannelId);
+ await smsUtils.Send(setting, entity, new SendSmsModel
+ {
+ PhoneNumber = entity.PhoneNumber,
+ TemplateCode = templateCode.Value,
+ Expiry = entity.Expiry,
+ }, templateParam, cancellationToken);
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/ApiTools.Application/SmsUtils/Queries/GetSmsSettingQueryHandler.cs b/ApiTools.Application/SmsUtils/Queries/GetSmsSettingQueryHandler.cs
new file mode 100644
index 0000000..38d1646
--- /dev/null
+++ b/ApiTools.Application/SmsUtils/Queries/GetSmsSettingQueryHandler.cs
@@ -0,0 +1,88 @@
+锘縰sing Aop.Api.Domain;
+using ApiTools.Core;
+using Furion.DatabaseAccessor;
+using Mapster;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.CommonServer.Application
+{
+ /// <summary>
+ /// 鏌ヨ鐭俊閰嶇疆
+ /// </summary>
+ public class GetSmsSettingQueryHandler(
+ IRepository<SmsSetting> rep,
+ IRepository<SmsLog> repSmsLog
+ ) :
+ IRequestHandler<GetSmsSettingQuery, GetSmsSettingQueryResult>,
+ IRequestHandler<GetSmsLogsQuery, GetSmsLogsQueryResult>
+ {
+ private readonly IRepository<SmsSetting> rep = rep;
+ private readonly IRepository<SmsLog> repSmsLog = repSmsLog;
+
+ /// <summary>
+ /// 鏌ヨ鐭俊閰嶇疆
+ /// </summary>
+ /// <param name="request"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<GetSmsSettingQueryResult> Handle(GetSmsSettingQuery request, CancellationToken cancellationToken)
+ {
+ var logier = JwtUtils.GetCurrentLogier();
+ var detail = await rep.AsQueryable().AsNoTracking()
+ .Where(it => it.ChannelId == logier.ChannelId)
+ .GetDetail<SmsSetting, GetSmsSettingQueryResult>();
+ detail.Accesses = detail.Accesses.OrderBy(it => it.Sort).ToList();
+ return detail;
+ }
+
+ public async Task<GetSmsLogsQueryResult> Handle(GetSmsLogsQuery request, CancellationToken cancellationToken)
+ {
+ var q = repSmsLog.AsQueryable().AsNoTracking();
+ if (request.CreatedTimeBegin.HasValue && request.CreatedTimeEnd.HasValue)
+ {
+ q = q.Where(it => request.CreatedTimeBegin <= it.CreatedTime && it.CreatedTime <= request.CreatedTimeEnd);
+ }
+ if (request.ChannelCreatedUserIds.IsNotNull())
+ {
+ q = q.Where(it => it.ChannelCreatedUserId.HasValue && request.ChannelCreatedUserIds.Contains(it.ChannelCreatedUserId.Value));
+ }
+ if (request.TraceId.IsNotNull())
+ {
+ q = q.Where(it => it.TraceId == request.TraceId);
+ }
+ if (request.Access.HasValue)
+ {
+ q = q.Where(it => it.Access == request.Access);
+ }
+ if (request.PhoneNumber.IsNotNull())
+ {
+ q = q.Where(it => it.PhoneNumber == request.PhoneNumber);
+ }
+ if (request.TemplateCode.IsNotNull())
+ {
+ q = q.Where(it => it.TemplateCode == request.TemplateCode);
+ }
+ if (request.TemplateParam.IsNotNull())
+ {
+ q = q.Where(it => it.TemplateParam.Contains(request.TemplateParam));
+ }
+ if (request.IsUsed.HasValue)
+ {
+ q = q.Where(it => it.IsUsed == request.IsUsed);
+ }
+ if (request.Status.HasValue)
+ {
+ q = q.Where(it => it.Status == request.Status);
+ }
+ var s = q.ProjectToType<GetSmsLogsQueryResultItem>();
+ var list = await request.PageModel.GetPagedListAsync<GetSmsLogsQueryResult, GetSmsLogsQueryResultItem>(s, cancellationToken);
+ return list;
+ }
+ }
+}
diff --git a/ApiTools.Core/ApiTools.Core.csproj b/ApiTools.Core/ApiTools.Core.csproj
new file mode 100644
index 0000000..90d13b5
--- /dev/null
+++ b/ApiTools.Core/ApiTools.Core.csproj
@@ -0,0 +1,40 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+
+ <PropertyGroup>
+ <TargetFramework>net9.0</TargetFramework>
+ <NoWarn>1701;1702;1591</NoWarn>
+ <DocumentationFile>ApiTools.Core.xml</DocumentationFile>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <None Remove="ApiTools.Core.xml" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="4.0.1" />
+ <PackageReference Include="AlipayEasySDK" Version="2.1.3" />
+ <PackageReference Include="AlipaySDKNet.Standard" Version="4.9.751" />
+ <PackageReference Include="aliyun-net-sdk-core" Version="1.5.6" />
+ <PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
+ <PackageReference Include="Baidu.AI" Version="4.15.16" />
+ <PackageReference Include="Consul" Version="1.7.14.8" />
+ <PackageReference Include="EFCore.BulkExtensions" Version="9.0.1" />
+ <PackageReference Include="Furion" Version="4.9.7.106" />
+ <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.106" />
+ <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.106" />
+ <PackageReference Include="MediatR" Version="13.0.0" />
+ <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.7" />
+ <PackageReference Include="MiniExcel" Version="1.41.3" />
+ <PackageReference Include="RabbitMQ.Client" Version="6.8.1" />
+ <PackageReference Include="sdk-dotnet" Version="2.4.0" />
+ <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="9.0.3" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <None Update="settings.json">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+
+</Project>
diff --git a/ApiTools.Core/ApiTools.Core.xml b/ApiTools.Core/ApiTools.Core.xml
new file mode 100644
index 0000000..6adf6cf
--- /dev/null
+++ b/ApiTools.Core/ApiTools.Core.xml
@@ -0,0 +1,6554 @@
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>ApiTools.Core</name>
+ </assembly>
+ <members>
+ <member name="T:ApiTools.Core.LogDbContextLocator">
+ <summary>
+ 鏃ュ織鏁版嵁搴撳畾浣嶅櫒
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.Id">
+ <summary>
+ 涓婚敭Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.Sort">
+ <summary>
+ 鎺掑簭
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.TraceId">
+ <summary>
+ 璺熻釜Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.CreatedTime">
+ <summary>
+ 鍒涘缓鏃堕棿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.CreatedUserId">
+ <summary>
+ 鍒涘缓鎿嶄綔浜�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.CreatedChannelId">
+ <summary>
+ 鍒涘缓娓犻亾Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.UpdatedTime">
+ <summary>
+ 鏈�鍚庢洿鏂版椂闂�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.UpdatedUserId">
+ <summary>
+ 鏈�鍚庢洿鏂版搷浣滀汉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CommonEntity.IsDeleted">
+ <summary>
+ 鏄惁鍒犻櫎
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ConsoleLog">
+ <summary>
+ 鎺у埗鍙版棩蹇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.Level">
+ <summary>
+ 绾у埆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.Content">
+ <summary>
+ 鍐呭
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.StackTrace">
+ <summary>
+ 鍫嗘爤璺熻釜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.Url">
+ <summary>
+ 閾炬帴鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.Request">
+ <summary>
+ 浼犲弬
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.Ext">
+ <summary>
+ 鎵╁睍
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ConsoleLog.ClientIpAddress">
+ <summary>
+ 瀹㈡埛IP鍦板潃
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.DbAuditLog">
+ <summary>
+ 鏁版嵁搴撳璁℃棩蹇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.DbAuditLog.TableName">
+ <summary>
+ 琛ㄥ悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.DbAuditLog.PrimaryKey">
+ <summary>
+ 涓婚敭
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.DbAuditLog.Operate">
+ <summary>
+ 鎿嶄綔
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.DbAuditLog.OldValues">
+ <summary>
+ 鏃у��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.DbAuditLog.NewValues">
+ <summary>
+ 鏂板��
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ExceptionLog">
+ <summary>
+ 寮傚父鏃ュ織
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ExceptionLog.Type">
+ <summary>
+ 绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ExceptionLog.Code">
+ <summary>
+ 浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ExceptionLog.Message">
+ <summary>
+ 娑堟伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ExceptionLog.StackTrace">
+ <summary>
+ 鍫嗘爤璺熻釜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.QueueLog">
+ <summary>
+ 娑堟伅闃熷垪鏃ュ織
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.QueueLog.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.QueueLog.EventId">
+ <summary>
+ 浜嬩欢Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.QueueLog.Data">
+ <summary>
+ 鏁版嵁
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.QueueLog.IsConsumOnce">
+ <summary>
+ 娑堟伅鏄惁鍙秷璐逛竴娆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.QueueLog.ElapsedMilliseconds">
+ <summary>
+ 鑰楁椂姣鏁�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.Entities.Common.ResourceLog">
+ <summary>
+ 璧勬簮鏃ュ織
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.Method">
+ <summary>
+ 璇锋眰鏂瑰紡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.Domain">
+ <summary>
+ 鍩熷悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.Path">
+ <summary>
+ 鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.RequestHeaders">
+ <summary>
+ 璇锋眰澶�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.Request">
+ <summary>
+ 璇锋眰鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.ResponseHeaders">
+ <summary>
+ 璇锋眰澶�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.Response">
+ <summary>
+ 鍝嶅簲缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.IsSuccess">
+ <summary>
+ 鏄惁鎴愬姛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.ClientIpAddress">
+ <summary>
+ 瀹㈡埛绔疘P鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.RefererUrl">
+ <summary>
+ 鏉ユ簮鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.ConsoleLogs">
+ <summary>
+ 鎺у埗鍙版棩蹇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Entities.Common.ResourceLog.ElapsedMilliseconds">
+ <summary>
+ 鑰楁椂姣鏁�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ScheduleJobTriggerTimeline">
+ <summary>
+ 瀹氭椂浠诲姟-浣滀笟瑙﹀彂鍣ㄨ繍琛岃褰�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.JobId">
+ <summary>
+ 浣滀笟 Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.TriggerId">
+ <summary>
+ 浣滀笟瑙﹀彂鍣� Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.NumberOfRuns">
+ <summary>
+ 褰撳墠杩愯娆℃暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.LastRunTime">
+ <summary>
+ 鏈�杩戣繍琛屾椂闂�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.NextRunTime">
+ <summary>
+ 涓嬩竴娆¤繍琛屾椂闂�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.Status">
+ <summary>
+ 浣滀笟瑙﹀彂鍣ㄧ姸鎬�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.Result">
+ <summary>
+ 鏈鎵ц缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.ElapsedTime">
+ <summary>
+ 鏈鎵ц鑰楁椂
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.Mode">
+ <summary>
+ 瑙﹀彂妯″紡
+ </summary>
+ <remarks>榛樿涓哄畾鏃惰Е鍙戯紝0:瀹氭椂锛�1:鎵嬪姩</remarks>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTriggerTimeline.Exception">
+ <summary>
+ 寮傚父淇℃伅
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ThreeResourceLog">
+ <summary>
+ 绗笁鏂硅祫婧愭棩蹇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.Method">
+ <summary>
+ 璇锋眰鏂瑰紡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.Domain">
+ <summary>
+ 鍩熷悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.Path">
+ <summary>
+ 鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.RequestHeaders">
+ <summary>
+ 璇锋眰澶�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.Request">
+ <summary>
+ 璇锋眰鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.ResponseHeaders">
+ <summary>
+ 璇锋眰澶�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.Response">
+ <summary>
+ 鍝嶅簲缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.IsSuccess">
+ <summary>
+ 鏄惁鎴愬姛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.ClientIpAddress">
+ <summary>
+ 瀹㈡埛绔疘P鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.RefererUrl">
+ <summary>
+ 鏉ユ簮鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.ConsoleLogs">
+ <summary>
+ 鎺у埗鍙版棩蹇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ThreeResourceLog.ElapsedMilliseconds">
+ <summary>
+ 鑰楁椂姣鏁�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.Resource">
+ <summary>
+ 璧勬簮
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ApplicationName">
+ <summary>
+ 搴旂敤鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.DynamicAssemblyName">
+ <summary>
+ 鍔ㄦ�佺▼搴忛泦鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ServiceName">
+ <summary>
+ 鏈嶅姟鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ControllerName">
+ <summary>
+ 鎺у埗鍣ㄥ悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ControllerSummary">
+ <summary>
+ 鎺у埗鍣ㄦ憳瑕�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ActionName">
+ <summary>
+ 濮旀墭鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ActionSummary">
+ <summary>
+ 濮旀墭鎽樿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.Code">
+ <summary>
+ 缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.AllowAnonymous">
+ <summary>
+ 蹇界暐鏉冮檺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.Method">
+ <summary>
+ 璇锋眰鏂瑰紡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.FileUpload">
+ <summary>
+ 鏂囦欢涓婁紶
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.IsFromForm">
+ <summary>
+ 鏄惁鏉ヨ嚜琛ㄥ崟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.CustomResponse">
+ <summary>
+ 鑷畾涔夌粨鏋�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.RouteArea">
+ <summary>
+ 璺敱鍖哄煙
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.Route">
+ <summary>
+ 璺敱
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.RequestTypeName">
+ <summary>
+ 璇锋眰绫诲瀷鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.RequestTypeFullName">
+ <summary>
+ 璇锋眰绫诲瀷鍏ㄥ悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ResponseTypeName">
+ <summary>
+ 鍝嶅簲绫诲瀷鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.ResponseTypeFullName">
+ <summary>
+ 鍝嶅簲绫诲瀷鍏ㄥ悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Resource.IsExpired">
+ <summary>
+ 鏄惁宸茶繃鏈�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ScheduleJobDetail">
+ <summary>
+ 瀹氭椂浠诲姟-浣滀笟璇︽儏
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.JobId">
+ <summary>
+ 浣滀笟Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.GroupName">
+ <summary>
+ 浣滀笟缁勫悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.JobType">
+ <summary>
+ 浣滀笟澶勭悊绋嬪簭绫诲瀷锛屽瓨鍌ㄧ殑鏄被鍨嬬殑 FullName
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.AssemblyName">
+ <summary>
+ 浣滀笟澶勭悊绋嬪簭绫诲瀷鎵�鍦ㄧ▼搴忛泦锛屽瓨鍌ㄧ殑鏄▼搴忛泦 Name
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.Description">
+ <summary>
+ 鎻忚堪淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.Concurrent">
+ <summary>
+ 浣滀笟鎵ц鏂瑰紡锛屽鏋滆缃负 false锛岄偅涔堜娇鐢� 涓茶 鎵ц锛屽惁鍒� 骞惰 鎵ц
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.IncludeAnnotations">
+ <summary>
+ 鏄惁鎵弿 IJob 瀹炵幇绫� [Trigger] 鐗规�цЕ鍙戝櫒
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobDetail.Properties">
+ <summary>
+ 浣滀笟淇℃伅棰濆鏁版嵁
+ 鐢� Dictionary string, object 搴忓垪鍖栨垚瀛楃涓插瓨鍌�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ScheduleJobTrigger">
+ <summary>
+ 瀹氭椂浠诲姟-浣滀笟瑙﹀彂鍣�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.TriggerId">
+ <summary>
+ 浣滀笟瑙﹀彂鍣↖d
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.JobId">
+ <summary>
+ 浣滀笟Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.TriggerType">
+ <summary>
+ 浣滀笟瑙﹀彂鍣ㄧ被鍨嬶紝瀛樺偍鐨勬槸绫诲瀷鐨� FullName
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.AssemblyName">
+ <summary>
+ 浣滀笟瑙﹀彂鍣ㄧ被鍨嬫墍鍦ㄧ▼搴忛泦锛屽瓨鍌ㄧ殑鏄▼搴忛泦 Name
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.Args">
+ <summary>
+ 浣滀笟瑙﹀彂鍣ㄥ垵濮嬪寲鍙傛暟锛岃繍琛屾椂灏嗗弽搴忓垪鍖栦负 object[] 绫诲瀷骞朵綔涓烘瀯閫犲嚱鏁板弬鏁�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.Description">
+ <summary>
+ 鎻忚堪淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.Status">
+ <summary>
+ 浣滀笟瑙﹀彂鍣ㄧ姸鎬�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.StartTime">
+ <summary>
+ 璧峰鏃堕棿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.EndTime">
+ <summary>
+ 缁撴潫鏃堕棿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.LastRunTime">
+ <summary>
+ 鏈�杩戣繍琛屾椂闂�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.NextRunTime">
+ <summary>
+ 涓嬩竴娆¤繍琛屾椂闂�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.NumberOfRuns">
+ <summary>
+ 褰撳墠杩愯娆℃暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.MaxNumberOfRuns">
+ <summary>
+ 鏈�澶цЕ鍙戞鏁帮紝0锛氫笉闄愬埗锛宯锛歂 娆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.NumberOfErrors">
+ <summary>
+ 鍑洪敊娆℃暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.MaxNumberOfErrors">
+ <summary>
+ 鏈�澶у嚭閿欐鏁帮紝0锛氫笉闄愬埗锛宯锛歂 娆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.NumRetries">
+ <summary>
+ 閲嶈瘯娆℃暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.RetryTimeout">
+ <summary>
+ 閲嶈瘯闂撮殧鏃堕棿锛屾绉掑崟浣�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.StartNow">
+ <summary>
+ 鏄惁绔嬪嵆鍚姩锛岃缃� false 灏嗘墜鍔ㄥ惎鍔�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.RunOnStart">
+ <summary>
+ 鏄惁鍚姩鏃舵墽琛屼竴娆�
+ 鍙�氳繃 StartTime 鎺у埗璧峰鏃堕棿
+ 鑻� StartTime 涓� null 鎴栧皬浜庡綋鍓嶆椂闂达紝鍒欏湪绋嬪簭鍚姩鏃舵墽琛�
+ 鍚﹀垯鍦� StartTime 鏃堕棿鎵ц
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.ResetOnlyOnce">
+ <summary>
+ 鏄惁鍦ㄥ惎鍔ㄦ椂閲嶇疆鏈�澶цЕ鍙戞鏁扮瓑浜庝竴娆$殑浣滀笟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.Result">
+ <summary>
+ 鏈鎵ц缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ScheduleJobTrigger.ElapsedTime">
+ <summary>
+ 鏈鎵ц鑰楁椂
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsLog">
+ <summary>
+ 鐭俊鏃ュ織
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.ChannelId">
+ <summary>
+ 娓犻亾Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.Channel">
+ <summary>
+ 娓犻亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.ChannelCreatedUserId">
+ <summary>
+ 娓犻亾鎿嶄綔浜�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.TemplateCode">
+ <summary>
+ 妯℃澘浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.TemplateParam">
+ <summary>
+ 妯℃澘鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.Expiry">
+ <summary>
+ 鏈夋晥鏈�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.IsUsed">
+ <summary>
+ 鏄惁浣跨敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.Status">
+ <summary>
+ 鐭俊鐘舵��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.RequestId">
+ <summary>
+ 璇锋眰Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.Code">
+ <summary>
+ 鍥炰紶浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLog.Message">
+ <summary>
+ 鍥炰紶娑堟伅
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsSetting">
+ <summary>
+ 鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.ChannelId">
+ <summary>
+ 娓犻亾Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.Channel">
+ <summary>
+ 娓犻亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.WithoutParams">
+ <summary>
+ 甯﹀嚭鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.MinutelyMaxCount">
+ <summary>
+ 姣忓垎閽熸渶澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.HourlyMaxCount">
+ <summary>
+ 姣忓皬鏃舵渶澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.DailyMaxCount">
+ <summary>
+ 姣忓ぉ鏈�澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSetting.Accesses">
+ <summary>
+ 閫氶亾閰嶇疆
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsSettingAccess">
+ <summary>
+ 鐭俊閫氶亾閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSettingAccess.ChannelId">
+ <summary>
+ 娓犻亾Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSettingAccess.Channel">
+ <summary>
+ 娓犻亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSettingAccess.SettingId">
+ <summary>
+ 閰嶇疆Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSettingAccess.Setting">
+ <summary>
+ 閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSettingAccess.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsSettingAccess.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.Channel">
+ <summary>
+ 娓犻亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Channel.Code">
+ <summary>
+ 缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Channel.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Channel.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.User">
+ <summary>
+ 鐢ㄦ埛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Type">
+ <summary>
+ 鐢ㄦ埛绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.ChannelId">
+ <summary>
+ 娓犻亾Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Channel">
+ <summary>
+ 娓犻亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Avatar">
+ <summary>
+ 澶村儚
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Name">
+ <summary>
+ 濮撳悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.UserName">
+ <summary>
+ 鐢ㄦ埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙�
+ </summary>
+ <remarks>鐧诲綍鎵嬫満鍙�</remarks>
+ </member>
+ <member name="P:ApiTools.Core.User.IsCheckPhoneNumber">
+ <summary>
+ 鏄惁宸叉牎楠屾墜鏈哄彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Password">
+ <summary>
+ 瀵嗙爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Level">
+ <summary>
+ 绾у埆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Remark">
+ <summary>
+ 澶囨敞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.User.Status">
+ <summary>
+ 鐘舵��
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s400">
+ <summary>
+ 鍙傛暟閿欒
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s401">
+ <summary>
+ 褰撳墠鐧诲綍鐢ㄦ埛宸插け鏁�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s404">
+ <summary>
+ {0}涓嶅瓨鍦�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s405">
+ <summary>
+ {0}宸插瓨鍦紝璇风‘璁ゅ悗鍐嶈瘯
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s406">
+ <summary>
+ 瀛樺湪閲嶅鏁版嵁锛歿0}锛岃纭鍚庡啀璇�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s410">
+ <summary>
+ 璇0}涓嶅彲淇敼
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s429">
+ <summary>
+ 鎿嶄綔棰戠箒
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s500">
+ <summary>
+ 鏈煡寮傚父
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumErrorCodeType.s510">
+ <summary>
+ 绯荤粺寮傚父
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumPagedListOrder">
+ <summary>
+ 鍒嗛〉鍒楄〃鎺掑簭
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumPagedListOrder.Asc">
+ <summary>
+ 鍗囧簭
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumPagedListOrder.Desc">
+ <summary>
+ 闄嶅簭
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumQueueAccess">
+ <summary>
+ 娑堟伅闃熷垪閫氶亾
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumQueueAccess.RabbitMQ">
+ <summary>
+ RabbitMQ
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserErrorCodeType.u1000">
+ <summary>
+ 璐﹀彿鎴栧瘑鐮佷笉瀛樺湪
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserErrorCodeType.u1001">
+ <summary>
+ 璐﹀彿宸茬鐢�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserErrorCodeType.u1010">
+ <summary>
+ 鎵嬫満鍙峰凡琚敞鍐�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserErrorCodeType.u1100">
+ <summary>
+ 褰撳墠璐﹀彿鏈粦瀹氬井淇″皬绋嬪簭
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserErrorCodeType.u1110">
+ <summary>
+ 鎵嬫満鎺堟潈澶辫触
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserErrorCodeType.u1120">
+ <summary>
+ 宸叉湁鍏朵粬寰俊缁戝畾璇ユ墜鏈哄彿
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumValidationTypes">
+ <summary>
+ 楠岃瘉绫诲瀷
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumValidationTypes.ValidPhoneNumber">
+ <summary>
+ 鎵嬫満鍙�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumValidationTypes.ValidIdentity">
+ <summary>
+ 韬唤璇佸彿
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumValidationTypes.ValidRealName">
+ <summary>
+ 濮撳悕
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumValidationTypes.ValidVerifyCode">
+ <summary>
+ 楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumConsoleLogAccess">
+ <summary>
+ 鎺у埗鍙版棩蹇楅�氶亾
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumConsoleLogAccess.Back">
+ <summary>
+ 鍚庣
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumConsoleLogAccess.Front">
+ <summary>
+ 鍓嶇
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumDbAuditOperate">
+ <summary>
+ 鏁版嵁搴撳璁℃棩蹇楁搷浣�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumDbAuditOperate.Added">
+ <summary>
+ 娣诲姞
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumDbAuditOperate.Modified">
+ <summary>
+ 淇敼
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumDbAuditOperate.Deleted">
+ <summary>
+ 鍒犻櫎
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumLogLevel">
+ <summary>
+ 鏃ュ織绾у埆
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumLogLevel.Trace">
+ <summary>
+ 璺熻釜
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumLogLevel.Debug">
+ <summary>
+ 璋冭瘯
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumLogLevel.Information">
+ <summary>
+ 淇℃伅
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumLogLevel.Warning">
+ <summary>
+ 璀﹀憡
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumLogLevel.Error">
+ <summary>
+ 閿欒
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumLogLevel.Critical">
+ <summary>
+ 涓ラ噸
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumResourceController">
+ <summary>
+ 璧勬簮鎺у埗鍣�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.CommonServerFileUtils">
+ <summary>
+ 鏂囦欢
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.CommonServerOcrUtils">
+ <summary>
+ 鏂囧瓧璇嗗埆
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.CommonServerLogRecords">
+ <summary>
+ 鏃ュ織璁板綍
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.CommonServerSmsUtils">
+ <summary>
+ 鐭俊宸ュ叿
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.UserServerAuth">
+ <summary>
+ 鐢ㄦ埛璁よ瘉
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.UserServerResource">
+ <summary>
+ 鐢ㄦ埛璧勬簮
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.UserServerUser">
+ <summary>
+ 鐢ㄦ埛淇℃伅
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.UserServerChannel">
+ <summary>
+ 娓犻亾淇℃伅
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceController.UserServerChannelUser">
+ <summary>
+ 娓犻亾鐢ㄦ埛
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumResourceMethod">
+ <summary>
+ 璧勬簮璇锋眰鏂瑰紡
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceMethod.None">
+ <summary>
+ 鏃�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceMethod.Get">
+ <summary>
+ 鏌ヨ
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceMethod.Post">
+ <summary>
+ 鎻愪氦
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceMethod.Put">
+ <summary>
+ 淇敼
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceMethod.Delete">
+ <summary>
+ 鍒犻櫎
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumResourceService">
+ <summary>
+ 璧勬簮鏈嶅姟
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceService.FlexJobServer">
+ <summary>
+ 鐏垫椿鐢ㄥ伐鏈嶅姟
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceService.CommonServer">
+ <summary>
+ 閫氱敤鏈嶅姟
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceService.UserServer">
+ <summary>
+ 鐢ㄦ埛鏈嶅姟
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceService.HumanResourcesServer">
+ <summary>
+ 浜哄姏璧勬簮鏈嶅姟
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumResourceService.ElectronSignServer">
+ <summary>
+ 鐢靛瓙绛炬湇鍔�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumSmsAccess">
+ <summary>
+ 鐭俊閫氶亾
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsAccess.None">
+ <summary>
+ 鏃�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsAccess.AliyunSms">
+ <summary>
+ 闃块噷浜戠煭淇�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsAccess.ChengLiYe">
+ <summary>
+ 璇氱珛涓�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumSmsStatus">
+ <summary>
+ 鐭俊鐘舵��
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsStatus.Wait">
+ <summary>
+ 寰呭彂閫�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsStatus.InProcess">
+ <summary>
+ 鍙戦�佷腑
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsStatus.Success">
+ <summary>
+ 鍙戦�佹垚鍔�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsStatus.Fail">
+ <summary>
+ 鍙戦�佸け璐�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumSmsTemplateCode">
+ <summary>
+ 鐭俊妯℃澘缂栧彿
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsTemplateCode.LoginOrRegister">
+ <summary>
+ 818骞冲彴鐧诲綍/娉ㄥ唽
+ 楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙扮櫥褰�/娉ㄥ唽锛岄獙璇佺爜10鍒嗛挓鍐呮湁鏁堛��
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsTemplateCode.UpdateUserPhoneNumber">
+ <summary>
+ 818鎵嬫満鍙风爜淇敼
+ 楠岃瘉鐮�${code}锛屾偍姝e湪杩涜淇敼鎵嬫満鍙风爜鎿嶄綔锛岃鍕挎硠闇诧紝鑻ラ潪鏈汉鎿嶄綔璇峰拷鐣ャ��
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsTemplateCode.BankWalletAccountOpen">
+ <summary>
+ 818閽卞寘寮�閫�
+ 楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙伴挶鍖呭紑閫氾紝璇ラ獙璇佺爜5鍒嗛挓鍐呮湁鏁堬紝璇峰嬁娉勯湶浜庝粬浜恒��
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsTemplateCode.InviteElectronSign">
+ <summary>
+ 鐢靛瓙绛鹃個绾�
+ ${name}璇锋偍鐐瑰嚮绛剧害http://testwww.81812333.com/sg/${code}
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumSmsTemplateCode.ElectronSignUrl">
+ <summary>
+ 绛剧害鍦板潃
+ ${name}璇锋偍鐐瑰嚮绛剧害https://testwww.81812333.com/sgu/${code}
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumClientType">
+ <summary>
+ 瀹㈡埛绔被鍨�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumClientType.PcWeb">
+ <summary>
+ 鐢佃剳缃戦〉
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumClientType.Wxmp">
+ <summary>
+ 寰俊灏忕▼搴�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumClientType.H5">
+ <summary>
+ H5鐧诲綍
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumClientType.Api">
+ <summary>
+ 鎺ュ彛
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumUserGender">
+ <summary>
+ 鐢ㄦ埛鎬у埆
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserGender.Male">
+ <summary>
+ 鐢�
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserGender.Female">
+ <summary>
+ 濂�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumUserStatus">
+ <summary>
+ 鐢ㄦ埛淇℃伅鐘舵��
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserStatus.Normal">
+ <summary>
+ 姝e父
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserStatus.Disabled">
+ <summary>
+ 绂佺敤
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumUserType">
+ <summary>
+ 鐢ㄦ埛绫诲瀷
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserType.Channel">
+ <summary>
+ 娓犻亾
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.EnumUserType.Operation">
+ <summary>
+ 杩愯惀
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.IIsDisabled">
+ <summary>
+ 鏄惁宸茬鐢�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IIsDisabled.IsDisabled">
+ <summary>
+ 鏄惁宸茬鐢�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.IPhysicalDeletion">
+ <summary>
+ 鐗╃悊鍒犻櫎
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ITreeData`1">
+ <summary>
+ 鏍戝舰鏁版嵁
+ </summary>
+ <typeparam name="TEntity"></typeparam>
+ </member>
+ <member name="P:ApiTools.Core.ITreeData`1.ParentId">
+ <summary>
+ 涓婄骇Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ITreeData`1.Parent">
+ <summary>
+ 涓婄骇
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ITreeData`1.Children">
+ <summary>
+ 涓嬬骇
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ITreeData`1.Path">
+ <summary>
+ 瀛楀吀璺緞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ITreeData`1.Code">
+ <summary>
+ 缂栧彿
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ChangePhoneNumberCommand">
+ <summary>
+ 鏇存崲鎵嬫満鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChangePhoneNumberCommand.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChangePhoneNumberCommand.VerifyCode">
+ <summary>
+ 楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PasswordLoginCommand">
+ <summary>
+ 瀵嗙爜鐧诲綍
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PasswordLoginCommand.UserName">
+ <summary>
+ 璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PasswordLoginCommand.Password">
+ <summary>
+ 瀵嗙爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PasswordLoginCommand.Type">
+ <summary>
+ 鐢ㄦ埛绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PasswordLoginCommand.ClientType">
+ <summary>
+ 瀹㈡埛绔被鍨�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.LoginCommandCallback">
+ <summary>
+ 瀵嗙爜鐧诲綍缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.LoginCommandCallback.Id">
+ <summary>
+ 鐢ㄦ埛Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.LoginCommandCallback.AccessToken">
+ <summary>
+ 鐢ㄦ埛璁块棶浠ょ墝
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.LoginCommandCallback.RefreshToken">
+ <summary>
+ 鍒锋柊浠ょ墝
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.LoginCommandCallback.SessionKey">
+ <summary>
+ 浼氳瘽绉橀挜锛堜粎鐢ㄤ簬寰俊灏忕▼搴忔巿鏉冪櫥褰曪級
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.LoginCommandCallback.IsBindPhoneNumber">
+ <summary>
+ 鏄惁宸茬粦瀹氭墜鏈哄彿锛堜粎鐢ㄤ簬寰俊灏忕▼搴忔巿鏉冪櫥褰曪級
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SendLoginOrRegisterVerifyCodeCommand">
+ <summary>
+ 鍙戦�佺櫥褰曟垨娉ㄥ唽鐭俊
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendLoginOrRegisterVerifyCodeCommand.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsLoginCommand">
+ <summary>
+ 鐭俊鐧诲綍
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLoginCommand.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLoginCommand.VerifyCode">
+ <summary>
+ 楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLoginCommand.Type">
+ <summary>
+ 鐢ㄦ埛绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsLoginCommand.ClientType">
+ <summary>
+ 瀹㈡埛绔被鍨�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.UpdatePhoneNumberVerifyCodeCommand">
+ <summary>
+ 鍙戦�佹洿鎹㈡墜鏈哄彿鐭俊
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.UpdatePhoneNumberVerifyCodeCommand.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetAliyunOSSAcsQuery">
+ <summary>
+ 鑾峰彇闃块噷浜慜SS鎺堟潈淇℃伅
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SaveChannelCommand">
+ <summary>
+ 淇濆瓨娓犻亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelCommand.Code">
+ <summary>
+ 缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelCommand.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelCommand.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetChannelsQuery">
+ <summary>
+ 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetChannelsQueryResult">
+ <summary>
+ 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetChannelsQueryResultItem">
+ <summary>
+ 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelsQueryResultItem.Id">
+ <summary>
+ Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelsQueryResultItem.Code">
+ <summary>
+ 缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelsQueryResultItem.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelsQueryResultItem.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SaveChannelUserCommand">
+ <summary>
+ 淇濆瓨娓犻亾鐢ㄦ埛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelUserCommand.ChannelId">
+ <summary>
+ 娓犻亾Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelUserCommand.Name">
+ <summary>
+ 濮撳悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelUserCommand.UserName">
+ <summary>
+ 鐢ㄦ埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelUserCommand.Password">
+ <summary>
+ 瀵嗙爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelUserCommand.Level">
+ <summary>
+ 绾у埆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelUserCommand.Remark">
+ <summary>
+ 澶囨敞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveChannelUserCommand.Status">
+ <summary>
+ 鐘舵��
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetChannelUsersQuery">
+ <summary>
+ 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetChannelUsersQueryResult">
+ <summary>
+ 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetChannelUsersQueryResultItem">
+ <summary>
+ 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.Id">
+ <summary>
+ Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.ChannelId">
+ <summary>
+ 娓犻亾Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.ChannelName">
+ <summary>
+ 娓犻亾鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.Name">
+ <summary>
+ 濮撳悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.UserName">
+ <summary>
+ 鐢ㄦ埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.Level">
+ <summary>
+ 绾у埆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.Remark">
+ <summary>
+ 澶囨敞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetChannelUsersQueryResultItem.Status">
+ <summary>
+ 鐘舵��
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.CheckVerifyCodeSmsCommand">
+ <summary>
+ 鏍¢獙楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CheckVerifyCodeSmsCommand.TemplateCode">
+ <summary>
+ 鐭俊妯℃澘缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CheckVerifyCodeSmsCommand.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CheckVerifyCodeSmsCommand.VerifyCode">
+ <summary>
+ 楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SaveSmsSettingCommand">
+ <summary>
+ 淇濆瓨鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommand.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommand.WithoutParams">
+ <summary>
+ 甯﹀嚭鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommand.MinutelyMaxCount">
+ <summary>
+ 姣忓垎閽熸渶澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommand.HourlyMaxCount">
+ <summary>
+ 姣忓皬鏃舵渶澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommand.DailyMaxCount">
+ <summary>
+ 姣忓ぉ鏈�澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommand.Accesses">
+ <summary>
+ 閫氶亾閰嶇疆
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SaveSmsSettingCommandAccess">
+ <summary>
+ 淇濆瓨鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommandAccess.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommandAccess.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveSmsSettingCommandAccess.Sort">
+ <summary>
+ 鎺掑簭
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SendSmsCommand">
+ <summary>
+ 鍙戦�佺煭淇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsCommand.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsCommand.TemplateCode">
+ <summary>
+ 鐭俊妯℃澘缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsCommand.TemplateParam">
+ <summary>
+ 妯℃澘鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsCommand.Expiry">
+ <summary>
+ 鏈夋晥鏈�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsCommand.ChannelCreatedUserId">
+ <summary>
+ 娓犻亾鎿嶄綔浜�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsAliyunNotifyCommand">
+ <summary>
+ 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.SendTime">
+ <summary>
+ 杞彂缁欒繍钀ュ晢鐨勬椂闂淬��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.ReportTime">
+ <summary>
+ 鏀跺埌杩愯惀鍟嗗洖鎵х殑鏃堕棿銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.Success">
+ <summary>
+ 鏄惁鍙戦�佹垚鍔熴��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.ErrMsg">
+ <summary>
+ 閿欒鐮佷俊鎭弿杩般��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.ErrCode">
+ <summary>
+ 閿欒鐮併��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.PhoneNumber">
+ <summary>
+ 鐭俊鎺ユ敹鍙风爜銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.SmsSize">
+ <summary>
+ 鐭俊闀垮害銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.BizId">
+ <summary>
+ 鍙戦�佸洖鎵D锛屽嵆鍙戦�佹祦姘村彿銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandItem.OutId">
+ <summary>
+ 璋冪敤鍙戦�佺煭淇endSms鎺ュ彛鏃朵紶鐨刼utId銆�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsAliyunNotifyCommandResult">
+ <summary>
+ 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandResult.Code">
+ <summary>
+ 鍥炶皟鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsAliyunNotifyCommandResult.Msg">
+ <summary>
+ 娑堟伅
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsChengLiYeNotifyCommand">
+ <summary>
+ 璇氱珛涓氱煭淇″钩鍙板洖浼犻�氱煡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommand.ResultCode">
+ <summary>
+ 鐘舵�佺爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommand.MsgReports">
+ <summary>
+ 鐘舵�佺爜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport">
+ <summary>
+ 璇氱珛涓氱煭淇¢�氱煡璇锋眰
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport.UserName">
+ <summary>
+ 鐢ㄦ埛鍚嶃�傛彁浜ゆ椂鐨勭敤鎴峰悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport.Msgid">
+ <summary>
+ 鎻愪氦杩斿洖鐨刴sgid
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport.Seqid">
+ <summary>
+ 鎻愪氦杩斿洖鐨剆eqid
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport.Mobile">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport.Status">
+ <summary>
+ 鎵嬫満鍙风爜鍙戦�佺姸鎬佺爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport.StatusDes">
+ <summary>
+ 鐘舵�佺爜鎻忚堪
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsChengLiYeNotifyCommandMsgReport.DoneTime">
+ <summary>
+ 鎶ュ憡杩斿洖鏃堕棿
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetSmsLogsQuery">
+ <summary>
+ 鏌ヨ鐭俊鏃ュ織
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.CreatedTimeBegin">
+ <summary>
+ 鍒涘缓鏃堕棿-璧峰
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.CreatedTimeEnd">
+ <summary>
+ 鍒涘缓鏃堕棿-鎴
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.ChannelCreatedUserIds">
+ <summary>
+ 娓犻亾鎿嶄綔浜�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.TraceId">
+ <summary>
+ 璺熻釜Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.TemplateCode">
+ <summary>
+ 妯℃澘浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.TemplateParam">
+ <summary>
+ 妯℃澘鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.IsUsed">
+ <summary>
+ 鏄惁浣跨敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQuery.Status">
+ <summary>
+ 鐭俊鐘舵��
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetSmsLogsQueryResult">
+ <summary>
+ 寮傚父鏃ュ織鍒嗛〉鍒楄〃鏌ヨ-缁撴灉
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetSmsLogsQueryResultItem">
+ <summary>
+ 寮傚父鏃ュ織鍒嗛〉鍒楄〃鏌ヨ-缁撴灉-椤�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.Id">
+ <summary>
+ Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.TraceId">
+ <summary>
+ 璺熻釜Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.TemplateCode">
+ <summary>
+ 妯℃澘浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.TemplateParam">
+ <summary>
+ 妯℃澘鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.Expiry">
+ <summary>
+ 鏈夋晥鏈�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.IsUsed">
+ <summary>
+ 鏄惁浣跨敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.Status">
+ <summary>
+ 鐭俊鐘舵��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.RequestId">
+ <summary>
+ 璇锋眰Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.Code">
+ <summary>
+ 鍥炰紶浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.Message">
+ <summary>
+ 鍥炰紶娑堟伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.ChannelName">
+ <summary>
+ 娓犻亾鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.ChannelCreatedUserId">
+ <summary>
+ 娓犻亾鎿嶄綔浜�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsLogsQueryResultItem.CreatedTime">
+ <summary>
+ 鍒涘缓鏃堕棿
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetSmsSettingQuery">
+ <summary>
+ 鏌ヨ鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetSmsSettingQueryResult">
+ <summary>
+ 鏌ヨ鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResult.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResult.WithoutParams">
+ <summary>
+ 甯﹀嚭鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResult.MinutelyMaxCount">
+ <summary>
+ 姣忓垎閽熸渶澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResult.HourlyMaxCount">
+ <summary>
+ 姣忓皬鏃舵渶澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResult.DailyMaxCount">
+ <summary>
+ 姣忓ぉ鏈�澶ф暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResult.Accesses">
+ <summary>
+ 閫氶亾閰嶇疆
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.GetSmsSettingQueryResultAccess">
+ <summary>
+ 鏌ヨ鐭俊閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResultAccess.Access">
+ <summary>
+ 閫氶亾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResultAccess.IsDisabled">
+ <summary>
+ 鏄惁绂佺敤
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.GetSmsSettingQueryResultAccess.Sort">
+ <summary>
+ 鎺掑簭
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.AlipayUtils">
+ <summary>
+ 闃块噷鏀粯宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.UserAgreementPageSign(Aop.Api.Domain.AlipayUserAgreementPageSignModel,System.String)">
+ <summary>
+ 鏀粯瀹濅釜浜哄崗璁〉闈㈢绾︽帴鍙�
+ </summary>
+ <param name="model"></param>
+ <param name="notifyUrl"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.UserAgreementQuery(Aop.Api.Domain.AlipayUserAgreementQueryModel)">
+ <summary>
+ 鏀粯瀹濅釜浜轰唬鎵e崗璁煡璇㈡帴鍙�
+ </summary>
+ <param name="model"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.UserAgreementUnsign(Aop.Api.Domain.AlipayUserAgreementUnsignModel)">
+ <summary>
+ 鏀粯瀹濅釜浜轰唬鎵e崗璁В绾︽帴鍙�
+ </summary>
+ <param name="model"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundAccountbookCreate(Aop.Api.Domain.AlipayFundAccountbookCreateModel)">
+ <summary>
+ 璧勯噾璁拌处鏈紑閫�
+ </summary>
+ <param name="model"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundAccountbookQuery(Aop.Api.Domain.AlipayFundAccountbookQueryModel)">
+ <summary>
+ 璧勯噾璁拌处鏈殑淇℃伅鏌ヨ
+ </summary>
+ <param name="model"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundTransPagePay(Aop.Api.Domain.AlipayFundTransPagePayModel,System.String)">
+ <summary>
+ 璧勯噾杞处椤甸潰鏀粯鎺ュ彛
+ </summary>
+ <param name="model"></param>
+ <param name="notifyUrl"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundTransUniTransfer(Aop.Api.Domain.AlipayFundTransUniTransferModel,System.String)">
+ <summary>
+ 鍗曠瑪杞处鎺ュ彛
+ </summary>
+ <param name="model"></param>
+ <param name="notifyUrl"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.DataBillEreceiptagentApply(Aop.Api.Domain.AlipayDataBillEreceiptagentApplyModel)">
+ <summary>
+ ISV浠g悊鍟嗘埛鐢宠璧勯噾涓氬姟鍥炲崟
+ </summary>
+ <param name="model"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.DataBillAccountbookereceiptQuery(Aop.Api.Domain.AlipayDataBillAccountbookereceiptQueryModel)">
+ <summary>
+ ISV浠g悊鍟嗘埛鏌ヨ璧勯噾涓氬姟鍥炲崟鐢宠鐘舵��
+ </summary>
+ <param name="model"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundTransCommonQuery(Aop.Api.Domain.AlipayFundTransCommonQueryModel)">
+ <summary>
+ 杞处涓氬姟鍗曟嵁鏌ヨ鎺ュ彛
+ </summary>
+ <param name="model"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundTransCommonQuery(Aop.Api.Domain.AlipayDataBillBizfundagentQueryModel)">
+ <summary>
+ 璐﹀崟涓庣數瀛愬嚟璇佷笅杞�
+ </summary>
+ <param name="model"></param>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundExpandindirectImageUpload(Aop.Api.Request.AlipayFundExpandindirectImageUploadRequest)">
+ <summary>
+ 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠舵枃浠朵笂浼犳帴鍙�
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundExpandindirectCreate(Aop.Api.Domain.AlipayFundExpandindirectCreateModel,System.String)">
+ <summary>
+ 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠�
+ </summary>
+ <param name="model"></param>
+ <param name="notifyUrl"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundExpandindirectOrderQuery(Aop.Api.Domain.AlipayFundExpandindirectOrderQueryModel)">
+ <summary>
+ 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠跺崟鏌ヨ鎺ュ彛
+ </summary>
+ <param name="model"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AlipayUtils.FundExpandindirectOrderCancel(Aop.Api.Domain.AlipayFundExpandindirectOrderCancelModel)">
+ <summary>
+ 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠跺崟鍙栨秷鎺ュ彛
+ </summary>
+ <param name="model"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.AliyunOptions">
+ <summary>
+ 闃块噷浜戦厤缃�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.AliyunOSSOptions">
+ <summary>
+ 闃块噷浜慜SS閰嶇疆
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.AliyunSMSOptions">
+ <summary>
+ 闃块噷浜戠煭淇¢厤缃�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.AliyunSMSOptions.Version">
+ <summary>
+ 鐗堟湰
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.AliyunSMSOptions.SignName">
+ <summary>
+ 绛惧悕鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.AliyunSMSOptions.RegionId">
+ <summary>
+ 鍖哄煙Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.AliyunSMSOptions.TemplateCodes">
+ <summary>
+ 妯℃澘浠g爜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.AliyunOSSUploadResult">
+ <summary>
+ 闃块噷浜慜SS涓婁紶缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.AliyunOSSUploadResult.Url">
+ <summary>
+ 鐩稿璺緞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.AliyunOSSUploadResult.Buffer">
+ <summary>
+ 瀛楄妭
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.AliyunOSSUtils">
+ <summary>
+ 闃块噷浜慜SS宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.AliyunOSSUtils.Upload(System.String,System.String,System.String)">
+ <summary>
+ 涓婁紶鏂囦欢
+ </summary>
+ <param name="scene"></param>
+ <param name="url"></param>
+ <param name="filename"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AliyunOSSUtils.Upload(System.String,System.String)">
+ <summary>
+ 涓婁紶鏂囦欢
+ </summary>
+ <param name="url"></param>
+ <param name="key"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AliyunOSSUtils.Upload(System.String,Microsoft.AspNetCore.Http.IFormFile,System.String)">
+ <summary>
+ 涓婁紶鏂囦欢
+ </summary>
+ <param name="scene"></param>
+ <param name="file"></param>
+ <param name="filename"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AliyunOSSUtils.Upload(System.String,System.IO.Stream,System.String)">
+ <summary>
+ 涓婁紶鏂囦欢
+ </summary>
+ <param name="scene"></param>
+ <param name="stream"></param>
+ <param name="filename"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AliyunOSSUtils.Upload(System.IO.Stream,System.String)">
+ <summary>
+ 涓婁紶鏂囦欢
+ </summary>
+ <param name="stream"></param>
+ <param name="key"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.AliyunOSSUtils.GetUrl(System.String,System.String)">
+ <summary>
+ 鑾峰彇Url
+ </summary>
+ <param name="url"></param>
+ <param name="process"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrBusinessLicenseResult">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResult.Url">
+ <summary>
+ 鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResult.Model">
+ <summary>
+ 妯″瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResult.ErrorCode">
+ <summary>
+ 閿欒鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResult.ErrorMessage">
+ <summary>
+ 閿欒娑堟伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResult.WordsResult">
+ <summary>
+ 鏂囧瓧缁撴灉
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrBusinessLicenseResultModel">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.EnterpriseName">
+ <summary>
+ 浼佷笟鍏ㄧО
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.SocietyCreditCode">
+ <summary>
+ 缁熶竴绀句細淇$敤浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.LegalPerson">
+ <summary>
+ 娉曚汉濮撳悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.EnterpriseType">
+ <summary>
+ 浼佷笟绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.RegisteredCapital">
+ <summary>
+ 娉ㄥ唽璧勬湰
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.EstablishmentDate">
+ <summary>
+ 鎴愮珛鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.Address">
+ <summary>
+ 浼佷笟鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrBusinessLicenseResultModel.MainBusiness">
+ <summary>
+ 缁忚惀鑼冨洿
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrIdentityBackResult">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResult.Url">
+ <summary>
+ 鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResult.Model">
+ <summary>
+ 妯″瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResult.ErrorCode">
+ <summary>
+ 閿欒鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResult.ErrorMessage">
+ <summary>
+ 閿欒娑堟伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResult.WordsResult">
+ <summary>
+ 鏂囧瓧缁撴灉
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrIdentityBackResultModel">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResultModel.ExpiryDateText">
+ <summary>
+ 澶辨晥鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResultModel.ExpiryDate">
+ <summary>
+ 澶辨晥鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResultModel.IssueAuthority">
+ <summary>
+ 绛惧彂鏈哄叧
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResultModel.IssueDateText">
+ <summary>
+ 绛惧彂鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityBackResultModel.IssueDate">
+ <summary>
+ 绛惧彂鏃ユ湡
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrIdentityFrontResult">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResult.Url">
+ <summary>
+ 鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResult.Model">
+ <summary>
+ 妯″瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResult.ErrorCode">
+ <summary>
+ 閿欒鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResult.ErrorMessage">
+ <summary>
+ 閿欒娑堟伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResult.WordsResult">
+ <summary>
+ 鏂囧瓧缁撴灉
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrIdentityFrontResultModel">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <!-- Badly formed XML comment ignored for member "P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.Name" -->
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.Identity">
+ <summary>
+ 韬唤璇佸彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.GenderText">
+ <summary>
+ 鎬у埆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.Gender">
+ <summary>
+ 鎬у埆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.BirthdayText">
+ <summary>
+ 鐢熸棩
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.Birthday">
+ <summary>
+ 鐢熸棩
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.Nation">
+ <summary>
+ 姘戞棌
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrIdentityFrontResultModel.Address">
+ <summary>
+ 浣忓潃
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrResultWord">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrResultWord.Location">
+ <summary>
+ 瀹氫綅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrResultWord.Words">
+ <summary>
+ 鏂囧瓧
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrResultWordLocation">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrResultWordLocation.Top">
+ <summary>
+ 璺濈椤堕儴
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrResultWordLocation.Left">
+ <summary>
+ 璺濈宸﹁竟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrResultWordLocation.Width">
+ <summary>
+ 瀹藉害
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrResultWordLocation.Height">
+ <summary>
+ 楂樺害
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrUtils">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.BaiduOcrUtils.OcrBusinessLicense(System.String,System.String,System.Boolean)">
+ <summary>
+ 钀ヤ笟鎵х収OCR
+ </summary>
+ <param name="url"></param>
+ <param name="scene"></param>
+ <param name="isOssUrl"></param>
+ </member>
+ <member name="M:ApiTools.Core.BaiduOcrUtils.OcrIdentityFront(System.String,System.String,System.Boolean)">
+ <summary>
+ 韬唤璇佹闈CR
+ </summary>
+ <param name="url"></param>
+ <param name="scene"></param>
+ <param name="isOssUrl"></param>
+ </member>
+ <member name="M:ApiTools.Core.BaiduOcrUtils.OcrIdentityBack(System.String,System.String,System.Boolean)">
+ <summary>
+ 韬唤璇佽儗闈CR
+ </summary>
+ <param name="url"></param>
+ <param name="scene"></param>
+ <param name="isOssUrl"></param>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOptions">
+ <summary>
+ 鐧惧害閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOptions.Ocr">
+ <summary>
+ 鏂囧瓧璇嗗埆
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.BaiduOcrOptions">
+ <summary>
+ 鐧惧害鏂囧瓧璇嗗埆閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrOptions.Key">
+ <summary>
+ 閿�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.BaiduOcrOptions.Secret">
+ <summary>
+ 绉橀挜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.OcrResult`1">
+ <summary>
+ OCR璇嗗埆缁撴灉
+ </summary>
+ <typeparam name="T"></typeparam>
+ </member>
+ <member name="P:ApiTools.Core.OcrResult`1.Url">
+ <summary>
+ 鍦板潃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.OcrResult`1.Data">
+ <summary>
+ 鏁版嵁
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.CollectionUtils.DistinctAdd``1(System.Collections.Generic.List{``0},``0,System.Collections.Generic.IEqualityComparer{``0})">
+ <summary>
+ 鍘婚噸娣诲姞
+ </summary>
+ <typeparam name="T">娉涘瀷瀵硅薄</typeparam>
+ <param name="list">闆嗗悎</param>
+ <param name="item">闇�娣诲姞鐨勯」</param>
+ <param name="comparer">姣旇緝</param>
+ <returns>闆嗗悎</returns>
+ </member>
+ <member name="M:ApiTools.Core.DatabaseLoggingWriter.Dispose">
+ <summary>
+ 閲婃斁鏈嶅姟浣滅敤鍩�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.DateTimeRange">
+ <summary>
+ 鏃堕棿鍩�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.DateTimeRange.Start">
+ <summary>
+ 寮�濮嬫椂闂�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.DateTimeRange.End">
+ <summary>
+ 缁撴潫鏃堕棿
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.DateTimeUtils">
+ <summary>
+ 鏃堕棿宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.ToDateTime(System.Object)">
+ <summary>
+ 杞椂闂�
+ </summary>
+ <param name="obj">瀵硅薄</param>
+ <returns>鏃堕棿</returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.ToDateTime(System.Object,System.String)">
+ <summary>
+ 杞椂闂�
+ </summary>
+ <param name="obj">瀵硅薄</param>
+ <param name="format"></param>
+ <returns>鏃堕棿</returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.ToDateTime``2(System.Collections.Generic.IDictionary{``0,``1},``0)">
+ <summary>
+ 杞椂闂�
+ </summary>
+ <param name="dic">瀛楀吀</param>
+ <param name="key">閿�</param>
+ <returns>鍊�</returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.ToTimeStamp(System.DateTime,System.Boolean)">
+ <summary>
+ 鏃堕棿杞椂闂存埑
+ </summary>
+ <param name="time">鏃堕棿</param>
+ <param name="milliseconds">true姣绾� false绉掔骇</param>
+ <returns>鏃堕棿鎴�</returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.ToDateTimeByMilliseconds(System.Int64,System.Boolean)">
+ <summary>
+ 鏃堕棿鎴宠浆鏃堕棿
+ </summary>
+ <param name="timestamp">鏃堕棿鎴�</param>
+ <param name="milliseconds">true姣绾� false绉掔骇</param>
+ <returns>鏃堕棿</returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.GetYYYYMMDD(System.Nullable{System.DateTime})">
+ <summary>
+ 鎴彇鏃ユ湡
+ </summary>
+ <param name="date">鏃堕棿</param>
+ <returns>鏃ユ湡</returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.GetYYYYMMDD(System.DateTime)">
+ <summary>
+ 鎴彇鏃ユ湡
+ </summary>
+ <param name="date">鏃堕棿</param>
+ <returns>鏃ユ湡</returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.GetAge(System.Nullable{System.DateTime})">
+ <summary>
+ 鑾峰彇骞撮緞
+ </summary>
+ <param name="birthday"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.TryToDateTimeRange(System.String,ApiTools.Core.DateTimeRange@)">
+ <summary>
+ 鑾峰彇鏃堕棿鑼冨洿閫夋嫨鍣�
+ </summary>
+ <param name="str"></param>
+ <param name="range"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.GetTodayRange">
+ <summary>
+ 鑾峰彇浠婂ぉ鑼冨洿
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DateTimeUtils.Format(System.TimeSpan)">
+ <summary>
+ 鏍煎紡鍖�
+ </summary>
+ <param name="span"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.DbUtils">
+ <summary>
+ 鏁版嵁搴撳伐鍏�
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.GetTreeDataPath``1(System.Nullable{System.Guid},System.Threading.CancellationToken)">
+ <summary>
+ 鑾峰彇鏍戝舰鏁版嵁璺緞
+ </summary>
+ <typeparam name="TEntity"></typeparam>
+ <param name="parentId"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.UpdateTreeDataChildrenPath``1(System.String,System.String,System.Threading.CancellationToken)">
+ <summary>
+ 鏇存柊鏍戝舰鏁版嵁涓嬬骇璺緞
+ </summary>
+ <param name="oldPath"></param>
+ <param name="newPath"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.GetSelect``3(ApiTools.Core.SelectQuery{``1,``2},System.Func{``2,``1},System.Func{``2,System.String},System.Func{System.Linq.IQueryable{``0},System.Linq.IQueryable{``0}},System.Threading.CancellationToken)">
+ <summary>
+ 鏌ヨ閫夋嫨鍣ㄦ暟鎹�
+ </summary>
+ <typeparam name="TEntity"></typeparam>
+ <typeparam name="TValue"></typeparam>
+ <typeparam name="TData"></typeparam>
+ <param name="request"></param>
+ <param name="getValue"></param>
+ <param name="getLabel"></param>
+ <param name="query"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.GetPagedListAsync``2(ApiTools.Core.PagedListQueryPageModel,System.Func{System.Linq.IQueryable{``0},System.Linq.IQueryable{``0}},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Threading.CancellationToken)">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ <typeparam name="TEntity"></typeparam>
+ <typeparam name="TItem"></typeparam>
+ <param name="page"></param>
+ <param name="query"></param>
+ <param name="selector"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.GetPagedListAsync``2(ApiTools.Core.PagedListQueryPageModel,System.Linq.IQueryable{``1},System.Threading.CancellationToken)">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ <typeparam name="TResult"></typeparam>
+ <typeparam name="TItem"></typeparam>
+ <param name="page"></param>
+ <param name="q"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.GetPagedListAsync``1(ApiTools.Core.PagedListQueryPageModel,System.Linq.IQueryable{``0},System.Threading.CancellationToken)">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+ </summary>
+ <typeparam name="TItem"></typeparam>
+ <param name="page"></param>
+ <param name="q"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.SetIsDisabled``1(ApiTools.Core.SetIsDisabledCommand,System.Func{System.Linq.IQueryable{``0},System.Linq.IQueryable{``0}},System.Threading.CancellationToken)">
+ <summary>
+ 璁剧疆鏄惁绂佺敤
+ </summary>
+ <typeparam name="TEntity"></typeparam>
+ <param name="request"></param>
+ <param name="query"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.DeleteData``1(ApiTools.Core.DeleteDataCommand,System.Func{System.Linq.IQueryable{``0},System.Linq.IQueryable{``0}},System.Threading.CancellationToken)">
+ <summary>
+ 鍒犻櫎鏁版嵁
+ </summary>
+ <typeparam name="TEntity"></typeparam>
+ <param name="request"></param>
+ <param name="query"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.SaveData``2(``1,System.Func{System.Linq.IQueryable{``0},System.Linq.IQueryable{``0}},System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}},System.Action{``0},System.Threading.CancellationToken)">
+ <summary>
+ 淇濆瓨鏁版嵁
+ </summary>
+ <typeparam name="TEntity"></typeparam>
+ <typeparam name="TRequest"></typeparam>
+ <param name="request"></param>
+ <param name="query"></param>
+ <param name="checkExist"></param>
+ <param name="update"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.BuildEntity(Microsoft.EntityFrameworkCore.ModelBuilder,System.Type)">
+ <summary>
+ 鐢熸垚瀹炰綋
+ </summary>
+ <param name="modelBuilder"></param>
+ <param name="dbContextLocator"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.DbUtils.SavingChangesEvent(Microsoft.EntityFrameworkCore.Diagnostics.DbContextEventData,Microsoft.EntityFrameworkCore.Diagnostics.InterceptionResult{System.Int32})">
+ <summary>
+ 鏁版嵁鍙樻洿浜嬩欢
+ </summary>
+ <param name="eventData"></param>
+ <param name="result"></param>
+ </member>
+ <member name="T:ApiTools.Core.DeleteDataCommand">
+ <summary>
+ 鍒犻櫎鍛戒护
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PagedListQuery`2">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃
+ </summary>
+ <typeparam name="TResult"></typeparam>
+ <typeparam name="TItem"></typeparam>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQuery`2.PageModel">
+ <summary>
+ 鍒嗛〉淇℃伅
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PagedListQueryPageModel">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃-鍒嗛〉淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryPageModel.Rows">
+ <summary>
+ 琛屾暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryPageModel.Page">
+ <summary>
+ 椤电爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryPageModel.OrderInput">
+ <summary>
+ 鎺掑簭
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PagedListQueryPageModelOrderInput">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃-鍒嗛〉淇℃伅-鎺掑簭淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryPageModelOrderInput.Property">
+ <summary>
+ 灞炴��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryPageModelOrderInput.Order">
+ <summary>
+ 鎺掑簭
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PagedListQueryResult`1">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃-缁撴灉
+ </summary>
+ <typeparam name="TItem"></typeparam>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryResult`1.PageModel">
+ <summary>
+ 鍒嗛〉淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryResult`1.Data">
+ <summary>
+ 鏁版嵁
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PagedListQueryResultPageModel">
+ <summary>
+ 鏌ヨ鍒嗛〉鍒楄〃-鍒嗛〉淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryResultPageModel.TotalCount">
+ <summary>
+ 鎬绘暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PagedListQueryResultPageModel.TotalPage">
+ <summary>
+ 椤垫暟
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SaveDataCommand">
+ <summary>
+ 淇濆瓨鏁版嵁鍛戒护
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SaveDataCommand.Id">
+ <summary>
+ Id
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SelectQuery`2">
+ <summary>
+ 閫夋嫨鍣ㄦ煡璇�
+ </summary>
+ <typeparam name="TValue"></typeparam>
+ <typeparam name="TData"></typeparam>
+ </member>
+ <member name="T:ApiTools.Core.SelectOption`2">
+ <summary>
+ 閫夋嫨鍣ㄦ煡璇�-缁撴灉-椤�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SelectOption`2.Value">
+ <summary>
+ 鍊�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SelectOption`2.Label">
+ <summary>
+ 鏍囩
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SelectOption`2.Data">
+ <summary>
+ 鏁版嵁
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SetIsDisabledCommand">
+ <summary>
+ 璁剧疆鏄惁宸茬鐢ㄥ懡浠�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SetIsDisabledCommand.IsDisabled">
+ <summary>
+ 鏄惁宸茬鐢�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModel.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModel.Description">
+ <summary>
+ 鎻忚堪
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModel.Items">
+ <summary>
+ 鏋氫妇椤�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModel`1.Items">
+ <summary>
+ 鏋氫妇椤�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModelItem.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModelItem.Value">
+ <summary>
+ 鍊�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModelItem.Description">
+ <summary>
+ 鎻忚堪
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.EnumModelItem`1.Enum">
+ <summary>
+ 鏋氫妇
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.EnumUtils">
+ <summary>
+ 鏋氫妇宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.EnumUtils.GetModel``1">
+ <summary>
+ 鑾峰彇妯″瀷
+ </summary>
+ <typeparam name="T"></typeparam>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.EnumUtils.GetModel(System.Type)">
+ <summary>
+ 鑾峰彇妯″瀷
+ </summary>
+ <param name="type"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.EnumUtils.GetDescription``1(ApiTools.Core.EnumModel{``0},``0)">
+ <summary>
+ 鑾峰彇鎻忚堪
+ </summary>
+ <typeparam name="T"></typeparam>
+ <param name="model"></param>
+ <param name="t"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.EnumUtils.GetEnum``1(System.String)">
+ <summary>
+ 鑾峰彇鏋氫妇
+ </summary>
+ <typeparam name="T"></typeparam>
+ <param name="model"></param>
+ <param name="name"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.EnumUtils.GetCustomAttribute``2(``0)">
+ <summary>
+ 鑾峰彇鑷畾涔夌壒鎬�
+ </summary>
+ <typeparam name="TEnum"></typeparam>
+ <typeparam name="TAttribute"></typeparam>
+ <param name="enum"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.EventBusServiceComponent">
+ <summary>
+ 浜嬩欢鎬荤嚎
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.RabbitMQEventSourceStorer._channel">
+ <summary>
+ 鍐呭瓨閫氶亾浜嬩欢婧愬瓨鍌ㄥ櫒
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.RabbitMQEventSourceStorer._model">
+ <summary>
+ 閫氶亾瀵硅薄
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.RabbitMQEventSourceStorer._connection">
+ <summary>
+ 杩炴帴瀵硅薄
+ </summary>
+ </member>
+ <member name="F:ApiTools.Core.RabbitMQEventSourceStorer._routeKey">
+ <summary>
+ 璺敱閿�
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.RabbitMQEventSourceStorer.#ctor(RabbitMQ.Client.ConnectionFactory,System.String,System.Int32)">
+ <summary>
+ 鏋勯�犲嚱鏁�
+ </summary>
+ <param name="factory">杩炴帴宸ュ巶</param>
+ <param name="routeKey">璺敱閿�</param>
+ <param name="capacity">瀛樺偍鍣ㄦ渶澶氳兘澶熷鐞嗗灏戞秷鎭紝瓒呰繃璇ュ閲忚繘鍏ョ瓑寰呭啓鍏�</param>
+ </member>
+ <member name="M:ApiTools.Core.RabbitMQEventSourceStorer.WriteAsync(Furion.EventBus.IEventSource,System.Threading.CancellationToken)">
+ <summary>
+ 灏嗕簨浠舵簮鍐欏叆瀛樺偍鍣�
+ </summary>
+ <param name="eventSource">浜嬩欢婧愬璞�</param>
+ <param name="cancellationToken">鍙栨秷浠诲姟 Token</param>
+ <returns><see cref="T:System.Threading.Tasks.ValueTask"/></returns>
+ </member>
+ <member name="M:ApiTools.Core.RabbitMQEventSourceStorer.ReadAsync(System.Threading.CancellationToken)">
+ <summary>
+ 浠庡瓨鍌ㄥ櫒涓鍙栦竴鏉′簨浠舵簮
+ </summary>
+ <param name="cancellationToken">鍙栨秷浠诲姟 Token</param>
+ <returns>浜嬩欢婧愬璞�</returns>
+ </member>
+ <member name="M:ApiTools.Core.RabbitMQEventSourceStorer.Dispose">
+ <summary>
+ 閲婃斁闈炴墭绠¤祫婧�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ExcelUtils">
+ <summary>
+ Excel宸ュ叿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IFriendlyResult.TraceId">
+ <summary>
+ 璺熻釜Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IFriendlyResult.Code">
+ <summary>
+ 鐘舵�佺爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IFriendlyResult.ErrorCode">
+ <summary>
+ 閿欒鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IFriendlyResult.Success">
+ <summary>
+ 鎵ц鎴愬姛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IFriendlyResult.Msg">
+ <summary>
+ 閿欒淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IFriendlyResult.Extras">
+ <summary>
+ 闄勫姞鏁版嵁
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.IFriendlyResult.Timestamp">
+ <summary>
+ 鏃堕棿鎴�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.FriendlyResult`1">
+ <summary>
+ 鍙嬪ソ杩斿洖鍊�
+ </summary>
+ <typeparam name="T"></typeparam>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.TraceId">
+ <summary>
+ 璺熻釜Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.Code">
+ <summary>
+ 鐘舵�佺爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.ErrorCode">
+ <summary>
+ 閿欒鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.Data">
+ <summary>
+ 鏁版嵁
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.Success">
+ <summary>
+ 鎵ц鎴愬姛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.Msg">
+ <summary>
+ 閿欒淇℃伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.Extras">
+ <summary>
+ 闄勫姞鏁版嵁
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.FriendlyResult`1.Timestamp">
+ <summary>
+ 鏃堕棿鎴�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.FriendlyResultProvider">
+ <summary>
+ RESTful 椋庢牸杩斿洖鍊�
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.FriendlyResultProvider.OnAuthorizeException(Microsoft.AspNetCore.Http.DefaultHttpContext,Furion.FriendlyException.ExceptionMetadata)">
+ <summary>
+ JWT 鎺堟潈寮傚父杩斿洖鍊�
+ </summary>
+ <param name="context"></param>
+ <param name="metadata"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.FriendlyResultProvider.OnException(Microsoft.AspNetCore.Mvc.Filters.ExceptionContext,Furion.FriendlyException.ExceptionMetadata)">
+ <summary>
+ 寮傚父杩斿洖鍊�
+ </summary>
+ <param name="context"></param>
+ <param name="metadata"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.FriendlyResultProvider.OnSucceeded(Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext,System.Object)">
+ <summary>
+ 鎴愬姛杩斿洖鍊�
+ </summary>
+ <param name="context"></param>
+ <param name="data"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.FriendlyResultProvider.OnValidateFailed(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext,Furion.DataValidation.ValidationMetadata)">
+ <summary>
+ 楠岃瘉澶辫触杩斿洖鍊�
+ </summary>
+ <param name="context"></param>
+ <param name="metadata"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.FriendlyResultProvider.OnResponseStatusCodes(Microsoft.AspNetCore.Http.HttpContext,System.Int32,Furion.UnifyResult.UnifyResultSettingsOptions)">
+ <summary>
+ 鐗瑰畾鐘舵�佺爜杩斿洖鍊�
+ </summary>
+ <param name="context"></param>
+ <param name="statusCode"></param>
+ <param name="unifyResultSettings"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.FriendlyResultProvider.GetResult(System.Int32,System.Boolean,System.Object,System.String,System.Object)">
+ <summary>
+ 杩斿洖 RESTful 椋庢牸缁撴灉闆�
+ </summary>
+ <param name="statusCode"></param>
+ <param name="succeeded"></param>
+ <param name="data"></param>
+ <param name="errorCode"></param>
+ <param name="errors"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.Utils.JsonUtils.NewtonsoftJsonSerializerProvider">
+ <summary>
+ Newtonsoft.Json 瀹炵幇
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.Utils.JsonUtils.NewtonsoftJsonSerializerProvider.Serialize(System.Object,System.Object)">
+ <summary>
+ 搴忓垪鍖栧璞�
+ </summary>
+ <param name="value"></param>
+ <param name="jsonSerializerOptions"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.Utils.JsonUtils.NewtonsoftJsonSerializerProvider.Deserialize``1(System.String,System.Object)">
+ <summary>
+ 鍙嶅簭鍒楀寲瀛楃涓�
+ </summary>
+ <typeparam name="T"></typeparam>
+ <param name="json"></param>
+ <param name="jsonSerializerOptions"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.Utils.JsonUtils.NewtonsoftJsonSerializerProvider.Deserialize(System.String,System.Type,System.Object)">
+ <summary>
+ 鍙嶅簭鍒楀寲瀛楃涓�
+ </summary>
+ <param name="json"></param>
+ <param name="returnType"></param>
+ <param name="jsonSerializerOptions"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.Utils.JsonUtils.NewtonsoftJsonSerializerProvider.GetSerializerOptions">
+ <summary>
+ 杩斿洖璇诲彇鍏ㄥ眬閰嶇疆鐨� JSON 閫夐」
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenRequest">
+ <summary>
+ 寰俊灏忕▼搴忚幏鍙栨帴鍙h皟鐢ㄥ嚟鎹�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenRequest.GrantType">
+ <summary>
+ 濉啓 client_credential
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenRequest.Appid">
+ <summary>
+ 灏忕▼搴忓敮涓�鍑瘉锛屽嵆 AppID锛屽彲鍦ㄣ�屽井淇″叕浼楀钩鍙� - 璁剧疆 - 寮�鍙戣缃�嶉〉涓幏寰椼�傦紙闇�瑕佸凡缁忔垚涓哄紑鍙戣�咃紝涓斿笎鍙锋病鏈夊紓甯哥姸鎬�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenRequest.Secret">
+ <summary>
+ 灏忕▼搴忓敮涓�鍑瘉瀵嗛挜锛屽嵆 AppSecret锛岃幏鍙栨柟寮忓悓 appid
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenResponse">
+ <summary>
+ 寰俊灏忕▼搴忚幏鍙栨帴鍙h皟鐢ㄥ嚟鎹�-缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenResponse.AccessToken">
+ <summary>
+ 鑾峰彇鍒扮殑鍑瘉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.Utils.WxmpUtils.WxmpGetAccessTokenResponse.ExpiresIn">
+ <summary>
+ 鍑瘉鏈夋晥鏃堕棿锛屽崟浣嶏細绉掋�傜洰鍓嶆槸7200绉掍箣鍐呯殑鍊笺��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.Id">
+ <summary>
+ 鐢ㄦ埛Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.AccessToken">
+ <summary>
+ 鐢ㄦ埛璁块棶浠ょ墝
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.RefreshToken">
+ <summary>
+ 鍒锋柊浠ょ墝
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.Avatar">
+ <summary>
+ 澶村儚
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.Name">
+ <summary>
+ 鏄电О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.UserName">
+ <summary>
+ 鐢ㄦ埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.Level">
+ <summary>
+ 绾у埆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.Type">
+ <summary>
+ 鐢ㄦ埛绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.ClientType">
+ <summary>
+ 瀹㈡埛绔被鍨�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CurrentLogier.ChannelId">
+ <summary>
+ 娓犻亾Id
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.JwtHandler.PipelineAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext,Microsoft.AspNetCore.Http.DefaultHttpContext)">
+ <summary>
+ 楠岃瘉绠¢亾锛屼篃灏辨槸楠岃瘉鏍稿績浠g爜
+ </summary>
+ <param name="context"></param>
+ <param name="httpContext"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.JwtUtils.GenerateToken(ApiTools.Core.CurrentLogier)">
+ <summary>
+ 鐢熸垚鐢ㄦ埛浠ょ墝
+ </summary>
+ <param name="logier"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.JwtUtils.GetCurrentLogier(ApiTools.Core.User,ApiTools.Core.EnumClientType,System.String)">
+ <summary>
+ 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛
+ </summary>
+ <param name="user"></param>
+ <param name="clientType"></param>
+ <param name="session_key"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.JwtUtils.GetCurrentLogier">
+ <summary>
+ 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.PasswordUtils">
+ <summary>
+ 瀵嗙爜宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.PasswordUtils.EncryptPassword(System.String)">
+ <summary>
+ 鍔犲瘑
+ </summary>
+ <param name="password"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.CorAcctBalanceQueryRequest">
+ <summary>
+ 浼佷笟璐︽埛浣欓鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryRequest.Account">
+ <summary>
+ 璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryRequest.CcyType">
+ <summary>
+ 閽炴眹鏍囧織 C 閽炴埛, R姹囨埛,榛樿涓篊
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryRequest.CcyCode">
+ <summary>
+ 璐у竵绫诲瀷 RMB 浜烘皯甯�,USD 缇庡厓锛孒KD 娓竵, 榛樿涓篟MB
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.CorAcctBalanceQueryResponse">
+ <summary>
+ 浼佷笟璐︽埛浣欓鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.Account">
+ <summary>
+ 璐﹀彿
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.CcyCode">
+ <summary>
+ 璐у竵绫诲瀷
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.CcyType">
+ <summary>
+ 閽炴眹鏍囧織
+ 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.AccountName">
+ <summary>
+ 璐︽埛鎴峰悕
+ 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.Balance">
+ <summary>
+ 鍙敤浣欓 涓嶅惈闆嗗洟鐜伴噾绠$悊鍚堢害浣欓
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.TotalAmount">
+ <summary>
+ 璐﹂潰浣欓 涓嶅惈闆嗗洟鐜伴噾绠$悊鍚堢害浣欓
+ 鏁版嵁闀垮害锛�13锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.AccountStatus">
+ <summary>
+ 璐︽埛鐘舵�� 璐︽埛灞傜姸鎬侊紝A姝e父銆丏涓嶅姩鎴枫�両 涔呮偓鎴凤紝鑻ユ湁澶氫釜鐘舵�侊紝鈥渱鈥濆垎鍓诧紝濡傦細A| DGZH02銆侱GZH02: 璐︽埛姝粯
+ 鏁版嵁闀垮害锛�10锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.HoldBalance">
+ <summary>
+ 鍐荤粨閲戦
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.StopBalance">
+ <summary>
+ 姝粯閲戦
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.LastBalance">
+ <summary>
+ 鏄ㄦ棩浣欓
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.HRate1">
+ <summary>
+ 娲绘湡瀛樻璁℃伅鎵ц鍒╃巼 鍗曚綅%
+ 鏁版嵁闀垮害锛�2,6锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.XDRate2">
+ <summary>
+ 鍗忓畾鎵ц鍒╃巼 鍗忚瀛樻璁℃伅鎵ц鍒╃巼锛屽崟浣�%
+ 鏁版嵁闀垮害锛�2,6锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.AcctBalance">
+ <summary>
+ 璐︽埛浣欓
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.AgreeDepReserveBalance">
+ <summary>
+ 鍗忓畾棰濆害 鍗忓畾瀛樻鐣欏瓨浣欓
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.BeginEffectDate">
+ <summary>
+ 寮�濮嬬敓鏁堟棩鏈�
+ 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.ExpiryDate">
+ <summary>
+ 鍒版湡鏃�
+ 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.AgreeDepositInterest">
+ <summary>
+ 鍒╂伅閲戦 鍗忓畾瀛樻鍒╂伅
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.AgreeDepositInterestType">
+ <summary>
+ 鍒╂伅绉嶇被 鍗忓畾鍒╂伅
+ 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.EnableFlagEndTime">
+ <summary>
+ 瑙﹀彂鏍囪瘑纭畾鍗忚鐨勭粨鏉熸椂闂� 鍗忓畾鍒版湡鏃�
+ 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorAcctBalanceQueryResponse.AccountStatusDesc">
+ <summary>
+ 璐︽埛鐘舵�佸瓧
+ 鑻ユ湁澶氫釜鐘舵�佸瓧锛屸�渱鈥濆垎鍓诧紝濡傦細DGZH02-璐︽埛姝粯|DGZH06-鍙敹涓嶄粯鐘舵�佸瓧鍊煎涓嬶紝鍙兘浼氭柊澧烇細
+ DGZH02-璐︽埛姝粯锛�
+ DGZH03-鍗伴壌鎸傚け锛�
+ DGZHE6-棰勫紑鎴凤紝
+ DGZHG9-寮�鎴蜂笁澶╃鎺э紝
+ DGZH06-鍙敹涓嶄粯锛�
+ DGZH07-涓嶄粯涓嶆敹锛�
+ DGZH08-鍙粯涓嶆敹锛�
+ DGBZ02-璐︽埛姝粯锛�
+ DGBZ07-涓嶄粯涓嶆敹锛�
+ DGBZG9-寮�鎴蜂笁澶╃鎺э紝
+ ZH9999-鍏朵粬寮傚父
+ 鏁版嵁闀垮害锛�500锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.CorSingleTransferQueryRequest">
+ <summary>
+ 鍗曠瑪杞处鎸囦护鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryRequest.OrigThirdVoucher">
+ <summary>
+ 杞处鍑瘉鍙�
+ "鎺ㄨ崘浣跨敤锛�
+ 浣跨敤4004鎺ュ彛涓婇�佺殑ThirdVoucher鎴栬��4014涓婇�佺殑SThirdVoucher"
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryRequest.OrigFrontLogNo">
+ <summary>
+ 閾惰娴佹按鍙�
+ 涓嶆帹鑽愪娇鐢紱閾惰杩斿洖鐨勮浆璐︽祦姘村彿
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.CorSingleTransferQueryResponse">
+ <summary>
+ 鍗曠瑪杞处鎸囦护鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.OrigThirdVoucher">
+ <summary>
+ 杞处鍑瘉鍙�
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.FrontLogNo">
+ <summary>
+ 閾惰娴佹按鍙�
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.CstInnerFlowNo">
+ <summary>
+ 瀹㈡埛鑷畾涔夊嚟璇佸彿
+ 瀹㈡埛涓婇�佸垯杩斿洖
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.CcyCode">
+ <summary>
+ 璐у竵绫诲瀷
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.OutAcctBankName">
+ <summary>
+ 杞嚭璐︽埛寮�鎴风綉鐐瑰悕
+ 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.OutAcctNo">
+ <summary>
+ 杞嚭璐︽埛
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.InAcctBankName">
+ <summary>
+ 杞叆璐︽埛缃戠偣鍚嶇О
+ 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.InAcctNo">
+ <summary>
+ 杞叆璐︽埛
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.InAcctName">
+ <summary>
+ 杞叆璐︽埛鎴峰悕
+ 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.TranAmount">
+ <summary>
+ 浜ゆ槗閲戦
+ 鏁版嵁闀垮害锛�13锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.UnionFlag">
+ <summary>
+ 琛屽唴璺ㄨ鏍囧織
+ 1锛氳鍐呰浆璐︼紝0锛氳法琛岃浆璐�
+ 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.Stt">
+ <summary>
+ 浜ゆ槗鐘舵�佹爣蹇�
+ "20锛氭垚鍔�
+ 30锛氬け璐�
+ 鍏朵粬涓洪摱琛屽彈鐞嗘垚鍔熷鐞嗕腑"
+ 鏁版嵁闀垮害锛�2锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.IsBack">
+ <summary>
+ 杞处閫�绁ㄦ爣蹇�
+ "0:鏈��绁�; 榛樿涓�0
+ 1:閫�绁�;"
+ 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.BackRem">
+ <summary>
+ 鏀粯澶辫触鎴栭��绁ㄥ師鍥犳弿杩�
+ "濡傛灉鏄秴绾х綉閾跺垯杩斿洖濡備笅淇℃伅:
+ RJ01瀵规柟杩斿洖锛氳处鍙蜂笉瀛樺湪
+ RJ02瀵规柟杩斿洖锛氳处鍙枫�佹埛鍚嶄笉绗�
+ 澶у皬棰濇敮浠樺垯杩斿洖澶辫触鎻忚堪"
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.Yhcljg">
+ <summary>
+ 閾惰澶勭悊缁撴灉
+ "鏍煎紡涓猴細鈥滃叚浣嶄唬鐮�:涓枃鎻忚堪鈥濄�傚啋鍙蜂负鍗婅銆傚锛�000000锛氳浆璐︽垚鍔�
+ 澶勭悊涓殑杩斿洖(浠ュ涓嬭繑鍥炲紑澶�)锛�
+ MA9111:浜ゆ槗姝e湪鍙楃悊涓�
+ 000000:浜ゆ槗鍙楃悊鎴愬姛寰呭鐞�
+ 000000:浜ゆ槗澶勭悊涓�
+ 000000:浜ゆ槗鍙楃悊鎴愬姛澶勭悊涓�
+ 鎴愬姛鐨勮繑鍥烇細
+ 000000:杞处浜ゆ槗鎴愬姛
+ 鍏朵粬鐨勮繑鍥為兘涓哄け璐�:
+ MA9112:杞处澶辫触"
+ 鏁版嵁闀垮害锛�40锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.SysFlag">
+ <summary>
+ 杞处鍔犳�ユ爣蹇�
+ Y锛氬姞鎬� N锛氭櫘閫歋锛氱壒鎬�
+ 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.Fee">
+ <summary>
+ 杞处鎵嬬画璐�
+ 鏁版嵁闀垮害锛�13锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.TransBsn">
+ <summary>
+ 杞处浠g爜绫诲瀷
+ "4004锛氬崟绗旇浆璐︼紱
+ 4014锛氬崟绗旀壒閲忥紱
+ 4034锛氭眹鎬绘壒閲�"
+ 鏁版嵁闀垮害锛�4锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.SubmitTime">
+ <summary>
+ 浜ゆ槗鍙楃悊鏃堕棿
+ 浜ゆ槗鍙楃悊鏃堕棿
+ 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.AccountDate">
+ <summary>
+ 璁拌处鏃ユ湡
+ 涓绘満璁拌处鏃ユ湡
+ 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.HostFlowNo">
+ <summary>
+ 涓绘満璁拌处娴佹按鍙�
+ 涓绘満璁拌处娴佹按
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.HostErrorCode">
+ <summary>
+ 閿欒鐮�
+ 浜ゆ槗澶辫触鐨勯敊璇唬鐮�
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.ProxyPayName">
+ <summary>
+ 浠g悊浜烘埛鍚�
+ 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.ProxyPayAcc">
+ <summary>
+ 浠g悊浜鸿处鍙�
+ 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CorSingleTransferQueryResponse.ProxyPayBankName">
+ <summary>
+ 浠g悊浜洪摱琛屽悕绉�
+ 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.HistoryBalanceQueryRequest">
+ <summary>
+ 鍘嗗彶浣欓鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryRequest.Account">
+ <summary>
+ 璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryRequest.RptDate">
+ <summary>
+ 鍘嗗彶鏃ユ湡 yyyyMMdd闄愬埗鏌ヨ褰撳墠鏃ユ湡鐨勫墠360澶╁唴鐨�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryRequest.Reserve">
+ <summary>
+ 淇濈暀鍩�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.HistoryBalanceQueryResponse">
+ <summary>
+ 鍘嗗彶浣欓鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.AcctNo">
+ <summary>
+ 璐﹀彿
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.CcyCode">
+ <summary>
+ 甯佺
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.BeginDate">
+ <summary>
+ 寮�濮嬫棩鏈�
+ "鑻ユ煡璇㈠綋鏃ユ槑缁嗭紝寮�濮嬨�佺粨鏉熸棩鏈熷繀椤讳负褰撳ぉ锛涜嫢鏌ヨ鍘嗗彶鏄庣粏锛屽紑濮嬨�佺粨鏉熸棩鏈熷繀椤绘槸鍘嗗彶鏃ユ湡銆�
+ 鏍煎紡yyyyMMdd"
+ 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.EndDate">
+ <summary>
+ 缁撴潫鏃ユ湡
+ 鏍煎紡yyyyMMdd
+ 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.PageNo">
+ <summary>
+ 鏌ヨ椤电爜
+ 1锛氱涓�椤碉紝渚濇閫掑
+ 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.PageSize">
+ <summary>
+ 姣忛〉鏄庣粏鏁伴噺
+ "褰撴棩鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�100鏉★紝鑻ヤ笂閫丳ageSize>100鏃犳晥锛岀瓑鍚�100锛�
+ 鍘嗗彶鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�1000鏉★紝鑻ヤ笂閫丳ageSize>1000鍒欐彁绀鸿緭鍏ラ敊璇紱
+ 涓旀瘡娆℃煡璇㈠繀椤诲浐瀹氫负姝ゅ�硷紝鍚﹀垯鍑虹幇鏄庣粏閬楁紡"
+ 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.Reserve">
+ <summary>
+ 棰勭暀瀛楁
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.OrderMode">
+ <summary>
+ 璁板綍鎺掑簭鏍囧織
+ "001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ 002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ 璇存槑锛�
+ 鈶� 褰撲负鍘嗗彶浜ゆ槗鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ 鈶� 褰撲负褰撴棩鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ 锛堟敞锛氬綋鏃ユ槑缁嗗湪浜ゆ槗閲忓ぇ鐨勬儏鍐典笅锛屽繀椤婚噰鐢ㄦ搴忔煡璇紝鍚﹀垯浼氬鑷翠氦鏄撻仐婕忓拰閲嶅锛�"
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.BankTranFlowNo">
+ <summary>
+ 閾惰浜ゆ槗娴佹按鍙�
+ 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.HistoryBalanceQueryResponse.OppAcctNo">
+ <summary>
+ 浜ゆ槗瀵规墜璐﹀彿
+ 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest">
+ <summary>
+ 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.AcctNo">
+ <summary>
+ 璐﹀彿
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.CcyCode">
+ <summary>
+ 甯佺
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.BeginDate">
+ <summary>
+ 寮�濮嬫棩鏈�
+ "鑻ユ煡璇㈠綋鏃ユ槑缁嗭紝寮�濮嬨�佺粨鏉熸棩鏈熷繀椤讳负褰撳ぉ锛涜嫢鏌ヨ鍘嗗彶鏄庣粏锛屽紑濮嬨�佺粨鏉熸棩鏈熷繀椤绘槸鍘嗗彶鏃ユ湡銆�
+ 鏍煎紡yyyyMMdd"
+ 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.EndDate">
+ <summary>
+ 缁撴潫鏃ユ湡
+ 鏍煎紡yyyyMMdd
+ 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.PageNo">
+ <summary>
+ 鏌ヨ椤电爜
+ 1锛氱涓�椤碉紝渚濇閫掑
+ 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.PageSize">
+ <summary>
+ 姣忛〉鏄庣粏鏁伴噺
+ "褰撴棩鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�100鏉★紝鑻ヤ笂閫丳ageSize>100鏃犳晥锛岀瓑鍚�100锛�
+ 鍘嗗彶鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�1000鏉★紝鑻ヤ笂閫丳ageSize>1000鍒欐彁绀鸿緭鍏ラ敊璇紱
+ 涓旀瘡娆℃煡璇㈠繀椤诲浐瀹氫负姝ゅ�硷紝鍚﹀垯鍑虹幇鏄庣粏閬楁紡"
+ 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.Reserve">
+ <summary>
+ 棰勭暀瀛楁
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.OrderMode">
+ <summary>
+ 璁板綍鎺掑簭鏍囧織
+ "001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ 002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ 璇存槑锛�
+ 鈶� 褰撲负鍘嗗彶浜ゆ槗鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ 鈶� 褰撲负褰撴棩鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ 锛堟敞锛氬綋鏃ユ槑缁嗗湪浜ゆ槗閲忓ぇ鐨勬儏鍐典笅锛屽繀椤婚噰鐢ㄦ搴忔煡璇紝鍚﹀垯浼氬鑷翠氦鏄撻仐婕忓拰閲嶅锛�"
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.BankTranFlowNo">
+ <summary>
+ 閾惰浜ゆ槗娴佹按鍙�
+ 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest.OppAcctNo">
+ <summary>
+ 浜ゆ槗瀵规墜璐﹀彿
+ 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponse">
+ <summary>
+ 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponse.AcctNo">
+ <summary>
+ 璐﹀彿
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponse.CcyCode">
+ <summary>
+ 璐у竵绫诲瀷
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponse.EndFlag">
+ <summary>
+ 鏁版嵁缁撴潫鏍囧織
+ "鈥淵鈥�---琛ㄧず鏌ヨ缁撴灉宸插叏閮ㄨ緭鍑哄畬姣曪紱
+ 鈥淣鈥�---琛ㄧず鏌ヨ缁撴灉鍙緭鍑轰竴閮ㄥ垎锛屽悗缁儴鍒嗘湁寰呰姹傝緭鍑猴紱"
+ 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponse.Reserve">
+ <summary>
+ 棰勭暀瀛楁
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponse.PageNo">
+ <summary>
+ 鏌ヨ椤电爜
+ 鍚屼笂閫�
+ 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細Y
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponse.PageRecCount">
+ <summary>
+ 璁板綍绗旀暟
+ 鏈杩斿洖鐨勭瑪鏁�
+ 鏁版嵁闀垮害锛�2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem">
+ <summary>
+ 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.AcctDate">
+ <summary>
+ 涓绘満璁拌处鏃ユ湡
+ 璁拌处鏃ユ湡
+ 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.TxTime">
+ <summary>
+ 浜ゆ槗鏃堕棿
+ 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.HostTrace">
+ <summary>
+ 涓绘満娴佹按鍙�
+ 閾惰璁拌处娴佹按鍙�
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.BussSeqNo">
+ <summary>
+ 涓氬姟娴佹按鍙�
+ 閾惰涓氬姟娴佹按鍙�
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.DetailSerialNo">
+ <summary>
+ 鏄庣粏搴忓彿
+ 鏄庣粏搴忓彿锛屽師鏉ュ拰鏍稿績姘村彿涓�璧峰尯鍒嗕氦鏄撳敮涓�鎬�
+ 鏁版嵁闀垮害锛�19锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.OutNode">
+ <summary>
+ 浠樻鏂圭綉鐐瑰彿
+ 鏁版嵁闀垮害锛�9锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.OutBankNo">
+ <summary>
+ 浠樻鏂硅仈琛屽彿
+ 鏁版嵁闀垮害锛�16锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.OutBankName">
+ <summary>
+ 浠樻琛屽悕绉�
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.OutAcctNo">
+ <summary>
+ 浠樻鏂硅处鍙�
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.OutAcctName">
+ <summary>
+ 浠樻鏂规埛鍚�
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.CcyCode">
+ <summary>
+ 缁撶畻甯佺
+ 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.TranAmount">
+ <summary>
+ 浜ゆ槗閲戦
+ 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.InNode">
+ <summary>
+ 鏀舵鏂圭綉鐐瑰彿
+ 鏁版嵁闀垮害锛�9锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.InBankNo">
+ <summary>
+ 鏀舵鏂硅仈琛屽彿
+ 鏁版嵁闀垮害锛�16锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.InBankName">
+ <summary>
+ 鏀舵鏂硅鍚�
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.InAcctNo">
+ <summary>
+ 鏀舵鏂硅处鍙�
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.InAcctName">
+ <summary>
+ 鏀舵鏂规埛鍚�
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.DcFlag">
+ <summary>
+ 鍊熻捶鏍囧織
+ D 鍊燂紱C 璐�
+ 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.AbstractStr">
+ <summary>
+ 鎽樿锛屾湭缈昏瘧鐨勬憳瑕侊紝濡俆RS
+ 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.VoucherNo">
+ <summary>
+ 鍑瘉鍙�
+ 绌�
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.TranFee">
+ <summary>
+ 鎵嬬画璐�
+ 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.PostFee">
+ <summary>
+ 閭數璐�
+ 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.AcctBalance">
+ <summary>
+ 璐﹂潰浣欓
+ 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.Purpose">
+ <summary>
+ 鐢ㄩ�旓紝闄勮█
+ 瀹㈡埛杞处涓婇�佺殑璧勯噾鐢ㄩ�斻��
+ 鏁版嵁闀垮害锛�300锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.AbstractStr_Desc">
+ <summary>
+ 涓枃鎽樿锛孉bstractStr鐨勪腑鏂囩炕璇�
+ 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.ProxyPayName">
+ <summary>
+ 浠g悊浜烘埛鍚�
+ 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.ProxyPayAcc">
+ <summary>
+ 浠g悊浜鸿处鍙�
+ 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.ProxyPayBankName">
+ <summary>
+ 浠g悊浜洪摱琛屽悕绉�
+ 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.HostDate">
+ <summary>
+ 涓绘満鏃ユ湡
+ 浜ゆ槗鑷劧鏃ユ湡
+ 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.TranSeqNo">
+ <summary>
+ 浜ゆ槗娴佹按鍙�
+ 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.Remark1">
+ <summary>
+ 澶囨敞1
+ 鏁版嵁闀垮害锛�300锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.Remark2">
+ <summary>
+ 澶囨敞2
+ 鏁版嵁闀垮害锛�300锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.BeReverseFlag">
+ <summary>
+ 琚啿姝f爣蹇�
+ "0--鏃犲叧锛�
+ 1--琚啿姝o紱
+ 2--鍐叉"
+ 鏁版嵁闀垮害锛�2锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.SeqTime">
+ <summary>
+ 鏃跺簭鏃堕棿
+ 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsResponseItem.FeeCode">
+ <summary>
+ 璐圭敤浠g爜
+ 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.InquiryAccountStopPaymentDetailsRequest">
+ <summary>
+ 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsRequest.AccountNo">
+ <summary>
+ 璐︽埛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsRequest.PageNo">
+ <summary>
+ 椤电爜 浠�1寮�濮嬮�掑锛岄粯璁�1
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.InquiryAccountStopPaymentDetailsResponse">
+ <summary>
+ 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponse.CSize">
+ <summary>
+ 褰撳墠椤佃褰曟暟閲�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponse.EndFlag">
+ <summary>
+ 缈婚〉缁撴潫鏍囧織 N-鏈粨鏉燂紝鏈変笅涓�椤碉紝椤甸潰閫掑锛沋-宸茬粨鏉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponse.List">
+ <summary>
+
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.InquiryAccountStopPaymentDetailsResponseItem">
+ <summary>
+ 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponseItem.StopPayFlw">
+ <summary>
+ 姝粯缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponseItem.StartDate">
+ <summary>
+ 鍐荤粨璧峰鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponseItem.EndDate">
+ <summary>
+ 鍐荤粨缁撴潫鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponseItem.Remark">
+ <summary>
+ 澶囨敞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponseItem.StopCode">
+ <summary>
+ 姝粯浠g爜 02-涓存椂姝粯
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.InquiryAccountStopPaymentDetailsResponseItem.FreezeStatu">
+ <summary>
+ 姝粯鐘舵�� 0-鏈夋晥 1-鏃犳晥
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PingAnPayBaseRequest.MrChCode">
+ <summary>
+ 浼佷笟閾朵紒鐩磋仈鏍囧噯浠g爜 閾惰鎻愪緵缁欎紒涓氱殑20浣嶅敮涓�鐨勬爣璇嗕唬鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PingAnPayBaseRequest.RecvLength">
+ <summary>
+ 鎺ユ敹鎶ユ枃闀垮害 鎶ユ枃鏁版嵁闀垮害锛涗笉鍖呮嫭闄勪欢鍐呭銆佺鍚嶅唴瀹圭殑闀垮害锛屼笉澶熷乏琛�0
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PingAnPayBaseRequest.TradeDate">
+ <summary>
+ 浜ゆ槗鏃ユ湡(yyyyMMdd)
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PingAnPayBaseRequest.TradeTime">
+ <summary>
+ 浜ゆ槗鏃堕棿 hhmmss
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PingAnPayBaseRequest.CnsmrSeqNo">
+ <summary>
+ 璇锋眰鏂圭郴缁熸祦姘村彿
+ 鍞竴鏍囪瘑涓�绗斾氦鏄� 澶囨敞锛氾紙濡傛灉鏌愮浜ゆ槗瑕佹湁澶氭璇锋眰鐨勬墠鑳藉畬鎴愮殑锛屽涓氦鏄撹姹傚寘娴佹按鍙疯淇濇寔涓�鑷达級
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest">
+ <summary>
+ 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.OutAccNo">
+ <summary>
+ 璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.AccountBeginDate">
+ <summary>
+ 璁拌处璧峰鏃ユ湡 鏌ヨ褰撴棩鏃犻渶杈撳叆姝ゅ瓧娈� 鏌ヨ鍘嗗彶鍥炲崟蹇呰緭(寮�濮嬬粨鏉熼兘闇�瑕佽緭鍏ワ紝蹇呴』鏄巻鍙叉棩鏈�)鏍煎紡YYYYMMDD
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.AccountEndDate">
+ <summary>
+ 璁拌处缁撴潫鏃ユ湡 鏌ヨ褰撴棩鏃犻渶杈撳叆姝ゅ瓧娈垫煡璇㈠巻鍙插洖鍗曞繀杈�(寮�濮嬬粨鏉熼兘闇�瑕佽緭鍏ワ紝蹇呴』鏄巻鍙叉棩鏈�)鏍煎紡YYYYMMDD
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.HostFlow">
+ <summary>
+ 鏍稿績娴佹按鍙� 閾惰鏍稿績娴佹按鍙枫�侀摱琛屼富鏈烘祦姘村彿銆傚鍙�4005杩斿洖鐨凥ostFlowNo锛�4013杩斿洖鐨凥ostFlowNo.
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.StartTranAmt">
+ <summary>
+ 璧峰浜ゆ槗閲戦
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.EndTranAmt">
+ <summary>
+ 缁撴潫浜ゆ槗閲戦
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.InAccNo">
+ <summary>
+ 鏀舵甯愬彿 瀵规柟甯愬彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.DcFlag">
+ <summary>
+ 鍊熻捶鏍囧織 D:鍊� C:璐�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.SortType">
+ <summary>
+ 鎺掑簭鏂瑰紡
+ 0锛氶粯璁ゆ帓搴�
+ 1:浜ゆ槗鏃堕棿浠庤繎鑷宠繙
+ 2:浜ゆ槗鏃堕棿浠庤繙鑷宠繎
+ 3:閲戦鍗囧簭(浠庡皬鑷冲ぇ)
+ 4:閲戦闄嶅簭(浠庡ぇ鑷冲皬)
+ 5:鍥炲崟鍙峰崌搴�
+ 6:鍥炲崟鍙烽檷搴�
+ 7:涓氬姟缂栧彿鍗囧簭
+ 8:涓氬姟缂栧彿闄嶅簭
+ 9:鏍稿績娴佹按鍙蜂粠杩戝埌杩�
+ 10:鏍稿績娴佹按鍙蜂粠杩滃埌杩�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.CCY">
+ <summary>
+ 甯佺 榛樿RMB
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.ReceiptType">
+ <summary>
+ 鍥炲崟绫诲瀷 榛樿涓篈LL 鍏ㄩ儴锛屽叿浣撳弬鑰�3.9浠g爜瀵圭収琛�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.SubReceiptType">
+ <summary>
+ 瀛愬洖鍗曠被鍨� 榛樿涓篈LL 鍏ㄩ儴锛屽叿浣撳弬鑰�3.9浠g爜瀵圭収琛�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.RecordStartNo">
+ <summary>
+ 璁板綍璧峰鍙� 璁板綍璧峰鍙� 鐢ㄤ簬鍒嗛〉榛樿锛�1
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryRequest.RecordNumber">
+ <summary>
+ 璇锋眰璁板綍鏁� 鍒嗛〉鏉℃暟鏈�澶�100鏉� 榛樿锛�100
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SameDayHistoryReceiptDataQueryResponse">
+ <summary>
+ 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem">
+ <summary>
+ 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.SeqNo">
+ <summary>
+ 璁板綍搴忓彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.ReceiptNo">
+ <summary>
+ 鍥炲崟鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.ValidateNo">
+ <summary>
+ 楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.ReceiptType">
+ <summary>
+ 鍥炲崟绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.SubReceiptType">
+ <summary>
+ 鍥炲崟瀛愮被
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.AccountDate">
+ <summary>
+ 璁拌处鏃ユ湡 璁拌处鏃ユ湡锛屾牸寮弝yyyMMdd
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.MainAcc">
+ <summary>
+ 涓诲紶鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.SubAccNo">
+ <summary>
+ 瀛愬笎鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.OutAccNo">
+ <summary>
+ 浠樻璐︽埛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.OutAccName">
+ <summary>
+ 浠樻鎴峰悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.OutBranchName">
+ <summary>
+ 浠樻閾惰鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.DcFlag">
+ <summary>
+ 鍊熻捶鏍囧織
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.InAccNo">
+ <summary>
+ 鏀舵鏂硅处鎴�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.InAccName">
+ <summary>
+ 鏀舵鏂规埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.InBranchName">
+ <summary>
+ 鏀舵鏂归摱琛屽悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.Amount">
+ <summary>
+ 浜ゆ槗閲戦
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.CcyCode">
+ <summary>
+ 甯佺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.Remark">
+ <summary>
+ 澶囨敞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.HostFlowNo">
+ <summary>
+ 涓绘満娴佹按
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SameDayHistoryReceiptDataQueryResponseItem.ReceiptName">
+ <summary>
+ 鍥炲崟鍚嶇О
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleApplicationSuspensionPaymentRequest">
+ <summary>
+ 鍗曠瑪鐩戠姝粯鏀粯鐢宠_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.ThirdVoucher">
+ <summary>
+ 杞处鍑瘉鍙� 鏍囩ず浜ゆ槗鍞竴鎬э紝鍚屼竴瀹㈡埛涓婇�佺殑涓嶅彲閲嶅锛屽缓璁牸寮忥細yyyymmddHHSS+8浣嶇郴鍒椼�傝姹�6涓湀鍐呭敮涓�銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.BatchNo">
+ <summary>
+ 鎵规鍙� 閾惰姣忔棩鎸夋壒娆″彿浜х敓鏄庣粏鍥炲崟锛岃嫢鏈夋壒娆″洖鍗曢渶姹傦紝闇�瑕佷笂閫佹鎵规鍙枫�備笉鍚岀殑鎵规鍙蜂骇鐢熶笉鍚屽洖鍗曘��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.FreezeNo">
+ <summary>
+ 姝粯缂栧彿 鏈夋晥鐘舵�佺殑骞冲畨鏄撴浠樼紪鍙凤紝浠嶫GF001姝粯鍚庤繑鍥炵殑
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.CstInnerFlowNo">
+ <summary>
+ 瀹㈡埛鑷畾涔夊嚟璇佸彿 鐢ㄤ簬瀹㈡埛杞处鐧昏鍜屽唴閮ㄨ瘑鍒紝閫氳繃杞处缁撴灉鏌ヨ鍙互杩斿洖銆傞摱琛屼笉妫�鏌ュ敮涓�鎬�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.CcyCode">
+ <summary>
+ 璐у竵绫诲瀷 RMB-浜烘皯甯�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.OutAcctNo">
+ <summary>
+ 浠樻浜鸿处鎴� 鎵f璐︽埛锛堟浠樼姸鎬佺殑璐︽埛锛�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.OutAcctName">
+ <summary>
+ 浠樻浜哄悕绉� 浠樻璐︽埛鎴峰悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.OutAcctAddr">
+ <summary>
+ 浠樻浜哄湴鍧� 寤鸿濉啓浠樻璐︽埛鐨勫垎琛屻�佺綉鐐瑰悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.InAcctBankNode">
+ <summary>
+ 鏀舵浜哄紑鎴疯琛屽彿 璺ㄨ杞处寤鸿蹇呰緭銆備负浜鸿鐧昏鍦ㄥ唽鐨勫晢涓氶摱琛屽彿锛岃嫢杈撳叆鍒欓暱搴﹀繀椤诲湪4 ~12浣嶄箣闂达紱
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.InAcctRecCode">
+ <summary>
+ 鎺ユ敹琛岃鍙� 寤鸿鍚屾敹娆句汉寮�鎴疯琛屽彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.InAcctNo">
+ <summary>
+ 鏀舵浜鸿处鎴�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.InAcctName">
+ <summary>
+ 鏀舵浜鸿处鎴锋埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.InAcctBankName">
+ <summary>
+ 鏀舵浜哄紑鎴疯鍚嶇О 寤鸿鏍煎紡锛歺xx閾惰
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.InAcctProvinceCode">
+ <summary>
+ 鏀舵璐︽埛閾惰寮�鎴风渷浠g爜鎴栫渷鍚嶇О 寤鸿璺ㄨ杞处杈撳叆锛涘鐓х爜鍙傝�冣�滈檮褰�-鐪佸鐓ц〃鈥濓紱涔熷彲杈撳叆鈥滈檮褰�-鐪佸鐓ц〃鈥濅腑鐨勭渷鍚嶇О銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.InAcctCityName">
+ <summary>
+ 鏀舵璐︽埛寮�鎴峰競 寤鸿璺ㄨ杞处杈撳叆锛�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.TranAmount">
+ <summary>
+ 杞嚭閲戦 濡備负XML鎶ユ枃锛屽垯鐩存帴杈撳叆杈撳嚭浠ュ厓涓哄崟浣嶇殑娴偣鏁板�硷紝濡�2.50 (涓ゅ厓浜旇)
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.UseEx">
+ <summary>
+ 璧勯噾鐢ㄩ�� 100涓眽瀛楋紝瀵规柟鑳藉惁鐪嬪埌姝ょ敤閫旇鏀舵鏂归摱琛岀殑鏀寔銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.UnionFlag">
+ <summary>
+ 琛屽唴璺ㄨ鏍囧織 1锛氳鍐呰浆璐︼紝0锛氳法琛岃浆璐�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.SysFlag">
+ <summary>
+ 杞处鍔犳�ユ爣蹇� N锛氭櫘閫氾紙澶у皬棰濊嚜鍔ㄩ�夋嫨锛夛紝榛樿鍊硷紱Y锛氬姞鎬� 锛堝ぇ棰濓級锛�
+ S锛氱壒鎬�(瓒呯骇缃戦摱)锛�
+ T1锛氭繁鍦冲悓鍩庢櫘閫氾紱
+ T2锛氭繁鍦冲悓鍩庡疄鏃讹紱
+ 榛樿涓篘
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentRequest.AddrFlag">
+ <summary>
+ 鍚屽煄/寮傚湴鏍囧織 鈥�1鈥濃�斿悓鍩� 鈥�2鈥濃�斿紓鍦帮紱鑻ユ棤娉曞尯鍒嗭紝鍙粯璁ら��1-鍚屽煄銆�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleApplicationSuspensionPaymentResponse">
+ <summary>
+ 鍗曠瑪鐩戠姝粯鏀粯鐢宠_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.ThirdVoucher">
+ <summary>
+ 杞处鍑瘉鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.FrontLogNo">
+ <summary>
+ 閾惰娴佹按鍙� 閾惰涓氬姟娴佹按鍙凤紱鍙互鐢ㄤ簬瀵硅处
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.CstInnerFlowNo">
+ <summary>
+ 瀹㈡埛鑷畾涔夊嚟璇佸彿 鐢ㄤ簬瀹㈡埛杞处鐧昏鍜屽唴閮ㄨ瘑鍒紝閫氳繃杞处缁撴灉鏌ヨ鍙互杩斿洖銆傞摱琛屼笉妫�鏌ュ敮涓�鎬�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.CcyCode">
+ <summary>
+ 璐у竵绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.OutAcctName">
+ <summary>
+ 浠樻浜鸿处鎴峰悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.OutAcctNo">
+ <summary>
+ 浠樻浜鸿处鎴�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.InAcctBankName">
+ <summary>
+ 鏀舵浜哄紑鎴疯鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.InAcctNo">
+ <summary>
+ 鏀舵浜鸿处鎴�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.InAcctName">
+ <summary>
+ 鏀舵浜鸿处鎴锋埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.TranAmount">
+ <summary>
+ 浜ゆ槗閲戦
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.UnionFlag">
+ <summary>
+ 琛屽唴璺ㄨ鏍囧織 1锛氳鍐呰浆璐︼紝0锛氳法琛岃浆璐�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.Fee1">
+ <summary>
+ 鎵嬬画璐� 杞处鎵嬬画璐归绠楋紝瀹為檯鎵嬬画璐圭敤浠ュ疄闄呮墸鍙栫殑涓哄噯銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.Fee2">
+ <summary>
+ 閭數璐�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.HostFlowNo">
+ <summary>
+ 閾惰杩斿洖娴佹按鍙� 閾惰璁拌处娴佹按鍙凤紱杞处鎴愬姛鍚庯紝閾惰杩斿洖鐨勬祦姘村彿銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.HostTxDate">
+ <summary>
+ 璁拌处鏃ユ湡 閾惰浜ゆ槗鎴愬姛鍚庣殑璁拌处鏃ユ湡锛屼粎瀵硅鍐呭疄鏃惰浆璐︿氦鏄撴湁鏁堛��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleApplicationSuspensionPaymentResponse.Stt">
+ <summary>
+ 浜ゆ槗鐘舵�佹爣蹇� 20锛氫氦鏄撴垚鍔� 30锛氬け璐ワ紱鍏朵粬涓洪摱琛屽彈鐞嗘垚鍔熷鐞嗕腑锛岃浣跨敤鈥滀氦鏄撹繘搴︽煡璇�4005鈥濇帴鍙h幏鍙栨渶缁堢姸鎬�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleDataQueryRequest">
+ <summary>
+ 鍥炲崟鏁版嵁鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.AcctNo">
+ <summary>
+ 璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.ReceiptType">
+ <summary>
+ 鍥炲崟绫诲瀷 鍙傜収鍥炲崟绫诲瀷 娉細鏌ュ叏閮ㄥ彲閫佲�淎LL鈥�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.SubType">
+ <summary>
+ 瀛愮被鍨� 鍙傜収鍥炲崟绫诲瀷 娉細鏌ュ叏閮ㄥ彲閫佲�淎LL鈥�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.StartDate">
+ <summary>
+ 璧峰鏃ユ湡 鏍煎紡yyyyMMdd锛堣璐︽棩鏈燂級
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.EndDate">
+ <summary>
+ 缁撴潫鏃ユ湡 鏍煎紡yyyyMMdd锛堣璐︽棩鏈燂級
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.StartRecord">
+ <summary>
+ 璧峰璁板綍鏁� 璧峰鍊间负1锛屼笉鑳介��0
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.RecordNum">
+ <summary>
+ 鏈壒璁板綍鏁�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.StartAmt">
+ <summary>
+ 寮�濮嬮噾棰� 锛堜氦鏄撻噾棰濓級double(20,4)
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.EntAmt">
+ <summary>
+ 缁撴潫閲戦 锛堜氦鏄撻噾棰濓級double(20,5)
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.OrderMode">
+ <summary>
+ 鎺掑簭鏂瑰紡 001锛氫氦鏄撴椂闂翠粠杩戝埌杩�
+ 002锛氫氦鏄撴椂闂翠粠杩滃埌杩�
+ 003锛氶噾棰濆崌搴忥紙浠庡皬鍒板ぇ锛�
+ 004锛氶噾棰濋檷搴忥紙浠庡ぇ鍒板皬锛�
+ 005锛氬洖鍗曞彿鍗囧簭
+ 006锛氬洖鍗曞彿闄嶅簭
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.PayeeAcctNo">
+ <summary>
+ 鏀舵浜鸿处鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.PayeeName">
+ <summary>
+ 鏀舵浜哄悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.DrCrFlag">
+ <summary>
+ 鍊熻捶鏍囧織 D锛氬�熸柟浜ゆ槗 C锛氳捶鏂逛氦鏄�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.Ccy">
+ <summary>
+ 甯佺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.SerialNo">
+ <summary>
+ 椤哄簭鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.PrintBranchId">
+ <summary>
+ 鎵撳嵃缃戠偣 浠g爜閲岄潰娌℃湁
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.ReceiptNo">
+ <summary>
+ 鍥炲崟鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryRequest.PrintFlag">
+ <summary>
+ 鎵撳嵃鏍囧織 0锛氶娆℃墦鍗� 1锛氳ˉ鎵�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleDataQueryResponse">
+ <summary>
+ 鍥炲崟鏁版嵁鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponse.RecordTotalCount">
+ <summary>
+ 璁板綍鎬绘暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponse.StartRecord">
+ <summary>
+ 璧峰璁板綍鏁�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponse.ResultNum">
+ <summary>
+ 鏈杩斿洖璁板綍鏁�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponse.EndFlag">
+ <summary>
+ 缁撴潫鏍囧織 Y:鏃犲墿浣欒褰� N:鏈夊墿浣欒褰�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleDataQueryResponseItem">
+ <summary>
+ 鍥炲崟鏁版嵁鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.ReceiptNo">
+ <summary>
+ 鍥炲崟鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.CheckCode">
+ <summary>
+ 楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.ReceiptType">
+ <summary>
+ 鍥炲崟绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.SubType">
+ <summary>
+ 鍥炲崟瀛愮被
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.BookingDate">
+ <summary>
+ 璁拌处鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayerName">
+ <summary>
+ 浠樻浜哄悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayeeName">
+ <summary>
+ 鏀舵浜哄悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayerAccNo">
+ <summary>
+ 浠樻浜鸿处鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayeeAccNo">
+ <summary>
+ 鏀舵浜鸿处鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayerAcctOpenBranchID">
+ <summary>
+ 浠樻浜哄紑鎴疯
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayeeAcctOpenBranchID">
+ <summary>
+ 鏀舵浜哄紑鎴疯
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayerAcctOpenBranchName">
+ <summary>
+ 浠樻浜哄紑鎴疯鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PayeeAcctOpenBranchName">
+ <summary>
+ 鏀舵浜哄紑鎴疯鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.MainAcctNo">
+ <summary>
+ 涓昏处鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.SubAcctNo">
+ <summary>
+ 瀛愯处鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.OldAcctNo">
+ <summary>
+ 鍘熻处鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.Ccy">
+ <summary>
+ 甯佺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.TranAmt">
+ <summary>
+ 浜ゆ槗閲戦
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.SubBranchID">
+ <summary>
+ 缃戠偣鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.DrCrFlag">
+ <summary>
+ 鍊熻捶鏍囧織
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.Crpp">
+ <summary>
+ 璧勯噾鐢ㄩ��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.Corpus">
+ <summary>
+ 鏈噾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.DepositIntRate">
+ <summary>
+ 瀛樻鍒╃巼
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.DepositReceiptNo">
+ <summary>
+ 瀛樺崟鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.StartPeriod">
+ <summary>
+ 璧峰鏈�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.EndPeriod">
+ <summary>
+ 缁撴潫鏈�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.InterestTax">
+ <summary>
+ 鍒╂伅绋�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.IntInterest">
+ <summary>
+ 鍒╂伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.OverdraftInterest">
+ <summary>
+ 閫忔敮鍒╂伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.TaxRate">
+ <summary>
+ 绋庣巼
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.LoanAcctNo">
+ <summary>
+ 璐锋璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.DuebillNo">
+ <summary>
+ 鍊熸嵁鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PaidAmt">
+ <summary>
+ 杩樻閲戦
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.RepayCorpus">
+ <summary>
+ 杩樻鏈噾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.ReplyInterest">
+ <summary>
+ 杩樻鍒╂伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.ComInterest">
+ <summary>
+ 澶嶅埄
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.CorpusBalance">
+ <summary>
+ 鏈噾浣欓
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.DueRepayCorpus">
+ <summary>
+ 搴旇繕鏈噾
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.RepayCount">
+ <summary>
+ 杩樻鏈熸暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.Commission">
+ <summary>
+ 鎵嬬画璐归噾棰�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.MaterialFee">
+ <summary>
+ 宸ユ湰璐�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.TaxedInterest">
+ <summary>
+ 绋庡悗鍒╂伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.HostSeqNo">
+ <summary>
+ 涓绘満娴佹按鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.LoanIntRate">
+ <summary>
+ 璐锋鍒╃巼
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.ReceivableInterest">
+ <summary>
+ 搴旀敹鍒╂伅
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.TellerNo">
+ <summary>
+ 鏌滃憳鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.AuthTellerNo">
+ <summary>
+ 鎺堟潈鏌滃憳鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PrintClientName">
+ <summary>
+ 鎵撳嵃瀹㈡埛绔悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PrintTime">
+ <summary>
+ 鎵撳嵃鏃堕棿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PrintTimes">
+ <summary>
+ 鎵撳嵃娆℃暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.RegionNo">
+ <summary>
+ 鍦板尯鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.TermNo">
+ <summary>
+ 缁堢鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.PrintNote">
+ <summary>
+ 鎵撳嵃鑺傜偣
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.BussType">
+ <summary>
+ 涓氬姟绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.IntSettleAcctNo">
+ <summary>
+ 缁撴伅璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.AcctOpenBranchID">
+ <summary>
+ 璐︽埛寮�鎴疯琛屽彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.TranDate">
+ <summary>
+ 浜ゆ槗鏃ユ湡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.TranTime">
+ <summary>
+ 浜ゆ槗鏃堕棿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.BranchId">
+ <summary>
+ 鏈烘瀯鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.SerialNo">
+ <summary>
+ 椤哄簭鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.RecordType">
+ <summary>
+ 璁板綍绫诲瀷
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.FrontEndCode">
+ <summary>
+ 鍓嶇疆鏈轰唬鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.RemarkCode">
+ <summary>
+ 鎽樿鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleDataQueryResponseItem.Summary">
+ <summary>
+ 鎽樿
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequest">
+ <summary>
+ 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequest.OutAccNo">
+ <summary>
+ 璐﹀彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequest.AccountBeginDate">
+ <summary>
+ 璁拌处璧峰鏃ユ湡 鏌ヨ鍘嗗彶鍥炲崟蹇呰緭淇濇寔鍜孍CL009鏌ヨ鏃ユ湡鐩稿悓 鏍煎紡YYYYMMDD
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequest.AccountEndDate">
+ <summary>
+ 璁拌处缁撴潫鏃ユ湡 鏌ヨ鍘嗗彶鍥炲崟蹇呰緭 淇濇寔鍜孍CL009鏌ヨ鏃ユ湡鐩稿悓鏍煎紡YYYYMMDD
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequest.PDFNum">
+ <summary>
+ 鐢熸垚PDF姣忛〉鏉℃暟璁剧疆
+ N锛氫竴椤祊df鏄剧ず涓�鏉″洖鍗曡褰曪紙榛樿锛�
+ Y锛氫竴椤祊df鏄剧ず鍥涙潯鍥炲崟璁板綍
+ T锛氫竴椤祊df鏄剧ず涓夋潯鍥炲崟璁板綍
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequestItem">
+ <summary>
+ 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequestItem.SeqNo">
+ <summary>
+ 璁板綍搴忓彿 鍙朎LC009鎺ュ彛搴旂瓟鐨刲ist. SeqNo
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequestItem.AccountDate">
+ <summary>
+ 璁拌处鏃ユ湡 鍙朎LC009鎺ュ彛搴旂瓟鐨刲ist.AccountDate
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequestItem.RecepitType">
+ <summary>
+ 鍥炲崟绫诲瀷 鍙朎LC009鎺ュ彛搴旂瓟鐨刲ist. ReceiptType
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewResponse">
+ <summary>
+ 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewResponse.FileName">
+ <summary>
+ 鏂囦欢鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewResponse.RandomPwd">
+ <summary>
+ 闅忔満瀵嗙爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewResponse.DocID">
+ <summary>
+ udmpId
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.StopPaymentAndSettlementAccountsRequest">
+ <summary>
+ 璐︽埛姝粯鍜岃В姝粯_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑姝粯銆佽В闄ゆ浠�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsRequest.SeqNo">
+ <summary>
+ 瀹㈡埛娴佹按鍙� 鍞竴鏍囧織璇ョ瑪浜ゆ槗鐨勬祦姘村彿锛屼笉鍙噸澶嶏紝闀垮害蹇呴』澶т簬10浣�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsRequest.AccountNo">
+ <summary>
+ 姝粯璐︽埛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsRequest.OpType">
+ <summary>
+ 鎿嶄綔绫诲瀷 A-姝粯 D-瑙i櫎姝粯
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsRequest.StopPayFlw">
+ <summary>
+ 姝粯缂栧彿 瑙i櫎姝粯蹇呴』涓婇��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsRequest.Remark">
+ <summary>
+ 澶囨敞
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsRequest.CcyCode">
+ <summary>
+ 甯佺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsResponse.SeqNo">
+ <summary>
+ 瀹㈡埛娴佹按鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsResponse.BizSeqNo">
+ <summary>
+ 閾惰涓氬姟娴佹按
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsResponse.StopPayFlw">
+ <summary>
+ 鍐荤粨姝粯缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsResponse.Stt">
+ <summary>
+ 鐘舵�佺爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.StopPaymentAndSettlementAccountsResponse.SttDesc">
+ <summary>
+ 鐘舵�佹弿杩�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PingAnPayOptions.MrChCode">
+ <summary>
+ 浼佷笟浠g爜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PingAnPayUtils">
+ <summary>
+ 骞冲畨鏀粯宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.#ctor(Microsoft.Extensions.Logging.ILogger{ApiTools.Core.PingAnPayUtils},Microsoft.Extensions.Options.IOptions{ApiTools.Core.PingAnPayOptions},Furion.DatabaseAccessor.IRepository{ApiTools.Core.ThreeResourceLog,ApiTools.Core.LogDbContextLocator})">
+ <summary>
+ 骞冲畨鏀粯宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.CorAcctBalanceQuery(ApiTools.Core.CorAcctBalanceQueryRequest)">
+ <summary>
+ 浼佷笟璐︽埛浣欓鏌ヨ_閾朵紒鐩磋仈姝ゆ帴鍙i�傚簲閾惰鎵�鏈夊竵绉嶇殑娲绘湡璐︽埛鐨勪綑棰濇煡璇紝鍏朵腑鐨勫彲鐢ㄤ綑棰濆彧鍖呭惈鑷韩鐨勮祫閲戠姸鍐碉紝鑰屼笉鍖呮嫭闆嗗洟鍐呴儴鐨勮祫閲戞睜銆傝处闈綑棰濓紝涔熷彧鏄嚜韬处鍙风殑璐﹂潰閲戦銆�
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.HistoryBalanceQuery(ApiTools.Core.HistoryBalanceQueryRequest)">
+ <summary>
+ 鍘嗗彶浣欓鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.InquiryAccountDayHistoryTransactionDetails(ApiTools.Core.InquiryAccountDayHistoryTransactionDetailsRequest)">
+ <summary>
+ 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.StopPaymentAndSettlementAccounts(ApiTools.Core.StopPaymentAndSettlementAccountsRequest)">
+ <summary>
+ 璐︽埛姝粯鍜岃В姝粯_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑姝粯銆佽В闄ゆ浠�
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.InquiryAccountStopPaymentDetails(ApiTools.Core.InquiryAccountStopPaymentDetailsRequest)">
+ <summary>
+ 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.SingleApplicationSuspensionPayment(ApiTools.Core.SingleApplicationSuspensionPaymentRequest)">
+ <summary>
+ 鍗曠瑪鐩戠姝粯鏀粯鐢宠_閾朵紒鐩磋仈
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.CorSingleTransferQuery(ApiTools.Core.CorSingleTransferQueryRequest)">
+ <summary>
+ 鍗曠瑪杞处鎸囦护鏌ヨ_閾朵紒鐩磋仈
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.SingleDataQuery(ApiTools.Core.SingleDataQueryRequest)">
+ <summary>
+ 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.SameDayHistoryReceiptDataQuery(ApiTools.Core.SameDayHistoryReceiptDataQueryRequest)">
+ <summary>
+ 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.SingleOrBatchReceiptPDFMergeDownloadNew(ApiTools.Core.SingleOrBatchReceiptPDFMergeDownloadNewRequest)">
+ <summary>
+ 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.PingAnPayUtils.Send``2(``0,System.String)">
+ <summary>
+ 鍙戦�佽姹�
+ </summary>
+ <typeparam name="TRequest"></typeparam>
+ <typeparam name="TResponse"></typeparam>
+ <param name="request"></param>
+ <param name="path"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.CustomResponseAttribute">
+ <summary>
+ 鑷畾涔夌粨鏋�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.DefaultResourceHttpProvider">
+ <summary>
+ 榛樿璧勬簮鎻愪緵鑰�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SystemUserResourceHttpProvider">
+ <summary>
+ 绯荤粺绠$悊鍛樿祫婧愭彁渚涜��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.TokenDataModel.AccessToken">
+ <summary>
+ 鐢ㄦ埛璁块棶浠ょ墝
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.TokenDataModel.RefreshToken">
+ <summary>
+ 鍒锋柊浠ょ墝
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.ResourceHttpUtils.SendHttpAsync(System.Object,System.String,System.String,ApiTools.Core.EnumResourceMethod,System.Nullable{ApiTools.Core.EnumResourceHttpProvider},System.String,System.String)">
+ <summary>
+ 鍙戦�佽姹�
+ </summary>
+ <param name="request">璇锋眰鍙傛暟</param>
+ <param name="serviceName">鏈嶅姟鍚嶇О</param>
+ <param name="route">璺敱</param>
+ <param name="method">璇锋眰鏂瑰紡</param>
+ <param name="provider">璧勬簮鎻愪緵鑰�</param>
+ <param name="accessToken">璁块棶浠ょ墝</param>
+ <param name="refreshToken">鍒锋柊浠ょ墝</param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.ResourceHttpUtils.SendHttpAsync``2(``0,System.Nullable{ApiTools.Core.EnumResourceHttpProvider})">
+ <summary>
+ 鍙戦�佽姹�
+ </summary>
+ <typeparam name="TRequest"></typeparam>
+ <typeparam name="TResponse"></typeparam>
+ <param name="request"></param>
+ <param name="provider"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.ResourceHttpUtils.GetHttpMethod(ApiTools.Core.EnumResourceMethod)">
+ <summary>
+ 鑾峰彇璇锋眰鏂瑰紡
+ </summary>
+ <param name="method"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.ResourceHttpUtils.GetUrl(System.String,System.String)">
+ <summary>
+ 鑾峰彇鍋ュ悍鏈嶅姟鍦板潃
+ </summary>
+ <param name="serviceName"></param>
+ <param name="route"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.ResourceHttpUtils.GetHealthyServiceDomain(System.String)">
+ <summary>
+ 鑾峰彇鍋ュ悍鏈嶅姟鍩熷悕
+ </summary>
+ <param name="serviceName"></param>
+ <returns></returns>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.TraceId">
+ <summary>
+ 璺熻釜Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ApplicationName">
+ <summary>
+ 搴旂敤鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.DynamicAssemblyName">
+ <summary>
+ 鍔ㄦ�佺▼搴忛泦鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ServiceName">
+ <summary>
+ 鏈嶅姟鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ControllerName">
+ <summary>
+ 鎺у埗鍣ㄥ悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ControllerSummary">
+ <summary>
+ 鎺у埗鍣ㄦ憳瑕�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ActionName">
+ <summary>
+ 濮旀墭鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ActionSummary">
+ <summary>
+ 濮旀墭鎽樿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.Code">
+ <summary>
+ 缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.AllowAnonymous">
+ <summary>
+ 蹇界暐鏉冮檺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.Method">
+ <summary>
+ 璇锋眰鏂瑰紡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.FileUpload">
+ <summary>
+ 鏂囦欢涓婁紶
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.IsFromForm">
+ <summary>
+ 鏄惁鏉ヨ嚜琛ㄥ崟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.CustomResponse">
+ <summary>
+ 鑷畾涔夌粨鏋�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.RouteArea">
+ <summary>
+ 璺敱鍖哄煙
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.Route">
+ <summary>
+ 璺敱
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.RequestTypeName">
+ <summary>
+ 璇锋眰绫诲瀷鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.RequestTypeFullName">
+ <summary>
+ 璇锋眰绫诲瀷鍏ㄥ悕
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ResponseTypeName">
+ <summary>
+ 鍝嶅簲绫诲瀷鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceModel.ResponseTypeFullName">
+ <summary>
+ 鍝嶅簲绫诲瀷鍏ㄥ悕
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ResourceAttribute">
+ <summary>
+ 璧勬簮鐗规��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceAttribute.Controllers">
+ <summary>
+ 璧勬簮鎺у埗鍣�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceAttribute.AllowAnonymous">
+ <summary>
+ 蹇界暐鏉冮檺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceAttribute.Method">
+ <summary>
+ 璇锋眰鏂瑰紡
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceAttribute.Route">
+ <summary>
+ 璺敱
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceAttribute.FileUpload">
+ <summary>
+ 鏂囦欢涓婁紶
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceAttribute.IsFromForm">
+ <summary>
+ 鏉ヨ嚜琛ㄥ崟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceAttribute.CustomResponse">
+ <summary>
+ 鑷畾涔夌粨鏋�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ResourceControllerAttribute">
+ <summary>
+ 璧勬簮鎺у埗鍣ㄧ壒鎬�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceControllerAttribute.Service">
+ <summary>
+ 鏈嶅姟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceControllerAttribute.ControllerName">
+ <summary>
+ 鎺у埗鍣ㄥ悕绉�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ResourceServiceAttribute">
+ <summary>
+ 璧勬簮鏈嶅姟鐗规��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceServiceAttribute.ApplicationName">
+ <summary>
+ 搴旂敤鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceServiceAttribute.RouteArea">
+ <summary>
+ 璺敱鍖哄煙
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ResourceServiceAttribute.ServiceName">
+ <summary>
+ 鏈嶅姟鍚嶇О
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ResourceUtils">
+ <summary>
+ 璧勬簮宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.ResourceUtils.BuildDynamicControllersAsync">
+ <summary>
+ 鐢熸垚鍔ㄦ�佹帶鍒跺櫒
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.ResourceUtils.SaveResourcesAsync(System.Collections.Generic.List{ApiTools.Core.ResourceModel},Furion.DatabaseAccessor.IRepository{ApiTools.Core.Resource})">
+ <summary>
+ 淇濆瓨璧勬簮
+ </summary>
+ <param name="models"></param>
+ <param name="rep"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.ResourceUtils.DynamicControllersHotPlug(System.Collections.Generic.List{ApiTools.Core.Resource},Furion.DynamicApiController.IDynamicApiRuntimeChangeProvider)">
+ <summary>
+ 鍔ㄦ�佹帶鍒跺櫒鐑彃
+ </summary>
+ <param name="resources"></param>
+ <param name="provider"></param>
+ </member>
+ <member name="M:ApiTools.Core.ResourceUtils.DynamicControllerHotPluck(ApiTools.Core.Resource,Furion.DynamicApiController.IDynamicApiRuntimeChangeProvider)">
+ <summary>
+ 鍔ㄦ�佹帶鍒跺櫒鐑嫈
+ </summary>
+ <param name="resource"></param>
+ <param name="provider"></param>
+ </member>
+ <member name="M:ApiTools.Core.ResourceUtils.GetCSharpFriendlyName(System.Type)">
+ <summary>
+ 鑾峰彇C#鍙嬪ソ鍚嶇О
+ </summary>
+ <param name="type"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.DbJobPersistence">
+ <summary>
+ 浣滀笟鎸佷箙鍖栵紙鏁版嵁搴擄級
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.DbJobPersistence.PreloadAsync(System.Threading.CancellationToken)">
+ <summary>
+ 浣滀笟璋冨害鏈嶅姟鍚姩鏃�
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.ChengLiYeSmsOptions">
+ <summary>
+ 璇氱珛涓氶厤缃�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsOptions.SignName">
+ <summary>
+ 绛惧悕鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsOptions.UserName">
+ <summary>
+ 鐢ㄦ埛鍚�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsOptions.Password">
+ <summary>
+ 瀵嗙爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsOptions.TemplateCodes">
+ <summary>
+ 妯℃澘浠g爜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ChengLiYeSmsSubmitRequest">
+ <summary>
+ 璇氱珛涓氬彂閫佺煭淇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.UserName">
+ <summary>
+ 鐢ㄦ埛鍚嶏紙蹇呭~锛�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.Sign">
+ <summary>
+ 绛惧悕锛堝繀濉級
+ MD5(userName+password+mobile+content)
+ password涓烘槑鏂囧瘑鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.Mobile">
+ <summary>
+ 鎵嬫満鍙枫�傚涓墜鏈哄彿涓虹敤鍗婅閫楀彿鍒嗗紑锛屽13899999999,13688888888(鏈�澶�1涓囦釜锛屽繀濉�)
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.Content">
+ <summary>
+ 鍙戦�佸唴瀹癸紙蹇呭~锛夛紝涓嶈秴杩�1000瀛�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.Dstime">
+ <summary>
+ 瀹氭椂鏃堕棿锛屼负绌烘椂琛ㄧず绔嬪嵆鍙戦�侊紙閫夊~锛�
+ 鏍煎紡锛歽yyy-MM-dd HH:mm:ss
+ 渚嬪锛�2016-09-10 09:00:00
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.Ext">
+ <summary>
+ 鐢ㄦ埛鑷畾涔夋墿灞曪紙閫夊~锛夈��106鐮佸彿鍚庨潰鎵╁睍鐨勯儴鍒嗐�傞渶瑕佸拰鍚庡彴浜哄憳纭鏉冮檺
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.Seqid">
+ <summary>
+ 瀹㈡埛鑷畾涔夋秷鎭痠d锛堥�夊~锛夛紝濡傛灉瀹㈡埛涓嶅~鍒欑敱骞冲彴渚х敓鎴愬敮涓�缂栧彿
+ 娉細涓嶈甯瀛楃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitRequest.Isms">
+ <summary>
+ 鏄惁鍥介檯鐭俊锛堥�夊~锛夛紝涓嶅~鍒欓粯璁や负0銆�
+ 0-鍥藉唴鐭俊锛堜笉鍖呭惈娓境鍙帮級
+ mobile瀛楁涓嶈甯�86鍥藉鍖哄煙璇嗗埆鐮併��
+ 1-鍥介檯鐭俊锛堝寘鍚腐婢冲彴锛�
+ mobile瀛楁甯︿笂鍥藉鍖哄煙浠g爜銆傚鏋滃�兼槸1锛屼笉瑕佸彂閫佸浗鍐呭彿鐮�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.ChengLiYeSmsSubmitResponse">
+ <summary>
+ 璇氱珛涓氬彂閫佺煭淇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitResponse.ResultCode">
+ <summary>
+ 鍥為敊璇唬鐮併��1-琛ㄧず鎴愬姛锛屽叾浠栧弬鑰冮敊璇唬鐮佹弿杩�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitResponse.ResultMsg">
+ <summary>
+ 閿欒浠g爜鎻忚堪
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitResponse.Msgid">
+ <summary>
+ 绯荤粺鐢熸垚鐨勬秷鎭紪鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.ChengLiYeSmsSubmitResponse.Seqid">
+ <summary>
+ 鐢ㄦ埛鎸囧畾鐨勬祦姘村彿.濡傛灉娌℃湁鎸囧畾锛屽垯涓簃sgid鍊�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.CheckVerifyCodeModel">
+ <summary>
+ 鏍¢獙楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CheckVerifyCodeModel.TemplateCode">
+ <summary>
+ 鐭俊妯℃澘缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CheckVerifyCodeModel.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.CheckVerifyCodeModel.VerifyCode">
+ <summary>
+ 楠岃瘉鐮�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SendSmsModel">
+ <summary>
+ 鍙戦�佺煭淇�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsModel.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsModel.TemplateCode">
+ <summary>
+ 鐭俊妯℃澘缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsModel.Expiry">
+ <summary>
+ 鏈夋晥鏈�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendSmsModel.ChannelCreatedUserId">
+ <summary>
+ 娓犻亾鎿嶄綔浜�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.SendVerifyCodeModel">
+ <summary>
+ 鍙戦�侀獙璇佺爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendVerifyCodeModel.PhoneNumber">
+ <summary>
+ 鎵嬫満鍙风爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SendVerifyCodeModel.TemplateCode">
+ <summary>
+ 鐭俊妯℃澘缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsResponse.Status">
+ <summary>
+ 鐭俊鐘舵��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsResponse.RequestId">
+ <summary>
+ 璇锋眰Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsResponse.Code">
+ <summary>
+ 鍥炰紶浠g爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.SmsResponse.Message">
+ <summary>
+ 鍥炰紶娑堟伅
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.AliyunSmsService.SendAsync(System.String,ApiTools.Core.EnumSmsTemplateCode,System.Object,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�佺煭淇�
+ </summary>
+ <param name="phoneNumber">鎵嬫満鍙风爜</param>
+ <param name="templateCode">妯℃澘浠g爜</param>
+ <param name="templateParam">妯℃澘鍙傛暟</param>
+ <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+ <returns></returns>
+ <exception cref="T:Furion.FriendlyException.Oops"></exception>
+ </member>
+ <member name="M:ApiTools.Core.AliyunSmsService.PercentEncode(System.String)">
+ <summary>
+ 鎺掗櫎鏁忔劅瀛楃涓�
+ </summary>
+ <param name="value">鏂囨湰</param>
+ <returns>鎺掗櫎鍚庢枃鏈�</returns>
+ </member>
+ <member name="M:ApiTools.Core.AliyunSmsService.ToHmacsha1(System.String,System.String)">
+ <summary>
+ HMAC-SHA1鍔犲瘑
+ </summary>
+ <param name="content"></param>
+ <param name="key"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.ISmsService.SendAsync(System.String,ApiTools.Core.EnumSmsTemplateCode,System.Object,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�佺煭淇�
+ </summary>
+ <param name="phoneNumber">鎵嬫満鍙风爜</param>
+ <param name="templateCode">妯℃澘浠g爜</param>
+ <param name="templateParam">妯℃澘鍙傛暟</param>
+ <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+ <returns></returns>
+ <exception cref="T:Furion.FriendlyException.Oops"></exception>
+ </member>
+ <member name="T:ApiTools.Core.SmsUtils">
+ <summary>
+ 鐭俊宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.SmsUtils.Send(ApiTools.Core.SendSmsModel,System.Object,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�佺煭淇�
+ </summary>
+ <param name="model"></param>
+ <param name="templateParam"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.SmsUtils.SendVerifyCode(ApiTools.Core.SendVerifyCodeModel,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�侀獙璇佺爜鐭俊
+ </summary>
+ <param name="model"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.SmsUtils.CheckVerifyCode(ApiTools.Core.CheckVerifyCodeModel,System.Threading.CancellationToken)">
+ <summary>
+ 鏍¢獙楠岃瘉鐮�
+ </summary>
+ <param name="model"></param>
+ <param name="cancellationToken"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.SmsUtils.CheckOperationTooFrequent(ApiTools.Core.CurrentLogier,ApiTools.Core.SmsSetting,ApiTools.Core.SendSmsModel)">
+ <summary>
+ 鏍¢獙鎿嶄綔棰戠箒
+ </summary>
+ <param name="logier"></param>
+ <param name="setting"></param>
+ <param name="model"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.SmsUtils.GetSmsAccess(ApiTools.Core.SmsSetting,ApiTools.Core.SmsLog)">
+ <summary>
+ 鑾峰彇鐭俊閫氶亾
+ </summary>
+ <param name="setting"></param>
+ <param name="fromEntity"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.SmsUtils.GetSmsService(ApiTools.Core.EnumSmsAccess)">
+ <summary>
+ 鑾峰彇鐭俊鏈嶅姟
+ </summary>
+ <param name="access"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.SmsUtils.Send(ApiTools.Core.SmsSetting,ApiTools.Core.SmsLog,ApiTools.Core.SendSmsModel,System.Object,System.Threading.CancellationToken)">
+ <summary>
+ 鍙戦�佺煭淇�
+ </summary>
+ <param name="setting"></param>
+ <param name="fromEntity"></param>
+ <param name="model"></param>
+ <param name="templateParam">妯℃澘鍙傛暟</param>
+ <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+ <returns></returns>
+ <exception cref="T:Furion.FriendlyException.Oops"></exception>
+ </member>
+ <member name="T:ApiTools.Core.StringUtils">
+ <summary>
+ 瀛楃涓插伐鍏�
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.StringUtils.IsNull(System.String)">
+ <summary>
+ 鏍¢獙瀛楃涓蹭负绌�
+ </summary>
+ <param name="str"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.StringUtils.IsNotNull(System.String)">
+ <summary>
+ 鏍¢獙瀛楁涓嶄负绌�
+ </summary>
+ <param name="str"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.StringUtils.GetPluralizedName(System.String)">
+ <summary>
+ 鑾峰彇澶嶆暟鑻辨枃鍚�
+ </summary>
+ <param name="singularName"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.StringUtils.GetGender(System.String)">
+ <summary>
+ 鑾峰彇鎬у埆
+ </summary>
+ <param name="identity"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.StringUtils.GetBirthday(System.String)">
+ <summary>
+ 鑾峰彇鐢熸棩
+ </summary>
+ <param name="identity"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.StringUtils.GetAge(System.String)">
+ <summary>
+ 鑾峰彇骞撮緞
+ </summary>
+ <param name="identity"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.StringUtils.GenerateRandomString(System.Int32)">
+ <summary>
+ 鐢熸垚闅忔満瀛楃涓�
+ </summary>
+ <param name="length"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayEcommerceFundBalancePathParamters">
+ <summary>
+ 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓-璇锋眰-鍦板潃鏍忎紶鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayEcommerceFundBalancePathParamters.SubMchid">
+ <summary>
+ 鐗圭害鍟嗘埛鍙�
+ 鏈嶅姟鍟嗙壒绾﹀晢鎴峰彿锛岀敱寰俊鏀粯鐢熸垚骞朵笅鍙�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayEcommerceFundBalanceQueryParamters">
+ <summary>
+ 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓-璇锋眰-鏌ヨ浼犲弬
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayEcommerceFundBalanceQueryParamters.AccountType">
+ <summary>
+ 鐗圭害鍟嗘埛璐︽埛绫诲瀷
+ BASIC: 鍩烘湰璐︽埛
+ FEES: 鎵嬬画璐硅处鎴�
+ OPERATION: 杩愯惀璐︽埛
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayEcommerceFundBalanceResponse">
+ <summary>
+ 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓-鍝嶅簲
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayEcommerceFundBalanceResponse.SubMchid">
+ <summary>
+ 鐗圭害鍟嗘埛鍙�
+ 鏈嶅姟鍟嗙壒绾﹀晢鎴峰彿锛岀敱寰俊鏀粯鐢熸垚骞朵笅鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayEcommerceFundBalanceResponse.available_amount">
+ <summary>
+ 鍙敤浣欓锛堝崟浣嶏細鍒嗭級
+ 鍙敤浣欓锛堝崟浣嶏細鍒嗭級锛屾浣欓鍙仛鎻愮幇鎿嶄綔
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayEcommerceFundBalanceResponse.pending_amount">
+ <summary>
+ 涓嶅彲鐢ㄤ綑棰濓紙鍗曚綅锛氬垎锛�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayEcommerceFundBalanceResponse.AccountType">
+ <summary>
+ 鐗圭害鍟嗘埛璐︽埛绫诲瀷
+ BASIC: 鍩烘湰璐︽埛
+ FEES: 鎵嬬画璐硅处鎴�
+ OPERATION: 杩愯惀璐︽埛
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters">
+ <summary>
+ 鍙戣捣鎵归噺杞处-璇锋眰-璇锋眰浣撲紶鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.SubMchId">
+ <summary>
+ 鐗圭害鍟嗘埛鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.SubAppId">
+ <summary>
+ 鐗圭害鍟嗘埛appid
+ 寰俊鍒嗛厤鐨勭壒绾﹀晢鎴峰叕浼楄处鍙稩D锛岀壒绾﹀晢鎴锋巿鏉冪被鍨嬩负INFORMATION_AUTHORIZATION_TYPE鍜孖NFORMATION_AND_FUND_AUTHORIZATION_TYPE鏃� 闇�瑕佸~鍐�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.AuthorizationType">
+ <summary>
+ 鐗圭害鍟嗘埛鎺堟潈绫诲瀷
+ INFORMATION_AUTHORIZATION_TYPE: 琛ㄧず浣跨敤鐗圭害鍟嗘埛鐢ㄦ埛淇℃伅锛屽嚭娆炬柟鏈嶅姟鍟�
+ FUND_AUTHORIZATION_TYPE: 琛ㄧず浣跨敤鐗圭害鍟嗘埛鐨勮祫閲戯紝鍑烘鏂逛负鐗圭害鍟嗘埛锛岀敤鎴蜂俊鎭负鏈嶅姟鍟哸ppid瀵瑰簲鐨刼penid
+ INFORMATION_AND_FUND_AUTHORIZATION_TYPE: 琛ㄧず浣跨敤鐗圭害鍟嗘埛鐨勭敤鎴蜂俊鎭笖鍑烘鏂逛负鐗圭害鍟嗘埛
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.OutBatchNo">
+ <summary>
+ 鍟嗗鎵规鍗曞彿
+ 鍟嗘埛绯荤粺鍐呴儴鐨勫晢瀹舵壒娆″崟鍙凤紝鍦ㄥ晢鎴风郴缁熷唴閮ㄥ敮涓�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.BatchName">
+ <summary>
+ 鎵规鍚嶇О
+ 璇ョ瑪鎵归噺杞处鐨勫悕绉�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.BatchRemark">
+ <summary>
+ 鎵规澶囨敞
+ 杞处璇存槑锛孶TF8缂栫爜锛屾渶澶氬厑璁�32涓瓧绗�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.TotalAmount">
+ <summary>
+ 杞处鎬婚噾棰�
+ 杞处閲戦鍗曚綅涓衡�滃垎鈥濄�傝浆璐︽�婚噾棰濆繀椤讳笌鎵规鍐呮墍鏈夋槑缁嗚浆璐﹂噾棰濅箣鍜屼繚鎸佷竴鑷达紝鍚﹀垯鏃犳硶鍙戣捣杞处鎿嶄綔
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.TotalNum">
+ <summary>
+ 杞处鎬荤瑪鏁�
+ 涓�涓浆璐︽壒娆″崟鏈�澶氬彂璧蜂竴鍗冪瑪杞处銆傝浆璐︽�荤瑪鏁板繀椤讳笌鎵规鍐呮墍鏈夋槑缁嗕箣鍜屼繚鎸佷竴鑷达紝鍚﹀垯鏃犳硶鍙戣捣杞处鎿嶄綔
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.TransferDetailList">
+ <summary>
+ 杞处鏄庣粏鍒楄〃
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.SpAppId">
+ <summary>
+ 鏈嶅姟鍟嗙殑appid
+ 寰俊鍒嗛厤鐨勬湇鍔″晢鍟嗘埛鍏紬璐﹀彿ID锛岀壒绾﹀晢鎴锋巿鏉冪被鍨嬩负FUND_AUTHORIZATION_TYPE鏃� 闇�瑕佸~鍐�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.TransferPurpose">
+ <summary>
+ 鎵归噺杞处鐢ㄩ��
+ GOODSPAYMENT: 缁欑敤鎴锋敮浠樿揣鐗╅噰璐祫閲�
+ COMMISSION: 缁欑敤鎴锋敮浠樹笟鍔℃帹骞夸剑閲�
+ REFUND: 缁欑敤鎴锋敮浠樹氦鏄撻��娆�
+ REIMBURSEMENT: 浼佷笟缁欏憳宸ユ敮浠樺樊鏃呯瓑鎶ラ攢璧勯噾
+ FREIGHT: 缁欏徃鏈烘敮浠樿繍杈撹垂鐢�
+ OTHERS: 鍏朵粬
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters.TransferScene">
+ <summary>
+ 杞处鍦烘櫙
+ ORDINARY_TRANSFER: 鏅�氳浆璐︼紙榛樿锛�
+ PAYROLL_CARD_TRANSFER: 缁欎娇鐢ㄥ井淇″姟宸ュ崱鐨勭敤鎴疯繘琛岃浆璐�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParametersDetail">
+ <summary>
+ 鍙戣捣鎵归噺杞处-璇锋眰-璇锋眰浣撲紶鍙�-杞处鏄庣粏
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParametersDetail.OutDetailNo">
+ <summary>
+ 鍟嗗鏄庣粏鍗曞彿
+ 鍟嗘埛绯荤粺鍐呴儴鍖哄垎杞处鎵规鍗曚笅涓嶅悓杞处鏄庣粏鍗曠殑鍞竴鏍囪瘑
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParametersDetail.TransferAmount">
+ <summary>
+ 杞处閲戦
+ 杞处閲戦鍗曚綅涓衡�滃垎鈥�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParametersDetail.TransferRemark">
+ <summary>
+ 杞处澶囨敞
+ 鍗曟潯杞处澶囨敞锛堝井淇$敤鎴蜂細鏀跺埌璇ュ娉級锛孶TF8缂栫爜锛屾渶澶氬厑璁�32涓瓧绗�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParametersDetail.OpenId">
+ <summary>
+ 鏀舵鐢ㄦ埛openid
+ 鏀舵鐢ㄦ埛openid銆傚鏋滆浆璐︾壒绾﹀晢鎴锋巿鏉冪被鍨嬫槸INFORMATION_AUTHORIZATION_TYPE锛屽搴旂殑鏄壒绾﹀晢鎴峰叕浼楀彿涓嬬殑openid銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParametersDetail.UserName">
+ <summary>
+ 鏀舵鐢ㄦ埛濮撳悕
+ 鏀舵鐢ㄦ埛濮撳悕銆傞噰鐢ㄦ爣鍑哛SA绠楁硶锛屽叕閽ョ敱寰俊渚ф彁渚�
+ 鏄庣粏杞处閲戦 >= 2,000鏃讹紝璇ョ瑪鏄庣粏蹇呴』濉啓鏀舵鐢ㄦ埛濮撳悕
+ 鍚屼竴鎵规杞处鏄庣粏涓殑濮撳悕瀛楁浼犲叆瑙勫垯闇�淇濇寔涓�鑷达紝涔熷嵆鍏ㄩ儴濉啓銆佹垨鍏ㄩ儴涓嶅~鍐�
+ 鑻ュ晢鎴蜂紶鍏ユ敹娆剧敤鎴峰鍚嶏紝寰俊鏀粯浼氭牎楠岀敤鎴穙penID涓庡鍚嶆槸鍚︿竴鑷达紝骞舵彁渚涚數瀛愬洖鍗�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParametersDetail.UserIdCard">
+ <summary>
+ 鏀舵鐢ㄦ埛韬唤璇�
+ 鏀舵鏂硅韩浠借瘉鍙凤紝鍙笉鐢ㄥ~锛堥噰鐢ㄦ爣鍑哛SA绠楁硶锛屽叕閽ョ敱寰俊渚ф彁渚涳級
+ 褰撳~鍏ユ敹娆炬柟韬唤璇佸彿鏃讹紝濮撳悕瀛楁蹇呴』濉叆
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.PartnerTransferBatchesResponse">
+ <summary>
+ 鍙戣捣鎵归噺杞处-鍝嶅簲
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PartnerTransferBatchesResponse.out_batch_no">
+ <summary>
+ 鍟嗗鎵规鍗曞彿
+ 鍟嗘埛绯荤粺鍐呴儴鐨勫晢瀹舵壒娆″崟鍙凤紝鍦ㄥ晢鎴风郴缁熷唴閮ㄥ敮涓�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PartnerTransferBatchesResponse.batch_id">
+ <summary>
+ 寰俊鏀粯鎵规鍗曞彿
+ 寰俊鏀粯鎵规鍗曞彿锛屽井淇″晢瀹惰浆璐︾郴缁熻繑鍥炵殑鍞竴鏍囪瘑
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.PartnerTransferBatchesResponse.create_time">
+ <summary>
+ 鎵规鍒涘缓鏃堕棿
+ 鎵规鍙楃悊鎴愬姛鏃惰繑鍥烇紝鎸夌収浣跨敤rfc3339鎵�瀹氫箟鐨勬牸寮忥紝鏍煎紡涓篩YYY-MM-DDThh:mm:ss+TIMEZONE
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayRequest`3">
+ <summary>
+ 寰俊鏀粯璇锋眰
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayRequest`3.PathParameters">
+ <summary>
+ 鍦板潃鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayRequest`3.QueryParamters">
+ <summary>
+ 鏌ヨ鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayRequest`3.BodyParamters">
+ <summary>
+ 璇锋眰浣撳弬鏁�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayResponse.Code">
+ <summary>
+ 閿欒鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayResponse.Message">
+ <summary>
+ 閿欒娑堟伅
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayOptions">
+ <summary>
+ 寰俊鏀粯閰嶇疆
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayOptions.MchId">
+ <summary>
+ 鍟嗘埛Id
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayOptions.SerialNo">
+ <summary>
+ 璇佷功搴忓垪鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayOptions.PublicKey">
+ <summary>
+ 璇佷功鍏挜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WeChatPayOptions.PrivateKey">
+ <summary>
+ 璇佷功绉侀挜
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WeChatPayUtils">
+ <summary>
+ 寰俊鏀粯宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.#ctor(Microsoft.Extensions.Options.IOptions{ApiTools.Core.WeChatPayOptions},Furion.HttpRemote.IHttpRemoteService,Furion.DatabaseAccessor.IRepository{ApiTools.Core.ThreeResourceLog,ApiTools.Core.LogDbContextLocator})">
+ <summary>
+ 寰俊鏀粯宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.PartnerTransferBatches(ApiTools.Core.WeChatPayRequest{System.Object,System.Object,ApiTools.Core.WeChatPayPartnerTransferBatchesBodyParameters})">
+ <summary>
+ 鍙戣捣鎵归噺杞处
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.EcommerceFundBalance(ApiTools.Core.WeChatPayRequest{ApiTools.Core.WeChatPayEcommerceFundBalancePathParamters,ApiTools.Core.WeChatPayEcommerceFundBalanceQueryParamters,System.Object})">
+ <summary>
+ 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓
+ </summary>
+ <param name="request"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.GetAuthorization(System.String,System.String,System.String,System.String,System.String,System.String)">
+ <summary>
+ 鐢熸垚璁よ瘉淇℃伅
+ </summary>
+ <param name="method"></param>
+ <param name="path"></param>
+ <param name="body"></param>
+ <param name="mchId"></param>
+ <param name="serialNo"></param>
+ <param name="privateKey"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.Encrypt(System.String,System.String)">
+ <summary>
+ 鍔犲瘑鏁忔劅瀛楁
+ </summary>
+ <param name="publicKey"></param>
+ <param name="data"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.Decrypt(System.String,System.String)">
+ <summary>
+ 瑙e瘑鏁忔劅瀛楁
+ </summary>
+ <param name="privareKey"></param>
+ <param name="encryptedBase64"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.GetSignature(System.String,System.String,System.String,System.String,System.Int64,System.String)">
+ <summary>
+ 鐢熸垚绛惧悕
+ </summary>
+ <param name="method"></param>
+ <param name="path"></param>
+ <param name="body"></param>
+ <param name="privateKey"></param>
+ <param name="timestamp"></param>
+ <param name="nonce_str"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.WeChatPayUtils.GetHexDumpRandom">
+ <summary>
+ 鐢熸垚涓�涓姹傞殢鏈轰覆
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.WxmpGetQrCodeCommand">
+ <summary>
+ 灏忕▼搴忚幏鍙栦簩缁寸爜
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeCommand.WxmpCode">
+ <summary>
+ 灏忕▼搴忕紪鍙�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeCommand.OssScene">
+ <summary>
+ 闃块噷浜慜SS鍦烘櫙
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeCommand.OssFileName">
+ <summary>
+ 鏂囦欢鍚�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WxmpGetQrCodeRequest">
+ <summary>
+ 灏忕▼搴忚幏鍙栦簩缁寸爜
+ </summary>
+ </member>
+ <!-- Badly formed XML comment ignored for member "P:ApiTools.Core.WxmpGetQrCodeRequest.Scene" -->
+ <member name="P:ApiTools.Core.WxmpGetQrCodeRequest.Page">
+ <summary>
+ 榛樿鏄富椤碉紝椤甸潰 page锛屼緥濡� pages/index/index锛屾牴璺緞鍓嶄笉瑕佸~鍔� /锛屼笉鑳芥惡甯﹀弬鏁帮紙鍙傛暟璇锋斁鍦╯cene瀛楁閲岋級锛屽鏋滀笉濉啓杩欎釜瀛楁锛岄粯璁よ烦涓婚〉闈€�俿cancode_time涓虹郴缁熶繚鐣欏弬鏁帮紝涓嶅厑璁搁厤缃�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeRequest.CheckPath">
+ <summary>
+ 榛樿鏄痶rue锛屾鏌age 鏄惁瀛樺湪锛屼负 true 鏃� page 蹇呴』鏄凡缁忓彂甯冪殑灏忕▼搴忓瓨鍦ㄧ殑椤甸潰锛堝惁鍒欐姤閿欙級锛涗负 false 鏃跺厑璁稿皬绋嬪簭鏈彂甯冩垨鑰� page 涓嶅瓨鍦紝 浣唒age 鏈夋暟閲忎笂闄愶紙60000涓級璇峰嬁婊ョ敤銆�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeRequest.EnvVersion">
+ <summary>
+ 瑕佹墦寮�鐨勫皬绋嬪簭鐗堟湰銆傛寮忕増涓� "release"锛屼綋楠岀増涓� "trial"锛屽紑鍙戠増涓� "develop"銆傞粯璁ゆ槸姝e紡鐗堛��
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeRequest.Width">
+ <summary>
+ 榛樿430锛屼簩缁寸爜鐨勫搴︼紝鍗曚綅 px锛屾渶灏� 280px锛屾渶澶� 1280px
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeRequest.AutoColor">
+ <summary>
+ 鑷姩閰嶇疆绾挎潯棰滆壊锛屽鏋滈鑹蹭緷鐒舵槸榛戣壊锛屽垯璇存槑涓嶅缓璁厤缃富鑹茶皟锛岄粯璁� false
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeRequest.LineColor">
+ <summary>
+ 榛樿鏄瘂"r":0,"g":0,"b":0} 銆俛uto_color 涓� false 鏃剁敓鏁堬紝浣跨敤 rgb 璁剧疆棰滆壊 渚嬪 {"r":"xxx","g":"xxx","b":"xxx"} 鍗佽繘鍒惰〃绀�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeRequest.IsHyaline">
+ <summary>
+ 榛樿鏄痜alse锛屾槸鍚﹂渶瑕侀�忔槑搴曡壊锛屼负 true 鏃讹紝鐢熸垚閫忔槑搴曡壊鐨勫皬绋嬪簭
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WxmpGetQrCodeResponse">
+ <summary>
+ 灏忕▼搴忚幏鍙栦簩缁寸爜-缁撴灉
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeResponse.Buffer">
+ <summary>
+ 鍥剧墖 Buffer
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeResponse.ErrorCode">
+ <summary>
+ 閿欒鐮�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpGetQrCodeResponse.ErrorMessage">
+ <summary>
+ 閿欒淇℃伅
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WxmpOptions">
+ <summary>
+ 寰俊灏忕▼搴忛厤缃�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpOptionsItem.Code">
+ <summary>
+ 缂栧彿
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpOptionsItem.AppId">
+ <summary>
+ 灏忕▼搴廔D
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpOptionsItem.AppSecret">
+ <summary>
+ 灏忕▼搴忓瘑閽�
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.WxmpOptionsItem.EnvVersion">
+ <summary>
+ 鐗堟湰
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.WxmpUtils">
+ <summary>
+ 寰俊灏忕▼搴忓伐鍏�
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.WxmpUtils.GetAccessToken(System.String)">
+ <summary>
+ 鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹�
+ </summary>
+ <param name="wxmpCode"></param>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.WxmpUtils.GetQrCodeOssUrl(ApiTools.Core.WxmpGetQrCodeCommand)">
+ <summary>
+ 鑾峰彇灏忕▼搴忕爜
+ </summary>
+ <param name="command"></param>
+ <returns></returns>
+ </member>
+ <member name="T:ApiTools.Core.XmlDoc">
+ <summary>
+ 娉ㄩ噴鏂囨。
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.XmlDoc.Members">
+ <summary>
+ 鎴愬憳
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.XmlDocMember">
+ <summary>
+ 娉ㄩ噴鏂囨。鎴愬憳
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.XmlDocMember.Name">
+ <summary>
+ 鍚嶇О
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.XmlDocMember.Summary">
+ <summary>
+ 娉ㄩ噴
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.XmlDocMember.Parameters">
+ <summary>
+ 鍙傛暟
+ </summary>
+ </member>
+ <member name="P:ApiTools.Core.XmlDocMember.Returm">
+ <summary>
+ 杩斿洖鍊�
+ </summary>
+ </member>
+ <member name="T:ApiTools.Core.XmlDocUtils">
+ <summary>
+ 娉ㄩ噴鏂囨。宸ュ叿
+ </summary>
+ </member>
+ <member name="M:ApiTools.Core.XmlDocUtils.BuildXmlDocAsync">
+ <summary>
+ 鐢熸垚娉ㄩ噴鏂囨。
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.XmlDocUtils.GetXmlDocAsync">
+ <summary>
+ 鑾峰彇娉ㄩ噴鏂囨。
+ </summary>
+ <returns></returns>
+ </member>
+ <member name="M:ApiTools.Core.XmlDocUtils.GetXmlDocMemberAsync(System.Reflection.MemberInfo,ApiTools.Core.XmlDoc)">
+ <summary>
+ 鑾峰彇娉ㄩ噴鏂囨。鎴愬憳
+ </summary>
+ <param name="memberInfo"></param>
+ <param name="xmlDoc"></param>
+ <returns></returns>
+ </member>
+ </members>
+</doc>
diff --git a/ApiTools.Core/DbContextLocators/LogDbContextLocator.cs b/ApiTools.Core/DbContextLocators/LogDbContextLocator.cs
new file mode 100644
index 0000000..eb18623
--- /dev/null
+++ b/ApiTools.Core/DbContextLocators/LogDbContextLocator.cs
@@ -0,0 +1,16 @@
+锘縰sing Furion.DatabaseAccessor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏃ュ織鏁版嵁搴撳畾浣嶅櫒
+ /// </summary>
+ public sealed class LogDbContextLocator : IDbContextLocator
+ {
+ }
+}
diff --git a/ApiTools.Core/Entities/CommonEntity.cs b/ApiTools.Core/Entities/CommonEntity.cs
new file mode 100644
index 0000000..2a9fb8a
--- /dev/null
+++ b/ApiTools.Core/Entities/CommonEntity.cs
@@ -0,0 +1,72 @@
+锘縰sing Furion.DatabaseAccessor;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public abstract class CommonEntity<TDbContextLocator1, TDbContextLocator2> : CommonEntity, IPrivateEntity
+ where TDbContextLocator1 : class, IDbContextLocator
+ where TDbContextLocator2 : class, IDbContextLocator
+ {
+ }
+
+ public abstract class CommonEntity<TDbContextLocator1> : CommonEntity, IPrivateEntity
+ where TDbContextLocator1 : class, IDbContextLocator
+ {
+ }
+
+ public abstract class CommonEntity : PrivateEntity<Guid>, IPrivateEntity
+ {
+ /// <summary>
+ /// 涓婚敭Id
+ /// </summary>
+ [Key]
+ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+ public override Guid Id { get; set; }
+
+ /// <summary>
+ /// 鎺掑簭
+ /// </summary>
+ public virtual int Sort { get; set; }
+
+ /// <summary>
+ /// 璺熻釜Id
+ /// </summary>
+ public virtual string TraceId { get; set; }
+
+ /// <summary>
+ /// 鍒涘缓鏃堕棿
+ /// </summary>
+ public override DateTimeOffset CreatedTime { get; set; }
+
+ /// <summary>
+ /// 鍒涘缓鎿嶄綔浜�
+ /// </summary>
+ public virtual Guid? CreatedUserId { get; set; }
+
+ /// <summary>
+ /// 鍒涘缓娓犻亾Id
+ /// </summary>
+ public virtual Guid? CreatedChannelId { get; set; }
+
+ /// <summary>
+ /// 鏈�鍚庢洿鏂版椂闂�
+ /// </summary>
+ public override DateTimeOffset? UpdatedTime { get; set; }
+
+ /// <summary>
+ /// 鏈�鍚庢洿鏂版搷浣滀汉
+ /// </summary>
+ public virtual Guid? UpdatedUserId { get; set; }
+
+ /// <summary>
+ /// 鏄惁鍒犻櫎
+ /// </summary>
+ public virtual bool IsDeleted { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/LogRecords/ConsoleLog.cs b/ApiTools.Core/Entities/LogRecords/ConsoleLog.cs
new file mode 100644
index 0000000..a52df7e
--- /dev/null
+++ b/ApiTools.Core/Entities/LogRecords/ConsoleLog.cs
@@ -0,0 +1,57 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鎺у埗鍙版棩蹇�
+ /// </summary>
+ public class ConsoleLog : CommonEntity<LogDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumConsoleLogAccess Access { get; set; }
+
+ /// <summary>
+ /// 绾у埆
+ /// </summary>
+ public EnumLogLevel Level { get; set; }
+
+ /// <summary>
+ /// 鍐呭
+ /// </summary>
+ [Required]
+ public string Content { get; set; }
+
+ /// <summary>
+ /// 鍫嗘爤璺熻釜
+ /// </summary>
+ public string StackTrace { get; set; }
+
+ /// <summary>
+ /// 閾炬帴鍦板潃
+ /// </summary>
+ public string Url { get; set; }
+
+ /// <summary>
+ /// 浼犲弬
+ /// </summary>
+ public string Request { get; set; }
+
+ /// <summary>
+ /// 鎵╁睍
+ /// </summary>
+ public string Ext { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛IP鍦板潃
+ /// </summary>
+ [MaxLength(32)]
+ public string ClientIpAddress { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/LogRecords/DbAuditLog.cs b/ApiTools.Core/Entities/LogRecords/DbAuditLog.cs
new file mode 100644
index 0000000..c8cb4a7
--- /dev/null
+++ b/ApiTools.Core/Entities/LogRecords/DbAuditLog.cs
@@ -0,0 +1,42 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏁版嵁搴撳璁℃棩蹇�
+ /// </summary>
+ public class DbAuditLog : CommonEntity<LogDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 琛ㄥ悕
+ /// </summary>
+ [MaxLength(128)]
+ [Required]
+ public string TableName { get; set; }
+
+ /// <summary>
+ /// 涓婚敭
+ /// </summary>
+ public Guid PrimaryKey { get; set; }
+
+ /// <summary>
+ /// 鎿嶄綔
+ /// </summary>
+ public EnumDbAuditOperate Operate { get; set; }
+
+ /// <summary>
+ /// 鏃у��
+ /// </summary>
+ public string OldValues { get; set; }
+
+ /// <summary>
+ /// 鏂板��
+ /// </summary>
+ public string NewValues { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/LogRecords/ExceptionLog.cs b/ApiTools.Core/Entities/LogRecords/ExceptionLog.cs
new file mode 100644
index 0000000..a14f205
--- /dev/null
+++ b/ApiTools.Core/Entities/LogRecords/ExceptionLog.cs
@@ -0,0 +1,37 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 寮傚父鏃ュ織
+ /// </summary>
+ public class ExceptionLog : CommonEntity<LogDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 绫诲瀷
+ /// </summary>
+ [MaxLength(256)]
+ public string Type { get; set; }
+
+ /// <summary>
+ /// 浠g爜
+ /// </summary>
+ [MaxLength(32)]
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 娑堟伅
+ /// </summary>
+ public string Message { get; set; }
+
+ /// <summary>
+ /// 鍫嗘爤璺熻釜
+ /// </summary>
+ public string StackTrace { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/LogRecords/QueueLog.cs b/ApiTools.Core/Entities/LogRecords/QueueLog.cs
new file mode 100644
index 0000000..03c2762
--- /dev/null
+++ b/ApiTools.Core/Entities/LogRecords/QueueLog.cs
@@ -0,0 +1,43 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 娑堟伅闃熷垪鏃ュ織
+ /// </summary>
+ public class QueueLog : CommonEntity<LogDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumQueueAccess Access { get; set; }
+
+ /// <summary>
+ /// 浜嬩欢Id
+ /// </summary>
+ [MaxLength(128)]
+ [Required]
+ public string EventId { get; set; }
+
+ /// <summary>
+ /// 鏁版嵁
+ /// </summary>
+ [Required]
+ public string Data { get; set; }
+
+ /// <summary>
+ /// 娑堟伅鏄惁鍙秷璐逛竴娆�
+ /// </summary>
+ public bool IsConsumOnce { get; set; }
+
+ /// <summary>
+ /// 鑰楁椂姣鏁�
+ /// </summary>
+ public long ElapsedMilliseconds { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/LogRecords/ResourceLog.cs b/ApiTools.Core/Entities/LogRecords/ResourceLog.cs
new file mode 100644
index 0000000..ffec92a
--- /dev/null
+++ b/ApiTools.Core/Entities/LogRecords/ResourceLog.cs
@@ -0,0 +1,75 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core.Entities.Common
+{
+ /// <summary>
+ /// 璧勬簮鏃ュ織
+ /// </summary>
+ public class ResourceLog : CommonEntity<LogDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 璇锋眰鏂瑰紡
+ /// </summary>
+ public EnumResourceMethod Method { get; set; }
+
+ /// <summary>
+ /// 鍩熷悕
+ /// </summary>
+ public string Domain { get; set; }
+
+ /// <summary>
+ /// 鍦板潃
+ /// </summary>
+ public string Path { get; set; }
+
+ /// <summary>
+ /// 璇锋眰澶�
+ /// </summary>
+ public string RequestHeaders { get; set; }
+
+ /// <summary>
+ /// 璇锋眰鍙傛暟
+ /// </summary>
+ public string Request { get; set; }
+
+ /// <summary>
+ /// 璇锋眰澶�
+ /// </summary>
+ public string ResponseHeaders { get; set; }
+
+ /// <summary>
+ /// 鍝嶅簲缁撴灉
+ /// </summary>
+ public string Response { get; set; }
+
+ /// <summary>
+ /// 鏄惁鎴愬姛
+ /// </summary>
+ public bool IsSuccess { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛绔疘P鍦板潃
+ /// </summary>
+ public string ClientIpAddress { get; set; }
+
+ /// <summary>
+ /// 鏉ユ簮鍦板潃
+ /// </summary>
+ public string RefererUrl { get; set; }
+
+ /// <summary>
+ /// 鎺у埗鍙版棩蹇�
+ /// </summary>
+ public string ConsoleLogs { get; set; }
+
+ /// <summary>
+ /// 鑰楁椂姣鏁�
+ /// </summary>
+ public long ElapsedMilliseconds { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/LogRecords/ScheduleJobTriggerTimeline.cs b/ApiTools.Core/Entities/LogRecords/ScheduleJobTriggerTimeline.cs
new file mode 100644
index 0000000..edf0888
--- /dev/null
+++ b/ApiTools.Core/Entities/LogRecords/ScheduleJobTriggerTimeline.cs
@@ -0,0 +1,67 @@
+锘縰sing Furion.Schedule;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 瀹氭椂浠诲姟-浣滀笟瑙﹀彂鍣ㄨ繍琛岃褰�
+ /// </summary>
+ public class ScheduleJobTriggerTimeline : CommonEntity<LogDbContextLocator>
+ {
+ /// <summary>
+ /// 浣滀笟 Id
+ /// </summary>
+ public string JobId { get; internal set; }
+
+ /// <summary>
+ /// 浣滀笟瑙﹀彂鍣� Id
+ /// </summary>
+ public string TriggerId { get; internal set; }
+
+ /// <summary>
+ /// 褰撳墠杩愯娆℃暟
+ /// </summary>
+ public long NumberOfRuns { get; internal set; }
+
+ /// <summary>
+ /// 鏈�杩戣繍琛屾椂闂�
+ /// </summary>
+ public DateTime? LastRunTime { get; internal set; }
+
+ /// <summary>
+ /// 涓嬩竴娆¤繍琛屾椂闂�
+ /// </summary>
+ public DateTime? NextRunTime { get; internal set; }
+
+ /// <summary>
+ /// 浣滀笟瑙﹀彂鍣ㄧ姸鎬�
+ /// </summary>
+ public TriggerStatus Status { get; internal set; }
+
+ /// <summary>
+ /// 鏈鎵ц缁撴灉
+ /// </summary>
+ public string Result { get; internal set; }
+
+ /// <summary>
+ /// 鏈鎵ц鑰楁椂
+ /// </summary>
+ public long ElapsedTime { get; internal set; }
+
+ /// <summary>
+ /// 瑙﹀彂妯″紡
+ /// </summary>
+ /// <remarks>榛樿涓哄畾鏃惰Е鍙戯紝0:瀹氭椂锛�1:鎵嬪姩</remarks>
+ public int Mode { get; internal set; }
+
+ /// <summary>
+ /// 寮傚父淇℃伅
+ /// </summary>
+ public string Exception { get; internal set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/LogRecords/ThreeResourceLog.cs b/ApiTools.Core/Entities/LogRecords/ThreeResourceLog.cs
new file mode 100644
index 0000000..854a465
--- /dev/null
+++ b/ApiTools.Core/Entities/LogRecords/ThreeResourceLog.cs
@@ -0,0 +1,74 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 绗笁鏂硅祫婧愭棩蹇�
+ /// </summary>
+ public class ThreeResourceLog : CommonEntity<LogDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 璇锋眰鏂瑰紡
+ /// </summary>
+ public EnumResourceMethod Method { get; set; }
+
+ /// <summary>
+ /// 鍩熷悕
+ /// </summary>
+ public string Domain { get; set; }
+
+ /// <summary>
+ /// 鍦板潃
+ /// </summary>
+ public string Path { get; set; }
+
+ /// <summary>
+ /// 璇锋眰澶�
+ /// </summary>
+ public string RequestHeaders { get; set; }
+
+ /// <summary>
+ /// 璇锋眰鍙傛暟
+ /// </summary>
+ public string Request { get; set; }
+
+ /// <summary>
+ /// 璇锋眰澶�
+ /// </summary>
+ public string ResponseHeaders { get; set; }
+
+ /// <summary>
+ /// 鍝嶅簲缁撴灉
+ /// </summary>
+ public string Response { get; set; }
+
+ /// <summary>
+ /// 鏄惁鎴愬姛
+ /// </summary>
+ public bool IsSuccess { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛绔疘P鍦板潃
+ /// </summary>
+ public string ClientIpAddress { get; set; }
+
+ /// <summary>
+ /// 鏉ユ簮鍦板潃
+ /// </summary>
+ public string RefererUrl { get; set; }
+
+ /// <summary>
+ /// 鎺у埗鍙版棩蹇�
+ /// </summary>
+ public string ConsoleLogs { get; set; }
+
+ /// <summary>
+ /// 鑰楁椂姣鏁�
+ /// </summary>
+ public long ElapsedMilliseconds { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/Resource.cs b/ApiTools.Core/Entities/Resource.cs
new file mode 100644
index 0000000..77f10c6
--- /dev/null
+++ b/ApiTools.Core/Entities/Resource.cs
@@ -0,0 +1,145 @@
+锘縰sing Furion.DatabaseAccessor;
+using Furion.FriendlyException;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璧勬簮
+ /// </summary>
+ public class Resource : CommonEntity<MasterDbContextLocator>, IDbAuditLogIgnore, IPhysicalDeletion
+ {
+ /// <summary>
+ /// 搴旂敤鍚嶇О
+ /// </summary>
+ public string ApplicationName { get; set; }
+
+ /// <summary>
+ /// 鍔ㄦ�佺▼搴忛泦鍚嶇О
+ /// </summary>
+ public string DynamicAssemblyName { get; set; }
+
+ /// <summary>
+ /// 鏈嶅姟鍚嶇О
+ /// </summary>
+ public string ServiceName { get; set; }
+
+ /// <summary>
+ /// 鎺у埗鍣ㄥ悕绉�
+ /// </summary>
+ public string ControllerName { get; set; }
+
+ /// <summary>
+ /// 鎺у埗鍣ㄦ憳瑕�
+ /// </summary>
+ public string ControllerSummary { get; set; }
+
+ /// <summary>
+ /// 濮旀墭鍚嶇О
+ /// </summary>
+ public string ActionName { get; set; }
+
+ /// <summary>
+ /// 濮旀墭鎽樿
+ /// </summary>
+ public string ActionSummary { get; set; }
+
+ /// <summary>
+ /// 缂栧彿
+ /// </summary>
+ [Required]
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ [Required]
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 蹇界暐鏉冮檺
+ /// </summary>
+ public bool AllowAnonymous { get; set; }
+
+ /// <summary>
+ /// 璇锋眰鏂瑰紡
+ /// </summary>
+ public EnumResourceMethod Method { get; set; }
+
+ /// <summary>
+ /// 鏂囦欢涓婁紶
+ /// </summary>
+ public bool FileUpload { get; set; }
+
+ /// <summary>
+ /// 鏄惁鏉ヨ嚜琛ㄥ崟
+ /// </summary>
+ public bool IsFromForm { get; set; }
+
+ /// <summary>
+ /// 鑷畾涔夌粨鏋�
+ /// </summary>
+ public bool CustomResponse { get; set; }
+
+ /// <summary>
+ /// 璺敱鍖哄煙
+ /// </summary>
+ public string RouteArea { get; set; }
+
+ /// <summary>
+ /// 璺敱
+ /// </summary>
+ [Required]
+ public string Route { get; set; }
+
+ /// <summary>
+ /// 璇锋眰绫诲瀷鍚嶇О
+ /// </summary>
+ [Required]
+ public string RequestTypeName { get; set; }
+
+ /// <summary>
+ /// 璇锋眰绫诲瀷鍏ㄥ悕
+ /// </summary>
+ [Required]
+ public string RequestTypeFullName { get; set; }
+
+ /// <summary>
+ /// 鍝嶅簲绫诲瀷鍚嶇О
+ /// </summary>
+ public string ResponseTypeName { get; set; }
+
+ /// <summary>
+ /// 鍝嶅簲绫诲瀷鍏ㄥ悕
+ /// </summary>
+ public string ResponseTypeFullName { get; set; }
+
+ /// <summary>
+ /// 鏄惁宸茶繃鏈�
+ /// </summary>
+ public bool IsExpired { get; set; }
+
+ public HttpMethod GetHttpMethod()
+ {
+ switch (Method)
+ {
+ case EnumResourceMethod.Get:
+ return HttpMethod.Get;
+ case EnumResourceMethod.Post:
+ return HttpMethod.Post;
+ case EnumResourceMethod.Put:
+ return HttpMethod.Put;
+ case EnumResourceMethod.Delete:
+ return HttpMethod.Delete;
+ default:
+ throw Oops.Oh(EnumErrorCodeType.s400, "涓嶆敮鎸佺殑璇锋眰绫诲瀷");
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Entities/ScheduleJobs/ScheduleJobDetail.cs b/ApiTools.Core/Entities/ScheduleJobs/ScheduleJobDetail.cs
new file mode 100644
index 0000000..dd75569
--- /dev/null
+++ b/ApiTools.Core/Entities/ScheduleJobs/ScheduleJobDetail.cs
@@ -0,0 +1,56 @@
+锘縰sing Furion.DatabaseAccessor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 瀹氭椂浠诲姟-浣滀笟璇︽儏
+ /// </summary>
+ public class ScheduleJobDetail : CommonEntity<MasterDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 浣滀笟Id
+ /// </summary>
+ public string JobId { get; set; }
+
+ /// <summary>
+ /// 浣滀笟缁勫悕绉�
+ /// </summary>
+ public string GroupName { get; set; }
+
+ /// <summary>
+ /// 浣滀笟澶勭悊绋嬪簭绫诲瀷锛屽瓨鍌ㄧ殑鏄被鍨嬬殑 FullName
+ /// </summary>
+ public string JobType { get; set; }
+
+ /// <summary>
+ /// 浣滀笟澶勭悊绋嬪簭绫诲瀷鎵�鍦ㄧ▼搴忛泦锛屽瓨鍌ㄧ殑鏄▼搴忛泦 Name
+ /// </summary>
+ public string AssemblyName { get; set; }
+
+ /// <summary>
+ /// 鎻忚堪淇℃伅
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// 浣滀笟鎵ц鏂瑰紡锛屽鏋滆缃负 false锛岄偅涔堜娇鐢� 涓茶 鎵ц锛屽惁鍒� 骞惰 鎵ц
+ /// </summary>
+ public bool Concurrent { get; set; }
+
+ /// <summary>
+ /// 鏄惁鎵弿 IJob 瀹炵幇绫� [Trigger] 鐗规�цЕ鍙戝櫒
+ /// </summary>
+ public bool IncludeAnnotations { get; set; }
+
+ /// <summary>
+ /// 浣滀笟淇℃伅棰濆鏁版嵁
+ /// 鐢� Dictionary string, object 搴忓垪鍖栨垚瀛楃涓插瓨鍌�
+ /// </summary>
+ public string Properties { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/ScheduleJobs/ScheduleJobTrigger.cs b/ApiTools.Core/Entities/ScheduleJobs/ScheduleJobTrigger.cs
new file mode 100644
index 0000000..c9ae446
--- /dev/null
+++ b/ApiTools.Core/Entities/ScheduleJobs/ScheduleJobTrigger.cs
@@ -0,0 +1,129 @@
+锘縰sing Furion.DatabaseAccessor;
+using Furion.Schedule;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 瀹氭椂浠诲姟-浣滀笟瑙﹀彂鍣�
+ /// </summary>
+ public class ScheduleJobTrigger : CommonEntity<MasterDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 浣滀笟瑙﹀彂鍣↖d
+ /// </summary>
+ public string TriggerId { get; set; }
+
+ /// <summary>
+ /// 浣滀笟Id
+ /// </summary>
+ public string JobId { get; set; }
+
+ /// <summary>
+ /// 浣滀笟瑙﹀彂鍣ㄧ被鍨嬶紝瀛樺偍鐨勬槸绫诲瀷鐨� FullName
+ /// </summary>
+ public string TriggerType { get; set; }
+
+ /// <summary>
+ /// 浣滀笟瑙﹀彂鍣ㄧ被鍨嬫墍鍦ㄧ▼搴忛泦锛屽瓨鍌ㄧ殑鏄▼搴忛泦 Name
+ /// </summary>
+ public string AssemblyName { get; set; }
+
+ /// <summary>
+ /// 浣滀笟瑙﹀彂鍣ㄥ垵濮嬪寲鍙傛暟锛岃繍琛屾椂灏嗗弽搴忓垪鍖栦负 object[] 绫诲瀷骞朵綔涓烘瀯閫犲嚱鏁板弬鏁�
+ /// </summary>
+ public string Args { get; set; }
+
+ /// <summary>
+ /// 鎻忚堪淇℃伅
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// 浣滀笟瑙﹀彂鍣ㄧ姸鎬�
+ /// </summary>
+ public TriggerStatus Status { get; set; }
+
+ /// <summary>
+ /// 璧峰鏃堕棿
+ /// </summary>
+ public DateTime? StartTime { get; set; }
+
+ /// <summary>
+ /// 缁撴潫鏃堕棿
+ /// </summary>
+ public DateTime? EndTime { get; set; }
+
+ /// <summary>
+ /// 鏈�杩戣繍琛屾椂闂�
+ /// </summary>
+ public DateTime? LastRunTime { get; set; }
+
+ /// <summary>
+ /// 涓嬩竴娆¤繍琛屾椂闂�
+ /// </summary>
+ public DateTime? NextRunTime { get; set; }
+
+ /// <summary>
+ /// 褰撳墠杩愯娆℃暟
+ /// </summary>
+ public long NumberOfRuns { get; set; }
+
+ /// <summary>
+ /// 鏈�澶цЕ鍙戞鏁帮紝0锛氫笉闄愬埗锛宯锛歂 娆�
+ /// </summary>
+ public long MaxNumberOfRuns { get; set; }
+
+ /// <summary>
+ /// 鍑洪敊娆℃暟
+ /// </summary>
+ public long NumberOfErrors { get; set; }
+
+ /// <summary>
+ /// 鏈�澶у嚭閿欐鏁帮紝0锛氫笉闄愬埗锛宯锛歂 娆�
+ /// </summary>
+ public long MaxNumberOfErrors { get; set; }
+
+ /// <summary>
+ /// 閲嶈瘯娆℃暟
+ /// </summary>
+ public long NumRetries { get; set; }
+
+ /// <summary>
+ /// 閲嶈瘯闂撮殧鏃堕棿锛屾绉掑崟浣�
+ /// </summary>
+ public int RetryTimeout { get; set; }
+
+ /// <summary>
+ /// 鏄惁绔嬪嵆鍚姩锛岃缃� false 灏嗘墜鍔ㄥ惎鍔�
+ /// </summary>
+ public bool StartNow { get; set; }
+
+ /// <summary>
+ /// 鏄惁鍚姩鏃舵墽琛屼竴娆�
+ /// 鍙�氳繃 StartTime 鎺у埗璧峰鏃堕棿
+ /// 鑻� StartTime 涓� null 鎴栧皬浜庡綋鍓嶆椂闂达紝鍒欏湪绋嬪簭鍚姩鏃舵墽琛�
+ /// 鍚﹀垯鍦� StartTime 鏃堕棿鎵ц
+ /// </summary>
+ public bool RunOnStart { get; set; }
+
+ /// <summary>
+ /// 鏄惁鍦ㄥ惎鍔ㄦ椂閲嶇疆鏈�澶цЕ鍙戞鏁扮瓑浜庝竴娆$殑浣滀笟
+ /// </summary>
+ public bool ResetOnlyOnce { get; set; }
+
+ /// <summary>
+ /// 鏈鎵ц缁撴灉
+ /// </summary>
+ public string Result { get; set; }
+
+ /// <summary>
+ /// 鏈鎵ц鑰楁椂
+ /// </summary>
+ public long ElapsedTime { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/ApiTools.Core/Entities/SmsUtils/SmsLog.cs b/ApiTools.Core/Entities/SmsUtils/SmsLog.cs
new file mode 100644
index 0000000..f5cb4bc
--- /dev/null
+++ b/ApiTools.Core/Entities/SmsUtils/SmsLog.cs
@@ -0,0 +1,85 @@
+锘縰sing Furion.DatabaseAccessor;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊鏃ュ織
+ /// </summary>
+ public class SmsLog : CommonEntity<MasterDbContextLocator>, IDbAuditLogIgnore
+ {
+ /// <summary>
+ /// 娓犻亾Id
+ /// </summary>
+ public Guid? ChannelId { get; set; }
+
+ /// <summary>
+ /// 娓犻亾
+ /// </summary>
+ public Channel Channel { get; set; }
+
+ /// <summary>
+ /// 娓犻亾鎿嶄綔浜�
+ /// </summary>
+ public Guid? ChannelCreatedUserId { get; set; }
+
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumSmsAccess Access { get; set; }
+
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [MaxLength(11)]
+ [Required]
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 妯℃澘浠g爜
+ /// </summary>
+ [MaxLength(128)]
+ [Required]
+ public string TemplateCode { get; set; }
+
+ /// <summary>
+ /// 妯℃澘鍙傛暟
+ /// </summary>
+ public string TemplateParam { get; set; }
+
+ /// <summary>
+ /// 鏈夋晥鏈�
+ /// </summary>
+ public DateTime? Expiry { get; set; }
+
+ /// <summary>
+ /// 鏄惁浣跨敤
+ /// </summary>
+ public bool IsUsed { get; set; }
+
+ /// <summary>
+ /// 鐭俊鐘舵��
+ /// </summary>
+ public EnumSmsStatus Status { get; set; }
+
+ /// <summary>
+ /// 璇锋眰Id
+ /// </summary>
+ public string RequestId { get; set; }
+
+ /// <summary>
+ /// 鍥炰紶浠g爜
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍥炰紶娑堟伅
+ /// </summary>
+ public string Message { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/SmsUtils/SmsSetting.cs b/ApiTools.Core/Entities/SmsUtils/SmsSetting.cs
new file mode 100644
index 0000000..6799922
--- /dev/null
+++ b/ApiTools.Core/Entities/SmsUtils/SmsSetting.cs
@@ -0,0 +1,60 @@
+锘縰sing Furion.DatabaseAccessor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊閰嶇疆
+ /// </summary>
+ public class SmsSetting : CommonEntity<MasterDbContextLocator>
+ {
+ public SmsSetting()
+ {
+ Accesses = [];
+ }
+
+ /// <summary>
+ /// 娓犻亾Id
+ /// </summary>
+ public Guid? ChannelId { get; set; }
+
+ /// <summary>
+ /// 娓犻亾
+ /// </summary>
+ public Channel Channel { get; set; }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+
+ /// <summary>
+ /// 甯﹀嚭鍙傛暟
+ /// </summary>
+ public bool WithoutParams { get; set; }
+
+ /// <summary>
+ /// 姣忓垎閽熸渶澶ф暟閲�
+ /// </summary>
+ public int MinutelyMaxCount { get; set; }
+
+ /// <summary>
+ /// 姣忓皬鏃舵渶澶ф暟閲�
+ /// </summary>
+ public int HourlyMaxCount { get; set; }
+
+ /// <summary>
+ /// 姣忓ぉ鏈�澶ф暟閲�
+ /// </summary>
+ public int DailyMaxCount { get; set; }
+
+ /// <summary>
+ /// 閫氶亾閰嶇疆
+ /// </summary>
+ public List<SmsSettingAccess> Accesses { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/SmsUtils/SmsSettingAccess.cs b/ApiTools.Core/Entities/SmsUtils/SmsSettingAccess.cs
new file mode 100644
index 0000000..28e56ef
--- /dev/null
+++ b/ApiTools.Core/Entities/SmsUtils/SmsSettingAccess.cs
@@ -0,0 +1,46 @@
+锘縰sing Furion.DatabaseAccessor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊閫氶亾閰嶇疆
+ /// </summary>
+ public class SmsSettingAccess : CommonEntity<MasterDbContextLocator>
+ {
+ /// <summary>
+ /// 娓犻亾Id
+ /// </summary>
+ public Guid? ChannelId { get; set; }
+
+ /// <summary>
+ /// 娓犻亾
+ /// </summary>
+ public Channel Channel { get; set; }
+
+ /// <summary>
+ /// 閰嶇疆Id
+ /// </summary>
+ public Guid SettingId { get; set; }
+
+ /// <summary>
+ /// 閰嶇疆
+ /// </summary>
+ public SmsSetting Setting { get; set; }
+
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumSmsAccess Access { get; set; }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+
+ }
+}
diff --git a/ApiTools.Core/Entities/Users/Channel.cs b/ApiTools.Core/Entities/Users/Channel.cs
new file mode 100644
index 0000000..b92c736
--- /dev/null
+++ b/ApiTools.Core/Entities/Users/Channel.cs
@@ -0,0 +1,30 @@
+锘縰sing Furion.DatabaseAccessor;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 娓犻亾
+ /// </summary>
+ public class Channel : CommonEntity<MasterDbContextLocator>
+ {
+ /// <summary>
+ /// 缂栧彿
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Entities/Users/User.cs b/ApiTools.Core/Entities/Users/User.cs
new file mode 100644
index 0000000..81db802
--- /dev/null
+++ b/ApiTools.Core/Entities/Users/User.cs
@@ -0,0 +1,100 @@
+锘縰sing Furion.DatabaseAccessor;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐢ㄦ埛
+ /// </summary>
+ public class User : CommonEntity<MasterDbContextLocator>, IEntitySeedData<User>
+ {
+ /// <summary>
+ /// 鐢ㄦ埛绫诲瀷
+ /// </summary>
+ public EnumUserType Type { get; set; }
+
+ /// <summary>
+ /// 娓犻亾Id
+ /// </summary>
+ public Guid? ChannelId { get; set; }
+
+ /// <summary>
+ /// 娓犻亾
+ /// </summary>
+ public Channel Channel { get; set; }
+
+ /// <summary>
+ /// 澶村儚
+ /// </summary>
+ public string Avatar { get; set; }
+
+ /// <summary>
+ /// 濮撳悕
+ /// </summary>
+ [MaxLength(32)]
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛鍚�
+ /// </summary>
+ [Required]
+ [MaxLength(32)]
+ public string UserName { get; set; }
+
+ /// <summary>
+ /// 鎵嬫満鍙�
+ /// </summary>
+ /// <remarks>鐧诲綍鎵嬫満鍙�</remarks>
+ [MaxLength(11)]
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 鏄惁宸叉牎楠屾墜鏈哄彿
+ /// </summary>
+ public bool IsCheckPhoneNumber { get; set; }
+
+ /// <summary>
+ /// 瀵嗙爜
+ /// </summary>
+ public string Password { get; set; }
+
+ /// <summary>
+ /// 绾у埆
+ /// </summary>
+ public int Level { get; set; }
+
+ /// <summary>
+ /// 澶囨敞
+ /// </summary>
+ public string Remark { get; set; }
+
+ /// <summary>
+ /// 鐘舵��
+ /// </summary>
+ public EnumUserStatus Status { get; set; }
+
+ public IEnumerable<User> HasData(DbContext dbContext, Type dbContextLocator)
+ {
+ return new List<User>
+ {
+ new User
+ {
+ Id = new Guid("11111111-1111-1111-1111-111111111111"),
+ Name = "绠$悊鍛�",
+ UserName = "system",
+ Password = "iEYggKrMhQ3ASUGLobra1w==:fn/DsMJUbD9FGpvBvR3moMpMPptdxzZlourPVhU479I=",
+ Type = EnumUserType.Operation,
+ Level = 999,
+ Status = EnumUserStatus.Normal,
+ CreatedTime = new DateTime(2000, 1, 1)
+ }
+ };
+ }
+ }
+}
diff --git a/ApiTools.Core/Enums/EnumErrorCodeType.cs b/ApiTools.Core/Enums/EnumErrorCodeType.cs
new file mode 100644
index 0000000..25bfe5f
--- /dev/null
+++ b/ApiTools.Core/Enums/EnumErrorCodeType.cs
@@ -0,0 +1,59 @@
+锘縰sing Furion.FriendlyException;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ [ErrorCodeType]
+ public enum EnumErrorCodeType
+ {
+ /// <summary>
+ /// 鍙傛暟閿欒
+ /// </summary>
+ [ErrorCodeItemMetadata("{0}")]
+ s400 = 400,
+ /// <summary>
+ /// 褰撳墠鐧诲綍鐢ㄦ埛宸插け鏁�
+ /// </summary>
+ [ErrorCodeItemMetadata("褰撳墠鐧诲綍鐢ㄦ埛宸插け鏁�")]
+ s401 = 401,
+ /// <summary>
+ /// {0}涓嶅瓨鍦�
+ /// </summary>
+ [ErrorCodeItemMetadata("{0}涓嶅瓨鍦�")]
+ s404 = 404,
+ /// <summary>
+ /// {0}宸插瓨鍦紝璇风‘璁ゅ悗鍐嶈瘯
+ /// </summary>
+ [ErrorCodeItemMetadata("{0}宸插瓨鍦紝璇风‘璁ゅ悗鍐嶈瘯")]
+ s405 = 405,
+ /// <summary>
+ /// 瀛樺湪閲嶅鏁版嵁锛歿0}锛岃纭鍚庡啀璇�
+ /// </summary>
+ [ErrorCodeItemMetadata("瀛樺湪閲嶅鏁版嵁锛歿0}锛岃纭鍚庡啀璇�")]
+ s406 = 406,
+ /// <summary>
+ /// 璇0}涓嶅彲淇敼
+ /// </summary>
+ [ErrorCodeItemMetadata("{0}涓嶅彲淇敼")]
+ s410 = 410,
+ /// <summary>
+ /// 鎿嶄綔棰戠箒
+ /// </summary>
+ [ErrorCodeItemMetadata("鎿嶄綔棰戠箒")]
+ s429 = 429,
+ /// <summary>
+ /// 鏈煡寮傚父
+ /// </summary>
+ [ErrorCodeItemMetadata("绯荤粺寮傚父锛岃鑱旂郴绠$悊鍛�")]
+ s500 = 500,
+ /// <summary>
+ /// 绯荤粺寮傚父
+ /// </summary>
+ [ErrorCodeItemMetadata("{0}")]
+ s510 = 510,
+ }
+}
diff --git a/ApiTools.Core/Enums/EnumPagedListOrder.cs b/ApiTools.Core/Enums/EnumPagedListOrder.cs
new file mode 100644
index 0000000..b97483c
--- /dev/null
+++ b/ApiTools.Core/Enums/EnumPagedListOrder.cs
@@ -0,0 +1,23 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍒嗛〉鍒楄〃鎺掑簭
+ /// </summary>
+ public enum EnumPagedListOrder
+ {
+ /// <summary>
+ /// 鍗囧簭
+ /// </summary>
+ Asc = 0,
+ /// <summary>
+ /// 闄嶅簭
+ /// </summary>
+ Desc = 1,
+ }
+}
diff --git a/ApiTools.Core/Enums/EnumQueueAccess.cs b/ApiTools.Core/Enums/EnumQueueAccess.cs
new file mode 100644
index 0000000..bf9362e
--- /dev/null
+++ b/ApiTools.Core/Enums/EnumQueueAccess.cs
@@ -0,0 +1,19 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 娑堟伅闃熷垪閫氶亾
+ /// </summary>
+ public enum EnumQueueAccess
+ {
+ /// <summary>
+ /// RabbitMQ
+ /// </summary>
+ RabbitMQ = 10
+ }
+}
diff --git a/ApiTools.Core/Enums/EnumUserErrorCodeType.cs b/ApiTools.Core/Enums/EnumUserErrorCodeType.cs
new file mode 100644
index 0000000..6854693
--- /dev/null
+++ b/ApiTools.Core/Enums/EnumUserErrorCodeType.cs
@@ -0,0 +1,46 @@
+锘縰sing Furion.FriendlyException;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ [ErrorCodeType]
+ public enum EnumUserErrorCodeType
+ {
+ /// <summary>
+ /// 璐﹀彿鎴栧瘑鐮佷笉瀛樺湪
+ /// </summary>
+ [ErrorCodeItemMetadata("璐﹀彿鎴栧瘑鐮佷笉瀛樺湪")]
+ u1000 = 1000,
+ /// <summary>
+ /// 璐﹀彿宸茬鐢�
+ /// </summary>
+ [ErrorCodeItemMetadata("璐﹀彿宸茬鐢�")]
+ u1001 = 1001,
+ /// <summary>
+ /// 鎵嬫満鍙峰凡琚敞鍐�
+ /// </summary>
+ [ErrorCodeItemMetadata("鎵嬫満鍙峰凡琚敞鍐�")]
+ u1010 = 1010,
+ /// <summary>
+ /// 褰撳墠璐﹀彿鏈粦瀹氬井淇″皬绋嬪簭
+ /// </summary>
+ [ErrorCodeItemMetadata("褰撳墠璐﹀彿鏈粦瀹氬井淇″皬绋嬪簭")]
+ u1100 = 1100,
+ /// <summary>
+ /// 鎵嬫満鎺堟潈澶辫触
+ /// </summary>
+ [ErrorCodeItemMetadata("鎵嬫満鎺堟潈澶辫触")]
+ u1110 = 1110,
+ /// <summary>
+ /// 宸叉湁鍏朵粬寰俊缁戝畾璇ユ墜鏈哄彿
+ /// </summary>
+ [ErrorCodeItemMetadata("宸叉湁鍏朵粬寰俊缁戝畾璇ユ墜鏈哄彿")]
+ u1120 = 1120,
+
+
+ }
+}
diff --git a/ApiTools.Core/Enums/EnumValidationTypes.cs b/ApiTools.Core/Enums/EnumValidationTypes.cs
new file mode 100644
index 0000000..89d9543
--- /dev/null
+++ b/ApiTools.Core/Enums/EnumValidationTypes.cs
@@ -0,0 +1,37 @@
+锘縰sing Furion.DataValidation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 楠岃瘉绫诲瀷
+ /// </summary>
+ [ValidationType]
+ public enum EnumValidationTypes
+ {
+ /// <summary>
+ /// 鎵嬫満鍙�
+ /// </summary>
+ [ValidationItemMetadata(@"^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$", "鎵嬫満鍙锋牸寮忎笉姝g‘")]
+ ValidPhoneNumber,
+ /// <summary>
+ /// 韬唤璇佸彿
+ /// </summary>
+ [ValidationItemMetadata(@"^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])\d{3}(\d|X|x)$", "韬唤璇佸彿鏍煎紡涓嶆纭�")]
+ ValidIdentity,
+ /// <summary>
+ /// 濮撳悕
+ /// </summary>
+ [ValidationItemMetadata(@"^[\u4E00-\u9FA5路]{2,15}$", "濮撳悕鏍煎紡涓嶆纭�")]
+ ValidRealName,
+ /// <summary>
+ /// 楠岃瘉鐮�
+ /// </summary>
+ [ValidationItemMetadata(@"^\d{6}$", "楠岃瘉鐮佹牸寮忎笉姝g‘")]
+ ValidVerifyCode,
+ }
+}
diff --git a/ApiTools.Core/Enums/LogRecords/EnumConsoleLogAccess.cs b/ApiTools.Core/Enums/LogRecords/EnumConsoleLogAccess.cs
new file mode 100644
index 0000000..cae1cac
--- /dev/null
+++ b/ApiTools.Core/Enums/LogRecords/EnumConsoleLogAccess.cs
@@ -0,0 +1,23 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鎺у埗鍙版棩蹇楅�氶亾
+ /// </summary>
+ public enum EnumConsoleLogAccess
+ {
+ /// <summary>
+ /// 鍚庣
+ /// </summary>
+ Back = 10,
+ /// <summary>
+ /// 鍓嶇
+ /// </summary>
+ Front = 20
+ }
+}
diff --git a/ApiTools.Core/Enums/LogRecords/EnumDbAuditOperate.cs b/ApiTools.Core/Enums/LogRecords/EnumDbAuditOperate.cs
new file mode 100644
index 0000000..a9ef6bd
--- /dev/null
+++ b/ApiTools.Core/Enums/LogRecords/EnumDbAuditOperate.cs
@@ -0,0 +1,27 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏁版嵁搴撳璁℃棩蹇楁搷浣�
+ /// </summary>
+ public enum EnumDbAuditOperate
+ {
+ /// <summary>
+ /// 娣诲姞
+ /// </summary>
+ Added = 10,
+ /// <summary>
+ /// 淇敼
+ /// </summary>
+ Modified = 20,
+ /// <summary>
+ /// 鍒犻櫎
+ /// </summary>
+ Deleted = 30
+ }
+}
diff --git a/ApiTools.Core/Enums/LogRecords/EnumLogLevel.cs b/ApiTools.Core/Enums/LogRecords/EnumLogLevel.cs
new file mode 100644
index 0000000..4a0f05d
--- /dev/null
+++ b/ApiTools.Core/Enums/LogRecords/EnumLogLevel.cs
@@ -0,0 +1,39 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏃ュ織绾у埆
+ /// </summary>
+ public enum EnumLogLevel
+ {
+ /// <summary>
+ /// 璺熻釜
+ /// </summary>
+ Trace = 10,
+ /// <summary>
+ /// 璋冭瘯
+ /// </summary>
+ Debug = 20,
+ /// <summary>
+ /// 淇℃伅
+ /// </summary>
+ Information = 30,
+ /// <summary>
+ /// 璀﹀憡
+ /// </summary>
+ Warning = 40,
+ /// <summary>
+ /// 閿欒
+ /// </summary>
+ Error = 50,
+ /// <summary>
+ /// 涓ラ噸
+ /// </summary>
+ Critical = 60
+ }
+}
diff --git a/ApiTools.Core/Enums/Resources/EnumResourceController.cs b/ApiTools.Core/Enums/Resources/EnumResourceController.cs
new file mode 100644
index 0000000..a1ae3f7
--- /dev/null
+++ b/ApiTools.Core/Enums/Resources/EnumResourceController.cs
@@ -0,0 +1,61 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璧勬簮鎺у埗鍣�
+ /// </summary>
+ public enum EnumResourceController
+ {
+ /// <summary>
+ /// 鏂囦欢
+ /// </summary>
+ [ResourceController(EnumResourceService.CommonServer, "FileUtils")]
+ CommonServerFileUtils,
+ /// <summary>
+ /// 鏂囧瓧璇嗗埆
+ /// </summary>
+ [ResourceController(EnumResourceService.CommonServer, "OcrUtils")]
+ CommonServerOcrUtils,
+ /// <summary>
+ /// 鏃ュ織璁板綍
+ /// </summary>
+ [ResourceController(EnumResourceService.CommonServer, "LogRecords")]
+ CommonServerLogRecords,
+ /// <summary>
+ /// 鐭俊宸ュ叿
+ /// </summary>
+ [ResourceController(EnumResourceService.CommonServer, "Sms")]
+ CommonServerSmsUtils,
+
+ /// <summary>
+ /// 鐢ㄦ埛璁よ瘉
+ /// </summary>
+ [ResourceController(EnumResourceService.UserServer, "Auth")]
+ UserServerAuth,
+ /// <summary>
+ /// 鐢ㄦ埛璧勬簮
+ /// </summary>
+ [ResourceController(EnumResourceService.UserServer, "Resource")]
+ UserServerResource,
+ /// <summary>
+ /// 鐢ㄦ埛淇℃伅
+ /// </summary>
+ [ResourceController(EnumResourceService.UserServer, "User")]
+ UserServerUser,
+ /// <summary>
+ /// 娓犻亾淇℃伅
+ /// </summary>
+ [ResourceController(EnumResourceService.UserServer, "Channel")]
+ UserServerChannel,
+ /// <summary>
+ /// 娓犻亾鐢ㄦ埛
+ /// </summary>
+ [ResourceController(EnumResourceService.UserServer, "ChannelUser")]
+ UserServerChannelUser,
+ }
+}
diff --git a/ApiTools.Core/Enums/Resources/EnumResourceMethod.cs b/ApiTools.Core/Enums/Resources/EnumResourceMethod.cs
new file mode 100644
index 0000000..9a68c64
--- /dev/null
+++ b/ApiTools.Core/Enums/Resources/EnumResourceMethod.cs
@@ -0,0 +1,35 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璧勬簮璇锋眰鏂瑰紡
+ /// </summary>
+ public enum EnumResourceMethod
+ {
+ /// <summary>
+ /// 鏃�
+ /// </summary>
+ None = 0,
+ /// <summary>
+ /// 鏌ヨ
+ /// </summary>
+ Get = 10,
+ /// <summary>
+ /// 鎻愪氦
+ /// </summary>
+ Post = 20,
+ /// <summary>
+ /// 淇敼
+ /// </summary>
+ Put = 30,
+ /// <summary>
+ /// 鍒犻櫎
+ /// </summary>
+ Delete = 40
+ }
+}
diff --git a/ApiTools.Core/Enums/Resources/EnumResourceService.cs b/ApiTools.Core/Enums/Resources/EnumResourceService.cs
new file mode 100644
index 0000000..4848616
--- /dev/null
+++ b/ApiTools.Core/Enums/Resources/EnumResourceService.cs
@@ -0,0 +1,41 @@
+锘縰sing Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璧勬簮鏈嶅姟
+ /// </summary>
+ public enum EnumResourceService
+ {
+ /// <summary>
+ /// 鐏垫椿鐢ㄥ伐鏈嶅姟
+ /// </summary>
+ [ResourceService(ServiceName = "FlexJobServer", ApplicationName = "ApiToolsFlexJobServer.Application", RouteArea = "flexjob")]
+ FlexJobServer,
+ /// <summary>
+ /// 閫氱敤鏈嶅姟
+ /// </summary>
+ [ResourceService(ServiceName = "FlexJobServer", ApplicationName = "ApiToolsCommonServer.Application", RouteArea = "common")]
+ CommonServer,
+ /// <summary>
+ /// 鐢ㄦ埛鏈嶅姟
+ /// </summary>
+ [ResourceService(ServiceName = "FlexJobServer", ApplicationName = "ApiToolsUserServer.Application", RouteArea = "user")]
+ UserServer,
+ /// <summary>
+ /// 浜哄姏璧勬簮鏈嶅姟
+ /// </summary>
+ [ResourceService(ServiceName = "HumanResourcesServer")]
+ HumanResourcesServer,
+ /// <summary>
+ /// 鐢靛瓙绛炬湇鍔�
+ /// </summary>
+ [ResourceService(ServiceName = "ElectronSignServer")]
+ ElectronSignServer
+ }
+}
diff --git a/ApiTools.Core/Enums/SmsUtils/EnumSmsAccess.cs b/ApiTools.Core/Enums/SmsUtils/EnumSmsAccess.cs
new file mode 100644
index 0000000..a8913b4
--- /dev/null
+++ b/ApiTools.Core/Enums/SmsUtils/EnumSmsAccess.cs
@@ -0,0 +1,27 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊閫氶亾
+ /// </summary>
+ public enum EnumSmsAccess
+ {
+ /// <summary>
+ /// 鏃�
+ /// </summary>
+ None = 0,
+ /// <summary>
+ /// 闃块噷浜戠煭淇�
+ /// </summary>
+ AliyunSms = 10,
+ /// <summary>
+ /// 璇氱珛涓�
+ /// </summary>
+ ChengLiYe = 20
+ }
+}
diff --git a/ApiTools.Core/Enums/SmsUtils/EnumSmsStatus.cs b/ApiTools.Core/Enums/SmsUtils/EnumSmsStatus.cs
new file mode 100644
index 0000000..f311c06
--- /dev/null
+++ b/ApiTools.Core/Enums/SmsUtils/EnumSmsStatus.cs
@@ -0,0 +1,31 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊鐘舵��
+ /// </summary>
+ public enum EnumSmsStatus
+ {
+ /// <summary>
+ /// 寰呭彂閫�
+ /// </summary>
+ Wait = 0,
+ /// <summary>
+ /// 鍙戦�佷腑
+ /// </summary>
+ InProcess = 10,
+ /// <summary>
+ /// 鍙戦�佹垚鍔�
+ /// </summary>
+ Success = 20,
+ /// <summary>
+ /// 鍙戦�佸け璐�
+ /// </summary>
+ Fail = 30,
+ }
+}
diff --git a/ApiTools.Core/Enums/SmsUtils/EnumSmsTemplateCode.cs b/ApiTools.Core/Enums/SmsUtils/EnumSmsTemplateCode.cs
new file mode 100644
index 0000000..ec6563a
--- /dev/null
+++ b/ApiTools.Core/Enums/SmsUtils/EnumSmsTemplateCode.cs
@@ -0,0 +1,40 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊妯℃澘缂栧彿
+ /// </summary>
+ public enum EnumSmsTemplateCode
+ {
+ /// <summary>
+ /// 818骞冲彴鐧诲綍/娉ㄥ唽
+ /// 楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙扮櫥褰�/娉ㄥ唽锛岄獙璇佺爜10鍒嗛挓鍐呮湁鏁堛��
+ /// </summary>
+ LoginOrRegister,
+ /// <summary>
+ /// 818鎵嬫満鍙风爜淇敼
+ /// 楠岃瘉鐮�${code}锛屾偍姝e湪杩涜淇敼鎵嬫満鍙风爜鎿嶄綔锛岃鍕挎硠闇诧紝鑻ラ潪鏈汉鎿嶄綔璇峰拷鐣ャ��
+ /// </summary>
+ UpdateUserPhoneNumber,
+ /// <summary>
+ /// 818閽卞寘寮�閫�
+ /// 楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙伴挶鍖呭紑閫氾紝璇ラ獙璇佺爜5鍒嗛挓鍐呮湁鏁堬紝璇峰嬁娉勯湶浜庝粬浜恒��
+ /// </summary>
+ BankWalletAccountOpen,
+ /// <summary>
+ /// 鐢靛瓙绛鹃個绾�
+ /// ${name}璇锋偍鐐瑰嚮绛剧害http://testwww.81812333.com/sg/${code}
+ /// </summary>
+ InviteElectronSign,
+ /// <summary>
+ /// 绛剧害鍦板潃
+ /// ${name}璇锋偍鐐瑰嚮绛剧害https://testwww.81812333.com/sgu/${code}
+ /// </summary>
+ ElectronSignUrl,
+ }
+}
diff --git a/ApiTools.Core/Enums/Users/EnumClientType.cs b/ApiTools.Core/Enums/Users/EnumClientType.cs
new file mode 100644
index 0000000..e0eb2f5
--- /dev/null
+++ b/ApiTools.Core/Enums/Users/EnumClientType.cs
@@ -0,0 +1,31 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 瀹㈡埛绔被鍨�
+ /// </summary>
+ public enum EnumClientType
+ {
+ /// <summary>
+ /// 鐢佃剳缃戦〉
+ /// </summary>
+ PcWeb = 10,
+ /// <summary>
+ /// 寰俊灏忕▼搴�
+ /// </summary>
+ Wxmp = 20,
+ /// <summary>
+ /// H5鐧诲綍
+ /// </summary>
+ H5 = 30,
+ /// <summary>
+ /// 鎺ュ彛
+ /// </summary>
+ Api = 40
+ }
+}
diff --git a/ApiTools.Core/Enums/Users/EnumUserGender.cs b/ApiTools.Core/Enums/Users/EnumUserGender.cs
new file mode 100644
index 0000000..a0dbf98
--- /dev/null
+++ b/ApiTools.Core/Enums/Users/EnumUserGender.cs
@@ -0,0 +1,23 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐢ㄦ埛鎬у埆
+ /// </summary>
+ public enum EnumUserGender
+ {
+ /// <summary>
+ /// 鐢�
+ /// </summary>
+ Male = 10,
+ /// <summary>
+ /// 濂�
+ /// </summary>
+ Female = 20
+ }
+}
diff --git a/ApiTools.Core/Enums/Users/EnumUserStatus.cs b/ApiTools.Core/Enums/Users/EnumUserStatus.cs
new file mode 100644
index 0000000..3ee2249
--- /dev/null
+++ b/ApiTools.Core/Enums/Users/EnumUserStatus.cs
@@ -0,0 +1,23 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐢ㄦ埛淇℃伅鐘舵��
+ /// </summary>
+ public enum EnumUserStatus
+ {
+ /// <summary>
+ /// 姝e父
+ /// </summary>
+ Normal = 10,
+ /// <summary>
+ /// 绂佺敤
+ /// </summary>
+ Disabled = 100,
+ }
+}
diff --git a/ApiTools.Core/Enums/Users/EnumUserType.cs b/ApiTools.Core/Enums/Users/EnumUserType.cs
new file mode 100644
index 0000000..811f329
--- /dev/null
+++ b/ApiTools.Core/Enums/Users/EnumUserType.cs
@@ -0,0 +1,23 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐢ㄦ埛绫诲瀷
+ /// </summary>
+ public enum EnumUserType
+ {
+ /// <summary>
+ /// 娓犻亾
+ /// </summary>
+ Channel = 20,
+ /// <summary>
+ /// 杩愯惀
+ /// </summary>
+ Operation = 100
+ }
+}
diff --git a/ApiTools.Core/Interfaces/IDbAuditLogIgnore.cs b/ApiTools.Core/Interfaces/IDbAuditLogIgnore.cs
new file mode 100644
index 0000000..805526c
--- /dev/null
+++ b/ApiTools.Core/Interfaces/IDbAuditLogIgnore.cs
@@ -0,0 +1,12 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public interface IDbAuditLogIgnore
+ {
+ }
+}
diff --git a/ApiTools.Core/Interfaces/IIsDisabled.cs b/ApiTools.Core/Interfaces/IIsDisabled.cs
new file mode 100644
index 0000000..f34815a
--- /dev/null
+++ b/ApiTools.Core/Interfaces/IIsDisabled.cs
@@ -0,0 +1,19 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏄惁宸茬鐢�
+ /// </summary>
+ public interface IIsDisabled
+ {
+ /// <summary>
+ /// 鏄惁宸茬鐢�
+ /// </summary>
+ bool IsDisabled { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Interfaces/IPhysicalDeletion.cs b/ApiTools.Core/Interfaces/IPhysicalDeletion.cs
new file mode 100644
index 0000000..83d271d
--- /dev/null
+++ b/ApiTools.Core/Interfaces/IPhysicalDeletion.cs
@@ -0,0 +1,15 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐗╃悊鍒犻櫎
+ /// </summary>
+ public interface IPhysicalDeletion
+ {
+ }
+}
diff --git a/ApiTools.Core/Interfaces/ITreeData.cs b/ApiTools.Core/Interfaces/ITreeData.cs
new file mode 100644
index 0000000..f5bc24c
--- /dev/null
+++ b/ApiTools.Core/Interfaces/ITreeData.cs
@@ -0,0 +1,42 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏍戝舰鏁版嵁
+ /// </summary>
+ /// <typeparam name="TEntity"></typeparam>
+ public interface ITreeData<TEntity>
+ where TEntity : CommonEntity, ITreeData<TEntity>, new()
+ {
+ /// <summary>
+ /// 涓婄骇Id
+ /// </summary>
+ Guid? ParentId { get; set; }
+
+ /// <summary>
+ /// 涓婄骇
+ /// </summary>
+ TEntity Parent { get; set; }
+
+ /// <summary>
+ /// 涓嬬骇
+ /// </summary>
+ List<TEntity> Children { get; set; }
+
+ /// <summary>
+ /// 瀛楀吀璺緞
+ /// </summary>
+ string Path { get; set; }
+
+ /// <summary>
+ /// 缂栧彿
+ /// </summary>
+ string Code { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Auths/Commands/ChangePhoneNumberCommand.cs b/ApiTools.Core/Models/Auths/Commands/ChangePhoneNumberCommand.cs
new file mode 100644
index 0000000..3532a7a
--- /dev/null
+++ b/ApiTools.Core/Models/Auths/Commands/ChangePhoneNumberCommand.cs
@@ -0,0 +1,29 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏇存崲鎵嬫満鍙�
+ /// </summary>
+ [Resource([EnumResourceController.UserServerAuth])]
+ public class ChangePhoneNumberCommand : IRequest<bool>
+ {
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [Required]
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 楠岃瘉鐮�
+ /// </summary>
+ [Required]
+ public string VerifyCode { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Auths/Commands/PasswordLoginCommand.cs b/ApiTools.Core/Models/Auths/Commands/PasswordLoginCommand.cs
new file mode 100644
index 0000000..f53ce23
--- /dev/null
+++ b/ApiTools.Core/Models/Auths/Commands/PasswordLoginCommand.cs
@@ -0,0 +1,70 @@
+锘縰sing Furion.DataValidation;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 瀵嗙爜鐧诲綍
+ /// </summary>
+ [Resource([EnumResourceController.UserServerAuth], AllowAnonymous = true)]
+ public class PasswordLoginCommand : IRequest<LoginCommandCallback>
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// </summary>
+ [Required]
+ public string UserName { get; set; }
+ /// <summary>
+ /// 瀵嗙爜
+ /// </summary>
+ [Required]
+ public string Password { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛绫诲瀷
+ /// </summary>
+ public EnumUserType Type { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛绔被鍨�
+ /// </summary>
+ public EnumClientType ClientType { get; set; }
+ }
+
+ /// <summary>
+ /// 瀵嗙爜鐧诲綍缁撴灉
+ /// </summary>
+ public class LoginCommandCallback
+ {
+ /// <summary>
+ /// 鐢ㄦ埛Id
+ /// </summary>
+ public Guid Id { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛璁块棶浠ょ墝
+ /// </summary>
+ public string AccessToken { get; set; }
+
+ /// <summary>
+ /// 鍒锋柊浠ょ墝
+ /// </summary>
+ public string RefreshToken { get; set; }
+
+ /// <summary>
+ /// 浼氳瘽绉橀挜锛堜粎鐢ㄤ簬寰俊灏忕▼搴忔巿鏉冪櫥褰曪級
+ /// </summary>
+ public string SessionKey { get; set; }
+
+ /// <summary>
+ /// 鏄惁宸茬粦瀹氭墜鏈哄彿锛堜粎鐢ㄤ簬寰俊灏忕▼搴忔巿鏉冪櫥褰曪級
+ /// </summary>
+ public bool IsBindPhoneNumber { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Auths/Commands/SendLoginOrRegisterVerifyCodeCommand.cs b/ApiTools.Core/Models/Auths/Commands/SendLoginOrRegisterVerifyCodeCommand.cs
new file mode 100644
index 0000000..035d182
--- /dev/null
+++ b/ApiTools.Core/Models/Auths/Commands/SendLoginOrRegisterVerifyCodeCommand.cs
@@ -0,0 +1,24 @@
+锘縰sing Furion.DataValidation;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍙戦�佺櫥褰曟垨娉ㄥ唽鐭俊
+ /// </summary>
+ [Resource([EnumResourceController.UserServerAuth], AllowAnonymous = true)]
+ public class SendLoginOrRegisterVerifyCodeCommand : IRequest<Guid>
+ {
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [Required, DataValidation(ValidationTypes.PhoneNumber)]
+ public string PhoneNumber { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Auths/Commands/SmsLoginCommand.cs b/ApiTools.Core/Models/Auths/Commands/SmsLoginCommand.cs
new file mode 100644
index 0000000..b7d0d8d
--- /dev/null
+++ b/ApiTools.Core/Models/Auths/Commands/SmsLoginCommand.cs
@@ -0,0 +1,37 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊鐧诲綍
+ /// </summary>
+ [Resource([EnumResourceController.UserServerAuth], AllowAnonymous = true)]
+ public class SmsLoginCommand : IRequest<LoginCommandCallback>
+ {
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 楠岃瘉鐮�
+ /// </summary>
+ public string VerifyCode { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛绫诲瀷
+ /// </summary>
+ public EnumUserType Type { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛绔被鍨�
+ /// </summary>
+ public EnumClientType ClientType { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Auths/Commands/UpdatePhoneNumberVerifyCodeCommand.cs b/ApiTools.Core/Models/Auths/Commands/UpdatePhoneNumberVerifyCodeCommand.cs
new file mode 100644
index 0000000..095d0f5
--- /dev/null
+++ b/ApiTools.Core/Models/Auths/Commands/UpdatePhoneNumberVerifyCodeCommand.cs
@@ -0,0 +1,24 @@
+锘縰sing Furion.DataValidation;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍙戦�佹洿鎹㈡墜鏈哄彿鐭俊
+ /// </summary>
+ [Resource([EnumResourceController.UserServerAuth])]
+ public class UpdatePhoneNumberVerifyCodeCommand : IRequest<Guid>
+ {
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [Required, DataValidation(ValidationTypes.PhoneNumber)]
+ public string PhoneNumber { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Auths/Queries/GetAliyunOSSAcsQuery.cs b/ApiTools.Core/Models/Auths/Queries/GetAliyunOSSAcsQuery.cs
new file mode 100644
index 0000000..24c69f8
--- /dev/null
+++ b/ApiTools.Core/Models/Auths/Queries/GetAliyunOSSAcsQuery.cs
@@ -0,0 +1,30 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鑾峰彇闃块噷浜慜SS鎺堟潈淇℃伅
+ /// </summary>
+ [Resource([EnumResourceController.UserServerAuth], AllowAnonymous = true)]
+ public class GetAliyunOSSAcsQuery : IRequest<GetAliyunOSSAcsQueryResult>
+ {
+ }
+
+ public class GetAliyunOSSAcsQueryResult
+ {
+ public string Expiration { get; set; }
+
+ public string OssAccessSecret { get; set; }
+
+ public string OssAccessKeyId { get; set; }
+
+ public string SecurityToken { get; set; }
+
+ public string RequestId { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/ChannelUsers/Commands/SaveChannelUserCommand.cs b/ApiTools.Core/Models/ChannelUsers/Commands/SaveChannelUserCommand.cs
new file mode 100644
index 0000000..c2801f8
--- /dev/null
+++ b/ApiTools.Core/Models/ChannelUsers/Commands/SaveChannelUserCommand.cs
@@ -0,0 +1,54 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 淇濆瓨娓犻亾鐢ㄦ埛
+ /// </summary>
+ [Resource([EnumResourceController.UserServerChannelUser])]
+ public class SaveChannelUserCommand : SaveDataCommand
+ {
+ /// <summary>
+ /// 娓犻亾Id
+ /// </summary>
+ public Guid ChannelId { get; set; }
+
+ /// <summary>
+ /// 濮撳悕
+ /// </summary>
+ [MaxLength(32)]
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛鍚�
+ /// </summary>
+ [Required]
+ [MaxLength(32)]
+ public string UserName { get; set; }
+
+ /// <summary>
+ /// 瀵嗙爜
+ /// </summary>
+ public string Password { get; set; }
+
+ /// <summary>
+ /// 绾у埆
+ /// </summary>
+ public int Level { get; set; }
+
+ /// <summary>
+ /// 澶囨敞
+ /// </summary>
+ public string Remark { get; set; }
+
+ /// <summary>
+ /// 鐘舵��
+ /// </summary>
+ public EnumUserStatus Status { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/ChannelUsers/Queries/GetChannelUsersQuery.cs b/ApiTools.Core/Models/ChannelUsers/Queries/GetChannelUsersQuery.cs
new file mode 100644
index 0000000..15756be
--- /dev/null
+++ b/ApiTools.Core/Models/ChannelUsers/Queries/GetChannelUsersQuery.cs
@@ -0,0 +1,74 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ [Resource([EnumResourceController.UserServerChannelUser])]
+ public class GetChannelUsersQuery : PagedListQuery<GetChannelUsersQueryResult, GetChannelUsersQueryResultItem>
+ {
+ }
+
+ /// <summary>
+ /// 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ public class GetChannelUsersQueryResult : PagedListQueryResult<GetChannelUsersQueryResultItem>
+ {
+
+ }
+
+ /// <summary>
+ /// 鏌ヨ娓犻亾鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ public class GetChannelUsersQueryResultItem
+ {
+ /// <summary>
+ /// Id
+ /// </summary>
+ public Guid Id { get; set; }
+
+ /// <summary>
+ /// 娓犻亾Id
+ /// </summary>
+ public Guid? ChannelId { get; set; }
+
+ /// <summary>
+ /// 娓犻亾鍚嶇О
+ /// </summary>
+ public string ChannelName { get; set; }
+
+ /// <summary>
+ /// 濮撳悕
+ /// </summary>
+ [MaxLength(32)]
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛鍚�
+ /// </summary>
+ [Required]
+ [MaxLength(32)]
+ public string UserName { get; set; }
+
+ /// <summary>
+ /// 绾у埆
+ /// </summary>
+ public int Level { get; set; }
+
+ /// <summary>
+ /// 澶囨敞
+ /// </summary>
+ public string Remark { get; set; }
+
+ /// <summary>
+ /// 鐘舵��
+ /// </summary>
+ public EnumUserStatus Status { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Channels/Commands/SaveChannelCommand.cs b/ApiTools.Core/Models/Channels/Commands/SaveChannelCommand.cs
new file mode 100644
index 0000000..0904514
--- /dev/null
+++ b/ApiTools.Core/Models/Channels/Commands/SaveChannelCommand.cs
@@ -0,0 +1,30 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 淇濆瓨娓犻亾
+ /// </summary>
+ [Resource([EnumResourceController.UserServerChannel])]
+ public class SaveChannelCommand : SaveDataCommand
+ {
+ /// <summary>
+ /// 缂栧彿
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/Channels/Queries/GetChannelsQuery.cs b/ApiTools.Core/Models/Channels/Queries/GetChannelsQuery.cs
new file mode 100644
index 0000000..2b3a382
--- /dev/null
+++ b/ApiTools.Core/Models/Channels/Queries/GetChannelsQuery.cs
@@ -0,0 +1,50 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ [Resource([EnumResourceController.UserServerChannel])]
+ public class GetChannelsQuery : PagedListQuery<GetChannelsQueryResult, GetChannelsQueryResultItem>
+ {
+ }
+
+ /// <summary>
+ /// 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ public class GetChannelsQueryResult : PagedListQueryResult<GetChannelsQueryResultItem>
+ {
+
+ }
+
+ /// <summary>
+ /// 鏌ヨ娓犻亾鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ public class GetChannelsQueryResultItem
+ {
+ /// <summary>
+ /// Id
+ /// </summary>
+ public Guid Id { get; set; }
+
+ /// <summary>
+ /// 缂栧彿
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/SmsUtils/Commands/CheckVerifyCodeSmsCommand.cs b/ApiTools.Core/Models/SmsUtils/Commands/CheckVerifyCodeSmsCommand.cs
new file mode 100644
index 0000000..c96f2a0
--- /dev/null
+++ b/ApiTools.Core/Models/SmsUtils/Commands/CheckVerifyCodeSmsCommand.cs
@@ -0,0 +1,31 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏍¢獙楠岃瘉鐮�
+ /// </summary>
+ [Resource([EnumResourceController.CommonServerSmsUtils], Method = EnumResourceMethod.Post)]
+ public class CheckVerifyCodeSmsCommand : IRequest<bool>
+ {
+ /// <summary>
+ /// 鐭俊妯℃澘缂栧彿
+ /// </summary>
+ public EnumSmsTemplateCode TemplateCode { get; set; }
+
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 楠岃瘉鐮�
+ /// </summary>
+ public string VerifyCode { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/SmsUtils/Commands/SaveSmsSettingCommand.cs b/ApiTools.Core/Models/SmsUtils/Commands/SaveSmsSettingCommand.cs
new file mode 100644
index 0000000..2987e7f
--- /dev/null
+++ b/ApiTools.Core/Models/SmsUtils/Commands/SaveSmsSettingCommand.cs
@@ -0,0 +1,72 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 淇濆瓨鐭俊閰嶇疆
+ /// </summary>
+ [Resource([EnumResourceController.CommonServerSmsUtils], Method = EnumResourceMethod.Post)]
+ public class SaveSmsSettingCommand : IRequest<Guid>
+ {
+ public SaveSmsSettingCommand()
+ {
+ Accesses = [];
+ }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+
+ /// <summary>
+ /// 甯﹀嚭鍙傛暟
+ /// </summary>
+ public bool WithoutParams { get; set; }
+
+ /// <summary>
+ /// 姣忓垎閽熸渶澶ф暟閲�
+ /// </summary>
+ public int MinutelyMaxCount { get; set; }
+
+ /// <summary>
+ /// 姣忓皬鏃舵渶澶ф暟閲�
+ /// </summary>
+ public int HourlyMaxCount { get; set; }
+
+ /// <summary>
+ /// 姣忓ぉ鏈�澶ф暟閲�
+ /// </summary>
+ public int DailyMaxCount { get; set; }
+
+ /// <summary>
+ /// 閫氶亾閰嶇疆
+ /// </summary>
+ public List<SaveSmsSettingCommandAccess> Accesses { get; set; }
+ }
+
+ /// <summary>
+ /// 淇濆瓨鐭俊閰嶇疆
+ /// </summary>
+ public class SaveSmsSettingCommandAccess
+ {
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumSmsAccess Access { get; set; }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+
+ /// <summary>
+ /// 鎺掑簭
+ /// </summary>
+ public int Sort { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/SmsUtils/Commands/SendSmsCommand.cs b/ApiTools.Core/Models/SmsUtils/Commands/SendSmsCommand.cs
new file mode 100644
index 0000000..53f78f9
--- /dev/null
+++ b/ApiTools.Core/Models/SmsUtils/Commands/SendSmsCommand.cs
@@ -0,0 +1,44 @@
+锘縰sing Furion.DataValidation;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍙戦�佺煭淇�
+ /// </summary>
+ [Resource([EnumResourceController.CommonServerSmsUtils], Method = EnumResourceMethod.Post)]
+ public class SendSmsCommand : IRequest<Guid>
+ {
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [Required, DataValidation(ValidationTypes.PhoneNumber)]
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 鐭俊妯℃澘缂栧彿
+ /// </summary>
+ public EnumSmsTemplateCode TemplateCode { get; set; }
+
+ /// <summary>
+ /// 妯℃澘鍙傛暟
+ /// </summary>
+ public object TemplateParam { get; set; }
+
+ /// <summary>
+ /// 鏈夋晥鏈�
+ /// </summary>
+ public DateTime? Expiry { get; set; }
+
+ /// <summary>
+ /// 娓犻亾鎿嶄綔浜�
+ /// </summary>
+ public Guid? ChannelCreatedUserId { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/SmsUtils/Commands/SmsAliyunNotifyCommand.cs b/ApiTools.Core/Models/SmsUtils/Commands/SmsAliyunNotifyCommand.cs
new file mode 100644
index 0000000..652f462
--- /dev/null
+++ b/ApiTools.Core/Models/SmsUtils/Commands/SmsAliyunNotifyCommand.cs
@@ -0,0 +1,82 @@
+锘縰sing MediatR;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ /// </summary>
+ [Resource([EnumResourceController.CommonServerSmsUtils], Method = EnumResourceMethod.Post, AllowAnonymous = true, CustomResponse = true)]
+ public class SmsAliyunNotifyCommand : List<SmsAliyunNotifyCommandItem>, IRequest<SmsAliyunNotifyCommandResult>
+ {
+ }
+
+ public class SmsAliyunNotifyCommandItem
+ {
+ /// <summary>
+ /// 杞彂缁欒繍钀ュ晢鐨勬椂闂淬��
+ /// </summary>
+ [JsonProperty("send_time")]
+ public DateTime? SendTime { get; set; }
+ /// <summary>
+ /// 鏀跺埌杩愯惀鍟嗗洖鎵х殑鏃堕棿銆�
+ /// </summary>
+ [JsonProperty("report_time")]
+ public DateTime? ReportTime { get; set; }
+ /// <summary>
+ /// 鏄惁鍙戦�佹垚鍔熴��
+ /// </summary>
+ [JsonProperty("success")]
+ public bool Success { get; set; }
+ /// <summary>
+ /// 閿欒鐮佷俊鎭弿杩般��
+ /// </summary>
+ [JsonProperty("err_msg")]
+ public string ErrMsg { get; set; }
+ /// <summary>
+ /// 閿欒鐮併��
+ /// </summary>
+ [JsonProperty("err_code")]
+ public string ErrCode { get; set; }
+ /// <summary>
+ /// 鐭俊鎺ユ敹鍙风爜銆�
+ /// </summary>
+ [JsonProperty("phone_number")]
+ public string PhoneNumber { get; set; }
+ /// <summary>
+ /// 鐭俊闀垮害銆�
+ /// </summary>
+ [JsonProperty("sms_size")]
+ public string SmsSize { get; set; }
+ /// <summary>
+ /// 鍙戦�佸洖鎵D锛屽嵆鍙戦�佹祦姘村彿銆�
+ /// </summary>
+ [JsonProperty("biz_id")]
+ public string BizId { get; set; }
+ /// <summary>
+ /// 璋冪敤鍙戦�佺煭淇endSms鎺ュ彛鏃朵紶鐨刼utId銆�
+ /// </summary>
+ [JsonProperty("out_id")]
+ public string OutId { get; set; }
+ }
+
+ /// <summary>
+ /// 闃块噷浜戠煭淇″钩鍙板洖浼犻�氱煡
+ /// </summary>
+ public class SmsAliyunNotifyCommandResult
+ {
+ /// <summary>
+ /// 鍥炶皟鐮�
+ /// </summary>
+ public int Code { get; set; }
+ /// <summary>
+ /// 娑堟伅
+ /// </summary>
+ public string Msg { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/SmsUtils/Commands/SmsChengLiYeNotifyCommand.cs b/ApiTools.Core/Models/SmsUtils/Commands/SmsChengLiYeNotifyCommand.cs
new file mode 100644
index 0000000..e871c46
--- /dev/null
+++ b/ApiTools.Core/Models/SmsUtils/Commands/SmsChengLiYeNotifyCommand.cs
@@ -0,0 +1,76 @@
+锘縰sing MediatR;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璇氱珛涓氱煭淇″钩鍙板洖浼犻�氱煡
+ /// </summary>
+ [Resource([EnumResourceController.CommonServerSmsUtils], Method = EnumResourceMethod.Post, AllowAnonymous = true)]
+ public class SmsChengLiYeNotifyCommand : IRequest<bool>
+ {
+ public SmsChengLiYeNotifyCommand()
+ {
+ MsgReports = [];
+ }
+
+ /// <summary>
+ /// 鐘舵�佺爜
+ /// </summary>
+ [JsonProperty("resultCode")]
+ public string ResultCode { get; set; }
+
+ /// <summary>
+ /// 鐘舵�佺爜
+ /// </summary>
+ [JsonProperty("msgReports")]
+ public List<SmsChengLiYeNotifyCommandMsgReport> MsgReports { get; set; }
+ }
+
+ /// <summary>
+ /// 璇氱珛涓氱煭淇¢�氱煡璇锋眰
+ /// </summary>
+ public class SmsChengLiYeNotifyCommandMsgReport
+ {
+ /// <summary>
+ /// 鐢ㄦ埛鍚嶃�傛彁浜ゆ椂鐨勭敤鎴峰悕
+ /// </summary>
+ [JsonProperty("userName")]
+ public string UserName { get; set; }
+ /// <summary>
+ /// 鎻愪氦杩斿洖鐨刴sgid
+ /// </summary>
+ [JsonProperty("msgid")]
+ public long Msgid { get; set; }
+ /// <summary>
+ /// 鎻愪氦杩斿洖鐨剆eqid
+ /// </summary>
+ [JsonProperty("seqid")]
+ public string Seqid { get; set; }
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [JsonProperty("mobile")]
+ public string Mobile { get; set; }
+ /// <summary>
+ /// 鎵嬫満鍙风爜鍙戦�佺姸鎬佺爜
+ /// </summary>
+ [JsonProperty("status")]
+ public string Status { get; set; }
+ /// <summary>
+ /// 鐘舵�佺爜鎻忚堪
+ /// </summary>
+ [JsonProperty("statusDes")]
+ public string StatusDes { get; set; }
+ /// <summary>
+ /// 鎶ュ憡杩斿洖鏃堕棿
+ /// </summary>
+ [JsonProperty("doneTime")]
+ public DateTime DoneTime { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/SmsUtils/Queries/GetSmsLogsQuery.cs b/ApiTools.Core/Models/SmsUtils/Queries/GetSmsLogsQuery.cs
new file mode 100644
index 0000000..3ffaf21
--- /dev/null
+++ b/ApiTools.Core/Models/SmsUtils/Queries/GetSmsLogsQuery.cs
@@ -0,0 +1,162 @@
+锘縰sing Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏌ヨ鐭俊鏃ュ織
+ /// </summary>
+ [Resource([EnumResourceController.CommonServerSmsUtils])]
+ public class GetSmsLogsQuery : PagedListQuery<GetSmsLogsQueryResult, GetSmsLogsQueryResultItem>
+ {
+ public GetSmsLogsQuery()
+ {
+ ChannelCreatedUserIds = [];
+ }
+
+ /// <summary>
+ /// 鍒涘缓鏃堕棿-璧峰
+ /// </summary>
+ public DateTime? CreatedTimeBegin { get; set; }
+
+ /// <summary>
+ /// 鍒涘缓鏃堕棿-鎴
+ /// </summary>
+ public DateTime? CreatedTimeEnd { get; set; }
+
+ /// <summary>
+ /// 娓犻亾鎿嶄綔浜�
+ /// </summary>
+ public List<Guid> ChannelCreatedUserIds { get; set; }
+
+ /// <summary>
+ /// 璺熻釜Id
+ /// </summary>
+ public string TraceId { get; set; }
+
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumSmsAccess? Access { get; set; }
+
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 妯℃澘浠g爜
+ /// </summary>
+ public string TemplateCode { get; set; }
+
+ /// <summary>
+ /// 妯℃澘鍙傛暟
+ /// </summary>
+ public string TemplateParam { get; set; }
+
+ /// <summary>
+ /// 鏄惁浣跨敤
+ /// </summary>
+ public bool? IsUsed { get; set; }
+
+ /// <summary>
+ /// 鐭俊鐘舵��
+ /// </summary>
+ public EnumSmsStatus? Status { get; set; }
+ }
+
+ /// <summary>
+ /// 寮傚父鏃ュ織鍒嗛〉鍒楄〃鏌ヨ-缁撴灉
+ /// </summary>
+ public class GetSmsLogsQueryResult : PagedListQueryResult<GetSmsLogsQueryResultItem>
+ {
+
+ }
+
+ /// <summary>
+ /// 寮傚父鏃ュ織鍒嗛〉鍒楄〃鏌ヨ-缁撴灉-椤�
+ /// </summary>
+ public class GetSmsLogsQueryResultItem
+ {
+ /// <summary>
+ /// Id
+ /// </summary>
+ public Guid Id { get; set; }
+
+ /// <summary>
+ /// 璺熻釜Id
+ /// </summary>
+ public string TraceId { get; set; }
+
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumSmsAccess Access { get; set; }
+
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 妯℃澘浠g爜
+ /// </summary>
+ public string TemplateCode { get; set; }
+
+ /// <summary>
+ /// 妯℃澘鍙傛暟
+ /// </summary>
+ public string TemplateParam { get; set; }
+
+ /// <summary>
+ /// 鏈夋晥鏈�
+ /// </summary>
+ public DateTime? Expiry { get; set; }
+
+ /// <summary>
+ /// 鏄惁浣跨敤
+ /// </summary>
+ public bool IsUsed { get; set; }
+
+ /// <summary>
+ /// 鐭俊鐘舵��
+ /// </summary>
+ public EnumSmsStatus Status { get; set; }
+
+ /// <summary>
+ /// 璇锋眰Id
+ /// </summary>
+ public string RequestId { get; set; }
+
+ /// <summary>
+ /// 鍥炰紶浠g爜
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍥炰紶娑堟伅
+ /// </summary>
+ public string Message { get; set; }
+
+ /// <summary>
+ /// 娓犻亾鍚嶇О
+ /// </summary>
+ public string ChannelName { get; set; }
+
+ /// <summary>
+ /// 娓犻亾鎿嶄綔浜�
+ /// </summary>
+ public Guid? ChannelCreatedUserId { get; set; }
+
+ /// <summary>
+ /// 鍒涘缓鏃堕棿
+ /// </summary>
+ public DateTimeOffset CreatedTime { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Models/SmsUtils/Queries/GetSmsSettingQuery.cs b/ApiTools.Core/Models/SmsUtils/Queries/GetSmsSettingQuery.cs
new file mode 100644
index 0000000..77e9e39
--- /dev/null
+++ b/ApiTools.Core/Models/SmsUtils/Queries/GetSmsSettingQuery.cs
@@ -0,0 +1,80 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏌ヨ鐭俊閰嶇疆
+ /// </summary>
+ [Resource([EnumResourceController.CommonServerSmsUtils], Method = EnumResourceMethod.Post)]
+ public class GetSmsSettingQuery : IRequest<GetSmsSettingQueryResult>
+ {
+
+ }
+
+ /// <summary>
+ /// 鏌ヨ鐭俊閰嶇疆
+ /// </summary>
+ public class GetSmsSettingQueryResult
+ {
+ public GetSmsSettingQueryResult()
+ {
+ Accesses = [];
+ }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+
+ /// <summary>
+ /// 甯﹀嚭鍙傛暟
+ /// </summary>
+ public bool WithoutParams { get; set; }
+
+ /// <summary>
+ /// 姣忓垎閽熸渶澶ф暟閲�
+ /// </summary>
+ public int MinutelyMaxCount { get; set; }
+
+ /// <summary>
+ /// 姣忓皬鏃舵渶澶ф暟閲�
+ /// </summary>
+ public int HourlyMaxCount { get; set; }
+
+ /// <summary>
+ /// 姣忓ぉ鏈�澶ф暟閲�
+ /// </summary>
+ public int DailyMaxCount { get; set; }
+
+ /// <summary>
+ /// 閫氶亾閰嶇疆
+ /// </summary>
+ public List<GetSmsSettingQueryResultAccess> Accesses { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ鐭俊閰嶇疆
+ /// </summary>
+ public class GetSmsSettingQueryResultAccess
+ {
+ /// <summary>
+ /// 閫氶亾
+ /// </summary>
+ public EnumSmsAccess Access { get; set; }
+
+ /// <summary>
+ /// 鏄惁绂佺敤
+ /// </summary>
+ public bool IsDisabled { get; set; }
+
+ /// <summary>
+ /// 鎺掑簭
+ /// </summary>
+ public int Sort { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/AlipayUtils/AlipayOptions.cs b/ApiTools.Core/Utils/AlipayUtils/AlipayOptions.cs
new file mode 100644
index 0000000..449e520
--- /dev/null
+++ b/ApiTools.Core/Utils/AlipayUtils/AlipayOptions.cs
@@ -0,0 +1,25 @@
+锘縰sing Furion.ConfigurableOptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class AlipayOptions : IConfigurableOptions
+ {
+ public string ServerUrl { get; set; }
+ public string AppId { get; set; }
+ public string PrivateKey { get; set; }
+ public string Format { get; set; }
+ public string Charset { get; set; }
+ public string SignType { get; set; }
+ public string AppCertPath { get; set; }
+ public string AlipayPublicCertPath { get; set; }
+ public string RootCertPath { get; set; }
+ public string AlipayPublicKey { get; set; }
+ public string NotifyUrl { get; set; }
+ public string EncryptKey { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/AlipayUtils/AlipayUtils.cs b/ApiTools.Core/Utils/AlipayUtils/AlipayUtils.cs
new file mode 100644
index 0000000..d7e16b0
--- /dev/null
+++ b/ApiTools.Core/Utils/AlipayUtils/AlipayUtils.cs
@@ -0,0 +1,293 @@
+锘縰sing Aliyun.Acs.Core.Logging;
+using Aliyun.OSS;
+using Aop.Api;
+using Aop.Api.Domain;
+using Aop.Api.Request;
+using Aop.Api.Response;
+using Aop.Api.Util;
+using Furion;
+using Furion.FriendlyException;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 闃块噷鏀粯宸ュ叿
+ /// </summary>
+ public class AlipayUtils
+ {
+ private readonly IAopClient alipayClient;
+ private readonly ILogger<AlipayUtils> logger;
+ private readonly IOptions<AlipayOptions> options;
+
+ public AlipayUtils(
+ ILogger<AlipayUtils> logger,
+ IOptions<AlipayOptions> options)
+ {
+ var appCertPath = Path.Combine(App.WebHostEnvironment.ContentRootPath, options.Value.AppCertPath);
+ var alipayPublicCertPath = Path.Combine(App.WebHostEnvironment.ContentRootPath, options.Value.AlipayPublicCertPath);
+ var rootCertPath = Path.Combine(App.WebHostEnvironment.ContentRootPath, options.Value.RootCertPath);
+ alipayClient = new DefaultAopClient(new AlipayConfig
+ {
+ ServerUrl = options.Value.ServerUrl,
+ AppId = options.Value.AppId,
+ PrivateKey = options.Value.PrivateKey,
+ Format = options.Value.Format,
+ Charset = options.Value.Charset,
+ SignType = options.Value.SignType,
+ AppCertPath = appCertPath,
+ AlipayPublicCertPath = alipayPublicCertPath,
+ RootCertPath = rootCertPath,
+ AlipayPublicKey = options.Value.AlipayPublicKey,
+ EncryptKey = options.Value.EncryptKey,
+ });
+ this.logger = logger;
+ this.options = options;
+ }
+
+ /// <summary>
+ /// 鏀粯瀹濅釜浜哄崗璁〉闈㈢绾︽帴鍙�
+ /// </summary>
+ /// <param name="model"></param>
+ /// <param name="notifyUrl"></param>
+ public AlipayUserAgreementPageSignResponse UserAgreementPageSign(AlipayUserAgreementPageSignModel model, string notifyUrl = null)
+ {
+ logger.LogInformation($"姝e湪鎵ц鏀粯瀹濅釜浜哄崗璁〉闈㈢绾︽帴鍙o細{model.ToJson()}");
+ AlipayUserAgreementPageSignRequest request = new AlipayUserAgreementPageSignRequest();
+ request.SetBizModel(model);
+ if (notifyUrl.IsNotNull())
+ {
+ notifyUrl = $"{options.Value.NotifyUrl}{notifyUrl}";
+ request.SetNotifyUrl(notifyUrl);
+ }
+ AlipayUserAgreementPageSignResponse response = alipayClient.pageExecute(request, null, "GET");
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 鏀粯瀹濅釜浜轰唬鎵e崗璁煡璇㈡帴鍙�
+ /// </summary>
+ /// <param name="model"></param>
+ public AlipayUserAgreementQueryResponse UserAgreementQuery(AlipayUserAgreementQueryModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц鏀粯瀹濅釜浜轰唬鎵e崗璁煡璇㈡帴鍙o細{model.ToJson()}");
+ AlipayUserAgreementQueryRequest request = new AlipayUserAgreementQueryRequest();
+ request.SetBizModel(model);
+ AlipayUserAgreementQueryResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 鏀粯瀹濅釜浜轰唬鎵e崗璁В绾︽帴鍙�
+ /// </summary>
+ /// <param name="model"></param>
+ public AlipayUserAgreementUnsignResponse UserAgreementUnsign(AlipayUserAgreementUnsignModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц鏀粯瀹濅釜浜轰唬鎵e崗璁В绾︽帴鍙o細{model.ToJson()}");
+ AlipayUserAgreementUnsignRequest request = new AlipayUserAgreementUnsignRequest();
+ request.SetBizModel(model);
+ AlipayUserAgreementUnsignResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璧勯噾璁拌处鏈紑閫�
+ /// </summary>
+ /// <param name="model"></param>
+ public AlipayFundAccountbookCreateResponse FundAccountbookCreate(AlipayFundAccountbookCreateModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц璧勯噾璁拌处鏈紑閫氭帴鍙o細{model.ToJson()}");
+ AlipayFundAccountbookCreateRequest request = new AlipayFundAccountbookCreateRequest();
+ request.SetBizModel(model);
+ AlipayFundAccountbookCreateResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璧勯噾璁拌处鏈殑淇℃伅鏌ヨ
+ /// </summary>
+ /// <param name="model"></param>
+ public AlipayFundAccountbookQueryResponse FundAccountbookQuery(AlipayFundAccountbookQueryModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц璧勯噾璁拌处鏈殑淇℃伅鏌ヨ鎺ュ彛锛歿model.ToJson()}");
+ AlipayFundAccountbookQueryRequest request = new AlipayFundAccountbookQueryRequest();
+ request.SetBizModel(model);
+ AlipayFundAccountbookQueryResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璧勯噾杞处椤甸潰鏀粯鎺ュ彛
+ /// </summary>
+ /// <param name="model"></param>
+ /// <param name="notifyUrl"></param>
+ public AlipayFundTransPagePayResponse FundTransPagePay(AlipayFundTransPagePayModel model, string notifyUrl = null)
+ {
+ logger.LogInformation($"姝e湪鎵ц璧勯噾杞处椤甸潰鏀粯鎺ュ彛锛歿model.ToJson()}");
+ AlipayFundTransPagePayRequest request = new AlipayFundTransPagePayRequest();
+ request.SetBizModel(model);
+ if (notifyUrl.IsNotNull())
+ {
+ notifyUrl = $"{options.Value.NotifyUrl}{notifyUrl}";
+ request.SetNotifyUrl(notifyUrl);
+ }
+ AlipayFundTransPagePayResponse response = alipayClient.pageExecute(request, null, "GET");
+ logger.LogInformation($"缁撴灉锛歿response.Body}");
+ return response;
+ }
+
+ /// <summary>
+ /// 鍗曠瑪杞处鎺ュ彛
+ /// </summary>
+ /// <param name="model"></param>
+ /// <param name="notifyUrl"></param>
+ public AlipayFundTransUniTransferResponse FundTransUniTransfer(AlipayFundTransUniTransferModel model, string notifyUrl = null)
+ {
+ logger.LogInformation($"姝e湪鎵ц鍗曠瑪杞处鎺ュ彛锛歿model.ToJson()}");
+ AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
+ request.SetBizModel(model);
+ if (notifyUrl.IsNotNull())
+ {
+ notifyUrl = $"{options.Value.NotifyUrl}{notifyUrl}";
+ request.SetNotifyUrl(notifyUrl);
+ }
+ AlipayFundTransUniTransferResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// ISV浠g悊鍟嗘埛鐢宠璧勯噾涓氬姟鍥炲崟
+ /// </summary>
+ /// <param name="model"></param>
+ /// <returns></returns>
+ public AlipayDataBillEreceiptagentApplyResponse DataBillEreceiptagentApply(AlipayDataBillEreceiptagentApplyModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц鐢宠璧勯噾涓氬姟鍥炲崟鎺ュ彛锛歿model.ToJson()}");
+ AlipayDataBillEreceiptagentApplyRequest request = new AlipayDataBillEreceiptagentApplyRequest();
+ request.SetBizModel(model);
+ AlipayDataBillEreceiptagentApplyResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// ISV浠g悊鍟嗘埛鏌ヨ璧勯噾涓氬姟鍥炲崟鐢宠鐘舵��
+ /// </summary>
+ /// <param name="model"></param>
+ /// <returns></returns>
+ public AlipayDataBillAccountbookereceiptQueryResponse DataBillAccountbookereceiptQuery(AlipayDataBillAccountbookereceiptQueryModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц鏌ヨ璧勯噾涓氬姟鍥炲崟鐢宠鐘舵�佹帴鍙o細{model.ToJson()}");
+ AlipayDataBillAccountbookereceiptQueryRequest request = new AlipayDataBillAccountbookereceiptQueryRequest();
+ request.SetBizModel(model);
+ AlipayDataBillAccountbookereceiptQueryResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 杞处涓氬姟鍗曟嵁鏌ヨ鎺ュ彛
+ /// </summary>
+ /// <param name="model"></param>
+ public AlipayFundTransCommonQueryResponse FundTransCommonQuery(AlipayFundTransCommonQueryModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц杞处涓氬姟鍗曟嵁鏌ヨ鎺ュ彛锛歿model.ToJson()}");
+ AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
+ request.SetBizModel(model);
+ AlipayFundTransCommonQueryResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璐﹀崟涓庣數瀛愬嚟璇佷笅杞�
+ /// </summary>
+ /// <param name="model"></param>
+ public AlipayDataBillBizfundagentQueryResponse FundTransCommonQuery(AlipayDataBillBizfundagentQueryModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц璐﹀崟涓庣數瀛愬嚟璇佷笅杞斤細{model.ToJson()}");
+ AlipayDataBillBizfundagentQueryRequest request = new AlipayDataBillBizfundagentQueryRequest();
+ request.SetBizModel(model);
+ AlipayDataBillBizfundagentQueryResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠舵枃浠朵笂浼犳帴鍙�
+ /// </summary>
+ /// <returns></returns>
+ public AlipayFundExpandindirectImageUploadResponse FundExpandindirectImageUpload(AlipayFundExpandindirectImageUploadRequest request)
+ {
+ logger.LogInformation("姝e湪鎵ц璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠舵枃浠朵笂浼犳帴鍙�");
+ AlipayFundExpandindirectImageUploadResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠�
+ /// </summary>
+ /// <param name="model"></param>
+ /// <param name="notifyUrl"></param>
+ /// <returns></returns>
+ public AlipayFundExpandindirectCreateResponse FundExpandindirectCreate(AlipayFundExpandindirectCreateModel model, string notifyUrl = null)
+ {
+ logger.LogInformation($"姝e湪鎵ц璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠讹細{model.ToJson()}");
+ AlipayFundExpandindirectCreateRequest request = new AlipayFundExpandindirectCreateRequest();
+ request.SetBizModel(model);
+ if (notifyUrl.IsNotNull())
+ {
+ notifyUrl = $"{options.Value.NotifyUrl}{notifyUrl}";
+ request.SetNotifyUrl(notifyUrl);
+ }
+ AlipayFundExpandindirectCreateResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠跺崟鏌ヨ鎺ュ彛
+ /// </summary>
+ /// <param name="model"></param>
+ /// <returns></returns>
+ public AlipayFundExpandindirectOrderQueryResponse FundExpandindirectOrderQuery(AlipayFundExpandindirectOrderQueryModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠跺崟鏌ヨ鎺ュ彛锛歿model.ToJson()}");
+ AlipayFundExpandindirectOrderQueryRequest request = new AlipayFundExpandindirectOrderQueryRequest();
+ request.SetBizModel(model);
+ AlipayFundExpandindirectOrderQueryResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+
+ /// <summary>
+ /// 璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠跺崟鍙栨秷鎺ュ彛
+ /// </summary>
+ /// <param name="model"></param>
+ /// <returns></returns>
+ public AlipayFundExpandindirectOrderCancelResponse FundExpandindirectOrderCancel(AlipayFundExpandindirectOrderCancelModel model)
+ {
+ logger.LogInformation($"姝e湪鎵ц璧勯噾浜岀骇鍟嗘埛KYB浠h繘浠跺崟鍙栨秷鎺ュ彛锛歿model.ToJson()}");
+ AlipayFundExpandindirectOrderCancelRequest request = new AlipayFundExpandindirectOrderCancelRequest();
+ request.SetBizModel(model);
+ AlipayFundExpandindirectOrderCancelResponse response = alipayClient.CertificateExecute(request);
+ logger.LogInformation($"缁撴灉锛歿response.ToJson()}");
+ return response;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/AliyunUtils/AliyunOSSUploadResult.cs b/ApiTools.Core/Utils/AliyunUtils/AliyunOSSUploadResult.cs
new file mode 100644
index 0000000..7a35861
--- /dev/null
+++ b/ApiTools.Core/Utils/AliyunUtils/AliyunOSSUploadResult.cs
@@ -0,0 +1,24 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 闃块噷浜慜SS涓婁紶缁撴灉
+ /// </summary>
+ public class AliyunOSSUploadResult
+ {
+ /// <summary>
+ /// 鐩稿璺緞
+ /// </summary>
+ public string Url { get; set; }
+
+ /// <summary>
+ /// 瀛楄妭
+ /// </summary>
+ public byte[] Buffer { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/AliyunUtils/AliyunOSSUtils.cs b/ApiTools.Core/Utils/AliyunUtils/AliyunOSSUtils.cs
new file mode 100644
index 0000000..64b17e2
--- /dev/null
+++ b/ApiTools.Core/Utils/AliyunUtils/AliyunOSSUtils.cs
@@ -0,0 +1,144 @@
+锘縰sing Aliyun.Acs.Core;
+using Aliyun.Acs.Core.Auth.Sts;
+using Aliyun.Acs.Core.Http;
+using Aliyun.Acs.Core.Profile;
+using Aliyun.OSS;
+using Furion;
+using Furion.DistributedIDGenerator;
+using Furion.HttpRemote;
+using Microsoft.AspNetCore.Http;
+using Microsoft.CodeAnalysis;
+using Microsoft.Extensions.Options;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 闃块噷浜慜SS宸ュ叿
+ /// </summary>
+ public static class AliyunOSSUtils
+ {
+ public static GetAliyunOSSAcsQueryResult GetOSSAcs()
+ {
+ var options = App.GetOptions<AliyunOptions>().OSS;
+ IClientProfile profile = DefaultProfile.GetProfile(options.RegionId, options.AccessKeyId, options.AccessSecret);
+ DefaultAcsClient client = new DefaultAcsClient(profile);
+ AssumeRoleRequest request = new AssumeRoleRequest();
+
+ request.Method = MethodType.POST;
+ request.RoleArn = options.RoleArn;
+ request.RoleSessionName = options.RoleSessionName;
+ request.Policy = options.Policy;
+ request.DurationSeconds = options.DurationSeconds;
+ AssumeRoleResponse response = client.GetAcsResponse(request);
+ var result = new GetAliyunOSSAcsQueryResult()
+ {
+ Expiration = response.Credentials.Expiration,
+ OssAccessKeyId = response.Credentials.AccessKeyId,
+ OssAccessSecret = response.Credentials.AccessKeySecret,
+ SecurityToken = response.Credentials.SecurityToken,
+ RequestId = response.RequestId
+ };
+ return result;
+ }
+
+ /// <summary>
+ /// 涓婁紶鏂囦欢
+ /// </summary>
+ /// <param name="scene"></param>
+ /// <param name="url"></param>
+ /// <param name="filename"></param>
+ /// <returns></returns>
+ public static AliyunOSSUploadResult Upload(string scene, string url, string filename = null)
+ {
+ if (filename.IsNull())
+ {
+ filename = url.Substring(url.LastIndexOf('/') + 1);
+ }
+ var stream = App.GetRequiredService<IHttpRemoteService>().GetAsStream(url);
+ return Upload(scene, stream, filename);
+ }
+
+ /// <summary>
+ /// 涓婁紶鏂囦欢
+ /// </summary>
+ /// <param name="url"></param>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ public static AliyunOSSUploadResult Upload(string url, string key)
+ {
+ var stream = App.GetRequiredService<IHttpRemoteService>().GetAsStream(url);
+ return Upload(stream, key);
+ }
+
+ /// <summary>
+ /// 涓婁紶鏂囦欢
+ /// </summary>
+ /// <param name="scene"></param>
+ /// <param name="file"></param>
+ /// <param name="filename"></param>
+ /// <returns></returns>
+ public static AliyunOSSUploadResult Upload(string scene, IFormFile file, string filename = null)
+ {
+ var stream = file.OpenReadStream();
+ filename = filename ?? file.FileName;
+ return Upload(scene, stream, filename);
+ }
+
+ /// <summary>
+ /// 涓婁紶鏂囦欢
+ /// </summary>
+ /// <param name="scene"></param>
+ /// <param name="stream"></param>
+ /// <param name="filename"></param>
+ /// <returns></returns>
+ public static AliyunOSSUploadResult Upload(string scene, Stream stream, string filename)
+ {
+ var key = $"Resource/FlexJob/{scene}/{DateTime.Now:yyyy-MM-dd}/{DateTime.Now.ToTimeStamp()}-{IDGen.NextID()}/{filename}";
+ return Upload(stream, key);
+ }
+
+ /// <summary>
+ /// 涓婁紶鏂囦欢
+ /// </summary>
+ /// <param name="stream"></param>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ public static AliyunOSSUploadResult Upload(Stream stream, string key)
+ {
+ var options = App.GetOptions<AliyunOptions>().OSS;
+ var client = new OssClient(options.Endpoint, options.AccessKeyId, options.AccessSecret);
+ client.PutObject(options.BucketName, key, stream);
+ var result = new AliyunOSSUploadResult
+ {
+ Url = key
+ };
+ stream.Seek(0, SeekOrigin.Begin);
+ result.Buffer = new byte[stream.Length];
+ stream.ReadExactly(result.Buffer);
+ return result;
+ }
+
+ /// <summary>
+ /// 鑾峰彇Url
+ /// </summary>
+ /// <param name="url"></param>
+ /// <param name="process"></param>
+ /// <returns></returns>
+ public static string GetUrl(string url, string process = null)
+ {
+ var options = App.GetOptions<AliyunOptions>().OSS;
+ var client = new OssClient(options.Endpoint, options.AccessKeyId, options.AccessSecret);
+ var req = new GeneratePresignedUriRequest(options.BucketName, url.TrimStart('/'), SignHttpMethod.Get)
+ {
+ Expiration = DateTime.Now.AddHours(1),
+ Process = process
+ };
+ url = client.GeneratePresignedUri(req).ToString();
+ return url;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/AliyunUtils/AliyunOptions.cs b/ApiTools.Core/Utils/AliyunUtils/AliyunOptions.cs
new file mode 100644
index 0000000..d8952ac
--- /dev/null
+++ b/ApiTools.Core/Utils/AliyunUtils/AliyunOptions.cs
@@ -0,0 +1,65 @@
+锘縰sing Furion.ConfigurableOptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 闃块噷浜戦厤缃�
+ /// </summary>
+ public class AliyunOptions : IConfigurableOptions
+ {
+ public AliyunOSSOptions OSS { get; set; }
+ public AliyunSMSOptions SMS { get; set; }
+ }
+
+ /// <summary>
+ /// 闃块噷浜慜SS閰嶇疆
+ /// </summary>
+ public class AliyunOSSOptions
+ {
+ public string AccessKeyId { get; set; }
+ public string AccessSecret { get; set; }
+ public string RegionId { get; set; }
+ public string Endpoint { get; set; }
+ public string BucketName { get; set; }
+ public string Url { get; set; }
+ public string RoleArn { get; set; }
+ public string RoleSessionName { get; set; }
+ public string Policy { get; set; }
+ public int DurationSeconds { get; set; }
+ }
+
+ /// <summary>
+ /// 闃块噷浜戠煭淇¢厤缃�
+ /// </summary>
+ public class AliyunSMSOptions
+ {
+ public string AccessKeyId { get; set; }
+
+ public string AccessSecret { get; set; }
+
+ /// <summary>
+ /// 鐗堟湰
+ /// </summary>
+ public string Version { get; set; }
+
+ /// <summary>
+ /// 绛惧悕鍚嶇О
+ /// </summary>
+ public string SignName { get; set; }
+
+ /// <summary>
+ /// 鍖哄煙Id
+ /// </summary>
+ public string RegionId { get; set; }
+
+ /// <summary>
+ /// 妯℃澘浠g爜
+ /// </summary>
+ public Dictionary<string, string> TemplateCodes { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/BaiduUtils/BaiduOcrBusinessLicenseResult.cs b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrBusinessLicenseResult.cs
new file mode 100644
index 0000000..aecb129
--- /dev/null
+++ b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrBusinessLicenseResult.cs
@@ -0,0 +1,90 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrBusinessLicenseResult
+ {
+ /// <summary>
+ /// 鍦板潃
+ /// </summary>
+ public string Url { get; set; }
+
+ /// <summary>
+ /// 妯″瀷
+ /// </summary>
+ public BaiduOcrBusinessLicenseResultModel Model { get; set; }
+
+ /// <summary>
+ /// 閿欒鐮�
+ /// </summary>
+ [JsonProperty("error_code")]
+ public string ErrorCode { get; set; }
+
+ /// <summary>
+ /// 閿欒娑堟伅
+ /// </summary>
+ [JsonProperty("error_msg")]
+ public string ErrorMessage { get; set; }
+
+ /// <summary>
+ /// 鏂囧瓧缁撴灉
+ /// </summary>
+ [JsonProperty("words_result")]
+ public Dictionary<string, BaiduOcrResultWord> WordsResult { get; set; }
+ }
+
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrBusinessLicenseResultModel
+ {
+ /// <summary>
+ /// 浼佷笟鍏ㄧО
+ /// </summary>
+ public string EnterpriseName { get; set; }
+
+ /// <summary>
+ /// 缁熶竴绀句細淇$敤浠g爜
+ /// </summary>
+ public string SocietyCreditCode { get; set; }
+
+ /// <summary>
+ /// 娉曚汉濮撳悕
+ /// </summary>
+ public string LegalPerson { get; set; }
+
+ /// <summary>
+ /// 浼佷笟绫诲瀷
+ /// </summary>
+ public string EnterpriseType { get; set; }
+
+ /// <summary>
+ /// 娉ㄥ唽璧勬湰
+ /// </summary>
+ public string RegisteredCapital { get; set; }
+
+ /// <summary>
+ /// 鎴愮珛鏃ユ湡
+ /// </summary>
+ public string EstablishmentDate { get; set; }
+
+ /// <summary>
+ /// 浼佷笟鍦板潃
+ /// </summary>
+ public string Address { get; set; }
+
+ /// <summary>
+ /// 缁忚惀鑼冨洿
+ /// </summary>
+ public string MainBusiness { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityBackResult.cs b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityBackResult.cs
new file mode 100644
index 0000000..1fc5a40
--- /dev/null
+++ b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityBackResult.cs
@@ -0,0 +1,78 @@
+锘縰sing Newtonsoft.Json;
+using Swashbuckle.AspNetCore.Annotations;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrIdentityBackResult
+ {
+ /// <summary>
+ /// 鍦板潃
+ /// </summary>
+ public string Url { get; set; }
+
+ /// <summary>
+ /// 妯″瀷
+ /// </summary>
+ public BaiduOcrIdentityBackResultModel Model { get; set; }
+
+ /// <summary>
+ /// 閿欒鐮�
+ /// </summary>
+ [JsonProperty("error_code")]
+ public string ErrorCode { get; set; }
+
+ /// <summary>
+ /// 閿欒娑堟伅
+ /// </summary>
+ [JsonProperty("error_msg")]
+ public string ErrorMessage { get; set; }
+
+ /// <summary>
+ /// 鏂囧瓧缁撴灉
+ /// </summary>
+ [JsonProperty("words_result")]
+ public Dictionary<string, BaiduOcrResultWord> WordsResult { get; set; }
+ }
+
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrIdentityBackResultModel
+ {
+ /// <summary>
+ /// 澶辨晥鏃ユ湡
+ /// </summary>
+ [JsonIgnore, SwaggerIgnore]
+ public string ExpiryDateText { get; set; }
+
+ /// <summary>
+ /// 澶辨晥鏃ユ湡
+ /// </summary>
+ public DateTime? ExpiryDate => ExpiryDateText?.ToDateTime("yyyyMMdd");
+
+ /// <summary>
+ /// 绛惧彂鏈哄叧
+ /// </summary>
+ public string IssueAuthority { get; set; }
+
+ /// <summary>
+ /// 绛惧彂鏃ユ湡
+ /// </summary>
+ [JsonIgnore, SwaggerIgnore]
+ public string IssueDateText { get; set; }
+
+ /// <summary>
+ /// 绛惧彂鏃ユ湡
+ /// </summary>
+ public DateTime? IssueDate => IssueDateText?.ToDateTime("yyyyMMdd");
+ }
+}
diff --git a/ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityFrontResult.cs b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityFrontResult.cs
new file mode 100644
index 0000000..e08a553
--- /dev/null
+++ b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrIdentityFrontResult.cs
@@ -0,0 +1,100 @@
+锘縰sing Newtonsoft.Json;
+using Swashbuckle.AspNetCore.Annotations;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrIdentityFrontResult
+ {
+ /// <summary>
+ /// 鍦板潃
+ /// </summary>
+ public string Url { get; set; }
+
+ /// <summary>
+ /// 妯″瀷
+ /// </summary>
+ public BaiduOcrIdentityFrontResultModel Model { get; set; }
+
+ /// <summary>
+ /// 閿欒鐮�
+ /// </summary>
+ [JsonProperty("error_code")]
+ public string ErrorCode { get; set; }
+
+ /// <summary>
+ /// 閿欒娑堟伅
+ /// </summary>
+ [JsonProperty("error_msg")]
+ public string ErrorMessage { get; set; }
+
+ /// <summary>
+ /// 鏂囧瓧缁撴灉
+ /// </summary>
+ [JsonProperty("words_result")]
+ public Dictionary<string, BaiduOcrResultWord> WordsResult { get; set; }
+ }
+
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrIdentityFrontResultModel
+ {
+ /// <summary>
+ /// <summary>
+ /// 濮撳悕
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 韬唤璇佸彿
+ /// </summary>
+ public string Identity { get; set; }
+
+ /// <summary>
+ /// 鎬у埆
+ /// </summary>
+ [JsonIgnore, SwaggerIgnore]
+ public string GenderText { get; set; }
+
+ /// <summary>
+ /// 鎬у埆
+ /// </summary>
+ public EnumUserGender? Gender =>
+ GenderText == "鐢�"
+ ? EnumUserGender.Male
+ : GenderText == "濂�"
+ ? EnumUserGender.Female
+ : null;
+
+ /// <summary>
+ /// 鐢熸棩
+ /// </summary>
+ [JsonIgnore, SwaggerIgnore]
+ public string BirthdayText { get; set; }
+
+ /// <summary>
+ /// 鐢熸棩
+ /// </summary>
+ public DateTime? Birthday => BirthdayText?.ToDateTime("yyyyMMdd");
+
+ /// <summary>
+ /// 姘戞棌
+ /// </summary>
+ public string Nation { get; set; }
+
+ /// <summary>
+ /// 浣忓潃
+ /// </summary>
+ public string Address { get; set; }
+
+ }
+}
diff --git a/ApiTools.Core/Utils/BaiduUtils/BaiduOcrResultWord.cs b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrResultWord.cs
new file mode 100644
index 0000000..f454e88
--- /dev/null
+++ b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrResultWord.cs
@@ -0,0 +1,57 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrResultWord
+ {
+ /// <summary>
+ /// 瀹氫綅
+ /// </summary>
+ [JsonProperty("location")]
+ public BaiduOcrResultWordLocation Location { get; set; }
+
+ /// <summary>
+ /// 鏂囧瓧
+ /// </summary>
+ [JsonProperty("words")]
+ public string Words { get; set; }
+ }
+
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆缁撴灉
+ /// </summary>
+ public class BaiduOcrResultWordLocation
+ {
+ /// <summary>
+ /// 璺濈椤堕儴
+ /// </summary>
+ [JsonProperty("top")]
+ public int Top { get; set; }
+
+ /// <summary>
+ /// 璺濈宸﹁竟
+ /// </summary>
+ [JsonProperty("left")]
+ public int Left { get; set; }
+
+ /// <summary>
+ /// 瀹藉害
+ /// </summary>
+ [JsonProperty("width")]
+ public int Width { get; set; }
+
+ /// <summary>
+ /// 楂樺害
+ /// </summary>
+ [JsonProperty("height")]
+ public int Height { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/BaiduUtils/BaiduOcrUtils.cs b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrUtils.cs
new file mode 100644
index 0000000..7dde3d1
--- /dev/null
+++ b/ApiTools.Core/Utils/BaiduUtils/BaiduOcrUtils.cs
@@ -0,0 +1,157 @@
+锘縰sing Baidu.Aip.Ocr;
+using Furion;
+using Furion.DistributedIDGenerator;
+using Furion.FriendlyException;
+using Furion.HttpRemote;
+using Microsoft.AspNetCore.DataProtection;
+using Microsoft.Extensions.Options;
+using NetTopologySuite.Operation.Buffer;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆宸ュ叿
+ /// </summary>
+ public static class BaiduOcrUtils
+ {
+ /// <summary>
+ /// 钀ヤ笟鎵х収OCR
+ /// </summary>
+ /// <param name="url"></param>
+ /// <param name="scene"></param>
+ /// <param name="isOssUrl"></param>
+ public static async Task<BaiduOcrBusinessLicenseResult> OcrBusinessLicense(this string url, string scene = null, bool isOssUrl = true)
+ {
+ var options = App.GetOptions<BaiduOptions>();
+ var ocr = new Ocr(options.Ocr.Key, options.Ocr.Secret);
+ ocr.Timeout = 60000;
+ JObject value;
+ if (isOssUrl)
+ {
+ var downloadUrl = AliyunOSSUtils.GetUrl(url);
+ var buffer = await App.GetRequiredService<IHttpRemoteService>().GetAsByteArrayAsync(downloadUrl);
+ value = ocr.BusinessLicense(buffer);
+ }
+ else
+ {
+ var upload = AliyunOSSUtils.Upload(scene, url, null);
+ url = upload.Url;
+ value = ocr.BusinessLicense(upload.Buffer);
+ }
+ var result = value.ToObject<BaiduOcrBusinessLicenseResult>();
+ result.Url = url;
+ if (result.ErrorCode.IsNotNull())
+ {
+ return result;
+ }
+ result.Model = new BaiduOcrBusinessLicenseResultModel
+ {
+ EnterpriseName = result.WordsResult.GetWords("鍗曚綅鍚嶇О"),
+ SocietyCreditCode = result.WordsResult.GetWords("绀句細淇$敤浠g爜"),
+ LegalPerson = result.WordsResult.GetWords("娉曚汉"),
+ EnterpriseType = result.WordsResult.GetWords("绫诲瀷"),
+ RegisteredCapital = result.WordsResult.GetWords("娉ㄥ唽璧勬湰"),
+ EstablishmentDate = result.WordsResult.GetWords("鎴愮珛鏃ユ湡"),
+ Address = result.WordsResult.GetWords("鍦板潃"),
+ MainBusiness = result.WordsResult.GetWords("缁忚惀鑼冨洿"),
+ };
+ return result;
+ }
+
+ /// <summary>
+ /// 韬唤璇佹闈CR
+ /// </summary>
+ /// <param name="url"></param>
+ /// <param name="scene"></param>
+ /// <param name="isOssUrl"></param>
+ public static async Task<BaiduOcrIdentityFrontResult> OcrIdentityFront(this string url, string scene = null, bool isOssUrl = true)
+ {
+ var options = App.GetOptions<BaiduOptions>();
+ var ocr = new Ocr(options.Ocr.Key, options.Ocr.Secret);
+ ocr.Timeout = 60000;
+ JObject value;
+ if (isOssUrl)
+ {
+ var downloadUrl = AliyunOSSUtils.GetUrl(url);
+ var buffer = await App.GetRequiredService<IHttpRemoteService>().GetAsByteArrayAsync(downloadUrl);
+ value = ocr.Idcard(buffer, "front");
+ }
+ else
+ {
+ var upload = AliyunOSSUtils.Upload(scene, url, null);
+ url = upload.Url;
+ value = ocr.Idcard(upload.Buffer, "front");
+ }
+ var result = value.ToObject<BaiduOcrIdentityFrontResult>();
+ result.Url = url;
+ if (result.ErrorCode.IsNotNull())
+ {
+ return result;
+ }
+
+ result.Model = new BaiduOcrIdentityFrontResultModel
+ {
+ Address = result.WordsResult.GetWords("浣忓潃"),
+ Identity = result.WordsResult.GetWords("鍏皯韬唤鍙风爜"),
+ BirthdayText = result.WordsResult.GetWords("鍑虹敓"),
+ Name = result.WordsResult.GetWords("濮撳悕"),
+ GenderText = result.WordsResult.GetWords("鎬у埆"),
+ Nation = result.WordsResult.GetWords("姘戞棌"),
+ };
+ return result;
+ }
+
+ /// <summary>
+ /// 韬唤璇佽儗闈CR
+ /// </summary>
+ /// <param name="url"></param>
+ /// <param name="scene"></param>
+ /// <param name="isOssUrl"></param>
+ public static async Task<BaiduOcrIdentityBackResult> OcrIdentityBack(this string url, string scene = null, bool isOssUrl = true)
+ {
+ var options = App.GetOptions<BaiduOptions>();
+ var ocr = new Ocr(options.Ocr.Key, options.Ocr.Secret);
+ ocr.Timeout = 60000;
+ JObject value;
+ if (isOssUrl)
+ {
+ var downloadUrl = AliyunOSSUtils.GetUrl(url);
+ var buffer = await App.GetRequiredService<IHttpRemoteService>().GetAsByteArrayAsync(downloadUrl);
+ value = ocr.Idcard(buffer, "back");
+ }
+ else
+ {
+ var upload = AliyunOSSUtils.Upload(scene, url, null);
+ url = upload.Url;
+ value = ocr.Idcard(upload.Buffer, "back");
+ }
+ var result = value.ToObject<BaiduOcrIdentityBackResult>();
+ result.Url = url;
+ if (result.ErrorCode.IsNotNull())
+ {
+ return result;
+ }
+
+ result.Model = new BaiduOcrIdentityBackResultModel
+ {
+ ExpiryDateText = result.WordsResult.GetWords("澶辨晥鏃ユ湡"),
+ IssueAuthority = result.WordsResult.GetWords("绛惧彂鏈哄叧"),
+ IssueDateText = result.WordsResult.GetWords("绛惧彂鏃ユ湡"),
+ };
+ return result;
+ }
+
+ public static string GetWords(this Dictionary<string, BaiduOcrResultWord> result, string name)
+ {
+ return result.ContainsKey(name) ? result[name].Words : null;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/BaiduUtils/BaiduOptions.cs b/ApiTools.Core/Utils/BaiduUtils/BaiduOptions.cs
new file mode 100644
index 0000000..179d9f7
--- /dev/null
+++ b/ApiTools.Core/Utils/BaiduUtils/BaiduOptions.cs
@@ -0,0 +1,36 @@
+锘縰sing Furion.ConfigurableOptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐧惧害閰嶇疆
+ /// </summary>
+ public class BaiduOptions : IConfigurableOptions
+ {
+ /// <summary>
+ /// 鏂囧瓧璇嗗埆
+ /// </summary>
+ public BaiduOcrOptions Ocr { get; set; }
+ }
+
+ /// <summary>
+ /// 鐧惧害鏂囧瓧璇嗗埆閰嶇疆
+ /// </summary>
+ public class BaiduOcrOptions
+ {
+ /// <summary>
+ /// 閿�
+ /// </summary>
+ public string Key { get; set; }
+
+ /// <summary>
+ /// 绉橀挜
+ /// </summary>
+ public string Secret { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/BaiduUtils/OcrResult.cs b/ApiTools.Core/Utils/BaiduUtils/OcrResult.cs
new file mode 100644
index 0000000..f16cbb5
--- /dev/null
+++ b/ApiTools.Core/Utils/BaiduUtils/OcrResult.cs
@@ -0,0 +1,26 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// OCR璇嗗埆缁撴灉
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public class OcrResult<T>
+ where T : class, new()
+ {
+ /// <summary>
+ /// 鍦板潃
+ /// </summary>
+ public string Url { get; set; }
+
+ /// <summary>
+ /// 鏁版嵁
+ /// </summary>
+ public T Data { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/CollectionUtils/CollectionUtils.cs b/ApiTools.Core/Utils/CollectionUtils/CollectionUtils.cs
new file mode 100644
index 0000000..5c87a72
--- /dev/null
+++ b/ApiTools.Core/Utils/CollectionUtils/CollectionUtils.cs
@@ -0,0 +1,73 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public static class CollectionUtils
+ {
+ /// <summary>
+ /// 鍘婚噸娣诲姞
+ /// </summary>
+ /// <typeparam name="T">娉涘瀷瀵硅薄</typeparam>
+ /// <param name="list">闆嗗悎</param>
+ /// <param name="item">闇�娣诲姞鐨勯」</param>
+ /// <param name="comparer">姣旇緝</param>
+ /// <returns>闆嗗悎</returns>
+ public static List<T> DistinctAdd<T>(this List<T> list, T item, IEqualityComparer<T> comparer = null)
+ {
+ if (list == null) return new List<T> { item };
+ if (!list.Contains(item, comparer)) list.Add(item);
+ return list;
+ }
+
+ public static List<TResult> DistinctSelect<TSource, TResult>(this IEnumerable<TSource> list, Func<TSource, TResult> selector)
+ {
+ return list.Select(selector).Distinct().ToList();
+ }
+
+ public static List<TResult> DistinctSelect<TSource, TResult>(this IEnumerable<TSource> list, Func<TSource, bool> predicate, Func<TSource, TResult> selector)
+ {
+ return list.Where(predicate).Select(selector).Distinct().ToList();
+ }
+
+ public static string SplitJoin(this IEnumerable<string> list, string split)
+ {
+ list = list.DistinctSelect(it => it.IsNotNull(), it => it);
+ return string.Join(split, list);
+ }
+
+ public static string SplitJoin<T>(this IEnumerable<T> list, Func<T, string> selector, string split)
+ {
+ return list.Select(selector).SplitJoin(split);
+ }
+
+ public static string SplitJoin<T>(this IEnumerable<T> list, Func<T, bool> predicate, Func<T, string> selector, string split)
+ {
+ return list.Where(predicate).Select(selector).SplitJoin(split);
+ }
+
+ public static bool IsNull<T>(this T[] list)
+ {
+ return list == null || list.Length == 0;
+ }
+
+ public static bool IsNotNull<T>(this T[] list)
+ {
+ return !list.IsNull();
+ }
+
+ public static bool IsNull<T>(this List<T> list)
+ {
+ return list == null || list.Count == 0;
+ }
+
+ public static bool IsNotNull<T>(this List<T> list)
+ {
+ return !list.IsNull();
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ConsoleLogUtils/ConsoleLogUtils.cs b/ApiTools.Core/Utils/ConsoleLogUtils/ConsoleLogUtils.cs
new file mode 100644
index 0000000..c0e4c4d
--- /dev/null
+++ b/ApiTools.Core/Utils/ConsoleLogUtils/ConsoleLogUtils.cs
@@ -0,0 +1,13 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public static class ConsoleLogUtils
+ {
+
+ }
+}
diff --git a/ApiTools.Core/Utils/ConsoleLogUtils/DatabaseLoggingWriter.cs b/ApiTools.Core/Utils/ConsoleLogUtils/DatabaseLoggingWriter.cs
new file mode 100644
index 0000000..0529d32
--- /dev/null
+++ b/ApiTools.Core/Utils/ConsoleLogUtils/DatabaseLoggingWriter.cs
@@ -0,0 +1,64 @@
+锘縰sing Furion;
+using Furion.DatabaseAccessor;
+using Furion.DistributedIDGenerator;
+using Furion.Logging;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
+ {
+ private readonly IServiceScope serviceScope;
+ private readonly IRepository<ConsoleLog, LogDbContextLocator> rep;
+
+ public DatabaseLoggingWriter(IServiceScopeFactory scopeFactory)
+ {
+ serviceScope = scopeFactory.CreateScope();
+ rep = serviceScope.ServiceProvider.GetRequiredService<IRepository<ConsoleLog, LogDbContextLocator>>();
+ }
+
+ public async Task WriteAsync(LogMessage logMsg, bool flush)
+ {
+ var logier = JwtUtils.GetCurrentLogier();
+ await rep.InsertNowAsync(new ConsoleLog
+ {
+ Id = IDGen.NextID(),
+ Access = EnumConsoleLogAccess.Back,
+ Content = logMsg.Message,
+ Level = logMsg.LogLevel == LogLevel.Trace
+ ? EnumLogLevel.Trace
+ : logMsg.LogLevel == LogLevel.Debug
+ ? EnumLogLevel.Debug
+ : logMsg.LogLevel == LogLevel.Information
+ ? EnumLogLevel.Information
+ : logMsg.LogLevel == LogLevel.Warning
+ ? EnumLogLevel.Warning
+ : logMsg.LogLevel == LogLevel.Error
+ ? EnumLogLevel.Error
+ : logMsg.LogLevel == LogLevel.Critical
+ ? EnumLogLevel.Critical
+ : EnumLogLevel.Information,
+ ClientIpAddress = App.HttpContext?.GetRemoteIpAddressToIPv4(),
+ TraceId = logMsg.TraceId,
+ CreatedTime = logMsg.LogDateTime,
+ CreatedUserId = logier?.Id,
+ CreatedChannelId = logier?.ChannelId
+ });
+ }
+
+ /// <summary>
+ /// 閲婃斁鏈嶅姟浣滅敤鍩�
+ /// </summary>
+ public void Dispose()
+ {
+ serviceScope.Dispose();
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ConsulUtils/ConsulApplicationComponent.cs b/ApiTools.Core/Utils/ConsulUtils/ConsulApplicationComponent.cs
new file mode 100644
index 0000000..4df3ee5
--- /dev/null
+++ b/ApiTools.Core/Utils/ConsulUtils/ConsulApplicationComponent.cs
@@ -0,0 +1,62 @@
+锘縰sing Consul;
+using Furion;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class ConsulApplicationComponent : IApplicationComponent
+ {
+ public void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext)
+ {
+ var consulClient = app.ApplicationServices.GetRequiredService<IConsulClient>();
+ var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();
+
+ // 鏈嶅姟閰嶇疆锛堜粠appsettings.json璇诲彇锛�
+ var serviceName = App.Configuration["Consul:ServiceName"] ?? "UnknownService";
+ var serviceHost = App.Configuration["Consul:ServiceIP"] ?? "localhost";
+ var servicePort = int.Parse(App.Configuration["Consul:ServicePort"]); // 鎴栫洿鎺ョ敤鍚姩绔彛
+
+ // 鏈嶅姟鍞竴ID锛堥伩鍏嶅悓涓�鏈嶅姟澶氬疄渚嬪啿绐侊級
+ var serviceId = $"{serviceName}-{serviceHost}-{servicePort}";
+
+ var check = new AgentServiceCheck
+ {
+ HTTP = $"http://{serviceHost}:{servicePort}{App.Configuration["Consul:ServiceHealthCheck"]}",
+ Interval = TimeSpan.FromSeconds(5),
+ Timeout = TimeSpan.FromSeconds(5),
+ DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(30)
+ };
+ if (env.IsDevelopment())
+ {
+ check.Timeout = TimeSpan.FromMinutes(5);
+ }
+ // 鏈嶅姟娉ㄥ唽淇℃伅
+ var registration = new AgentServiceRegistration
+ {
+ ID = serviceId,
+ Name = serviceName,
+ Address = serviceHost,
+ Port = servicePort,
+ // 鍋ュ悍妫�鏌ラ厤缃�
+ Check = check
+ };
+
+ // 娉ㄥ唽鏈嶅姟
+ consulClient.Agent.ServiceRegister(registration).Wait();
+
+ // 搴旂敤鍋滄鏃舵敞閿�鏈嶅姟
+ lifetime.ApplicationStopping.Register(() =>
+ {
+ consulClient.Agent.ServiceDeregister(serviceId).Wait();
+ });
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ConsulUtils/ConsulServiceComponent.cs b/ApiTools.Core/Utils/ConsulUtils/ConsulServiceComponent.cs
new file mode 100644
index 0000000..4e709af
--- /dev/null
+++ b/ApiTools.Core/Utils/ConsulUtils/ConsulServiceComponent.cs
@@ -0,0 +1,23 @@
+锘縰sing Consul;
+using Furion;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class ConsulServiceComponent : IServiceComponent
+ {
+ public void Load(IServiceCollection services, ComponentContext componentContext)
+ {
+ services.AddSingleton<IConsulClient, ConsulClient>(p => new ConsulClient(config =>
+ {
+ var address = App.Configuration["Consul:Address"] ?? "http://localhost:8500";
+ config.Address = new Uri(address);
+ }));
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/DateTimeUtils/DateTimeRange.cs b/ApiTools.Core/Utils/DateTimeUtils/DateTimeRange.cs
new file mode 100644
index 0000000..930cad2
--- /dev/null
+++ b/ApiTools.Core/Utils/DateTimeUtils/DateTimeRange.cs
@@ -0,0 +1,23 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏃堕棿鍩�
+ /// </summary>
+ public class DateTimeRange
+ {
+ /// <summary>
+ /// 寮�濮嬫椂闂�
+ /// </summary>
+ public DateTime Start { get; set; }
+ /// <summary>
+ /// 缁撴潫鏃堕棿
+ /// </summary>
+ public DateTime End { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/DateTimeUtils/DateTimeUtils.cs b/ApiTools.Core/Utils/DateTimeUtils/DateTimeUtils.cs
new file mode 100644
index 0000000..0a3b172
--- /dev/null
+++ b/ApiTools.Core/Utils/DateTimeUtils/DateTimeUtils.cs
@@ -0,0 +1,241 @@
+锘縰sing Microsoft.SqlServer.Server;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏃堕棿宸ュ叿
+ /// </summary>
+ public static class DateTimeUtils
+ {
+ /// <summary>
+ /// 杞椂闂�
+ /// </summary>
+ /// <param name="obj">瀵硅薄</param>
+ /// <returns>鏃堕棿</returns>
+ public static DateTime? ToDateTime(this object obj)
+ {
+ if (obj != null && DateTime.TryParse(obj.ToString(), out var date) && date != DateTime.MinValue && date != DateTimeOffset.MinValue)
+ {
+ return date;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// 杞椂闂�
+ /// </summary>
+ /// <param name="obj">瀵硅薄</param>
+ /// <param name="format"></param>
+ /// <returns>鏃堕棿</returns>
+ public static DateTime? ToDateTime(this object obj, string format)
+ {
+ if (obj != null && DateTime.TryParseExact(obj.ToString(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date) && date != DateTime.MinValue && date != DateTimeOffset.MinValue)
+ {
+ return date;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// 杞椂闂�
+ /// </summary>
+ /// <param name="dic">瀛楀吀</param>
+ /// <param name="key">閿�</param>
+ /// <returns>鍊�</returns>
+ public static DateTime? ToDateTime<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key)
+ {
+ if (dic != null && dic.ContainsKey(key) && dic[key] != null && DateTime.TryParse(dic[key]?.ToString(), out var date) && date != DateTime.MinValue) return date;
+ return null;
+ }
+
+ /// <summary>
+ /// 鏃堕棿杞椂闂存埑
+ /// </summary>
+ /// <param name="time">鏃堕棿</param>
+ /// <param name="milliseconds">true姣绾� false绉掔骇</param>
+ /// <returns>鏃堕棿鎴�</returns>
+ public static long ToTimeStamp(this DateTime time, bool milliseconds = true)
+ {
+ var timespan = time.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0);
+ return milliseconds ? (long)timespan.TotalMilliseconds : (long)timespan.TotalSeconds;
+ }
+
+ /// <summary>
+ /// 鏃堕棿鎴宠浆鏃堕棿
+ /// </summary>
+ /// <param name="timestamp">鏃堕棿鎴�</param>
+ /// <param name="milliseconds">true姣绾� false绉掔骇</param>
+ /// <returns>鏃堕棿</returns>
+ public static DateTime ToDateTimeByMilliseconds(this long timestamp, bool milliseconds = true)
+ {
+ var time = new DateTime(1970, 1, 1, 0, 0, 0);
+ time = milliseconds ? time.AddMilliseconds(timestamp) : time.AddSeconds(timestamp);
+ return time.ToLocalTime();
+ }
+
+ /// <summary>
+ /// 鎴彇鏃ユ湡
+ /// </summary>
+ /// <param name="date">鏃堕棿</param>
+ /// <returns>鏃ユ湡</returns>
+ public static DateTime? GetYYYYMMDD(this DateTime? date)
+ {
+ return date.HasValue ? date.Value.GetYYYYMMDD() : null;
+ }
+
+ /// <summary>
+ /// 鎴彇鏃ユ湡
+ /// </summary>
+ /// <param name="date">鏃堕棿</param>
+ /// <returns>鏃ユ湡</returns>
+ public static DateTime GetYYYYMMDD(this DateTime date)
+ {
+ return new DateTime(date.Year, date.Month, date.Day);
+ }
+
+ /// <summary>
+ /// 鑾峰彇骞撮緞
+ /// </summary>
+ /// <param name="birthday"></param>
+ /// <returns></returns>
+ public static int? GetAge(this DateTime? birthday)
+ {
+ if (birthday == null) return null;
+ var age = DateTime.Now.Year - birthday.Value.Year;
+ if (birthday.Value.Date > DateTime.Today.AddYears(-age))
+ {
+ age--;
+ }
+ return age;
+ }
+
+ /// <summary>
+ /// 鑾峰彇鏃堕棿鑼冨洿閫夋嫨鍣�
+ /// </summary>
+ /// <param name="str"></param>
+ /// <param name="range"></param>
+ /// <returns></returns>
+ public static bool TryToDateTimeRange(this string str, out DateTimeRange range)
+ {
+ range = new DateTimeRange();
+ if (str.IsNotNull())
+ {
+ if (str.Contains(","))
+ {
+ var times = str.Split(',');
+ if (times.Length == 2
+ && DateTime.TryParse(times[0], out var start) && start != DateTime.MinValue
+ && DateTime.TryParse(times[1], out var end) && end != DateTime.MinValue
+ && end >= start)
+ {
+ range.Start = start;
+ range.End = end;
+ }
+ }
+ else if (str.StartsWith("Relative"))
+ {
+ var splits = str.Split("_");
+ if (splits.Length == 4
+ && int.TryParse(splits[2], out var quantity))
+ {
+ var type = splits[1];
+ var unit = splits[3];
+ if ((type == "Before" || type == "Current" || type == "After")
+ && (unit == "Day" || unit == "Week" || unit == "Month"))
+ {
+ var now = DateTime.Now;
+ range.Start = new DateTime(now.Year, now.Month, now.Day);
+ if (type == "Before")
+ {
+ quantity = 0 - quantity;
+ }
+ switch (unit)
+ {
+ case "Day":
+ range.Start = range.Start.AddDays(quantity);
+ range.End = new DateTime(range.Start.Year, range.Start.Month, range.Start.Day, 23, 59, 59, 999);
+ break;
+ case "Week":
+ var week = (int)range.Start.DayOfWeek;
+ range.Start = range.Start.AddDays(0 - week);
+ range.Start = range.Start.AddDays(quantity * 7);
+ range.End = new DateTime(range.Start.Year, range.Start.Month, range.Start.Day, 23, 59, 59, 999).AddDays(6);
+ break;
+ case "Month":
+ range.Start = new DateTime(now.Year, now.Month, 1).AddMonths(quantity);
+ range.End = new DateTime(range.Start.Year, range.Start.Month, DateTime.DaysInMonth(range.Start.Year, range.Start.Month), 23, 59, 59, 999);
+ break;
+ }
+ }
+ }
+ }
+ else if (DateTime.TryParse(str, out var time) && time != DateTime.MinValue)
+ {
+ range.Start = time;
+ range.End = time;
+ }
+ }
+ if (range.Start == DateTime.MinValue && range.End == DateTime.MinValue)
+ {
+ range = null;
+ return false;
+ }
+ else if (
+ range.Start.Hour == 0 && range.Start.Minute == 0 && range.Start.Second == 0
+ && range.End.Hour == 0 && range.End.Minute == 0 && range.End.Second == 0)
+ {
+ range.End = new DateTime(range.End.Year, range.End.Month, range.End.Day, 23, 59, 59, 999);
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// 鑾峰彇浠婂ぉ鑼冨洿
+ /// </summary>
+ /// <returns></returns>
+ public static DateTimeRange GetTodayRange()
+ {
+ var now = DateTime.Now;
+ var range = new DateTimeRange();
+ range.Start = new DateTime(now.Year, now.Month, now.Day);
+ range.End = new DateTime(now.Year, now.Month, now.Day, 23, 59, 59, 999);
+ return range;
+ }
+
+ /// <summary>
+ /// 鏍煎紡鍖�
+ /// </summary>
+ /// <param name="span"></param>
+ /// <returns></returns>
+ public static string Format(this TimeSpan span)
+ {
+ if (span.Days > 0)
+ {
+ return $"{span.Days}澶�";
+ }
+ else if (span.Hours > 0)
+ {
+ return $"{span.Hours}灏忔椂{span.Minutes}鍒�";
+ }
+ else if (span.Minutes > 0)
+ {
+ return $"{span.Minutes}鍒唟span.Seconds}绉�";
+ }
+ else if (span.Seconds > 0)
+ {
+ return $"{span.Seconds}绉�";
+ }
+ else if (span.Milliseconds > 0)
+ {
+ return $"{span.Milliseconds}姣";
+ }
+ return null;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/DbUtils/DbUtils.cs b/ApiTools.Core/Utils/DbUtils/DbUtils.cs
new file mode 100644
index 0000000..75e00d4
--- /dev/null
+++ b/ApiTools.Core/Utils/DbUtils/DbUtils.cs
@@ -0,0 +1,611 @@
+锘縰sing Consul.Filtering;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.DistributedIDGenerator;
+using Furion.FriendlyException;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.ChangeTracking;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.Extensions.Configuration;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Timers;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏁版嵁搴撳伐鍏�
+ /// </summary>
+ public static class DbUtils
+ {
+ /// <summary>
+ /// 鑾峰彇鏍戝舰鏁版嵁璺緞
+ /// </summary>
+ /// <typeparam name="TEntity"></typeparam>
+ /// <param name="parentId"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task<string> GetTreeDataPath<TEntity>(
+ Guid? parentId,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, ITreeData<TEntity>, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ if (parentId.HasValue)
+ {
+ var parent = await rep.AsQueryable().AsNoTracking()
+ .Where(it => it.Id == parentId)
+ .Select(it => new
+ {
+ it.Path,
+ it.Code
+ })
+ .FirstOrDefaultAsync(cancellationToken);
+ var summary = typeof(TEntity).GetSummary();
+ if (parent == null) throw Oops.Oh(EnumErrorCodeType.s404, $"涓婄骇{summary}");
+ return $"{parent.Path}{parent.Code}/";
+ }
+ else
+ {
+ return "/";
+ }
+ }
+
+ /// <summary>
+ /// 鏇存柊鏍戝舰鏁版嵁涓嬬骇璺緞
+ /// </summary>
+ /// <param name="oldPath"></param>
+ /// <param name="newPath"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task UpdateTreeDataChildrenPath<TEntity>(
+ string oldPath,
+ string newPath,
+ CancellationToken cancellationToken)
+ where TEntity : CommonEntity, ITreeData<TEntity>, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ var models = await rep.AsQueryable()
+ .Where(it => it.Path.StartsWith(oldPath))
+ .ToListAsync(cancellationToken);
+ if (models.IsNotNull())
+ {
+ foreach (var model in models)
+ {
+ model.Path = model.Path.Replace(oldPath, newPath);
+ }
+ await rep.UpdateAsync(models);
+ }
+ }
+
+ /// <summary>
+ /// 鏌ヨ閫夋嫨鍣ㄦ暟鎹�
+ /// </summary>
+ /// <typeparam name="TEntity"></typeparam>
+ /// <typeparam name="TValue"></typeparam>
+ /// <typeparam name="TData"></typeparam>
+ /// <param name="request"></param>
+ /// <param name="getValue"></param>
+ /// <param name="getLabel"></param>
+ /// <param name="query"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task<List<SelectOption<TValue, TData>>> GetSelect<TEntity, TValue, TData>(
+ this SelectQuery<TValue, TData> request,
+ Func<TData, TValue> getValue,
+ Func<TData, string> getLabel,
+ Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ var q = rep.AsQueryable().AsNoTracking();
+ if (query != null) q = query(q);
+ else q = q.OrderBy(it => it.Sort).ThenBy(it => it.CreatedTime);
+ var models = await q
+ .ProjectToType<TData>()
+ .ToListAsync(cancellationToken);
+ var options = new List<SelectOption<TValue, TData>>();
+ foreach (var model in models)
+ {
+ var option = new SelectOption<TValue, TData>();
+ option.Data = model;
+ option.Value = getValue(model);
+ option.Label = getLabel(model);
+ options.Add(option);
+ }
+ return options;
+ }
+
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ /// <typeparam name="TEntity"></typeparam>
+ /// <typeparam name="TItem"></typeparam>
+ /// <param name="page"></param>
+ /// <param name="query"></param>
+ /// <param name="selector"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task<PagedListQueryResult<TItem>> GetPagedListAsync<TEntity, TItem>(
+ this PagedListQueryPageModel page,
+ Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+ Expression<Func<TEntity, TItem>> selector = null,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, new()
+ where TItem : class, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ var q = rep.AsQueryable().AsNoTracking();
+ if (query != null) q = query(q);
+ else q = q.OrderBy(it => it.Sort).ThenBy(it => it.CreatedTime);
+ if (page.OrderInput.IsNotNull())
+ q = q.CustomOrderBy(page.OrderInput);
+ var s = selector == null
+ ? q.ProjectToType<TItem>()
+ : q.Select(selector);
+ var pagedList = await s.ToPagedListAsync(page.Page, page.Rows, cancellationToken);
+ var result = new PagedListQueryResult<TItem>();
+ result.PageModel = page.Adapt<PagedListQueryResultPageModel>();
+ result.PageModel.TotalCount = pagedList.TotalCount;
+ result.PageModel.TotalPage = pagedList.TotalPages;
+ result.Data = pagedList.Items.ToList();
+ return result;
+ }
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ /// <typeparam name="TResult"></typeparam>
+ /// <typeparam name="TItem"></typeparam>
+ /// <param name="page"></param>
+ /// <param name="q"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task<TResult> GetPagedListAsync<TResult, TItem>(
+ this PagedListQueryPageModel page,
+ IQueryable<TItem> q,
+ CancellationToken cancellationToken = default)
+ where TItem : class, new()
+ where TResult : PagedListQueryResult<TItem>, new()
+ {
+ if (page.OrderInput.IsNotNull())
+ q = q.CustomOrderBy(page.OrderInput);
+ var pagedList = await q.ToPagedListAsync(page.Page, page.Rows, cancellationToken);
+ var result = new TResult();
+ result.PageModel = page.Adapt<PagedListQueryResultPageModel>();
+ result.PageModel.TotalCount = pagedList.TotalCount;
+ result.PageModel.TotalPage = pagedList.TotalPages;
+ result.Data = pagedList.Items.ToList();
+ return result;
+ }
+
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃鏁版嵁
+ /// </summary>
+ /// <typeparam name="TItem"></typeparam>
+ /// <param name="page"></param>
+ /// <param name="q"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static Task<PagedListQueryResult<TItem>> GetPagedListAsync<TItem>(
+ this PagedListQueryPageModel page,
+ IQueryable<TItem> q,
+ CancellationToken cancellationToken = default)
+ where TItem : class, new()
+ {
+ return GetPagedListAsync<PagedListQueryResult<TItem>, TItem>(page, q, cancellationToken);
+ }
+
+ public static IOrderedQueryable<T> CustomOrderBy<T>(this IQueryable<T> q, List<PagedListQueryPageModelOrderInput> orders)
+ {
+ ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
+ PagedListQueryPageModelOrderInput orderInput = orders[0];
+ IOrderedQueryable<T> orderedQueryable = (orderInput.Order == EnumPagedListOrder.Asc)
+ ? OrderBy(q, orderInput.Property, parameter)
+ : OrderByDescending(q, orderInput.Property, parameter);
+ for (int i = 1; i < orders.Count; i++)
+ {
+ PagedListQueryPageModelOrderInput orderInput2 = orders[i];
+ orderedQueryable = (orderInput2.Order == EnumPagedListOrder.Asc)
+ ? ThenBy(orderedQueryable, orderInput2.Property, parameter)
+ : ThenByDescending(orderedQueryable, orderInput2.Property, parameter);
+ }
+
+ return orderedQueryable;
+ }
+
+ private static IOrderedQueryable<T> Ordering<T>(IQueryable<T> source, ParameterExpression parameter, string propertyName, string methodName)
+ {
+ Type typeFromHandle = typeof(T);
+ MemberExpression memberExpression = Expression.PropertyOrField(parameter, propertyName);
+ LambdaExpression expression = Expression.Lambda(memberExpression, parameter);
+ MethodCallExpression expression2 = Expression.Call(typeof(Queryable), methodName, [typeFromHandle, memberExpression.Type], source.Expression, Expression.Quote(expression));
+ return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(expression2);
+ }
+
+ public static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> source, string propertyName, ParameterExpression parameter)
+ {
+ return Ordering(source, parameter, propertyName, "OrderBy");
+ }
+
+ public static IOrderedQueryable<T> OrderByDescending<T>(IQueryable<T> source, string propertyName, ParameterExpression parameter)
+ {
+ return Ordering(source, parameter, propertyName, "OrderByDescending");
+ }
+
+ public static IOrderedQueryable<T> ThenBy<T>(IOrderedQueryable<T> source, string propertyName, ParameterExpression parameter)
+ {
+ return Ordering(source, parameter, propertyName, "ThenBy");
+ }
+
+ public static IOrderedQueryable<T> ThenByDescending<T>(IOrderedQueryable<T> source, string propertyName, ParameterExpression parameter)
+ {
+ return Ordering(source, parameter, propertyName, "ThenByDescending");
+ }
+
+ public static async Task<TResult> GetDetail<TEntity, TResult>(
+ this Guid id,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ return await rep.AsQueryable().AsNoTracking()
+ .Where(it => it.Id == id)
+ .GetDetail<TEntity, TResult>(cancellationToken);
+ }
+
+ public static async Task<TResult> GetDetail<TEntity, TResult>(
+ this IQueryable<TEntity> q,
+ CancellationToken cancellationToken = default)
+ {
+ var model = await q
+ .ProjectToType<TResult>()
+ .FirstOrDefaultAsync(cancellationToken);
+ if (model == null)
+ {
+ var summary = await typeof(TEntity).GetSummary();
+ throw Oops.Oh(EnumErrorCodeType.s404, $"{summary ?? "淇℃伅"}");
+ }
+ return model;
+ }
+
+ /// <summary>
+ /// 璁剧疆鏄惁绂佺敤
+ /// </summary>
+ /// <typeparam name="TEntity"></typeparam>
+ /// <param name="request"></param>
+ /// <param name="query"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task<int> SetIsDisabled<TEntity>(
+ this SetIsDisabledCommand request,
+ Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, IIsDisabled, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ var q = rep.AsQueryable();
+ if (query != null) q = query(q);
+ var entities = await q
+ .Where(it => request.Ids.Contains(it.Id) && it.IsDisabled != request.IsDisabled)
+ .ToListAsync();
+ foreach (var entity in entities)
+ {
+ entity.IsDisabled = request.IsDisabled;
+ }
+ return entities.Count;
+ }
+
+ /// <summary>
+ /// 鍒犻櫎鏁版嵁
+ /// </summary>
+ /// <typeparam name="TEntity"></typeparam>
+ /// <param name="request"></param>
+ /// <param name="query"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task<int> DeleteData<TEntity>(
+ this DeleteDataCommand request, Func<IQueryable<TEntity>,
+ IQueryable<TEntity>> query = null,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ var q = rep.AsQueryable();
+ if (query != null) q = query(q);
+ var entities = await q
+ .Where(it => request.Ids.Contains(it.Id))
+ .ToListAsync(cancellationToken);
+ return entities.Any()
+ ? await rep.DeleteNowAsync(entities, cancellationToken)
+ : 0;
+ }
+
+ public static async Task<Guid> UpdateData<TEntity, TRequest>(
+ this IQueryable<TEntity> q,
+ TRequest request,
+ Action<TEntity> update = null,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, new()
+ {
+ var rep = Db.GetRepository<TEntity>();
+ var entity = await q.FirstOrDefaultAsync();
+ if (entity == null)
+ {
+ var summary = await typeof(TEntity).GetSummary();
+ throw Oops.Oh(EnumErrorCodeType.s404, $"{summary ?? "淇℃伅"}");
+ }
+
+ if (update != null) update(entity);
+ else request.Adapt(entity);
+ await rep.UpdateAsync(entity);
+ return entity.Id;
+ }
+
+ /// <summary>
+ /// 淇濆瓨鏁版嵁
+ /// </summary>
+ /// <typeparam name="TEntity"></typeparam>
+ /// <typeparam name="TRequest"></typeparam>
+ /// <param name="request"></param>
+ /// <param name="query"></param>
+ /// <param name="checkExist"></param>
+ /// <param name="update"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public static async Task<TEntity> SaveData<TEntity, TRequest>(
+ this TRequest request,
+ Func<IQueryable<TEntity>, IQueryable<TEntity>> query = null,
+ Expression<Func<TEntity, bool>> checkExist = null,
+ Action<TEntity> update = null,
+ CancellationToken cancellationToken = default)
+ where TEntity : CommonEntity, new()
+ where TRequest : SaveDataCommand, new()
+ {
+ var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+ var summary = await typeof(TEntity).GetSummary(xmlDoc);
+ var rep = Db.GetRepository<TEntity>();
+ if (checkExist != null && await rep.AsQueryable().AsNoTracking().AnyAsync(checkExist))
+ throw Oops.Oh(EnumErrorCodeType.s405, $"{summary ?? "淇℃伅"}");
+ if (request.Id.HasValue)
+ {
+ var q = rep.AsQueryable();
+ if (query != null) q = query(q);
+ var entity = await q.FirstOrDefaultAsync(it => it.Id == request.Id, cancellationToken);
+ if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, $"{summary ?? "淇℃伅"}");
+ if (update != null) update(entity);
+ else request.Adapt(entity);
+ await rep.UpdateAsync(entity);
+ return entity;
+ }
+ else
+ {
+ var entity = new TEntity();
+ if (update != null) update(entity);
+ else request.Adapt(entity);
+ await rep.InsertAsync(entity);
+ return entity;
+ }
+ }
+
+ /// <summary>
+ /// 鐢熸垚瀹炰綋
+ /// </summary>
+ /// <param name="modelBuilder"></param>
+ /// <param name="dbContextLocator"></param>
+ /// <returns></returns>
+ public static async Task BuildEntity(ModelBuilder modelBuilder, Type dbContextLocator = null)
+ {
+ if (App.GetService<IMigrator>() != null)
+ {
+ var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+ foreach (var entityType in modelBuilder.Model.GetEntityTypes())
+ {
+ Console.WriteLine($"姝e湪鐢熸垚琛細{entityType.Name}");
+ // 鑾峰彇瀹炰綋绫荤殑XML娉ㄩ噴锛屽苟璁剧疆涓鸿〃娉ㄩ噴
+ var entityBuilder = modelBuilder.Entity(entityType.ClrType);
+ string typeComment = (await entityType.ClrType.GetXmlDocMemberAsync(xmlDoc))?.Summary;
+ if (!string.IsNullOrEmpty(typeComment))
+ {
+ Console.WriteLine($"姝e湪鐢熸垚琛ㄦ敞閲婏細{entityType.Name}-{typeComment}");
+ entityBuilder.ToTable(it => it.HasComment(typeComment));
+ }
+ // 鑾峰彇瀹炰綋灞炴�х殑XML娉ㄩ噴锛屽苟璁剧疆涓哄垪娉ㄩ噴
+ var properties = entityType.ClrType.GetProperties()
+ .Where(p =>
+ p.CanRead
+ && p.CanWrite
+ && !typeof(System.Collections.ICollection).IsAssignableFrom(p.PropertyType)
+ && (p.PropertyType.IsClass ? p.PropertyType.FullName.Contains("System.") : true));
+ foreach (var property in properties)
+ {
+ string propComment = (await property.GetXmlDocMemberAsync(xmlDoc))?.Summary;
+ if (!string.IsNullOrEmpty(propComment))
+ {
+ Console.WriteLine($"姝e湪鐢熸垚灞炴�ф敞閲婏細{property.Name}-{propComment}");
+ entityBuilder.Property(property.Name).HasComment(propComment);
+ }
+ }
+ }
+ }
+
+ foreach (var entityType in modelBuilder.Model.GetEntityTypes())
+ {
+ if (typeof(CommonEntity).IsAssignableFrom(entityType.ClrType))
+ {
+ // 鏋勫缓绛涢�夋潯浠讹細IsDeleted == false
+ var parameter = Expression.Parameter(entityType.ClrType, "e");
+ var property = Expression.Property(parameter, "IsDeleted");
+ var constant = Expression.Constant(false);
+ var equal = Expression.Equal(property, constant);
+ var lambda = Expression.Lambda(equal, parameter);
+
+ // 娣诲姞鍏ㄥ眬绛涢�夊櫒
+ modelBuilder.Entity(entityType.ClrType).HasQueryFilter(lambda);
+ }
+ }
+ }
+
+ /// <summary>
+ /// 鏁版嵁鍙樻洿浜嬩欢
+ /// </summary>
+ /// <param name="eventData"></param>
+ /// <param name="result"></param>
+ public static void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)
+ {
+ // 鑾峰彇褰撳墠浜嬩欢瀵瑰簲涓婁笅鏂�
+ var dbContext = eventData.Context;
+
+ // 寮哄埗閲嶆柊妫�鏌ヤ竴杈瑰疄浣撴洿鏀逛俊鎭�
+ // dbContext.ChangeTracker.DetectChanges();
+
+ // 鑾峰彇鎵�鏈夋洿鏀癸紝鍒犻櫎锛屾柊澧炵殑瀹炰綋
+ var dbAuditLogIgnoreType = typeof(IDbAuditLogIgnore);
+ var physicalDeletionType = typeof(IPhysicalDeletion);
+ var entities = dbContext.ChangeTracker.Entries()
+ .Where(u =>
+ u.GetType() != typeof(DbAuditLog)
+ && (u.State == EntityState.Modified
+ || u.State == EntityState.Deleted
+ || u.State == EntityState.Added))
+ .ToList();
+
+ // 閫氳繃璇锋眰涓幏鍙栧綋鍓嶆搷浣滀汉
+ var logier = JwtUtils.GetCurrentLogier();
+ var traceId = App.GetTraceId();
+
+ // 鑾峰彇鎵�鏈夊凡鏇存敼鐨勫疄浣�
+ foreach (var entity in entities)
+ {
+ // 鑾峰彇瀹炰綋绫诲瀷
+ var entityType = entity.Entity.GetType();
+
+ if (entity.State == EntityState.Added)
+ {
+ // 璧嬪�煎垱寤烘棩鏈�
+ var prop = entity.Property(nameof(CommonEntity.CreatedTime));
+ if (prop != null && prop.CurrentValue?.ToDateTime() == null)
+ {
+ prop.CurrentValue = DateTimeOffset.Now;
+ }
+
+ // 鐢熸垚Id
+ prop = entity.Property(nameof(CommonEntity.Id));
+ var defaultValue = Activator.CreateInstance(prop.Metadata.ClrType);
+ if (prop != null && (prop.CurrentValue == null || prop.CurrentValue.Equals(defaultValue)))
+ {
+ prop.CurrentValue = IDGen.NextID();
+ }
+
+ // 璧嬪�肩敤鎴蜂俊鎭疘d
+ prop = entity.Property(nameof(CommonEntity.CreatedUserId));
+ if (prop != null && prop.CurrentValue == null)
+ {
+ prop.CurrentValue = logier?.Id;
+ }
+
+ // 璧嬪�间紒涓欼d
+ prop = entity.Property(nameof(CommonEntity.CreatedChannelId));
+ if (prop != null && prop.CurrentValue == null)
+ {
+ prop.CurrentValue = logier?.ChannelId;
+ }
+
+ // 璧嬪�艰窡韪狪d
+ prop = entity.Property(nameof(CommonEntity.TraceId));
+ if (prop != null && prop.CurrentValue == null && traceId.IsNotNull())
+ {
+ prop.CurrentValue = traceId;
+ }
+ }
+ else
+ {
+ // 璧嬪�间慨鏀规棩鏈�
+ var prop = entity.Property(nameof(CommonEntity.UpdatedTime));
+ if (prop != null)
+ {
+ prop.CurrentValue = DateTimeOffset.Now;
+ }
+
+ // 璧嬪�肩敤鎴蜂俊鎭疘d
+ prop = entity.Property(nameof(CommonEntity.UpdatedUserId));
+ if (prop != null)
+ {
+ prop.CurrentValue = logier?.Id;
+ }
+
+ // 璧嬪�艰窡韪狪d
+ prop = entity.Property(nameof(CommonEntity.TraceId));
+ if (prop != null && traceId.IsNotNull())
+ {
+ prop.CurrentValue = traceId;
+ }
+
+ // 杞垹闄�
+ if (entity.State == EntityState.Deleted && !physicalDeletionType.IsAssignableFrom(entityType))
+ {
+ entity.State = EntityState.Modified;
+
+ prop = entity.Property(nameof(CommonEntity.IsDeleted));
+ if (prop != null)
+ {
+ prop.CurrentValue = true;
+ }
+ }
+ }
+
+ if (dbAuditLogIgnoreType.IsAssignableFrom(entityType))
+ {
+ continue;
+ }
+
+ var log = new DbAuditLog
+ {
+ Id = IDGen.NextID(),
+ TableName = entityType.Name,
+ PrimaryKey = (Guid)entity.Property("Id").CurrentValue,
+ TraceId = App.GetTraceId(),
+ CreatedTime = DateTime.Now,
+ CreatedUserId = logier?.Id,
+ CreatedChannelId = logier?.ChannelId
+ };
+ log.Operate =
+ entity.State == EntityState.Added
+ ? EnumDbAuditOperate.Added
+ : entity.State == EntityState.Modified
+ ? EnumDbAuditOperate.Modified
+ : EnumDbAuditOperate.Deleted;
+ if (entity.Property(nameof(CommonEntity.IsDeleted)).CurrentValue is bool isDeleted && isDeleted == true)
+ {
+ log.Operate = EnumDbAuditOperate.Deleted;
+ }
+ log.NewValues =
+ log.Operate == EnumDbAuditOperate.Deleted
+ ? null
+ : JsonConvert.SerializeObject(entity.Properties
+ .Where(p => log.Operate == EnumDbAuditOperate.Modified
+ ? p.IsModified
+ : true)
+ .ToDictionary(p => p.Metadata.Name, p => p.CurrentValue));
+ log.OldValues =
+ log.Operate == EnumDbAuditOperate.Added
+ ? null
+ : JsonConvert.SerializeObject(entity.Properties
+ .Where(p => log.Operate == EnumDbAuditOperate.Modified
+ ? p.IsModified
+ : true)
+ .ToDictionary(p => p.Metadata.Name, p => p.OriginalValue));
+ Db.GetRepository<DbAuditLog, LogDbContextLocator>().InsertNow(log);
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/DbUtils/DeleteDataCommand.cs b/ApiTools.Core/Utils/DbUtils/DeleteDataCommand.cs
new file mode 100644
index 0000000..c797e42
--- /dev/null
+++ b/ApiTools.Core/Utils/DbUtils/DeleteDataCommand.cs
@@ -0,0 +1,24 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍒犻櫎鍛戒护
+ /// </summary>
+ public abstract class DeleteDataCommand : IRequest<int>
+ {
+ protected DeleteDataCommand()
+ {
+ Ids = [];
+ }
+
+ [Required]
+ public List<Guid> Ids { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/DbUtils/PagedListQuery.cs b/ApiTools.Core/Utils/DbUtils/PagedListQuery.cs
new file mode 100644
index 0000000..69670a8
--- /dev/null
+++ b/ApiTools.Core/Utils/DbUtils/PagedListQuery.cs
@@ -0,0 +1,119 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃
+ /// </summary>
+ /// <typeparam name="TResult"></typeparam>
+ /// <typeparam name="TItem"></typeparam>
+ public abstract class PagedListQuery<TResult, TItem> : IRequest<TResult>
+ where TResult : PagedListQueryResult<TItem>, new()
+ where TItem : class, new()
+ {
+ protected PagedListQuery()
+ {
+ PageModel = new PagedListQueryPageModel();
+ }
+
+ /// <summary>
+ /// 鍒嗛〉淇℃伅
+ /// </summary>
+ public PagedListQueryPageModel PageModel { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃-鍒嗛〉淇℃伅
+ /// </summary>
+ public class PagedListQueryPageModel
+ {
+ public PagedListQueryPageModel()
+ {
+ Page = 1;
+ Rows = 40;
+ OrderInput = [];
+ }
+
+ /// <summary>
+ /// 琛屾暟
+ /// </summary>
+ public int Rows { get; set; }
+
+ /// <summary>
+ /// 椤电爜
+ /// </summary>
+ public int Page { get; set; }
+
+ /// <summary>
+ /// 鎺掑簭
+ /// </summary>
+ public List<PagedListQueryPageModelOrderInput> OrderInput { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃-鍒嗛〉淇℃伅-鎺掑簭淇℃伅
+ /// </summary>
+ public class PagedListQueryPageModelOrderInput
+ {
+ /// <summary>
+ /// 灞炴��
+ /// </summary>
+ public string Property { get; set; }
+
+ /// <summary>
+ /// 鎺掑簭
+ /// </summary>
+ public EnumPagedListOrder Order { get; set; }
+ }
+
+ public interface IPagedListQueryResult<TItem>
+ where TItem : class, new()
+ {
+ PagedListQueryResultPageModel PageModel { get; set; }
+ List<TItem> Data { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃-缁撴灉
+ /// </summary>
+ /// <typeparam name="TItem"></typeparam>
+ public class PagedListQueryResult<TItem> : IPagedListQueryResult<TItem>
+ where TItem : class, new()
+ {
+ public PagedListQueryResult()
+ {
+ Data = [];
+ }
+
+ /// <summary>
+ /// 鍒嗛〉淇℃伅
+ /// </summary>
+ public PagedListQueryResultPageModel PageModel { get; set; }
+
+ /// <summary>
+ /// 鏁版嵁
+ /// </summary>
+ public List<TItem> Data { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ鍒嗛〉鍒楄〃-鍒嗛〉淇℃伅
+ /// </summary>
+ public class PagedListQueryResultPageModel : PagedListQueryPageModel
+ {
+ /// <summary>
+ /// 鎬绘暟
+ /// </summary>
+ public int TotalCount { get; set; }
+
+ /// <summary>
+ /// 椤垫暟
+ /// </summary>
+ public int TotalPage { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/DbUtils/SaveDataCommand.cs b/ApiTools.Core/Utils/DbUtils/SaveDataCommand.cs
new file mode 100644
index 0000000..60e867a
--- /dev/null
+++ b/ApiTools.Core/Utils/DbUtils/SaveDataCommand.cs
@@ -0,0 +1,20 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 淇濆瓨鏁版嵁鍛戒护
+ /// </summary>
+ public abstract class SaveDataCommand : IRequest<Guid>
+ {
+ /// <summary>
+ /// Id
+ /// </summary>
+ public virtual Guid? Id { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/DbUtils/SelectQuery.cs b/ApiTools.Core/Utils/DbUtils/SelectQuery.cs
new file mode 100644
index 0000000..8805127
--- /dev/null
+++ b/ApiTools.Core/Utils/DbUtils/SelectQuery.cs
@@ -0,0 +1,40 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 閫夋嫨鍣ㄦ煡璇�
+ /// </summary>
+ /// <typeparam name="TValue"></typeparam>
+ /// <typeparam name="TData"></typeparam>
+ public abstract class SelectQuery<TValue, TData> : IRequest<List<SelectOption<TValue, TData>>>
+ {
+
+ }
+
+ /// <summary>
+ /// 閫夋嫨鍣ㄦ煡璇�-缁撴灉-椤�
+ /// </summary>
+ public class SelectOption<TValue, TData>
+ {
+ /// <summary>
+ /// 鍊�
+ /// </summary>
+ public TValue Value { get; set; }
+
+ /// <summary>
+ /// 鏍囩
+ /// </summary>
+ public string Label { get; set; }
+
+ /// <summary>
+ /// 鏁版嵁
+ /// </summary>
+ public TData Data { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/DbUtils/SetIsDisabledCommand.cs b/ApiTools.Core/Utils/DbUtils/SetIsDisabledCommand.cs
new file mode 100644
index 0000000..f35801b
--- /dev/null
+++ b/ApiTools.Core/Utils/DbUtils/SetIsDisabledCommand.cs
@@ -0,0 +1,27 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璁剧疆鏄惁宸茬鐢ㄥ懡浠�
+ /// </summary>
+ public abstract class SetIsDisabledCommand : IRequest<int>, IIsDisabled
+ {
+ protected SetIsDisabledCommand()
+ {
+ Ids = [];
+ }
+
+ public List<Guid> Ids { get; set; }
+
+ /// <summary>
+ /// 鏄惁宸茬鐢�
+ /// </summary>
+ public bool IsDisabled { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/DistributedCacheUtils/DistributedCacheServiceComponent.cs b/ApiTools.Core/Utils/DistributedCacheUtils/DistributedCacheServiceComponent.cs
new file mode 100644
index 0000000..e2194d2
--- /dev/null
+++ b/ApiTools.Core/Utils/DistributedCacheUtils/DistributedCacheServiceComponent.cs
@@ -0,0 +1,23 @@
+锘縰sing Furion;
+using Microsoft.Extensions.DependencyInjection;
+using StackExchange.Redis;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public sealed class DistributedCacheServiceComponent : IServiceComponent
+ {
+ public void Load(IServiceCollection services, ComponentContext componentContext)
+ {
+ services.AddStackExchangeRedisCache(options =>
+ {
+ options.Configuration = App.Configuration["DistributedCache:Configuration"];
+ options.InstanceName = "FlexJobApi";
+ });
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/EnumUtils/EnumModel.cs b/ApiTools.Core/Utils/EnumUtils/EnumModel.cs
new file mode 100644
index 0000000..5bc39db
--- /dev/null
+++ b/ApiTools.Core/Utils/EnumUtils/EnumModel.cs
@@ -0,0 +1,72 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class EnumModel
+ {
+ public EnumModel()
+ {
+ Items = [];
+ }
+
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鎻忚堪
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// 鏋氫妇椤�
+ /// </summary>
+ public List<EnumModelItem> Items { get; set; }
+ }
+
+ public class EnumModel<T> : EnumModel
+ where T : struct
+ {
+ public EnumModel()
+ {
+ Items = [];
+ }
+
+ /// <summary>
+ /// 鏋氫妇椤�
+ /// </summary>
+ public new List<EnumModelItem<T>> Items { get; set; }
+ }
+
+ public class EnumModelItem
+ {
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鍊�
+ /// </summary>
+ public int Value { get; set; }
+
+ /// <summary>
+ /// 鎻忚堪
+ /// </summary>
+ public string Description { get; set; }
+ }
+
+ public class EnumModelItem<T> : EnumModelItem
+ where T : struct
+ {
+ /// <summary>
+ /// 鏋氫妇
+ /// </summary>
+ public T Enum { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/EnumUtils/EnumUtils.cs b/ApiTools.Core/Utils/EnumUtils/EnumUtils.cs
new file mode 100644
index 0000000..e27ec75
--- /dev/null
+++ b/ApiTools.Core/Utils/EnumUtils/EnumUtils.cs
@@ -0,0 +1,115 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏋氫妇宸ュ叿
+ /// </summary>
+ public static class EnumUtils
+ {
+ /// <summary>
+ /// 鑾峰彇妯″瀷
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns></returns>
+ public static async Task<EnumModel<T>> GetModel<T>()
+ where T : struct
+ {
+ var type = typeof(T);
+ var model = new EnumModel<T>();
+ var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+ var xmlDocMember = await XmlDocUtils.GetXmlDocMemberAsync(type, xmlDoc);
+ model.Name = type.Name;
+ model.Description = xmlDocMember?.Summary;
+
+ foreach (var enumValue in Enum.GetValues(type))
+ {
+ var item = new EnumModelItem<T>();
+ item.Name = enumValue.ToString();
+ item.Value = (int)enumValue;
+ item.Enum = (T)enumValue;
+ var enumMember = type.GetMember(enumValue.ToString()).FirstOrDefault();
+ var enumXmlDocMember = await XmlDocUtils.GetXmlDocMemberAsync(enumMember, xmlDoc);
+ item.Description = enumXmlDocMember?.Summary;
+ model.Items.Add(item);
+ }
+ return model;
+ }
+
+ /// <summary>
+ /// 鑾峰彇妯″瀷
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ public static async Task<EnumModel> GetModel(this Type type)
+ {
+ var model = new EnumModel();
+ var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+ var xmlDocMember = await XmlDocUtils.GetXmlDocMemberAsync(type, xmlDoc);
+ model.Name = type.Name;
+ model.Description = xmlDocMember?.Summary;
+
+ foreach (var enumValue in Enum.GetValues(type))
+ {
+ var item = new EnumModelItem();
+ item.Name = enumValue.ToString();
+ item.Value = (int)enumValue;
+ var enumMember = type.GetMember(enumValue.ToString()).FirstOrDefault();
+ var enumXmlDocMember = await XmlDocUtils.GetXmlDocMemberAsync(enumMember, xmlDoc);
+ item.Description = enumXmlDocMember?.Summary;
+ model.Items.Add(item);
+ }
+ return model;
+ }
+
+ /// <summary>
+ /// 鑾峰彇鎻忚堪
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="model"></param>
+ /// <param name="t"></param>
+ /// <returns></returns>
+ public static string GetDescription<T>(this EnumModel<T> model, T t)
+ where T : struct
+ {
+ return model.Items
+ .Where(it => it.Enum.Equals(t))
+ .Select(it => it.Description)
+ .FirstOrDefault();
+ }
+
+ /// <summary>
+ /// 鑾峰彇鏋氫妇
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="model"></param>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ public static T GetEnum<T>(string name)
+ where T : struct, Enum
+ {
+ name = Enum.GetNames<T>().FirstOrDefault(it => it.Equals(name, StringComparison.OrdinalIgnoreCase));
+ return Enum.Parse<T>(name);
+ }
+
+ /// <summary>
+ /// 鑾峰彇鑷畾涔夌壒鎬�
+ /// </summary>
+ /// <typeparam name="TEnum"></typeparam>
+ /// <typeparam name="TAttribute"></typeparam>
+ /// <param name="enum"></param>
+ /// <returns></returns>
+ public static TAttribute GetCustomAttribute<TEnum, TAttribute>(this TEnum @enum)
+ where TEnum : struct
+ where TAttribute : Attribute
+ {
+
+ return typeof(TEnum).GetMember(@enum.ToString())[0].GetCustomAttribute<TAttribute>();
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/EventBusUtils/EventBusServiceComponent.cs b/ApiTools.Core/Utils/EventBusUtils/EventBusServiceComponent.cs
new file mode 100644
index 0000000..88490a8
--- /dev/null
+++ b/ApiTools.Core/Utils/EventBusUtils/EventBusServiceComponent.cs
@@ -0,0 +1,43 @@
+锘縰sing Furion;
+using Furion.EventBus;
+using Microsoft.Extensions.DependencyInjection;
+using RabbitMQ.Client;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 浜嬩欢鎬荤嚎
+ /// </summary>
+ public class EventBusServiceComponent : IServiceComponent
+ {
+ public void Load(IServiceCollection services, ComponentContext componentContext)
+ {
+ services.AddEventBus(options =>
+ {
+ // 鍒涘缓杩炴帴宸ュ巶
+ var factory = new ConnectionFactory
+ {
+ HostName = "118.178.252.28",
+ Port = 5672,
+ UserName = "admin",
+ Password = "Bole12345678",
+ };
+
+ // 鍒涘缓榛樿鍐呭瓨閫氶亾浜嬩欢婧愬璞★紝鍙嚜瀹氫箟闃熷垪璺敱key锛屾瘮濡傝繖閲屾槸鍚姩椤圭洰鍚嶇О
+ var rbmqEventSourceStorer = new RabbitMQEventSourceStorer(factory, Assembly.GetExecutingAssembly().GetName().Name, 12000);
+
+ // 鏇挎崲榛樿浜嬩欢鎬荤嚎瀛樺偍鍣�
+ options.ReplaceStorer(serviceProvider =>
+ {
+ return rbmqEventSourceStorer;
+ });
+ });
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/EventBusUtils/RabbitMQEventSourceStorer.cs b/ApiTools.Core/Utils/EventBusUtils/RabbitMQEventSourceStorer.cs
new file mode 100644
index 0000000..2dfe60b
--- /dev/null
+++ b/ApiTools.Core/Utils/EventBusUtils/RabbitMQEventSourceStorer.cs
@@ -0,0 +1,139 @@
+锘縰sing Furion.EventBus;
+using RabbitMQ.Client;
+using RabbitMQ.Client.Events;
+using System;
+using System.Text;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Channels;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public sealed class RabbitMQEventSourceStorer : IEventSourceStorer, IDisposable
+ {
+ /// <summary>
+ /// 鍐呭瓨閫氶亾浜嬩欢婧愬瓨鍌ㄥ櫒
+ /// </summary>
+ private readonly Channel<IEventSource> _channel;
+
+ /// <summary>
+ /// 閫氶亾瀵硅薄
+ /// </summary>
+ private readonly IModel _model;
+
+ /// <summary>
+ /// 杩炴帴瀵硅薄
+ /// </summary>
+ private readonly IConnection _connection;
+
+ /// <summary>
+ /// 璺敱閿�
+ /// </summary>
+ private readonly string _routeKey;
+
+ /// <summary>
+ /// 鏋勯�犲嚱鏁�
+ /// </summary>
+ /// <param name="factory">杩炴帴宸ュ巶</param>
+ /// <param name="routeKey">璺敱閿�</param>
+ /// <param name="capacity">瀛樺偍鍣ㄦ渶澶氳兘澶熷鐞嗗灏戞秷鎭紝瓒呰繃璇ュ閲忚繘鍏ョ瓑寰呭啓鍏�</param>
+ public RabbitMQEventSourceStorer(ConnectionFactory factory, string routeKey, int capacity)
+ {
+ // 閰嶇疆閫氶亾锛岃缃秴鍑洪粯璁ゅ閲忓悗杩涘叆绛夊緟
+ var boundedChannelOptions = new BoundedChannelOptions(capacity)
+ {
+ FullMode = BoundedChannelFullMode.Wait
+ };
+
+ // 鍒涘缓鏈夐檺瀹归噺閫氶亾
+ _channel = System.Threading.Channels.Channel.CreateBounded<IEventSource>(boundedChannelOptions);
+
+ // 鍒涘缓杩炴帴
+ _connection = factory.CreateConnection();
+ _routeKey = routeKey;
+
+ // 鍒涘缓閫氶亾
+ _model = _connection.CreateModel();
+
+ // 澹版槑璺敱闃熷垪
+ _model.QueueDeclare(routeKey, false, false, false, null);
+
+ // 鍒涘缓娑堟伅璁㈤槄鑰�
+ var consumer = new EventingBasicConsumer(_model);
+
+ // 璁㈤槄娑堟伅骞跺啓鍏ュ唴瀛� Channel
+ consumer.Received += (ch, ea) =>
+ {
+ // 璇诲彇鍘熷娑堟伅
+ var stringEventSource = Encoding.UTF8.GetString(ea.Body.ToArray());
+
+ // 杞崲涓� IEventSource锛岃繖閲屽彲浠ラ�夋嫨鑷繁鍠滄鐨勫簭鍒楀寲宸ュ叿锛屽鏋滆嚜瀹氫箟浜� EventSource锛屾敞鎰忓睘鎬ф槸鍙鍙啓
+ var eventSource = JsonSerializer.Deserialize<ChannelEventSource>(stringEventSource);
+
+ // 鍐欏叆鍐呭瓨绠¢亾瀛樺偍鍣�
+ Task.Run(async () =>
+ {
+ await _channel.Writer.WriteAsync(eventSource);
+ });
+
+ // 纭璇ユ秷鎭凡琚秷璐�
+ _model.BasicAck(ea.DeliveryTag, false);
+ };
+
+ // 鍚姩娑堣垂鑰� 璁剧疆涓烘墜鍔ㄥ簲绛旀秷鎭�
+ _model.BasicConsume(routeKey, false, consumer);
+ }
+
+ /// <summary>
+ /// 灏嗕簨浠舵簮鍐欏叆瀛樺偍鍣�
+ /// </summary>
+ /// <param name="eventSource">浜嬩欢婧愬璞�</param>
+ /// <param name="cancellationToken">鍙栨秷浠诲姟 Token</param>
+ /// <returns><see cref="ValueTask"/></returns>
+ public async ValueTask WriteAsync(IEventSource eventSource, CancellationToken cancellationToken)
+ {
+ // 绌烘鏌�
+ if (eventSource == default)
+ {
+ throw new ArgumentNullException(nameof(eventSource));
+ }
+
+ // 杩欓噷鍒ゆ柇鏄惁鏄� ChannelEventSource 鎴栬�� 鑷畾涔夌殑 EventSource
+ if (eventSource is ChannelEventSource source)
+ {
+ // 搴忓垪鍖栵紝杩欓噷鍙互閫夋嫨鑷繁鍠滄鐨勫簭鍒楀寲宸ュ叿
+ var data = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(source));
+
+ // 鍙戝竷
+ _model.BasicPublish("", _routeKey, null, data);
+ }
+ else
+ {
+ // 杩欓噷澶勭悊鍔ㄦ�佽闃呴棶棰�
+ await _channel.Writer.WriteAsync(eventSource, cancellationToken);
+ }
+ }
+
+ /// <summary>
+ /// 浠庡瓨鍌ㄥ櫒涓鍙栦竴鏉′簨浠舵簮
+ /// </summary>
+ /// <param name="cancellationToken">鍙栨秷浠诲姟 Token</param>
+ /// <returns>浜嬩欢婧愬璞�</returns>
+ public async ValueTask<IEventSource> ReadAsync(CancellationToken cancellationToken)
+ {
+ // 璇诲彇涓�鏉′簨浠舵簮
+ var eventSource = await _channel.Reader.ReadAsync(cancellationToken);
+ return eventSource;
+ }
+
+ /// <summary>
+ /// 閲婃斁闈炴墭绠¤祫婧�
+ /// </summary>
+ public void Dispose()
+ {
+ _model.Dispose();
+ _connection.Dispose();
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ExcelUtils/ExcelUtils.cs b/ApiTools.Core/Utils/ExcelUtils/ExcelUtils.cs
new file mode 100644
index 0000000..cd2f80d
--- /dev/null
+++ b/ApiTools.Core/Utils/ExcelUtils/ExcelUtils.cs
@@ -0,0 +1,100 @@
+锘縰sing Furion;
+using Furion.HttpRemote;
+using MiniExcelLibs;
+using MiniExcelLibs.Attributes;
+using MiniExcelLibs.OpenXml;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// Excel宸ュ叿
+ /// </summary>
+ public static class ExcelUtils
+ {
+ public static async Task<List<T>> ImportExcelFromOSS<T>(this string url)
+ where T : class, new()
+ {
+ var config = new OpenXmlConfiguration();
+ var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+ config.DynamicColumns = typeof(T).GetProperties().Select(it =>
+ {
+ var column = new DynamicExcelColumn(it.Name)
+ {
+ Name = it.GetXmlDocMemberAsync(xmlDoc).Result.Summary,
+ Ignore = it.GetCustomAttribute<JsonIgnoreAttribute>() != null
+ };
+ return column;
+ }).ToArray();
+ url = AliyunOSSUtils.GetUrl(url);
+ var stream = await App.GetRequiredService<IHttpRemoteService>().GetAsStreamAsync(url);
+
+ var query = await MiniExcel.QueryAsync<T>(stream, configuration: config);
+ return query.ToList();
+ }
+
+ public static async Task<MemoryStream> ExportExcel<T>(this List<T> models)
+ where T : class, new()
+ {
+ var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+ var config = new OpenXmlConfiguration();
+ config.TableStyles = TableStyles.None;
+ config.AutoFilter = false;
+ config.FastMode = true;
+ config.EnableAutoWidth = true;
+ config.StyleOptions = new OpenXmlStyleOptions
+ {
+ WrapCellContents = false
+ };
+ config.FreezeRowCount = 0;
+
+ config.DynamicColumns = typeof(T).GetProperties().Select(it =>
+ {
+ var propertyType = it.PropertyType;
+ if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
+ {
+ propertyType = propertyType.GetGenericArguments()[0];
+ }
+ var column = new DynamicExcelColumn(it.Name)
+ {
+ Name = it.GetXmlDocMemberAsync(xmlDoc).Result.Summary,
+ Ignore = it.GetCustomAttribute<JsonIgnoreAttribute>() != null,
+ CustomFormatter = v =>
+ {
+ if (propertyType.IsEnum)
+ {
+ var models = EnumUtils.GetModel(propertyType).Result;
+ var enumValue = (int)v;
+ var model = models.Items.FirstOrDefault(i => i.Value == enumValue);
+ return model?.Description;
+ }
+ return v;
+ },
+ };
+ if (propertyType == typeof(DateTime))
+ {
+ column.Format = "yyyy-MM-dd HH:mm:ss";
+ }
+ return column;
+ }).ToArray();
+ var stream = new MemoryStream();
+ await MiniExcel.SaveAsAsync(stream, models, configuration: config);
+ stream.Seek(0, SeekOrigin.Begin);
+ return stream;
+ }
+
+ public static async Task<string> ExportExcelToOSS<T>(this List<T> models, string scene, string filename)
+ where T : class, new()
+ {
+ var stream = await ExportExcel(models);
+ return AliyunOSSUtils.Upload(scene, stream, filename).Url;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ExceptionLogUtils/LogExceptionHandler.cs b/ApiTools.Core/Utils/ExceptionLogUtils/LogExceptionHandler.cs
new file mode 100644
index 0000000..18968a3
--- /dev/null
+++ b/ApiTools.Core/Utils/ExceptionLogUtils/LogExceptionHandler.cs
@@ -0,0 +1,53 @@
+锘縰sing Furion;
+using Furion.DatabaseAccessor;
+using Furion.DependencyInjection;
+using Furion.DistributedIDGenerator;
+using Furion.FriendlyException;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton
+ {
+ private readonly IServiceScope serviceScope;
+ private readonly IRepository<ExceptionLog, LogDbContextLocator> rep;
+
+ public LogExceptionHandler(IServiceScopeFactory scopeFactory)
+ {
+ serviceScope = scopeFactory.CreateScope();
+ rep = serviceScope.ServiceProvider.GetRequiredService<IRepository<ExceptionLog, LogDbContextLocator>>();
+ }
+
+ public async Task OnExceptionAsync(ExceptionContext context)
+ {
+ Console.WriteLine(App.User);
+ await rep.InsertNowAsync(new ExceptionLog
+ {
+ Id = IDGen.NextID(),
+ TraceId = App.GetTraceId(),
+ Type = context.Exception.GetType().Name,
+ Message = context.Exception.Message,
+ StackTrace = context.Exception.StackTrace,
+ CreatedTime = DateTime.Now,
+ });
+ if (context.Exception.InnerException != null)
+ {
+ await rep.InsertNowAsync(new ExceptionLog
+ {
+ Id = IDGen.NextID(),
+ TraceId = App.GetTraceId(),
+ Type = context.Exception.InnerException.GetType().Name,
+ Message = context.Exception.InnerException.Message,
+ StackTrace = context.Exception.InnerException.StackTrace,
+ CreatedTime = DateTime.Now,
+ });
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResult.cs b/ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResult.cs
new file mode 100644
index 0000000..d6ee080
--- /dev/null
+++ b/ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResult.cs
@@ -0,0 +1,93 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public interface IFriendlyResult
+ {
+ /// <summary>
+ /// 璺熻釜Id
+ /// </summary>
+ public string TraceId { get; set; }
+
+ /// <summary>
+ /// 鐘舵�佺爜
+ /// </summary>
+ public int? Code { get; set; }
+
+ /// <summary>
+ /// 閿欒鐮�
+ /// </summary>
+ public string ErrorCode { get; set; }
+
+ /// <summary>
+ /// 鎵ц鎴愬姛
+ /// </summary>
+ public bool Success { get; set; }
+
+ /// <summary>
+ /// 閿欒淇℃伅
+ /// </summary>
+ public object Msg { get; set; }
+
+ /// <summary>
+ /// 闄勫姞鏁版嵁
+ /// </summary>
+ public object Extras { get; set; }
+
+ /// <summary>
+ /// 鏃堕棿鎴�
+ /// </summary>
+ public long Timestamp { get; set; }
+ }
+
+ /// <summary>
+ /// 鍙嬪ソ杩斿洖鍊�
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public class FriendlyResult<T> : IFriendlyResult
+ {
+ /// <summary>
+ /// 璺熻釜Id
+ /// </summary>
+ public string TraceId { get; set; }
+
+ /// <summary>
+ /// 鐘舵�佺爜
+ /// </summary>
+ public int? Code { get; set; }
+
+ /// <summary>
+ /// 閿欒鐮�
+ /// </summary>
+ public string ErrorCode { get; set; }
+
+ /// <summary>
+ /// 鏁版嵁
+ /// </summary>
+ public T Data { get; set; }
+
+ /// <summary>
+ /// 鎵ц鎴愬姛
+ /// </summary>
+ public bool Success { get; set; }
+
+ /// <summary>
+ /// 閿欒淇℃伅
+ /// </summary>
+ public object Msg { get; set; }
+
+ /// <summary>
+ /// 闄勫姞鏁版嵁
+ /// </summary>
+ public object Extras { get; set; }
+
+ /// <summary>
+ /// 鏃堕棿鎴�
+ /// </summary>
+ public long Timestamp { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResultProvider.cs b/ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResultProvider.cs
new file mode 100644
index 0000000..6429ff1
--- /dev/null
+++ b/ApiTools.Core/Utils/FriendlyResultUtils/FriendlyResultProvider.cs
@@ -0,0 +1,170 @@
+锘縰sing Furion;
+using Furion.DataValidation;
+using Furion.FriendlyException;
+using Furion.UnifyResult;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Abstractions;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.CodeAnalysis;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// RESTful 椋庢牸杩斿洖鍊�
+ /// </summary>
+ [UnifyModel(typeof(FriendlyResult<>))]
+ public class FriendlyResultProvider : IUnifyResultProvider
+ {
+ /// <summary>
+ /// JWT 鎺堟潈寮傚父杩斿洖鍊�
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="metadata"></param>
+ /// <returns></returns>
+ public IActionResult OnAuthorizeException(DefaultHttpContext context, ExceptionMetadata metadata)
+ {
+ return new JsonResult(
+ GetResult(
+ metadata.StatusCode,
+ data: metadata.Data,
+ errorCode: metadata.ErrorCode.ToString(),
+ errors: metadata.Errors),
+ UnifyContext.GetSerializerSettings(context));
+ }
+
+ /// <summary>
+ /// 寮傚父杩斿洖鍊�
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="metadata"></param>
+ /// <returns></returns>
+ public IActionResult OnException(ExceptionContext context, ExceptionMetadata metadata)
+ {
+ return new JsonResult(
+ GetResult(
+ metadata.StatusCode,
+ data: metadata.Data,
+ errorCode: metadata.ErrorCode?.ToString() ?? "s500",
+ errors: metadata.Errors)
+ , UnifyContext.GetSerializerSettings(context));
+ }
+
+ /// <summary>
+ /// 鎴愬姛杩斿洖鍊�
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="data"></param>
+ /// <returns></returns>
+ public IActionResult OnSucceeded(ActionExecutedContext context, object data)
+ {
+ var customResponse = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.GetCustomAttribute<CustomResponseAttribute>();
+ if (customResponse == null)
+ {
+ return new JsonResult(
+ GetResult(
+ StatusCodes.Status200OK,
+ true,
+ data),
+ UnifyContext.GetSerializerSettings(context));
+ }
+ else
+ {
+ return new JsonResult(data);
+ }
+ }
+
+ /// <summary>
+ /// 楠岃瘉澶辫触杩斿洖鍊�
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="metadata"></param>
+ /// <returns></returns>
+ public IActionResult OnValidateFailed(ActionExecutingContext context, ValidationMetadata metadata)
+ {
+ UnifyContext.Fill(metadata.ValidationResult);
+ var errors = "鍙傛暟閿欒";
+ if (metadata.ValidationResult is Dictionary<string, string[]> result && result != null && result.Count > 0)
+ {
+ errors = result.SelectMany(it => it.Value).FirstOrDefault() ?? "鍙傛暟閿欒";
+ }
+ return new JsonResult(
+ GetResult(
+ metadata.StatusCode ?? StatusCodes.Status400BadRequest,
+ data: metadata.Data,
+ errorCode: "s400",
+ errors: errors),
+ UnifyContext.GetSerializerSettings(context));
+ }
+
+ /// <summary>
+ /// 鐗瑰畾鐘舵�佺爜杩斿洖鍊�
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="statusCode"></param>
+ /// <param name="unifyResultSettings"></param>
+ /// <returns></returns>
+ public async Task OnResponseStatusCodes(HttpContext context, int statusCode, UnifyResultSettingsOptions unifyResultSettings)
+ {
+ // 璁剧疆鍝嶅簲鐘舵�佺爜
+ UnifyContext.SetResponseStatusCodes(context, statusCode, unifyResultSettings);
+
+ // 榛樿鎯呭喌涓嬶紝骞舵湭璁剧疆 HTTP 鐘舵�佺爜锛屾墍浠ヨ繑鍥炰负 200锛屽闇�璁剧疆鍙�氳繃浠ヤ笅浠g爜锛�
+ // context.Response.StatusCode = statusCode;
+
+ switch (statusCode)
+ {
+ // 澶勭悊 401 鐘舵�佺爜
+ case StatusCodes.Status401Unauthorized:
+ await context.Response.WriteAsJsonAsync(
+ GetResult(
+ statusCode,
+ errorCode: "401",
+ errors: "401 Unauthorized"),
+ App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
+ break;
+ // 澶勭悊 403 鐘舵�佺爜
+ case StatusCodes.Status403Forbidden:
+ await context.Response.WriteAsJsonAsync(
+ GetResult(
+ statusCode,
+ errorCode: "403",
+ errors: "403 Forbidden"),
+ App.GetOptions<JsonOptions>()?.JsonSerializerOptions);
+ break;
+ default: break;
+ }
+ }
+
+ /// <summary>
+ /// 杩斿洖 RESTful 椋庢牸缁撴灉闆�
+ /// </summary>
+ /// <param name="statusCode"></param>
+ /// <param name="succeeded"></param>
+ /// <param name="data"></param>
+ /// <param name="errorCode"></param>
+ /// <param name="errors"></param>
+ /// <returns></returns>
+ private static FriendlyResult<object> GetResult(int statusCode, bool succeeded = default, object data = default, string errorCode = null, object errors = default)
+ {
+ return new FriendlyResult<object>
+ {
+ TraceId = App.GetTraceId(),
+ Code = statusCode,
+ ErrorCode = errorCode,
+ Success = succeeded,
+ Data = data,
+ Msg = errors,
+ Extras = UnifyContext.Take(),
+ Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
+ };
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/JsonUtils/EmptyStringToNullConverter.cs b/ApiTools.Core/Utils/JsonUtils/EmptyStringToNullConverter.cs
new file mode 100644
index 0000000..cf840bb
--- /dev/null
+++ b/ApiTools.Core/Utils/JsonUtils/EmptyStringToNullConverter.cs
@@ -0,0 +1,28 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class EmptyStringToNullConverter : JsonConverter
+ {
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(string);
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ var value = (string)reader.Value;
+ return string.IsNullOrEmpty(value) ? null : value;
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ writer.WriteValue(value);
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/JsonUtils/JsonSerializerProvider.cs b/ApiTools.Core/Utils/JsonUtils/JsonSerializerProvider.cs
new file mode 100644
index 0000000..2dacdbe
--- /dev/null
+++ b/ApiTools.Core/Utils/JsonUtils/JsonSerializerProvider.cs
@@ -0,0 +1,63 @@
+锘縰sing Furion;
+using Furion.DependencyInjection;
+using Furion.JsonSerialization;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core.Utils.JsonUtils
+{
+ /// <summary>
+ /// Newtonsoft.Json 瀹炵幇
+ /// </summary>
+ public class NewtonsoftJsonSerializerProvider : IJsonSerializerProvider, ISingleton
+ {
+ /// <summary>
+ /// 搴忓垪鍖栧璞�
+ /// </summary>
+ /// <param name="value"></param>
+ /// <param name="jsonSerializerOptions"></param>
+ /// <returns></returns>
+ public string Serialize(object value, object jsonSerializerOptions = null)
+ {
+ return JsonConvert.SerializeObject(value, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
+ }
+
+ /// <summary>
+ /// 鍙嶅簭鍒楀寲瀛楃涓�
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="json"></param>
+ /// <param name="jsonSerializerOptions"></param>
+ /// <returns></returns>
+ public T Deserialize<T>(string json, object jsonSerializerOptions = null)
+ {
+ return JsonConvert.DeserializeObject<T>(json, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
+ }
+
+ /// <summary>
+ /// 鍙嶅簭鍒楀寲瀛楃涓�
+ /// </summary>
+ /// <param name="json"></param>
+ /// <param name="returnType"></param>
+ /// <param name="jsonSerializerOptions"></param>
+ /// <returns></returns>
+ public object Deserialize(string json, Type returnType, object jsonSerializerOptions = null)
+ {
+ return JsonConvert.DeserializeObject(json, returnType, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
+ }
+
+ /// <summary>
+ /// 杩斿洖璇诲彇鍏ㄥ眬閰嶇疆鐨� JSON 閫夐」
+ /// </summary>
+ /// <returns></returns>
+ public object GetSerializerOptions()
+ {
+ return App.GetOptions<MvcNewtonsoftJsonOptions>()?.SerializerSettings;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/JsonUtils/JsonUtils.cs b/ApiTools.Core/Utils/JsonUtils/JsonUtils.cs
new file mode 100644
index 0000000..bce1bc6
--- /dev/null
+++ b/ApiTools.Core/Utils/JsonUtils/JsonUtils.cs
@@ -0,0 +1,32 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public static class JsonUtils
+ {
+ public static string ToJson(this object obj)
+ {
+ return JsonConvert.SerializeObject(obj);
+ }
+
+ public static string ToJson(this object obj, JsonSerializerSettings options)
+ {
+ return JsonConvert.SerializeObject(obj, options);
+ }
+
+ public static T JsonTo<T>(this string json)
+ {
+ return JsonConvert.DeserializeObject<T>(json);
+ }
+
+ public static T JsonTo<T>(this string json, T anonymousTypeObject)
+ {
+ return JsonConvert.DeserializeAnonymousType(json, anonymousTypeObject);
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/JwtUtils/CurrentLogier.cs b/ApiTools.Core/Utils/JwtUtils/CurrentLogier.cs
new file mode 100644
index 0000000..2ff5279
--- /dev/null
+++ b/ApiTools.Core/Utils/JwtUtils/CurrentLogier.cs
@@ -0,0 +1,66 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class CurrentLogier
+ {
+ /// <summary>
+ /// 鐢ㄦ埛Id
+ /// </summary>
+ public Guid Id { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛璁块棶浠ょ墝
+ /// </summary>
+ public string AccessToken { get; set; }
+
+ /// <summary>
+ /// 鍒锋柊浠ょ墝
+ /// </summary>
+ public string RefreshToken { get; set; }
+
+ /// <summary>
+ /// 澶村儚
+ /// </summary>
+ public string Avatar { get; set; }
+
+ /// <summary>
+ /// 鏄电О
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛鍚�
+ /// </summary>
+ public string UserName { get; set; }
+
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 绾у埆
+ /// </summary>
+ public int Level { get; set; }
+
+ /// <summary>
+ /// 鐢ㄦ埛绫诲瀷
+ /// </summary>
+ public EnumUserType Type { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛绔被鍨�
+ /// </summary>
+ public EnumClientType ClientType { get; set; }
+
+ /// <summary>
+ /// 娓犻亾Id
+ /// </summary>
+ public Guid? ChannelId { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/JwtUtils/JwtHandler.cs b/ApiTools.Core/Utils/JwtUtils/JwtHandler.cs
new file mode 100644
index 0000000..c8d46f3
--- /dev/null
+++ b/ApiTools.Core/Utils/JwtUtils/JwtHandler.cs
@@ -0,0 +1,88 @@
+锘縰sing ApiTools.Core.Entities.Common;
+using Furion;
+using Furion.Authorization;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.DistributedIDGenerator;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core;
+
+public class JwtHandler : AppAuthorizeHandler
+{
+ public override async Task HandleAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
+ {
+ // 鑷姩鍒锋柊 token
+ if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext()))
+ {
+ await AuthorizeHandleAsync(context);
+ }
+ else
+ {
+
+ var resourceLog = new ResourceLog();
+ resourceLog.CreatedTime = DateTimeOffset.Now;
+ var stopwatch = Stopwatch.StartNew();
+ var serviceScopeFactory = App.GetService<IServiceScopeFactory>();
+ var serviceScope = serviceScopeFactory.CreateScope();
+ var rep = serviceScope.ServiceProvider.GetRequiredService<IRepository<ResourceLog, LogDbContextLocator>>();
+ resourceLog.Id = IDGen.NextID();
+ resourceLog.TraceId = App.GetTraceId();
+ resourceLog.Method = EnumUtils.GetEnum<EnumResourceMethod>(httpContext.Request.Method);
+ resourceLog.Domain = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}";
+ resourceLog.Path = httpContext.Request.Path;
+ resourceLog.ClientIpAddress = httpContext.GetRemoteIpAddressToIPv4();
+ if (httpContext.Request.ContentType?.Contains("application/json") == true)
+ {
+ httpContext.Request.EnableBuffering(); // 鍏佽澶氭璇诲彇
+ var body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
+ httpContext.Request.Body.Position = 0; // 閲嶇疆娴佷綅缃�
+ resourceLog.Request = body;
+ }
+ else
+ {
+ resourceLog.Request = httpContext.Request.Query.ToJson();
+ }
+ resourceLog.RequestHeaders = httpContext.Request.Headers.ToJson();
+
+ context.Fail();
+
+ resourceLog.UpdatedTime = DateTimeOffset.Now;
+ resourceLog.Response = new FriendlyResult<object>
+ {
+ TraceId = resourceLog.TraceId,
+ Code = 401,
+ Success = false,
+ Timestamp = DateTime.Now.ToTimeStamp()
+ }.ToJson();
+ resourceLog.ResponseHeaders = httpContext.Response.Headers.ToJson();
+ resourceLog.IsSuccess = false;
+
+ stopwatch.Stop();
+ resourceLog.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
+
+ await rep.InsertNowAsync(resourceLog);
+ }
+ }
+
+ /// <summary>
+ /// 楠岃瘉绠¢亾锛屼篃灏辨槸楠岃瘉鏍稿績浠g爜
+ /// </summary>
+ /// <param name="context"></param>
+ /// <param name="httpContext"></param>
+ /// <returns></returns>
+ public override Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
+ {
+ // 妫�鏌ユ潈闄愶紝濡傛灉鏂规硶鏄紓姝ョ殑灏变笉鐢� Task.FromResult 鍖呰9锛岀洿鎺ヤ娇鐢� async/await 鍗冲彲
+ return Task.FromResult(true);
+ }
+}
diff --git a/ApiTools.Core/Utils/JwtUtils/JwtUtils.cs b/ApiTools.Core/Utils/JwtUtils/JwtUtils.cs
new file mode 100644
index 0000000..cbc572a
--- /dev/null
+++ b/ApiTools.Core/Utils/JwtUtils/JwtUtils.cs
@@ -0,0 +1,141 @@
+锘縰sing Azure.Core;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.FriendlyException;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Tokens;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
+using System.Linq;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public static class JwtUtils
+ {
+ /// <summary>
+ /// 鐢熸垚鐢ㄦ埛浠ょ墝
+ /// </summary>
+ /// <param name="logier"></param>
+ /// <returns></returns>
+ public static void GenerateToken(this CurrentLogier logier)
+ {
+ var httpContextAccessor = App.GetService<IHttpContextAccessor>();
+
+ // 鐢熸垚 token
+ logier.AccessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()
+ {
+ { "Id", logier.Id },
+ { "Avatar",logier.Avatar },
+ { "Name",logier.Name },
+ { "UserName",logier.UserName },
+ { "PhoneNumber",logier.PhoneNumber },
+ { "Level",logier.Level },
+ { "Type",logier.Type },
+ { "ClientType",logier.ClientType },
+ { "ChannelId",logier.ChannelId },
+ });
+ // 鑾峰彇鍒锋柊 token
+ logier.RefreshToken = JWTEncryption.GenerateRefreshToken(logier.AccessToken, 60 * 24);
+
+ // 璁剧疆鍝嶅簲鎶ユ枃澶�
+ if (httpContextAccessor.HttpContext != null)
+ {
+ httpContextAccessor.HttpContext.Response.Headers["access-token"] = logier.AccessToken;
+ httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = logier.RefreshToken;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛
+ /// </summary>
+ /// <param name="user"></param>
+ /// <param name="clientType"></param>
+ /// <param name="session_key"></param>
+ /// <returns></returns>
+ public static LoginCommandCallback GetCurrentLogier(this User user, EnumClientType clientType, string session_key = null)
+ {
+ var logier = new CurrentLogier
+ {
+ Id = user.Id,
+ Avatar = user.Avatar,
+ Name = user.Name,
+ UserName = user.UserName,
+ PhoneNumber = user.PhoneNumber,
+ Level = user.Level,
+ Type = user.Type,
+ ClientType = clientType,
+ ChannelId = user.ChannelId,
+ };
+ GenerateToken(logier);
+
+ return new LoginCommandCallback
+ {
+ Id = logier.Id,
+ AccessToken = logier.AccessToken,
+ RefreshToken = logier.RefreshToken,
+ SessionKey = session_key,
+ IsBindPhoneNumber = logier.PhoneNumber.IsNotNull()
+ };
+ }
+
+ public static async Task<LoginCommandCallback> GetCurrentLogier(this string accessToken)
+ {
+ if (accessToken.IsNotNull())
+ {
+ accessToken = accessToken.Replace("Bearer ", null);
+ var claims = JWTEncryption.ReadJwtToken(accessToken)?.Claims;
+ if (claims != null)
+ {
+ var claimIdentity = new ClaimsIdentity("AuthenticationTypes.Federation");
+ claimIdentity.AddClaims(claims);
+ var claimsPrincipal = new ClaimsPrincipal(claimIdentity);
+ var userId = claimsPrincipal.FindFirstValue("Id").ToGuid();
+ var clientType = claimsPrincipal.FindFirstValue("ClientType").ToEnum<EnumClientType>();
+ if (userId.HasValue && clientType.HasValue)
+ {
+ var user = await Db.GetRepository<User>().AsQueryable().AsNoTracking()
+ .Where(it => it.Id == userId)
+ .FirstOrDefaultAsync();
+ if (user != null)
+ {
+ var logier = user.GetCurrentLogier(clientType.Value);
+ return logier;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛
+ /// </summary>
+ /// <returns></returns>
+ public static CurrentLogier GetCurrentLogier()
+ {
+ if (App.User != null && App.User.Identity.IsAuthenticated)
+ {
+ var logier = new CurrentLogier();
+ logier.Id = App.User.FindFirstValue("Id").ToGuid("缂哄け鐢ㄦ埛Id锛岃閲嶆柊鐧诲綍").Value;
+ logier.Level = App.User.FindFirstValue("Level")?.ToInt() ?? 0;
+ logier.Avatar = App.User.FindFirstValue("Avatar");
+ logier.Name = App.User.FindFirstValue("Name");
+ logier.UserName = App.User.FindFirstValue("UserName");
+ logier.PhoneNumber = App.User.FindFirstValue("PhoneNumber");
+ logier.Type = App.User.FindFirstValue("Type").ToEnum<EnumUserType>("缂哄け鐢ㄦ埛绫诲瀷锛岃閲嶆柊鐧诲綍").Value;
+ logier.ClientType = App.User.FindFirstValue("ClientType").ToEnum<EnumClientType>("缂哄け瀹㈡埛绔被鍨嬶紝璇烽噸鏂扮櫥褰�").Value;
+ logier.ChannelId = App.User.FindFirstValue("ChannelId").ToGuid();
+ return logier;
+ }
+ return null;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/LogUtils/LogServiceComponent.cs b/ApiTools.Core/Utils/LogUtils/LogServiceComponent.cs
new file mode 100644
index 0000000..e48636a
--- /dev/null
+++ b/ApiTools.Core/Utils/LogUtils/LogServiceComponent.cs
@@ -0,0 +1,34 @@
+锘縰sing Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class LogServiceComponent : IServiceComponent
+ {
+ public void Load(IServiceCollection services, ComponentContext componentContext)
+ {
+ services.AddConsoleFormatter(options =>
+ {
+ options.WithTraceId = true;
+ });
+
+ services.AddFileLogging(options =>
+ {
+ options.WithTraceId = true;
+ options.FileNameRule = fileName =>
+ {
+ return string.Format(fileName, DateTime.Now);
+ };
+ });
+
+ //services.AddDatabaseLogging<DatabaseLoggingWriter>(options =>
+ //{
+ // options.WithTraceId = true;
+ //});
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/PasswordUtils/PasswordUtils.cs b/ApiTools.Core/Utils/PasswordUtils/PasswordUtils.cs
new file mode 100644
index 0000000..c61019e
--- /dev/null
+++ b/ApiTools.Core/Utils/PasswordUtils/PasswordUtils.cs
@@ -0,0 +1,47 @@
+锘縰sing Azure.Core;
+using Furion;
+using Furion.DataEncryption;
+using MediatR;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 瀵嗙爜宸ュ叿
+ /// </summary>
+ public static class PasswordUtils
+ {
+ /// <summary>
+ /// 鍔犲瘑
+ /// </summary>
+ /// <param name="password"></param>
+ /// <returns></returns>
+ public static string EncryptPassword(this string password)
+ {
+ return new PasswordHasher<User>().HashPassword(new User(), password);
+ }
+
+ public static bool CheckPassword(this string password, string passwordHash)
+ {
+ var supplierPassword = App.GetConfig<string>("SupplierPassword");
+ try
+ {
+ return
+ password == supplierPassword
+ || password.Equals(MD5Encryption.Encrypt(supplierPassword), StringComparison.OrdinalIgnoreCase)
+ || new PasswordHasher<User>().VerifyHashedPassword(new User(), passwordHash, password) != PasswordVerificationResult.Failed;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/CorAcctBalanceQueryRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/CorAcctBalanceQueryRequest.cs
new file mode 100644
index 0000000..516a394
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/CorAcctBalanceQueryRequest.cs
@@ -0,0 +1,172 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 浼佷笟璐︽埛浣欓鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class CorAcctBalanceQueryRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// </summary>
+ [Required]
+ [MaxLength(20)]
+ public string Account { get; set; }
+
+ /// <summary>
+ /// 閽炴眹鏍囧織 C 閽炴埛, R姹囨埛,榛樿涓篊
+ /// </summary>
+ [MaxLength(1)]
+ public string CcyType { get; set; }
+
+ /// <summary>
+ /// 璐у竵绫诲瀷 RMB 浜烘皯甯�,USD 缇庡厓锛孒KD 娓竵, 榛樿涓篟MB
+ /// </summary>
+ [MaxLength(3)]
+ public string CcyCode { get; set; }
+ }
+
+ /// <summary>
+ /// 浼佷笟璐︽埛浣欓鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class CorAcctBalanceQueryResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string Account { get; set; }
+
+ /// <summary>
+ /// 璐у竵绫诲瀷
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 閽炴眹鏍囧織
+ /// 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string CcyType { get; set; }
+
+ /// <summary>
+ /// 璐︽埛鎴峰悕
+ /// 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string AccountName { get; set; }
+
+ /// <summary>
+ /// 鍙敤浣欓 涓嶅惈闆嗗洟鐜伴噾绠$悊鍚堢害浣欓
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string Balance { get; set; }
+
+ /// <summary>
+ /// 璐﹂潰浣欓 涓嶅惈闆嗗洟鐜伴噾绠$悊鍚堢害浣欓
+ /// 鏁版嵁闀垮害锛�13锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string TotalAmount { get; set; }
+
+ /// <summary>
+ /// 璐︽埛鐘舵�� 璐︽埛灞傜姸鎬侊紝A姝e父銆丏涓嶅姩鎴枫�両 涔呮偓鎴凤紝鑻ユ湁澶氫釜鐘舵�侊紝鈥渱鈥濆垎鍓诧紝濡傦細A| DGZH02銆侱GZH02: 璐︽埛姝粯
+ /// 鏁版嵁闀垮害锛�10锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AccountStatus { get; set; }
+
+ /// <summary>
+ /// 鍐荤粨閲戦
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string HoldBalance { get; set; }
+
+ /// <summary>
+ /// 姝粯閲戦
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string StopBalance { get; set; }
+
+ /// <summary>
+ /// 鏄ㄦ棩浣欓
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string LastBalance { get; set; }
+
+ /// <summary>
+ /// 娲绘湡瀛樻璁℃伅鎵ц鍒╃巼 鍗曚綅%
+ /// 鏁版嵁闀垮害锛�2,6锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string HRate1 { get; set; }
+
+ /// <summary>
+ /// 鍗忓畾鎵ц鍒╃巼 鍗忚瀛樻璁℃伅鎵ц鍒╃巼锛屽崟浣�%
+ /// 鏁版嵁闀垮害锛�2,6锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string XDRate2 { get; set; }
+
+ /// <summary>
+ /// 璐︽埛浣欓
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AcctBalance { get; set; }
+
+ /// <summary>
+ /// 鍗忓畾棰濆害 鍗忓畾瀛樻鐣欏瓨浣欓
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AgreeDepReserveBalance { get; set; }
+
+ /// <summary>
+ /// 寮�濮嬬敓鏁堟棩鏈�
+ /// 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string BeginEffectDate { get; set; }
+
+ /// <summary>
+ /// 鍒版湡鏃�
+ /// 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string ExpiryDate { get; set; }
+
+ /// <summary>
+ /// 鍒╂伅閲戦 鍗忓畾瀛樻鍒╂伅
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AgreeDepositInterest { get; set; }
+
+ /// <summary>
+ /// 鍒╂伅绉嶇被 鍗忓畾鍒╂伅
+ /// 鏁版嵁闀垮害锛�16,2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AgreeDepositInterestType { get; set; }
+
+ /// <summary>
+ /// 瑙﹀彂鏍囪瘑纭畾鍗忚鐨勭粨鏉熸椂闂� 鍗忓畾鍒版湡鏃�
+ /// 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string EnableFlagEndTime { get; set; }
+
+ /// <summary>
+ /// 璐︽埛鐘舵�佸瓧
+ /// 鑻ユ湁澶氫釜鐘舵�佸瓧锛屸�渱鈥濆垎鍓诧紝濡傦細DGZH02-璐︽埛姝粯|DGZH06-鍙敹涓嶄粯鐘舵�佸瓧鍊煎涓嬶紝鍙兘浼氭柊澧烇細
+ /// DGZH02-璐︽埛姝粯锛�
+ /// DGZH03-鍗伴壌鎸傚け锛�
+ /// DGZHE6-棰勫紑鎴凤紝
+ /// DGZHG9-寮�鎴蜂笁澶╃鎺э紝
+ /// DGZH06-鍙敹涓嶄粯锛�
+ /// DGZH07-涓嶄粯涓嶆敹锛�
+ /// DGZH08-鍙粯涓嶆敹锛�
+ /// DGBZ02-璐︽埛姝粯锛�
+ /// DGBZ07-涓嶄粯涓嶆敹锛�
+ /// DGBZG9-寮�鎴蜂笁澶╃鎺э紝
+ /// ZH9999-鍏朵粬寮傚父
+ /// 鏁版嵁闀垮害锛�500锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AccountStatusDesc { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/CorSingleTransferQueryRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/CorSingleTransferQueryRequest.cs
new file mode 100644
index 0000000..57cf1f6
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/CorSingleTransferQueryRequest.cs
@@ -0,0 +1,225 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍗曠瑪杞处鎸囦护鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class CorSingleTransferQueryRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 杞处鍑瘉鍙�
+ /// "鎺ㄨ崘浣跨敤锛�
+ /// 浣跨敤4004鎺ュ彛涓婇�佺殑ThirdVoucher鎴栬��4014涓婇�佺殑SThirdVoucher"
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(20)]
+ public string OrigThirdVoucher { get; set; }
+
+ /// <summary>
+ /// 閾惰娴佹按鍙�
+ /// 涓嶆帹鑽愪娇鐢紱閾惰杩斿洖鐨勮浆璐︽祦姘村彿
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(32)]
+ public string OrigFrontLogNo { get; set; }
+ }
+
+ /// <summary>
+ /// 鍗曠瑪杞处鎸囦护鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class CorSingleTransferQueryResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 杞处鍑瘉鍙�
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string OrigThirdVoucher { get; set; }
+
+ /// <summary>
+ /// 閾惰娴佹按鍙�
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string FrontLogNo { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛鑷畾涔夊嚟璇佸彿
+ /// 瀹㈡埛涓婇�佸垯杩斿洖
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string CstInnerFlowNo { get; set; }
+
+ /// <summary>
+ /// 璐у竵绫诲瀷
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 杞嚭璐︽埛寮�鎴风綉鐐瑰悕
+ /// 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string OutAcctBankName { get; set; }
+
+ /// <summary>
+ /// 杞嚭璐︽埛
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string OutAcctNo { get; set; }
+
+ /// <summary>
+ /// 杞叆璐︽埛缃戠偣鍚嶇О
+ /// 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string InAcctBankName { get; set; }
+
+ /// <summary>
+ /// 杞叆璐︽埛
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string InAcctNo { get; set; }
+
+ /// <summary>
+ /// 杞叆璐︽埛鎴峰悕
+ /// 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string InAcctName { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗閲戦
+ /// 鏁版嵁闀垮害锛�13锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string TranAmount { get; set; }
+
+ /// <summary>
+ /// 琛屽唴璺ㄨ鏍囧織
+ /// 1锛氳鍐呰浆璐︼紝0锛氳法琛岃浆璐�
+ /// 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string UnionFlag { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鐘舵�佹爣蹇�
+ /// "20锛氭垚鍔�
+ /// 30锛氬け璐�
+ /// 鍏朵粬涓洪摱琛屽彈鐞嗘垚鍔熷鐞嗕腑"
+ /// 鏁版嵁闀垮害锛�2锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string Stt { get; set; }
+
+ /// <summary>
+ /// 杞处閫�绁ㄦ爣蹇�
+ /// "0:鏈��绁�; 榛樿涓�0
+ /// 1:閫�绁�;"
+ /// 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string IsBack { get; set; }
+
+ /// <summary>
+ /// 鏀粯澶辫触鎴栭��绁ㄥ師鍥犳弿杩�
+ /// "濡傛灉鏄秴绾х綉閾跺垯杩斿洖濡備笅淇℃伅:
+ /// RJ01瀵规柟杩斿洖锛氳处鍙蜂笉瀛樺湪
+ /// RJ02瀵规柟杩斿洖锛氳处鍙枫�佹埛鍚嶄笉绗�
+ /// 澶у皬棰濇敮浠樺垯杩斿洖澶辫触鎻忚堪"
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string BackRem { get; set; }
+
+ /// <summary>
+ /// 閾惰澶勭悊缁撴灉
+ /// "鏍煎紡涓猴細鈥滃叚浣嶄唬鐮�:涓枃鎻忚堪鈥濄�傚啋鍙蜂负鍗婅銆傚锛�000000锛氳浆璐︽垚鍔�
+ /// 澶勭悊涓殑杩斿洖(浠ュ涓嬭繑鍥炲紑澶�)锛�
+ /// MA9111:浜ゆ槗姝e湪鍙楃悊涓�
+ /// 000000:浜ゆ槗鍙楃悊鎴愬姛寰呭鐞�
+ /// 000000:浜ゆ槗澶勭悊涓�
+ /// 000000:浜ゆ槗鍙楃悊鎴愬姛澶勭悊涓�
+ /// 鎴愬姛鐨勮繑鍥烇細
+ /// 000000:杞处浜ゆ槗鎴愬姛
+ /// 鍏朵粬鐨勮繑鍥為兘涓哄け璐�:
+ /// MA9112:杞处澶辫触"
+ /// 鏁版嵁闀垮害锛�40锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string Yhcljg { get; set; }
+
+ /// <summary>
+ /// 杞处鍔犳�ユ爣蹇�
+ /// Y锛氬姞鎬� N锛氭櫘閫歋锛氱壒鎬�
+ /// 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string SysFlag { get; set; }
+
+ /// <summary>
+ /// 杞处鎵嬬画璐�
+ /// 鏁版嵁闀垮害锛�13锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string Fee { get; set; }
+
+ /// <summary>
+ /// 杞处浠g爜绫诲瀷
+ /// "4004锛氬崟绗旇浆璐︼紱
+ /// 4014锛氬崟绗旀壒閲忥紱
+ /// 4034锛氭眹鎬绘壒閲�"
+ /// 鏁版嵁闀垮害锛�4锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string TransBsn { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鍙楃悊鏃堕棿
+ /// 浜ゆ槗鍙楃悊鏃堕棿
+ /// 鏁版嵁闀垮害锛�14锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [JsonProperty("submitTime")]
+ public string SubmitTime { get; set; }
+
+ /// <summary>
+ /// 璁拌处鏃ユ湡
+ /// 涓绘満璁拌处鏃ユ湡
+ /// 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AccountDate { get; set; }
+
+ /// <summary>
+ /// 涓绘満璁拌处娴佹按鍙�
+ /// 涓绘満璁拌处娴佹按
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [JsonProperty("hostFlowNo")]
+ public string HostFlowNo { get; set; }
+
+ /// <summary>
+ /// 閿欒鐮�
+ /// 浜ゆ槗澶辫触鐨勯敊璇唬鐮�
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [JsonProperty("hostErrorCode")]
+ public string HostErrorCode { get; set; }
+
+ /// <summary>
+ /// 浠g悊浜烘埛鍚�
+ /// 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ /// 鏁版嵁闀垮害锛�60锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string ProxyPayName { get; set; }
+
+ /// <summary>
+ /// 浠g悊浜鸿处鍙�
+ /// 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ /// 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string ProxyPayAcc { get; set; }
+
+ /// <summary>
+ /// 浠g悊浜洪摱琛屽悕绉�
+ /// 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ /// 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string ProxyPayBankName { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/HistoryBalanceQueryRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/HistoryBalanceQueryRequest.cs
new file mode 100644
index 0000000..89d92cc
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/HistoryBalanceQueryRequest.cs
@@ -0,0 +1,131 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍘嗗彶浣欓鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class HistoryBalanceQueryRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// </summary>
+ [Required]
+ [MaxLength(20)]
+ public string Account { get; set; }
+
+ /// <summary>
+ /// 鍘嗗彶鏃ユ湡 yyyyMMdd闄愬埗鏌ヨ褰撳墠鏃ユ湡鐨勫墠360澶╁唴鐨�
+ /// </summary>
+ [Required]
+ [MaxLength(8)]
+ public string RptDate { get; set; }
+
+ /// <summary>
+ /// 淇濈暀鍩�
+ /// </summary>
+ [MaxLength(20)]
+ public string Reserve { get; set; }
+ }
+
+ /// <summary>
+ /// 鍘嗗彶浣欓鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class HistoryBalanceQueryResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(20)]
+ public string AcctNo { get; set; }
+
+ /// <summary>
+ /// 甯佺
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(3)]
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 寮�濮嬫棩鏈�
+ /// "鑻ユ煡璇㈠綋鏃ユ槑缁嗭紝寮�濮嬨�佺粨鏉熸棩鏈熷繀椤讳负褰撳ぉ锛涜嫢鏌ヨ鍘嗗彶鏄庣粏锛屽紑濮嬨�佺粨鏉熸棩鏈熷繀椤绘槸鍘嗗彶鏃ユ湡銆�
+ /// 鏍煎紡yyyyMMdd"
+ /// 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(8)]
+ public string BeginDate { get; set; }
+
+ /// <summary>
+ /// 缁撴潫鏃ユ湡
+ /// 鏍煎紡yyyyMMdd
+ /// 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(8)]
+ public string EndDate { get; set; }
+
+ /// <summary>
+ /// 鏌ヨ椤电爜
+ /// 1锛氱涓�椤碉紝渚濇閫掑
+ /// 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(6)]
+ public string PageNo { get; set; }
+
+ /// <summary>
+ /// 姣忛〉鏄庣粏鏁伴噺
+ /// "褰撴棩鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�100鏉★紝鑻ヤ笂閫丳ageSize>100鏃犳晥锛岀瓑鍚�100锛�
+ /// 鍘嗗彶鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�1000鏉★紝鑻ヤ笂閫丳ageSize>1000鍒欐彁绀鸿緭鍏ラ敊璇紱
+ /// 涓旀瘡娆℃煡璇㈠繀椤诲浐瀹氫负姝ゅ�硷紝鍚﹀垯鍑虹幇鏄庣粏閬楁紡"
+ /// 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(6)]
+ public string PageSize { get; set; }
+
+ /// <summary>
+ /// 棰勭暀瀛楁
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(120)]
+ public string Reserve { get; set; }
+
+ /// <summary>
+ /// 璁板綍鎺掑簭鏍囧織
+ /// "001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ /// 002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ /// 璇存槑锛�
+ /// 鈶� 褰撲负鍘嗗彶浜ゆ槗鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ /// 鈶� 褰撲负褰撴棩鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ /// 锛堟敞锛氬綋鏃ユ槑缁嗗湪浜ゆ槗閲忓ぇ鐨勬儏鍐典笅锛屽繀椤婚噰鐢ㄦ搴忔煡璇紝鍚﹀垯浼氬鑷翠氦鏄撻仐婕忓拰閲嶅锛�"
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(3)]
+ public string OrderMode { get; set; }
+
+ /// <summary>
+ /// 閾惰浜ゆ槗娴佹按鍙�
+ /// 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ /// 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(30)]
+ public string BankTranFlowNo { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗瀵规墜璐﹀彿
+ /// 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ /// 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(30)]
+ public string OppAcctNo { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountDayHistoryTransactionDetailsRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountDayHistoryTransactionDetailsRequest.cs
new file mode 100644
index 0000000..60b3cc2
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountDayHistoryTransactionDetailsRequest.cs
@@ -0,0 +1,386 @@
+锘縰sing MediatR;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ /// </summary>
+ public class InquiryAccountDayHistoryTransactionDetailsRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(20)]
+ public string AcctNo { get; set; }
+
+ /// <summary>
+ /// 甯佺
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(3)]
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 寮�濮嬫棩鏈�
+ /// "鑻ユ煡璇㈠綋鏃ユ槑缁嗭紝寮�濮嬨�佺粨鏉熸棩鏈熷繀椤讳负褰撳ぉ锛涜嫢鏌ヨ鍘嗗彶鏄庣粏锛屽紑濮嬨�佺粨鏉熸棩鏈熷繀椤绘槸鍘嗗彶鏃ユ湡銆�
+ /// 鏍煎紡yyyyMMdd"
+ /// 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(8)]
+ public string BeginDate { get; set; }
+
+ /// <summary>
+ /// 缁撴潫鏃ユ湡
+ /// 鏍煎紡yyyyMMdd
+ /// 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(8)]
+ public string EndDate { get; set; }
+
+ /// <summary>
+ /// 鏌ヨ椤电爜
+ /// 1锛氱涓�椤碉紝渚濇閫掑
+ /// 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ [Required]
+ [MaxLength(6)]
+ public string PageNo { get; set; }
+
+ /// <summary>
+ /// 姣忛〉鏄庣粏鏁伴噺
+ /// "褰撴棩鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�100鏉★紝鑻ヤ笂閫丳ageSize>100鏃犳晥锛岀瓑鍚�100锛�
+ /// 鍘嗗彶鏄庣粏榛樿姣忛〉30鏉¤褰曪紝鏀寔鏈�澶ф瘡椤�1000鏉★紝鑻ヤ笂閫丳ageSize>1000鍒欐彁绀鸿緭鍏ラ敊璇紱
+ /// 涓旀瘡娆℃煡璇㈠繀椤诲浐瀹氫负姝ゅ�硷紝鍚﹀垯鍑虹幇鏄庣粏閬楁紡"
+ /// 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(6)]
+ public string PageSize { get; set; }
+
+ /// <summary>
+ /// 棰勭暀瀛楁
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(120)]
+ public string Reserve { get; set; }
+
+ /// <summary>
+ /// 璁板綍鎺掑簭鏍囧織
+ /// "001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ /// 002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ /// 璇存槑锛�
+ /// 鈶� 褰撲负鍘嗗彶浜ゆ槗鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収001锛氭寜浜ゆ槗鏃堕棿闄嶅簭锛�
+ /// 鈶� 褰撲负褰撴棩鏄庣粏鏌ヨ鏃讹紝榛樿鎸夌収002锛氭寜浜ゆ槗鏃堕棿鍗囧簭锛�
+ /// 锛堟敞锛氬綋鏃ユ槑缁嗗湪浜ゆ槗閲忓ぇ鐨勬儏鍐典笅锛屽繀椤婚噰鐢ㄦ搴忔煡璇紝鍚﹀垯浼氬鑷翠氦鏄撻仐婕忓拰閲嶅锛�"
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(3)]
+ public string OrderMode { get; set; }
+
+ /// <summary>
+ /// 閾惰浜ゆ槗娴佹按鍙�
+ /// 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ /// 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(30)]
+ public string BankTranFlowNo { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗瀵规墜璐﹀彿
+ /// 杈撳叆鍒欐煡璇㈣繃婊ゆ寚瀹氭潯浠剁殑璁板綍
+ /// 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ [MaxLength(30)]
+ public string OppAcctNo { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ /// </summary>
+ public class InquiryAccountDayHistoryTransactionDetailsResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string AcctNo { get; set; }
+
+ /// <summary>
+ /// 璐у竵绫诲瀷
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 鏁版嵁缁撴潫鏍囧織
+ /// "鈥淵鈥�---琛ㄧず鏌ヨ缁撴灉宸插叏閮ㄨ緭鍑哄畬姣曪紱
+ /// 鈥淣鈥�---琛ㄧず鏌ヨ缁撴灉鍙緭鍑轰竴閮ㄥ垎锛屽悗缁儴鍒嗘湁寰呰姹傝緭鍑猴紱"
+ /// 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string EndFlag { get; set; }
+
+ /// <summary>
+ /// 棰勭暀瀛楁
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string Reserve { get; set; }
+
+ /// <summary>
+ /// 鏌ヨ椤电爜
+ /// 鍚屼笂閫�
+ /// 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細Y
+ /// </summary>
+ public string PageNo { get; set; }
+
+ /// <summary>
+ /// 璁板綍绗旀暟
+ /// 鏈杩斿洖鐨勭瑪鏁�
+ /// 鏁版嵁闀垮害锛�2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string PageRecCount { get; set; }
+
+ [JsonProperty("list")]
+ public List<InquiryAccountDayHistoryTransactionDetailsResponseItem> List { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ /// </summary>
+ public class InquiryAccountDayHistoryTransactionDetailsResponseItem
+ {
+ /// <summary>
+ /// 涓绘満璁拌处鏃ユ湡
+ /// 璁拌处鏃ユ湡
+ /// 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AcctDate { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鏃堕棿
+ /// 鏁版嵁闀垮害锛�6锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string TxTime { get; set; }
+
+ /// <summary>
+ /// 涓绘満娴佹按鍙�
+ /// 閾惰璁拌处娴佹按鍙�
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string HostTrace { get; set; }
+
+ /// <summary>
+ /// 涓氬姟娴佹按鍙�
+ /// 閾惰涓氬姟娴佹按鍙�
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string BussSeqNo { get; set; }
+
+ /// <summary>
+ /// 鏄庣粏搴忓彿
+ /// 鏄庣粏搴忓彿锛屽師鏉ュ拰鏍稿績姘村彿涓�璧峰尯鍒嗕氦鏄撳敮涓�鎬�
+ /// 鏁版嵁闀垮害锛�19锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string DetailSerialNo { get; set; }
+
+ /// <summary>
+ /// 浠樻鏂圭綉鐐瑰彿
+ /// 鏁版嵁闀垮害锛�9锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string OutNode { get; set; }
+
+ /// <summary>
+ /// 浠樻鏂硅仈琛屽彿
+ /// 鏁版嵁闀垮害锛�16锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string OutBankNo { get; set; }
+
+ /// <summary>
+ /// 浠樻琛屽悕绉�
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string OutBankName { get; set; }
+
+ /// <summary>
+ /// 浠樻鏂硅处鍙�
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string OutAcctNo { get; set; }
+
+ /// <summary>
+ /// 浠樻鏂规埛鍚�
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string OutAcctName { get; set; }
+
+ /// <summary>
+ /// 缁撶畻甯佺
+ /// 鏁版嵁闀垮害锛�3锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗閲戦
+ /// 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string TranAmount { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂圭綉鐐瑰彿
+ /// 鏁版嵁闀垮害锛�9锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string InNode { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂硅仈琛屽彿
+ /// 鏁版嵁闀垮害锛�16锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string InBankNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂硅鍚�
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string InBankName { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂硅处鍙�
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string InAcctNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂规埛鍚�
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string InAcctName { get; set; }
+
+ /// <summary>
+ /// 鍊熻捶鏍囧織
+ /// D 鍊燂紱C 璐�
+ /// 鏁版嵁闀垮害锛�1锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string DcFlag { get; set; }
+
+ /// <summary>
+ /// 鎽樿锛屾湭缈昏瘧鐨勬憳瑕侊紝濡俆RS
+ /// 鏁版嵁闀垮害锛�120锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AbstractStr { get; set; }
+
+ /// <summary>
+ /// 鍑瘉鍙�
+ /// 绌�
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string VoucherNo { get; set; }
+
+ /// <summary>
+ /// 鎵嬬画璐�
+ /// 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string TranFee { get; set; }
+
+ /// <summary>
+ /// 閭數璐�
+ /// 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string PostFee { get; set; }
+
+ /// <summary>
+ /// 璐﹂潰浣欓
+ /// 鏁版嵁闀垮害锛�15锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AcctBalance { get; set; }
+
+ /// <summary>
+ /// 鐢ㄩ�旓紝闄勮█
+ /// 瀹㈡埛杞处涓婇�佺殑璧勯噾鐢ㄩ�斻��
+ /// 鏁版嵁闀垮害锛�300锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string Purpose { get; set; }
+
+ /// <summary>
+ /// 涓枃鎽樿锛孉bstractStr鐨勪腑鏂囩炕璇�
+ /// 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string AbstractStr_Desc { get; set; }
+
+ /// <summary>
+ /// 浠g悊浜烘埛鍚�
+ /// 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ /// 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string ProxyPayName { get; set; }
+
+ /// <summary>
+ /// 浠g悊浜鸿处鍙�
+ /// 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ /// 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string ProxyPayAcc { get; set; }
+
+ /// <summary>
+ /// 浠g悊浜洪摱琛屽悕绉�
+ /// 鐢ㄤ簬浠g悊琛屾敮浠樺姛鑳�
+ /// 鏁版嵁闀垮害锛�100锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string ProxyPayBankName { get; set; }
+
+ /// <summary>
+ /// 涓绘満鏃ユ湡
+ /// 浜ゆ槗鑷劧鏃ユ湡
+ /// 鏁版嵁闀垮害锛�8锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string HostDate { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗娴佹按鍙�
+ /// 鏁版嵁闀垮害锛�32锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string TranSeqNo { get; set; }
+
+ /// <summary>
+ /// 澶囨敞1
+ /// 鏁版嵁闀垮害锛�300锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string Remark1 { get; set; }
+
+ /// <summary>
+ /// 澶囨敞2
+ /// 鏁版嵁闀垮害锛�300锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string Remark2 { get; set; }
+
+ /// <summary>
+ /// 琚啿姝f爣蹇�
+ /// "0--鏃犲叧锛�
+ /// 1--琚啿姝o紱
+ /// 2--鍐叉"
+ /// 鏁版嵁闀垮害锛�2锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string BeReverseFlag { get; set; }
+
+ /// <summary>
+ /// 鏃跺簭鏃堕棿
+ /// 鏁版嵁闀垮害锛�30锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string SeqTime { get; set; }
+
+ /// <summary>
+ /// 璐圭敤浠g爜
+ /// 鏁版嵁闀垮害锛�20锛屾槸鍚﹀繀杈擄細N
+ /// </summary>
+ public string FeeCode { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountStopPaymentDetailsRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountStopPaymentDetailsRequest.cs
new file mode 100644
index 0000000..2ece117
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/InquiryAccountStopPaymentDetailsRequest.cs
@@ -0,0 +1,88 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ /// </summary>
+ public class InquiryAccountStopPaymentDetailsRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 璐︽埛
+ /// </summary>
+ [MaxLength(10)]
+ [Required]
+ [JsonProperty("accountNo")]
+ public string AccountNo { get; set; }
+
+ /// <summary>
+ /// 椤电爜 浠�1寮�濮嬮�掑锛岄粯璁�1
+ /// </summary>
+ [MaxLength(3)]
+ [JsonProperty("pageNo")]
+ public string PageNo { get; set; }
+ }
+
+ /// <summary>
+ /// 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ /// </summary>
+ public class InquiryAccountStopPaymentDetailsResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 褰撳墠椤佃褰曟暟閲�
+ /// </summary>
+ public string CSize { get; set; }
+
+ /// <summary>
+ /// 缈婚〉缁撴潫鏍囧織 N-鏈粨鏉燂紝鏈変笅涓�椤碉紝椤甸潰閫掑锛沋-宸茬粨鏉�
+ /// </summary>
+ public string EndFlag { get; set; }
+
+ /// <summary>
+ ///
+ /// </summary>
+ public List<InquiryAccountStopPaymentDetailsResponseItem> List { get; set; }
+ }
+
+ /// <summary>
+ /// 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ /// </summary>
+ public class InquiryAccountStopPaymentDetailsResponseItem
+ {
+ /// <summary>
+ /// 姝粯缂栧彿
+ /// </summary>
+ public string StopPayFlw { get; set; }
+
+ /// <summary>
+ /// 鍐荤粨璧峰鏃ユ湡
+ /// </summary>
+ public string StartDate { get; set; }
+
+ /// <summary>
+ /// 鍐荤粨缁撴潫鏃ユ湡
+ /// </summary>
+ public string EndDate { get; set; }
+
+ /// <summary>
+ /// 澶囨敞
+ /// </summary>
+ public string Remark { get; set; }
+
+ /// <summary>
+ /// 姝粯浠g爜 02-涓存椂姝粯
+ /// </summary>
+ public string StopCode { get; set; }
+
+ /// <summary>
+ /// 姝粯鐘舵�� 0-鏈夋晥 1-鏃犳晥
+ /// </summary>
+ public string FreezeStatu { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseRequest.cs
new file mode 100644
index 0000000..ba51feb
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseRequest.cs
@@ -0,0 +1,44 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 浼佷笟閾朵紒鐩磋仈鏍囧噯浠g爜 閾惰鎻愪緵缁欎紒涓氱殑20浣嶅敮涓�鐨勬爣璇嗕唬鐮�
+ /// </summary>
+ [MaxLength(20)]
+ public string MrChCode { get; set; }
+
+ /// <summary>
+ /// 鎺ユ敹鎶ユ枃闀垮害 鎶ユ枃鏁版嵁闀垮害锛涗笉鍖呮嫭闄勪欢鍐呭銆佺鍚嶅唴瀹圭殑闀垮害锛屼笉澶熷乏琛�0
+ /// </summary>
+ public int RecvLength { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鏃ユ湡(yyyyMMdd)
+ /// </summary>
+ [JsonProperty("tradeDate")]
+ public int TradeDate { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鏃堕棿 hhmmss
+ /// </summary>
+ [JsonProperty("tradeTime")]
+ public int TradeTime { get; set; }
+
+ /// <summary>
+ /// 璇锋眰鏂圭郴缁熸祦姘村彿
+ /// 鍞竴鏍囪瘑涓�绗斾氦鏄� 澶囨敞锛氾紙濡傛灉鏌愮浜ゆ槗瑕佹湁澶氭璇锋眰鐨勬墠鑳藉畬鎴愮殑锛屽涓氦鏄撹姹傚寘娴佹按鍙疯淇濇寔涓�鑷达級
+ /// </summary>
+ [MaxLength(20)]
+ [Required]
+ public string CnsmrSeqNo { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseResponse.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseResponse.cs
new file mode 100644
index 0000000..ac7f604
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/PingAnPayBaseResponse.cs
@@ -0,0 +1,26 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class PingAnPayBaseResponse
+ {
+ public PingAnPayBaseResponse()
+ {
+ Errors = [];
+ }
+
+ public string Code { get; set; }
+ public string Message { get; set; }
+ public List<PingAnPayBaseResponseError> Errors { get; set; }
+ }
+
+ public class PingAnPayBaseResponseError
+ {
+ public string ErrorCode { get; set; }
+ public string ErrorMessage { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/SameDayHistoryReceiptDataQueryRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/SameDayHistoryReceiptDataQueryRequest.cs
new file mode 100644
index 0000000..8ba796b
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/SameDayHistoryReceiptDataQueryRequest.cs
@@ -0,0 +1,231 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ /// </summary>
+ public class SameDayHistoryReceiptDataQueryRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// </summary>
+ [Required]
+ [MaxLength(20)]
+ public string OutAccNo { get; set; }
+
+ /// <summary>
+ /// 璁拌处璧峰鏃ユ湡 鏌ヨ褰撴棩鏃犻渶杈撳叆姝ゅ瓧娈� 鏌ヨ鍘嗗彶鍥炲崟蹇呰緭(寮�濮嬬粨鏉熼兘闇�瑕佽緭鍏ワ紝蹇呴』鏄巻鍙叉棩鏈�)鏍煎紡YYYYMMDD
+ /// </summary>
+ [MaxLength(8)]
+ public string AccountBeginDate { get; set; }
+
+ /// <summary>
+ /// 璁拌处缁撴潫鏃ユ湡 鏌ヨ褰撴棩鏃犻渶杈撳叆姝ゅ瓧娈垫煡璇㈠巻鍙插洖鍗曞繀杈�(寮�濮嬬粨鏉熼兘闇�瑕佽緭鍏ワ紝蹇呴』鏄巻鍙叉棩鏈�)鏍煎紡YYYYMMDD
+ /// </summary>
+ [MaxLength(8)]
+ public string AccountEndDate { get; set; }
+
+ /// <summary>
+ /// 鏍稿績娴佹按鍙� 閾惰鏍稿績娴佹按鍙枫�侀摱琛屼富鏈烘祦姘村彿銆傚鍙�4005杩斿洖鐨凥ostFlowNo锛�4013杩斿洖鐨凥ostFlowNo.
+ /// </summary>
+ [MaxLength(30)]
+ public string HostFlow { get; set; }
+
+ /// <summary>
+ /// 璧峰浜ゆ槗閲戦
+ /// </summary>
+ [MaxLength(13)]
+ public string StartTranAmt { get; set; }
+
+ /// <summary>
+ /// 缁撴潫浜ゆ槗閲戦
+ /// </summary>
+ [MaxLength(13)]
+ public string EndTranAmt { get; set; }
+
+ /// <summary>
+ /// 鏀舵甯愬彿 瀵规柟甯愬彿
+ /// </summary>
+ [MaxLength(20)]
+ public string InAccNo { get; set; }
+
+ /// <summary>
+ /// 鍊熻捶鏍囧織 D:鍊� C:璐�
+ /// </summary>
+ [MaxLength(2)]
+ public string DcFlag { get; set; }
+
+ /// <summary>
+ /// 鎺掑簭鏂瑰紡
+ /// 0锛氶粯璁ゆ帓搴�
+ /// 1:浜ゆ槗鏃堕棿浠庤繎鑷宠繙
+ /// 2:浜ゆ槗鏃堕棿浠庤繙鑷宠繎
+ /// 3:閲戦鍗囧簭(浠庡皬鑷冲ぇ)
+ /// 4:閲戦闄嶅簭(浠庡ぇ鑷冲皬)
+ /// 5:鍥炲崟鍙峰崌搴�
+ /// 6:鍥炲崟鍙烽檷搴�
+ /// 7:涓氬姟缂栧彿鍗囧簭
+ /// 8:涓氬姟缂栧彿闄嶅簭
+ /// 9:鏍稿績娴佹按鍙蜂粠杩戝埌杩�
+ /// 10:鏍稿績娴佹按鍙蜂粠杩滃埌杩�
+ /// </summary>
+ [MaxLength(2)]
+ public string SortType { get; set; }
+
+ /// <summary>
+ /// 甯佺 榛樿RMB
+ /// </summary>
+ [MaxLength(3)]
+ public string CCY { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟绫诲瀷 榛樿涓篈LL 鍏ㄩ儴锛屽叿浣撳弬鑰�3.9浠g爜瀵圭収琛�
+ /// </summary>
+ public string ReceiptType { get; set; }
+
+ /// <summary>
+ /// 瀛愬洖鍗曠被鍨� 榛樿涓篈LL 鍏ㄩ儴锛屽叿浣撳弬鑰�3.9浠g爜瀵圭収琛�
+ /// </summary>
+ public string SubReceiptType { get; set; }
+
+ /// <summary>
+ /// 璁板綍璧峰鍙� 璁板綍璧峰鍙� 鐢ㄤ簬鍒嗛〉榛樿锛�1
+ /// </summary>
+ public string RecordStartNo { get; set; }
+
+ /// <summary>
+ /// 璇锋眰璁板綍鏁� 鍒嗛〉鏉℃暟鏈�澶�100鏉� 榛樿锛�100
+ /// </summary>
+ public string RecordNumber { get; set; }
+ }
+
+ /// <summary>
+ /// 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ /// </summary>
+ public class SameDayHistoryReceiptDataQueryResponse : PingAnPayBaseResponse
+ {
+ public string ResultNum { get; set; }
+
+ public string EndFlag { get; set; }
+
+ public string ReceiptType { get; set; }
+
+ public string SubReceiptType { get; set; }
+
+ [JsonProperty("list")]
+ public List<SameDayHistoryReceiptDataQueryResponseItem> List { get; set; }
+ }
+
+ /// <summary>
+ /// 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ /// </summary>
+ public class SameDayHistoryReceiptDataQueryResponseItem
+ {
+ /// <summary>
+ /// 璁板綍搴忓彿
+ /// </summary>
+ public string SeqNo { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟鍙�
+ /// </summary>
+ public string ReceiptNo { get; set; }
+
+ /// <summary>
+ /// 楠岃瘉鐮�
+ /// </summary>
+ public string ValidateNo { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟绫诲瀷
+ /// </summary>
+ public string ReceiptType { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟瀛愮被
+ /// </summary>
+ public string SubReceiptType { get; set; }
+
+ /// <summary>
+ /// 璁拌处鏃ユ湡 璁拌处鏃ユ湡锛屾牸寮弝yyyMMdd
+ /// </summary>
+ public string AccountDate { get; set; }
+
+ /// <summary>
+ /// 涓诲紶鍙�
+ /// </summary>
+ public string MainAcc { get; set; }
+
+ /// <summary>
+ /// 瀛愬笎鍙�
+ /// </summary>
+ public string SubAccNo { get; set; }
+
+ /// <summary>
+ /// 浠樻璐︽埛
+ /// </summary>
+ public string OutAccNo { get; set; }
+
+ /// <summary>
+ /// 浠樻鎴峰悕
+ /// </summary>
+ public string OutAccName { get; set; }
+
+ /// <summary>
+ /// 浠樻閾惰鍚嶇О
+ /// </summary>
+ public string OutBranchName { get; set; }
+
+ /// <summary>
+ /// 鍊熻捶鏍囧織
+ /// </summary>
+ public string DcFlag { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂硅处鎴�
+ /// </summary>
+ public string InAccNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂规埛鍚�
+ /// </summary>
+ public string InAccName { get; set; }
+
+ /// <summary>
+ /// 鏀舵鏂归摱琛屽悕绉�
+ /// </summary>
+ public string InBranchName { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗閲戦
+ /// </summary>
+ public string Amount { get; set; }
+
+ /// <summary>
+ /// 甯佺
+ /// </summary>
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 澶囨敞
+ /// </summary>
+ public string Remark { get; set; }
+
+ /// <summary>
+ /// 涓绘満娴佹按
+ /// </summary>
+ public string HostFlowNo { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟鍚嶇О
+ /// </summary>
+ public string ReceiptName { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleApplicationSuspensionPaymentRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleApplicationSuspensionPaymentRequest.cs
new file mode 100644
index 0000000..b1a39b7
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleApplicationSuspensionPaymentRequest.cs
@@ -0,0 +1,241 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍗曠瑪鐩戠姝粯鏀粯鐢宠_閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleApplicationSuspensionPaymentRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 杞处鍑瘉鍙� 鏍囩ず浜ゆ槗鍞竴鎬э紝鍚屼竴瀹㈡埛涓婇�佺殑涓嶅彲閲嶅锛屽缓璁牸寮忥細yyyymmddHHSS+8浣嶇郴鍒椼�傝姹�6涓湀鍐呭敮涓�銆�
+ /// </summary>
+ [MaxLength(20)]
+ [Required]
+ public string ThirdVoucher { get; set; }
+
+ /// <summary>
+ /// 鎵规鍙� 閾惰姣忔棩鎸夋壒娆″彿浜х敓鏄庣粏鍥炲崟锛岃嫢鏈夋壒娆″洖鍗曢渶姹傦紝闇�瑕佷笂閫佹鎵规鍙枫�備笉鍚岀殑鎵规鍙蜂骇鐢熶笉鍚屽洖鍗曘��
+ /// </summary>
+ [MaxLength(20)]
+
+ public string BatchNo { get; set; }
+
+ /// <summary>
+ /// 姝粯缂栧彿 鏈夋晥鐘舵�佺殑骞冲畨鏄撴浠樼紪鍙凤紝浠嶫GF001姝粯鍚庤繑鍥炵殑
+ /// </summary>
+ [MaxLength(30)]
+ [Required]
+ public string FreezeNo { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛鑷畾涔夊嚟璇佸彿 鐢ㄤ簬瀹㈡埛杞处鐧昏鍜屽唴閮ㄨ瘑鍒紝閫氳繃杞处缁撴灉鏌ヨ鍙互杩斿洖銆傞摱琛屼笉妫�鏌ュ敮涓�鎬�
+ /// </summary>
+ [MaxLength(20)]
+
+ public string CstInnerFlowNo { get; set; }
+
+ /// <summary>
+ /// 璐у竵绫诲瀷 RMB-浜烘皯甯�
+ /// </summary>
+ [MaxLength(3)]
+ [Required]
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 浠樻浜鸿处鎴� 鎵f璐︽埛锛堟浠樼姸鎬佺殑璐︽埛锛�
+ /// </summary>
+ [MaxLength(20)]
+ [Required]
+ public string OutAcctNo { get; set; }
+
+ /// <summary>
+ /// 浠樻浜哄悕绉� 浠樻璐︽埛鎴峰悕
+ /// </summary>
+ [MaxLength(60)]
+ [Required]
+ public string OutAcctName { get; set; }
+
+ /// <summary>
+ /// 浠樻浜哄湴鍧� 寤鸿濉啓浠樻璐︽埛鐨勫垎琛屻�佺綉鐐瑰悕绉�
+ /// </summary>
+ [MaxLength(60)]
+
+ public string OutAcctAddr { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜哄紑鎴疯琛屽彿 璺ㄨ杞处寤鸿蹇呰緭銆備负浜鸿鐧昏鍦ㄥ唽鐨勫晢涓氶摱琛屽彿锛岃嫢杈撳叆鍒欓暱搴﹀繀椤诲湪4 ~12浣嶄箣闂达紱
+ /// </summary>
+ [MaxLength(12)]
+
+ public string InAcctBankNode { get; set; }
+
+ /// <summary>
+ /// 鎺ユ敹琛岃鍙� 寤鸿鍚屾敹娆句汉寮�鎴疯琛屽彿
+ /// </summary>
+ [MaxLength(12)]
+
+ public string InAcctRecCode { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜鸿处鎴�
+ /// </summary>
+ [MaxLength(32)]
+
+ public string InAcctNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜鸿处鎴锋埛鍚�
+ /// </summary>
+ [MaxLength(60)]
+ [Required]
+ public string InAcctName { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜哄紑鎴疯鍚嶇О 寤鸿鏍煎紡锛歺xx閾惰
+ /// </summary>
+ [MaxLength(60)]
+ [Required]
+ public string InAcctBankName { get; set; }
+
+ /// <summary>
+ /// 鏀舵璐︽埛閾惰寮�鎴风渷浠g爜鎴栫渷鍚嶇О 寤鸿璺ㄨ杞处杈撳叆锛涘鐓х爜鍙傝�冣�滈檮褰�-鐪佸鐓ц〃鈥濓紱涔熷彲杈撳叆鈥滈檮褰�-鐪佸鐓ц〃鈥濅腑鐨勭渷鍚嶇О銆�
+ /// </summary>
+ [MaxLength(10)]
+ public string InAcctProvinceCode { get; set; }
+
+ /// <summary>
+ /// 鏀舵璐︽埛寮�鎴峰競 寤鸿璺ㄨ杞处杈撳叆锛�
+ /// </summary>
+ [MaxLength(12)]
+ public string InAcctCityName { get; set; }
+
+ /// <summary>
+ /// 杞嚭閲戦 濡備负XML鎶ユ枃锛屽垯鐩存帴杈撳叆杈撳嚭浠ュ厓涓哄崟浣嶇殑娴偣鏁板�硷紝濡�2.50 (涓ゅ厓浜旇)
+ /// </summary>
+ [MaxLength(20)]
+ [Required]
+ public string TranAmount { get; set; }
+
+ /// <summary>
+ /// 璧勯噾鐢ㄩ�� 100涓眽瀛楋紝瀵规柟鑳藉惁鐪嬪埌姝ょ敤閫旇鏀舵鏂归摱琛岀殑鏀寔銆�
+ /// </summary>
+ [MaxLength(100)]
+ public string UseEx { get; set; }
+
+ /// <summary>
+ /// 琛屽唴璺ㄨ鏍囧織 1锛氳鍐呰浆璐︼紝0锛氳法琛岃浆璐�
+ /// </summary>
+ [MaxLength(1)]
+ [Required]
+ public string UnionFlag { get; set; }
+
+ /// <summary>
+ /// 杞处鍔犳�ユ爣蹇� N锛氭櫘閫氾紙澶у皬棰濊嚜鍔ㄩ�夋嫨锛夛紝榛樿鍊硷紱Y锛氬姞鎬� 锛堝ぇ棰濓級锛�
+ /// S锛氱壒鎬�(瓒呯骇缃戦摱)锛�
+ /// T1锛氭繁鍦冲悓鍩庢櫘閫氾紱
+ /// T2锛氭繁鍦冲悓鍩庡疄鏃讹紱
+ /// 榛樿涓篘
+ /// </summary>
+ [MaxLength(1)]
+ public string SysFlag { get; set; }
+
+ /// <summary>
+ /// 鍚屽煄/寮傚湴鏍囧織 鈥�1鈥濃�斿悓鍩� 鈥�2鈥濃�斿紓鍦帮紱鑻ユ棤娉曞尯鍒嗭紝鍙粯璁ら��1-鍚屽煄銆�
+ /// </summary>
+ [MaxLength(1)]
+ [Required]
+ public string AddrFlag { get; set; }
+ }
+
+ /// <summary>
+ /// 鍗曠瑪鐩戠姝粯鏀粯鐢宠_閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleApplicationSuspensionPaymentResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 杞处鍑瘉鍙�
+ /// </summary>
+ public string ThirdVoucher { get; set; }
+
+ /// <summary>
+ /// 閾惰娴佹按鍙� 閾惰涓氬姟娴佹按鍙凤紱鍙互鐢ㄤ簬瀵硅处
+ /// </summary>
+ public string FrontLogNo { get; set; }
+
+ /// <summary>
+ /// 瀹㈡埛鑷畾涔夊嚟璇佸彿 鐢ㄤ簬瀹㈡埛杞处鐧昏鍜屽唴閮ㄨ瘑鍒紝閫氳繃杞处缁撴灉鏌ヨ鍙互杩斿洖銆傞摱琛屼笉妫�鏌ュ敮涓�鎬�
+ /// </summary>
+ public string CstInnerFlowNo { get; set; }
+
+ /// <summary>
+ /// 璐у竵绫诲瀷
+ /// </summary>
+ public string CcyCode { get; set; }
+
+ /// <summary>
+ /// 浠樻浜鸿处鎴峰悕绉�
+ /// </summary>
+ public string OutAcctName { get; set; }
+
+ /// <summary>
+ /// 浠樻浜鸿处鎴�
+ /// </summary>
+ public string OutAcctNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜哄紑鎴疯鍚嶇О
+ /// </summary>
+ public string InAcctBankName { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜鸿处鎴�
+ /// </summary>
+ public string InAcctNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜鸿处鎴锋埛鍚�
+ /// </summary>
+ public string InAcctName { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗閲戦
+ /// </summary>
+ public string TranAmount { get; set; }
+
+ /// <summary>
+ /// 琛屽唴璺ㄨ鏍囧織 1锛氳鍐呰浆璐︼紝0锛氳法琛岃浆璐�
+ /// </summary>
+ public string UnionFlag { get; set; }
+
+ /// <summary>
+ /// 鎵嬬画璐� 杞处鎵嬬画璐归绠楋紝瀹為檯鎵嬬画璐圭敤浠ュ疄闄呮墸鍙栫殑涓哄噯銆�
+ /// </summary>
+ public string Fee1 { get; set; }
+
+ /// <summary>
+ /// 閭數璐�
+ /// </summary>
+ public string Fee2 { get; set; }
+
+ /// <summary>
+ /// 閾惰杩斿洖娴佹按鍙� 閾惰璁拌处娴佹按鍙凤紱杞处鎴愬姛鍚庯紝閾惰杩斿洖鐨勬祦姘村彿銆�
+ /// </summary>
+ public string HostFlowNo { get; set; }
+
+ /// <summary>
+ /// 璁拌处鏃ユ湡 閾惰浜ゆ槗鎴愬姛鍚庣殑璁拌处鏃ユ湡锛屼粎瀵硅鍐呭疄鏃惰浆璐︿氦鏄撴湁鏁堛��
+ /// </summary>
+ public string HostTxDate { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鐘舵�佹爣蹇� 20锛氫氦鏄撴垚鍔� 30锛氬け璐ワ紱鍏朵粬涓洪摱琛屽彈鐞嗘垚鍔熷鐞嗕腑锛岃浣跨敤鈥滀氦鏄撹繘搴︽煡璇�4005鈥濇帴鍙h幏鍙栨渶缁堢姸鎬�
+ /// </summary>
+ public string Stt { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleDataQueryRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleDataQueryRequest.cs
new file mode 100644
index 0000000..11a79a5
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleDataQueryRequest.cs
@@ -0,0 +1,487 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍥炲崟鏁版嵁鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleDataQueryRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 璐﹀彿
+ /// </summary>
+ [Required]
+ [MaxLength(50)]
+ public string AcctNo { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟绫诲瀷 鍙傜収鍥炲崟绫诲瀷 娉細鏌ュ叏閮ㄥ彲閫佲�淎LL鈥�
+ /// </summary>
+ [Required]
+ [MaxLength(10)]
+ public string ReceiptType { get; set; }
+
+ /// <summary>
+ /// 瀛愮被鍨� 鍙傜収鍥炲崟绫诲瀷 娉細鏌ュ叏閮ㄥ彲閫佲�淎LL鈥�
+ /// </summary>
+ [Required]
+ [MaxLength(3)]
+ public string SubType { get; set; }
+
+ /// <summary>
+ /// 璧峰鏃ユ湡 鏍煎紡yyyyMMdd锛堣璐︽棩鏈燂級
+ /// </summary>
+ [Required]
+ [MaxLength(8)]
+ public string StartDate { get; set; }
+
+ /// <summary>
+ /// 缁撴潫鏃ユ湡 鏍煎紡yyyyMMdd锛堣璐︽棩鏈燂級
+ /// </summary>
+ [Required]
+ [MaxLength(8)]
+ public string EndDate { get; set; }
+
+ /// <summary>
+ /// 璧峰璁板綍鏁� 璧峰鍊间负1锛屼笉鑳介��0
+ /// </summary>
+ [Required]
+ public int StartRecord { get; set; }
+
+ /// <summary>
+ /// 鏈壒璁板綍鏁�
+ /// </summary>
+ [Required]
+ public int RecordNum { get; set; }
+
+ /// <summary>
+ /// 寮�濮嬮噾棰� 锛堜氦鏄撻噾棰濓級double(20,4)
+ /// </summary>
+ public double StartAmt { get; set; }
+
+ /// <summary>
+ /// 缁撴潫閲戦 锛堜氦鏄撻噾棰濓級double(20,5)
+ /// </summary>
+ public double EntAmt { get; set; }
+
+ /// <summary>
+ /// 鎺掑簭鏂瑰紡 001锛氫氦鏄撴椂闂翠粠杩戝埌杩�
+ /// 002锛氫氦鏄撴椂闂翠粠杩滃埌杩�
+ /// 003锛氶噾棰濆崌搴忥紙浠庡皬鍒板ぇ锛�
+ /// 004锛氶噾棰濋檷搴忥紙浠庡ぇ鍒板皬锛�
+ /// 005锛氬洖鍗曞彿鍗囧簭
+ /// 006锛氬洖鍗曞彿闄嶅簭
+ /// </summary>
+ [MaxLength(10)]
+ public string OrderMode { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜鸿处鍙�
+ /// </summary>
+ [MaxLength(50)]
+ public string PayeeAcctNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜哄悕绉�
+ /// </summary>
+ [MaxLength(300)]
+ public string PayeeName { get; set; }
+
+ /// <summary>
+ /// 鍊熻捶鏍囧織 D锛氬�熸柟浜ゆ槗 C锛氳捶鏂逛氦鏄�
+ /// </summary>
+ [MaxLength(4)]
+ public string DrCrFlag { get; set; }
+
+ /// <summary>
+ /// 甯佺
+ /// </summary>
+ [MaxLength(3)]
+ public string Ccy { get; set; }
+
+ /// <summary>
+ /// 椤哄簭鍙�
+ /// </summary>
+ [MaxLength(70)]
+ public string SerialNo { get; set; }
+
+ /// <summary>
+ /// 鎵撳嵃缃戠偣 浠g爜閲岄潰娌℃湁
+ /// </summary>
+ [MaxLength(20)]
+ public string PrintBranchId { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟鍙�
+ /// </summary>
+ [MaxLength(32)]
+ public string ReceiptNo { get; set; }
+
+ /// <summary>
+ /// 鎵撳嵃鏍囧織 0锛氶娆℃墦鍗� 1锛氳ˉ鎵�
+ /// </summary>
+ [MaxLength(2)]
+ public string PrintFlag { get; set; }
+ }
+
+ /// <summary>
+ /// 鍥炲崟鏁版嵁鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleDataQueryResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 璁板綍鎬绘暟
+ /// </summary>
+ public string RecordTotalCount { get; set; }
+
+ /// <summary>
+ /// 璧峰璁板綍鏁�
+ /// </summary>
+ public string StartRecord { get; set; }
+
+ /// <summary>
+ /// 鏈杩斿洖璁板綍鏁�
+ /// </summary>
+ public string ResultNum { get; set; }
+
+ /// <summary>
+ /// 缁撴潫鏍囧織 Y:鏃犲墿浣欒褰� N:鏈夊墿浣欒褰�
+ /// </summary>
+ public string EndFlag { get; set; }
+
+ [JsonProperty("list")]
+ public List<SingleDataQueryResponseItem> List { get; set; }
+ }
+
+ /// <summary>
+ /// 鍥炲崟鏁版嵁鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleDataQueryResponseItem
+ {
+ /// <summary>
+ /// 鍥炲崟鍙�
+ /// </summary>
+ public string ReceiptNo { get; set; }
+
+ /// <summary>
+ /// 楠岃瘉鐮�
+ /// </summary>
+ public string CheckCode { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟绫诲瀷
+ /// </summary>
+ public string ReceiptType { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟瀛愮被
+ /// </summary>
+ public string SubType { get; set; }
+
+ /// <summary>
+ /// 璁拌处鏃ユ湡
+ /// </summary>
+ public string BookingDate { get; set; }
+
+ /// <summary>
+ /// 浠樻浜哄悕绉�
+ /// </summary>
+ public string PayerName { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜哄悕绉�
+ /// </summary>
+ public string PayeeName { get; set; }
+
+ /// <summary>
+ /// 浠樻浜鸿处鍙�
+ /// </summary>
+ public string PayerAccNo { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜鸿处鍙�
+ /// </summary>
+ public string PayeeAccNo { get; set; }
+
+ /// <summary>
+ /// 浠樻浜哄紑鎴疯
+ /// </summary>
+ public string PayerAcctOpenBranchID { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜哄紑鎴疯
+ /// </summary>
+ public string PayeeAcctOpenBranchID { get; set; }
+
+ /// <summary>
+ /// 浠樻浜哄紑鎴疯鍚嶇О
+ /// </summary>
+ public string PayerAcctOpenBranchName { get; set; }
+
+ /// <summary>
+ /// 鏀舵浜哄紑鎴疯鍚嶇О
+ /// </summary>
+ public string PayeeAcctOpenBranchName { get; set; }
+
+ /// <summary>
+ /// 涓昏处鍙�
+ /// </summary>
+ public string MainAcctNo { get; set; }
+
+ /// <summary>
+ /// 瀛愯处鍙�
+ /// </summary>
+ public string SubAcctNo { get; set; }
+
+ /// <summary>
+ /// 鍘熻处鍙�
+ /// </summary>
+ public string OldAcctNo { get; set; }
+
+ /// <summary>
+ /// 甯佺
+ /// </summary>
+ public string Ccy { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗閲戦
+ /// </summary>
+ public double TranAmt { get; set; }
+
+ /// <summary>
+ /// 缃戠偣鍙�
+ /// </summary>
+ public string SubBranchID { get; set; }
+
+ /// <summary>
+ /// 鍊熻捶鏍囧織
+ /// </summary>
+ public string DrCrFlag { get; set; }
+
+ /// <summary>
+ /// 璧勯噾鐢ㄩ��
+ /// </summary>
+ public string Crpp { get; set; }
+
+ /// <summary>
+ /// 鏈噾
+ /// </summary>
+ public double Corpus { get; set; }
+
+ /// <summary>
+ /// 瀛樻鍒╃巼
+ /// </summary>
+ public double DepositIntRate { get; set; }
+
+ /// <summary>
+ /// 瀛樺崟鍙�
+ /// </summary>
+ public string DepositReceiptNo { get; set; }
+
+ /// <summary>
+ /// 璧峰鏈�
+ /// </summary>
+ public string StartPeriod { get; set; }
+
+ /// <summary>
+ /// 缁撴潫鏈�
+ /// </summary>
+ public string EndPeriod { get; set; }
+
+ /// <summary>
+ /// 鍒╂伅绋�
+ /// </summary>
+ public double InterestTax { get; set; }
+
+ /// <summary>
+ /// 鍒╂伅
+ /// </summary>
+ public double IntInterest { get; set; }
+
+ /// <summary>
+ /// 閫忔敮鍒╂伅
+ /// </summary>
+ public double OverdraftInterest { get; set; }
+
+ /// <summary>
+ /// 绋庣巼
+ /// </summary>
+ public double TaxRate { get; set; }
+
+ /// <summary>
+ /// 璐锋璐﹀彿
+ /// </summary>
+ public string LoanAcctNo { get; set; }
+
+ /// <summary>
+ /// 鍊熸嵁鍙�
+ /// </summary>
+ public string DuebillNo { get; set; }
+
+ /// <summary>
+ /// 杩樻閲戦
+ /// </summary>
+ public double PaidAmt { get; set; }
+
+ /// <summary>
+ /// 杩樻鏈噾
+ /// </summary>
+ public double RepayCorpus { get; set; }
+
+ /// <summary>
+ /// 杩樻鍒╂伅
+ /// </summary>
+ public double ReplyInterest { get; set; }
+
+ /// <summary>
+ /// 澶嶅埄
+ /// </summary>
+ public double ComInterest { get; set; }
+
+ /// <summary>
+ /// 鏈噾浣欓
+ /// </summary>
+ public double CorpusBalance { get; set; }
+
+ /// <summary>
+ /// 搴旇繕鏈噾
+ /// </summary>
+ public double DueRepayCorpus { get; set; }
+
+ /// <summary>
+ /// 杩樻鏈熸暟
+ /// </summary>
+ public int RepayCount { get; set; }
+
+ /// <summary>
+ /// 鎵嬬画璐归噾棰�
+ /// </summary>
+ public double Commission { get; set; }
+
+ /// <summary>
+ /// 宸ユ湰璐�
+ /// </summary>
+ public double MaterialFee { get; set; }
+
+ /// <summary>
+ /// 绋庡悗鍒╂伅
+ /// </summary>
+ public double TaxedInterest { get; set; }
+
+ /// <summary>
+ /// 涓绘満娴佹按鍙�
+ /// </summary>
+ public string HostSeqNo { get; set; }
+
+ /// <summary>
+ /// 璐锋鍒╃巼
+ /// </summary>
+ public double LoanIntRate { get; set; }
+
+ /// <summary>
+ /// 搴旀敹鍒╂伅
+ /// </summary>
+ public double ReceivableInterest { get; set; }
+
+ /// <summary>
+ /// 鏌滃憳鍙�
+ /// </summary>
+ public string TellerNo { get; set; }
+
+ /// <summary>
+ /// 鎺堟潈鏌滃憳鍙�
+ /// </summary>
+ public string AuthTellerNo { get; set; }
+
+ /// <summary>
+ /// 鎵撳嵃瀹㈡埛绔悕绉�
+ /// </summary>
+ public string PrintClientName { get; set; }
+
+ /// <summary>
+ /// 鎵撳嵃鏃堕棿
+ /// </summary>
+ public string PrintTime { get; set; }
+
+ /// <summary>
+ /// 鎵撳嵃娆℃暟
+ /// </summary>
+ public int PrintTimes { get; set; }
+
+ /// <summary>
+ /// 鍦板尯鍙�
+ /// </summary>
+ public string RegionNo { get; set; }
+
+ /// <summary>
+ /// 缁堢鍙�
+ /// </summary>
+ public string TermNo { get; set; }
+
+ /// <summary>
+ /// 鎵撳嵃鑺傜偣
+ /// </summary>
+ public string PrintNote { get; set; }
+
+ /// <summary>
+ /// 涓氬姟绫诲瀷
+ /// </summary>
+ public string BussType { get; set; }
+
+ /// <summary>
+ /// 缁撴伅璐﹀彿
+ /// </summary>
+ public string IntSettleAcctNo { get; set; }
+
+ /// <summary>
+ /// 璐︽埛寮�鎴疯琛屽彿
+ /// </summary>
+ public string AcctOpenBranchID { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鏃ユ湡
+ /// </summary>
+ public string TranDate { get; set; }
+
+ /// <summary>
+ /// 浜ゆ槗鏃堕棿
+ /// </summary>
+ public string TranTime { get; set; }
+
+ /// <summary>
+ /// 鏈烘瀯鍙�
+ /// </summary>
+ public string BranchId { get; set; }
+
+ /// <summary>
+ /// 椤哄簭鍙�
+ /// </summary>
+ public string SerialNo { get; set; }
+
+ /// <summary>
+ /// 璁板綍绫诲瀷
+ /// </summary>
+ public string RecordType { get; set; }
+
+ /// <summary>
+ /// 鍓嶇疆鏈轰唬鐮�
+ /// </summary>
+ public string FrontEndCode { get; set; }
+
+ /// <summary>
+ /// 鎽樿鐮�
+ /// </summary>
+ public string RemarkCode { get; set; }
+
+ /// <summary>
+ /// 鎽樿
+ /// </summary>
+ public string Summary { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleOrBatchReceiptPDFMergeDownloadNewRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleOrBatchReceiptPDFMergeDownloadNewRequest.cs
new file mode 100644
index 0000000..1e2087f
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/SingleOrBatchReceiptPDFMergeDownloadNewRequest.cs
@@ -0,0 +1,98 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleOrBatchReceiptPDFMergeDownloadNewRequest : PingAnPayBaseRequest
+ {
+ public SingleOrBatchReceiptPDFMergeDownloadNewRequest()
+ {
+ List = [];
+ }
+
+ /// <summary>
+ /// 璐﹀彿
+ /// </summary>
+ [Required]
+ [MaxLength(20)]
+ public string OutAccNo { get; set; }
+
+ /// <summary>
+ /// 璁拌处璧峰鏃ユ湡 鏌ヨ鍘嗗彶鍥炲崟蹇呰緭淇濇寔鍜孍CL009鏌ヨ鏃ユ湡鐩稿悓 鏍煎紡YYYYMMDD
+ /// </summary>
+ [MaxLength(8)]
+ public string AccountBeginDate { get; set; }
+
+ /// <summary>
+ /// 璁拌处缁撴潫鏃ユ湡 鏌ヨ鍘嗗彶鍥炲崟蹇呰緭 淇濇寔鍜孍CL009鏌ヨ鏃ユ湡鐩稿悓鏍煎紡YYYYMMDD
+ /// </summary>
+ [MaxLength(8)]
+ public string AccountEndDate { get; set; }
+
+ /// <summary>
+ /// 鐢熸垚PDF姣忛〉鏉℃暟璁剧疆
+ /// N锛氫竴椤祊df鏄剧ず涓�鏉″洖鍗曡褰曪紙榛樿锛�
+ /// Y锛氫竴椤祊df鏄剧ず鍥涙潯鍥炲崟璁板綍
+ /// T锛氫竴椤祊df鏄剧ず涓夋潯鍥炲崟璁板綍
+ /// </summary>
+ [MaxLength(5)]
+ public string PDFNum { get; set; }
+
+ public List<SingleOrBatchReceiptPDFMergeDownloadNewRequestItem> List { get; set; }
+ }
+
+ /// <summary>
+ /// 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleOrBatchReceiptPDFMergeDownloadNewRequestItem
+ {
+ /// <summary>
+ /// 璁板綍搴忓彿 鍙朎LC009鎺ュ彛搴旂瓟鐨刲ist. SeqNo
+ /// </summary>
+ [MaxLength(30)]
+ [Required]
+ public string SeqNo { get; set; }
+
+ /// <summary>
+ /// 璁拌处鏃ユ湡 鍙朎LC009鎺ュ彛搴旂瓟鐨刲ist.AccountDate
+ /// </summary>
+ [MaxLength(30)]
+ [Required]
+ public string AccountDate { get; set; }
+
+ /// <summary>
+ /// 鍥炲崟绫诲瀷 鍙朎LC009鎺ュ彛搴旂瓟鐨刲ist. ReceiptType
+ /// </summary>
+ [MaxLength(20)]
+ [Required]
+ public string RecepitType { get; set; }
+ }
+
+ /// <summary>
+ /// 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ /// </summary>
+ public class SingleOrBatchReceiptPDFMergeDownloadNewResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 鏂囦欢鍚嶇О
+ /// </summary>
+ public string FileName { get; set; }
+
+ /// <summary>
+ /// 闅忔満瀵嗙爜
+ /// </summary>
+ public string RandomPwd { get; set; }
+
+ /// <summary>
+ /// udmpId
+ /// </summary>
+ public string DocID { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/Models/StopPaymentAndSettlementAccountsRequest.cs b/ApiTools.Core/Utils/PingAnPayUtils/Models/StopPaymentAndSettlementAccountsRequest.cs
new file mode 100644
index 0000000..c82577c
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/Models/StopPaymentAndSettlementAccountsRequest.cs
@@ -0,0 +1,89 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璐︽埛姝粯鍜岃В姝粯_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑姝粯銆佽В闄ゆ浠�
+ /// </summary>
+ public class StopPaymentAndSettlementAccountsRequest : PingAnPayBaseRequest
+ {
+ /// <summary>
+ /// 瀹㈡埛娴佹按鍙� 鍞竴鏍囧織璇ョ瑪浜ゆ槗鐨勬祦姘村彿锛屼笉鍙噸澶嶏紝闀垮害蹇呴』澶т簬10浣�
+ /// </summary>
+ [MaxLength(30)]
+ [Required]
+ [JsonProperty("seqNo")]
+ public string SeqNo { get; set; }
+
+ /// <summary>
+ /// 姝粯璐︽埛
+ /// </summary>
+ [MaxLength(30)]
+ [Required]
+ [JsonProperty("accountNo")]
+ public string AccountNo { get; set; }
+
+ /// <summary>
+ /// 鎿嶄綔绫诲瀷 A-姝粯 D-瑙i櫎姝粯
+ /// </summary>
+ [MaxLength(1)]
+ [Required]
+ [JsonProperty("opType")]
+ public string OpType { get; set; }
+
+ /// <summary>
+ /// 姝粯缂栧彿 瑙i櫎姝粯蹇呴』涓婇��
+ /// </summary>
+ [MaxLength(30)]
+ [JsonProperty("stopPayFlw")]
+ public string StopPayFlw { get; set; }
+
+ /// <summary>
+ /// 澶囨敞
+ /// </summary>
+ [MaxLength(100)]
+ [JsonProperty("remark")]
+ public string Remark { get; set; }
+
+ /// <summary>
+ /// 甯佺
+ /// </summary>
+ [MaxLength(3)]
+ [JsonProperty("ccyCode")]
+ public string CcyCode { get; set; }
+ }
+
+ public class StopPaymentAndSettlementAccountsResponse : PingAnPayBaseResponse
+ {
+ /// <summary>
+ /// 瀹㈡埛娴佹按鍙�
+ /// </summary>
+ public string SeqNo { get; set; }
+
+ /// <summary>
+ /// 閾惰涓氬姟娴佹按
+ /// </summary>
+ public string BizSeqNo { get; set; }
+
+ /// <summary>
+ /// 鍐荤粨姝粯缂栧彿
+ /// </summary>
+ public string StopPayFlw { get; set; }
+
+ /// <summary>
+ /// 鐘舵�佺爜
+ /// </summary>
+ public string Stt { get; set; }
+
+ /// <summary>
+ /// 鐘舵�佹弿杩�
+ /// </summary>
+ public string SttDesc { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/PingAnPayOptions.cs b/ApiTools.Core/Utils/PingAnPayUtils/PingAnPayOptions.cs
new file mode 100644
index 0000000..feb6cc2
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/PingAnPayOptions.cs
@@ -0,0 +1,17 @@
+锘縰sing Furion.ConfigurableOptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class PingAnPayOptions : IConfigurableOptions
+ {
+ /// <summary>
+ /// 浼佷笟浠g爜
+ /// </summary>
+ public string MrChCode { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/PingAnPayUtils/PingAnPayUtils.cs b/ApiTools.Core/Utils/PingAnPayUtils/PingAnPayUtils.cs
new file mode 100644
index 0000000..f0ab5d9
--- /dev/null
+++ b/ApiTools.Core/Utils/PingAnPayUtils/PingAnPayUtils.cs
@@ -0,0 +1,233 @@
+锘縰sing Aop.Api.Domain;
+using ApiTools.Core.Entities.Common;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.DependencyInjection;
+using Furion.DistributedIDGenerator;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Org.BouncyCastle.Ocsp;
+using pingan.openbank.api.sdk.client;
+using pingan.openbank.api.sdk.common.helper;
+using pingan.openbank.api.sdk.common.http;
+using pingan.openbank.api.sdk.common.util;
+using pingan.openbank.api.sdk.entity;
+using pingan.openbank.api.sdk.exception;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 骞冲畨鏀粯宸ュ叿
+ /// </summary>
+ public class PingAnPayUtils(
+ ILogger<PingAnPayUtils> logger,
+ IOptions<PingAnPayOptions> options,
+ IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog
+ ) : ITransient
+ {
+ private readonly ILogger<PingAnPayUtils> logger = logger;
+ private readonly IOptions<PingAnPayOptions> options = options;
+ private readonly IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog = repThreeResourceLog;
+
+ /// <summary>
+ /// 浼佷笟璐︽埛浣欓鏌ヨ_閾朵紒鐩磋仈姝ゆ帴鍙i�傚簲閾惰鎵�鏈夊竵绉嶇殑娲绘湡璐︽埛鐨勪綑棰濇煡璇紝鍏朵腑鐨勫彲鐢ㄤ綑棰濆彧鍖呭惈鑷韩鐨勮祫閲戠姸鍐碉紝鑰屼笉鍖呮嫭闆嗗洟鍐呴儴鐨勮祫閲戞睜銆傝处闈綑棰濓紝涔熷彧鏄嚜韬处鍙风殑璐﹂潰閲戦銆�
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<CorAcctBalanceQueryResponse> CorAcctBalanceQuery(CorAcctBalanceQueryRequest request)
+ {
+ return await Send<CorAcctBalanceQueryRequest, CorAcctBalanceQueryResponse>(request, "/V1.0/bedl/CorAcctBalanceQuery");
+ }
+
+ /// <summary>
+ /// 鍘嗗彶浣欓鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<HistoryBalanceQueryResponse> HistoryBalanceQuery(HistoryBalanceQueryRequest request)
+ {
+ return await Send<HistoryBalanceQueryRequest, HistoryBalanceQueryResponse>(request, "/V1.0/bedl/HistoryBalanceQuery");
+ }
+
+ /// <summary>
+ /// 鏌ヨ璐︽埛褰撴棩鍘嗗彶浜ゆ槗鏄庣粏_閾朵紒鐩磋仈
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<InquiryAccountDayHistoryTransactionDetailsResponse> InquiryAccountDayHistoryTransactionDetails(InquiryAccountDayHistoryTransactionDetailsRequest request)
+ {
+ return await Send<InquiryAccountDayHistoryTransactionDetailsRequest, InquiryAccountDayHistoryTransactionDetailsResponse>(request, "/V1.0/bedl/InquiryAccountDayHistoryTransactionDetails");
+ }
+
+ /// <summary>
+ /// 璐︽埛姝粯鍜岃В姝粯_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑姝粯銆佽В闄ゆ浠�
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<StopPaymentAndSettlementAccountsResponse> StopPaymentAndSettlementAccounts(StopPaymentAndSettlementAccountsRequest request)
+ {
+ return await Send<StopPaymentAndSettlementAccountsRequest, StopPaymentAndSettlementAccountsResponse>(request, "/V1.0/bedl/StopPaymentAndSettlementAccounts");
+ }
+
+ /// <summary>
+ /// 璐︽埛姝粯璇︽儏鏌ヨ_閾朵紒鐩磋仈 瀵瑰叕璐︽埛灞傜殑鍐荤粨/姝粯璇︽儏鏌ヨ锛屾瘡椤垫渶澶�100鏉°��
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<InquiryAccountStopPaymentDetailsResponse> InquiryAccountStopPaymentDetails(InquiryAccountStopPaymentDetailsRequest request)
+ {
+ return await Send<InquiryAccountStopPaymentDetailsRequest, InquiryAccountStopPaymentDetailsResponse>(request, "/V1.0/bedl/InquiryAccountStopPaymentDetails");
+ }
+
+ /// <summary>
+ /// 鍗曠瑪鐩戠姝粯鏀粯鐢宠_閾朵紒鐩磋仈
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<SingleApplicationSuspensionPaymentResponse> SingleApplicationSuspensionPayment(SingleApplicationSuspensionPaymentRequest request)
+ {
+ return await Send<SingleApplicationSuspensionPaymentRequest, SingleApplicationSuspensionPaymentResponse>(request, "/V1.0/bedl/SingleApplicationSuspensionPayment");
+ }
+
+ /// <summary>
+ /// 鍗曠瑪杞处鎸囦护鏌ヨ_閾朵紒鐩磋仈
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<CorSingleTransferQueryResponse> CorSingleTransferQuery(CorSingleTransferQueryRequest request)
+ {
+ return await Send<CorSingleTransferQueryRequest, CorSingleTransferQueryResponse>(request, "/V1.0/bedl/CorSingleTransferQuery");
+ }
+
+ /// <summary>
+ /// 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<SingleDataQueryResponse> SingleDataQuery(SingleDataQueryRequest request)
+ {
+ return await Send<SingleDataQueryRequest, SingleDataQueryResponse>(request, "/V1.0/bedl/SingleDataQuery");
+ }
+
+ /// <summary>
+ /// 褰撴棩鍘嗗彶鍥炲崟鏁版嵁鏌ヨ鎺ュ彛_閾朵紒鐩磋仈
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<SameDayHistoryReceiptDataQueryResponse> SameDayHistoryReceiptDataQuery(SameDayHistoryReceiptDataQueryRequest request)
+ {
+ return await Send<SameDayHistoryReceiptDataQueryRequest, SameDayHistoryReceiptDataQueryResponse>(request, "/V1.0/bedl/SameDayHistoryReceiptDataQuery");
+ }
+
+ /// <summary>
+ /// 鍗曠瑪鎴栧绗斿洖鍗昉DF鍚堝苟涓嬭浇锛堟柊锛塤閾朵紒鐩磋仈
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<SingleOrBatchReceiptPDFMergeDownloadNewResponse> SingleOrBatchReceiptPDFMergeDownloadNew(SingleOrBatchReceiptPDFMergeDownloadNewRequest request)
+ {
+ return await Send<SingleOrBatchReceiptPDFMergeDownloadNewRequest, SingleOrBatchReceiptPDFMergeDownloadNewResponse>(request, "/V1.0/bedl/SingleOrBatchReceiptPDFMergeDownloadNew");
+ }
+
+ /// <summary>
+ /// 鍙戦�佽姹�
+ /// </summary>
+ /// <typeparam name="TRequest"></typeparam>
+ /// <typeparam name="TResponse"></typeparam>
+ /// <param name="request"></param>
+ /// <param name="path"></param>
+ /// <returns></returns>
+ public async Task<TResponse> Send<TRequest, TResponse>(TRequest request, string path)
+ where TRequest : PingAnPayBaseRequest, new()
+ where TResponse : PingAnPayBaseResponse, new()
+ {
+ var logier = JwtUtils.GetCurrentLogier();
+ var sdkRequest = new SdkRequest();
+ sdkRequest.SetInterfaceName(path);
+ if (request.CnsmrSeqNo.IsNull())
+ {
+ request.CnsmrSeqNo = $"{DateTime.Now:yyyyMMddHHmmssfff}{new Random(IDGen.NextID().GetHashCode()).Next(100, 999)}";
+ }
+ request.MrChCode = options.Value.MrChCode;
+ var body = JObject.FromObject(request);
+ sdkRequest.SetBody(body);
+ sdkRequest.SetExtraHeaders(null);
+ //string text = sdkRequest.GetAppId();
+ //if (text.IsNull())
+ //{
+ // string configFilePath = sdkRequest.GetConfigFilePath();
+ // text = ((!configFilePath.IsNull()) ? configFilePath : AbstractApiClient.CheckAppIdOnlyOne());
+ //}
+ var log = new ThreeResourceLog
+ {
+ CreatedTime = DateTimeOffset.Now,
+ Id = IDGen.NextID(),
+ TraceId = App.GetTraceId(),
+ Method = EnumResourceMethod.Post,
+ //Domain = AbstractApiClient.GetOpenBankConfig(text).GetBaseUrl(),
+ Path = path,
+ CreatedUserId = logier?.Id,
+ CreatedChannelId = logier?.ChannelId,
+ Request = request.ToJson(),
+ };
+ await repThreeResourceLog.InsertNowAsync(log);
+ var stopwatch = Stopwatch.StartNew();
+ HttpResult httpResult = GetClient().Invoke<HttpResult>(sdkRequest);
+ var sdkReturn = httpResult.GetData();
+ stopwatch.Stop();
+
+ var result = sdkReturn.JsonTo<TResponse>();
+
+ log.UpdatedTime = DateTimeOffset.Now;
+ log.Response = sdkReturn;
+ log.IsSuccess = result.Code.IsNotNull();
+ log.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
+ await repThreeResourceLog.UpdateNowAsync(log);
+
+ return result;
+ }
+
+ public string DownloadFile(string documentId, string fileName)
+ {
+ try
+ {
+ var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UserFiles", "PingAnPay");
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+ path += Path.DirectorySeparatorChar;
+
+ var fileRequest = new FileRequest();
+ fileRequest.SetFileNo(documentId);
+ fileRequest.SetFilePathName(path);
+ GetClient().FileDownLoad(fileRequest);
+ return $"{path}{documentId}.zip";
+ }
+ catch (OpenBankSdkException ex)
+ {
+ Console.WriteLine(ex);
+ throw;
+ }
+ }
+
+ private ApiClient GetClient()
+ {
+ var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PingAnPayCert", "config.properties");
+ var propertyOper = new PropertyOper(path);
+ var client = ApiClient.GetInstance(propertyOper);
+ return client;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/BuildDynamicControllersHostedService.cs b/ApiTools.Core/Utils/ResourceUtils/BuildDynamicControllersHostedService.cs
new file mode 100644
index 0000000..c4603e8
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/BuildDynamicControllersHostedService.cs
@@ -0,0 +1,23 @@
+锘縰sing Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class BuildDynamicControllersHostedService : IHostedService
+ {
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ return ResourceUtils.BuildDynamicControllersAsync();
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/CustomResponseAttribute.cs b/ApiTools.Core/Utils/ResourceUtils/CustomResponseAttribute.cs
new file mode 100644
index 0000000..0f4120e
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/CustomResponseAttribute.cs
@@ -0,0 +1,15 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鑷畾涔夌粨鏋�
+ /// </summary>
+ public class CustomResponseAttribute : Attribute
+ {
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceActionFilter.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceActionFilter.cs
new file mode 100644
index 0000000..097f214
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceActionFilter.cs
@@ -0,0 +1,90 @@
+锘縰sing ApiTools.Core.Entities.Common;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.DistributedIDGenerator;
+using Furion.Schedule;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class ResourceActionFilter : IAsyncActionFilter
+ {
+ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+ {
+ var stopwatch = Stopwatch.StartNew();
+
+ //StringWriter consoleWriter = new();
+ //TextWriter originalConsoleOut = Console.Out;
+
+ //try
+ //{
+ // Console.SetOut(consoleWriter);
+
+ var serviceScopeFactory = App.GetService<IServiceScopeFactory>();
+ var serviceScope = serviceScopeFactory.CreateScope();
+ var rep = serviceScope.ServiceProvider.GetRequiredService<IRepository<ResourceLog, LogDbContextLocator>>();
+ var logier = JwtUtils.GetCurrentLogier();
+
+ var resourceLog = new ResourceLog();
+ resourceLog.CreatedTime = DateTimeOffset.Now;
+ resourceLog.Id = IDGen.NextID();
+ resourceLog.TraceId = App.GetTraceId();
+ resourceLog.Method = EnumUtils.GetEnum<EnumResourceMethod>(context.HttpContext.Request.Method);
+ resourceLog.Domain = $"{context.HttpContext.Request.Scheme}://{context.HttpContext.Request.Host}";
+ resourceLog.Path = context.HttpContext.Request.Path;
+ resourceLog.ClientIpAddress = context.HttpContext.GetRemoteIpAddressToIPv4();
+ resourceLog.CreatedUserId = logier?.Id;
+ resourceLog.CreatedChannelId = logier?.ChannelId;
+ resourceLog.Request = context.ActionArguments?.ToJson();
+ resourceLog.RequestHeaders = context.HttpContext.Request.Headers.ToJson();
+
+ if (resourceLog.Path != "/api/user/resource/checkHealth"
+ && resourceLog.Path != "/api/common/logRecords/saveFrontConsoleLog")
+ {
+ //Console.SetOut(originalConsoleOut);
+ await rep.InsertNowAsync(resourceLog);
+ //Console.SetOut(consoleWriter);
+ }
+
+ //============== 杩欓噷鏄墽琛屾柟娉曚箣鍚庤幏鍙栨暟鎹� ====================
+ var actionContext = await next();
+ //Console.SetOut(originalConsoleOut);
+
+ resourceLog.UpdatedTime = DateTimeOffset.Now;
+ if (actionContext.Result is JsonResult jsonResult)
+ {
+ resourceLog.Response = jsonResult.Value.ToJson();
+ }
+ resourceLog.ResponseHeaders = context.HttpContext.Response.Headers.ToJson();
+ resourceLog.IsSuccess = actionContext.Exception == null;
+ //resourceLog.ConsoleLogs = consoleWriter.ToString();
+
+ stopwatch.Stop();
+ resourceLog.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
+
+ if (resourceLog.Path != "/api/user/resource/checkHealth"
+ && resourceLog.Path != "/api/common/logRecords/saveFrontConsoleLog")
+ {
+ await rep.UpdateNowAsync(resourceLog);
+ }
+ //}
+ //finally
+ //{
+ // Console.SetOut(originalConsoleOut); // 鎭㈠ Console 鍘熷杈撳嚭娴�
+ // consoleWriter.Dispose(); // 閲婃斁娴佽祫婧�
+ //}
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/DefaultResourceHttpProvider.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/DefaultResourceHttpProvider.cs
new file mode 100644
index 0000000..7075931
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/DefaultResourceHttpProvider.cs
@@ -0,0 +1,83 @@
+锘縰sing Furion;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.HttpRemote;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Security.Claims;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 榛樿璧勬簮鎻愪緵鑰�
+ /// </summary>
+ public class DefaultResourceHttpProvider : IResourceHttpProvider
+ {
+ public async Task<string> SendAsStringAsync(HttpRequestBuilder builder)
+ {
+ var httpRemoteService = App.GetRequiredService<IHttpRemoteService>();
+ builder = WithHeader(builder, "Authorization");
+ builder = WithHeader(builder, "X-Authorization");
+ var body = (builder.RawContent as JsonDocument).RootElement.ToString();
+ var response = await httpRemoteService.SendAsStringAsync(builder);
+ try
+ {
+ var result = response.JsonTo(new
+ {
+ Code = 0
+ });
+ if (result.Code == 401)
+ {
+ var accessToken = GetHeaderValue(builder, "Authorization");
+ var logier = await accessToken.GetCurrentLogier();
+ if (logier != null)
+ {
+ var builderNew = HttpRequestBuilder.Create(builder.HttpMethod, builder.RequestUri);
+
+ if (builder.HttpMethod == HttpMethod.Get)
+ builderNew = builderNew.WithQueryParameters(builderNew.QueryParameters);
+ else
+ builderNew = builderNew.SetJsonContent(body);
+
+ builderNew = builderNew.WithHeader("Authorization", $"Bearer {logier.AccessToken}");
+ builderNew = builderNew.WithHeader("X-Authorization", $"Bearer {logier.RefreshToken}");
+ response = await httpRemoteService.SendAsStringAsync(builderNew);
+ }
+ }
+ }
+ catch { }
+ return response;
+ }
+
+ public string GetHeaderValue(HttpRequestBuilder builder, string name)
+ {
+ string value = null;
+ if (builder.Headers?.ContainsKey(name) ?? false)
+ {
+ value = builder.Headers[name].FirstOrDefault();
+ }
+ else if (App.HttpContext.Request.Headers.ContainsKey(name))
+ {
+ value = App.HttpContext.Request.Headers[name].ToString();
+ }
+ return value;
+ }
+
+ private HttpRequestBuilder WithHeader(HttpRequestBuilder builder, string name, string value = null)
+ {
+ value ??= GetHeaderValue(builder, name);
+ if (value.IsNotNull())
+ {
+ builder = builder.WithHeader(name, value, replace: true);
+ }
+ return builder;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/IResourceHttpProvider.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/IResourceHttpProvider.cs
new file mode 100644
index 0000000..ed06b5e
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/IResourceHttpProvider.cs
@@ -0,0 +1,31 @@
+锘縰sing Azure;
+using Azure.Core;
+using Furion;
+using Furion.FriendlyException;
+using Furion.HttpRemote;
+using Furion.Shapeless;
+using Mapster;
+using Microsoft.Extensions.Caching.Distributed;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public interface IResourceHttpProvider
+ {
+ Task<string> SendAsStringAsync(HttpRequestBuilder builder);
+ }
+
+ public enum EnumResourceHttpProvider
+ {
+ Default,
+ SystemUser,
+ ElectronSignServer,
+ ElectronSignServerCustomer
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/SystemUserResourceHttpProvider.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/SystemUserResourceHttpProvider.cs
new file mode 100644
index 0000000..53f6b26
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpProvider/SystemUserResourceHttpProvider.cs
@@ -0,0 +1,89 @@
+锘縰sing Furion;
+using Furion.HttpRemote;
+using Mapster;
+using Microsoft.Extensions.Caching.Distributed;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 绯荤粺绠$悊鍛樿祫婧愭彁渚涜��
+ /// </summary>
+ public class SystemUserResourceHttpProvider : IResourceHttpProvider
+ {
+ public async Task<string> SendAsStringAsync(HttpRequestBuilder builder)
+ {
+ var httpRemoteService = App.GetRequiredService<IHttpRemoteService>();
+ builder = WithToken(httpRemoteService, builder);
+ var response = await httpRemoteService.SendAsStringAsync(builder);
+ try
+ {
+ var result = response.JsonTo(new
+ {
+ Code = 0
+ });
+ if (result.Code == 401)
+ {
+ builder = WithToken(httpRemoteService, builder, true);
+ response = await httpRemoteService.SendAsStringAsync(builder);
+ }
+ }
+ catch { }
+ return response;
+ }
+
+ private HttpRequestBuilder WithToken(IHttpRemoteService httpRemoteService, HttpRequestBuilder builder, bool recache = false)
+ {
+ var cacheKey = "SystemUserToken";
+ var distributedCache = App.GetRequiredService<IDistributedCache>();
+ var token = distributedCache.GetString(cacheKey);
+ if (token == null || recache)
+ {
+ var logier = new CurrentLogier
+ {
+ Id = new Guid("11111111-1111-1111-1111-111111111111"),
+ Name = "绠$悊鍛�",
+ UserName = "system",
+ Level = 999,
+ };
+ JwtUtils.GenerateToken(logier);
+ token = logier.Adapt<TokenDataModel>().ToJson();
+ distributedCache.SetString(cacheKey, token, new DistributedCacheEntryOptions
+ {
+ AbsoluteExpiration = DateTime.Now.AddMinutes(60 * 23)
+ });
+ }
+ if (token.IsNotNull())
+ {
+ var model = token.JsonTo<TokenDataModel>();
+ if (model.AccessToken.IsNotNull())
+ {
+ builder = builder.WithHeader("Authorization", model.AccessToken);
+ }
+
+ if (model.RefreshToken.IsNotNull())
+ {
+ builder = builder.WithHeader("X-Authorization", model.RefreshToken);
+ }
+ }
+ return builder;
+ }
+ }
+ public class TokenDataModel
+ {
+ /// <summary>
+ /// 鐢ㄦ埛璁块棶浠ょ墝
+ /// </summary>
+ public string AccessToken { get; set; }
+
+ /// <summary>
+ /// 鍒锋柊浠ょ墝
+ /// </summary>
+ public string RefreshToken { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceHttpUtils.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpUtils.cs
new file mode 100644
index 0000000..5130324
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceHttpUtils.cs
@@ -0,0 +1,174 @@
+锘縰sing Azure;
+using Consul;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.FriendlyException;
+using Furion.HttpRemote;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Caching.Distributed;
+using Newtonsoft.Json.Linq;
+using RabbitMQ.Client;
+using RTools_NTS.Util;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Design;
+using System.Linq;
+using System.Net.Http;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public static class ResourceHttpUtils
+ {
+ /// <summary>
+ /// 鍙戦�佽姹�
+ /// </summary>
+ /// <param name="request">璇锋眰鍙傛暟</param>
+ /// <param name="serviceName">鏈嶅姟鍚嶇О</param>
+ /// <param name="route">璺敱</param>
+ /// <param name="method">璇锋眰鏂瑰紡</param>
+ /// <param name="provider">璧勬簮鎻愪緵鑰�</param>
+ /// <param name="accessToken">璁块棶浠ょ墝</param>
+ /// <param name="refreshToken">鍒锋柊浠ょ墝</param>
+ /// <returns></returns>
+ public static async Task<string> SendHttpAsync(
+ this object request,
+ string serviceName,
+ string route,
+ EnumResourceMethod method,
+ EnumResourceHttpProvider? provider = null,
+ string accessToken = null,
+ string refreshToken = null)
+ {
+ serviceName = App.GetConfig<string>($"{serviceName}:ServiceName");
+ var url = await GetUrl(serviceName, route);
+ var builder = HttpRequestBuilder.Create(method.GetHttpMethod(), url);
+
+ if (method == EnumResourceMethod.Get)
+ builder = builder.WithQueryParameters(JObject.Parse(request.ToString()));
+ else
+ builder = builder.SetJsonContent(request);
+
+ if (accessToken.IsNotNull())
+ {
+ builder = builder.WithHeader("Authorization", accessToken);
+ }
+ if (refreshToken.IsNotNull())
+ {
+ builder = builder.WithHeader("X-Authorization", refreshToken);
+ }
+
+ IResourceHttpProvider httpProvider =
+ provider == EnumResourceHttpProvider.SystemUser
+ ? new SystemUserResourceHttpProvider()
+ : new DefaultResourceHttpProvider();
+ var response = await httpProvider.SendAsStringAsync(builder);
+ return response;
+ }
+
+ /// <summary>
+ /// 鍙戦�佽姹�
+ /// </summary>
+ /// <typeparam name="TRequest"></typeparam>
+ /// <typeparam name="TResponse"></typeparam>
+ /// <param name="request"></param>
+ /// <param name="provider"></param>
+ /// <returns></returns>
+ public static async Task<TResponse> SendHttpAsync<TRequest, TResponse>(
+ this TRequest request,
+ EnumResourceHttpProvider? provider = null)
+ {
+ var requestType = typeof(TRequest);
+ var resourceAttribute = requestType.GetCustomAttribute<ResourceAttribute>();
+ if (resourceAttribute == null) throw Oops.Oh(EnumErrorCodeType.s400, "缂哄け璧勬簮鐗规��");
+ var controller = resourceAttribute.Controllers.FirstOrDefault();
+ var resourceControllerAttribute = controller.GetCustomAttribute<EnumResourceController, ResourceControllerAttribute>();
+ if (resourceAttribute == null) throw Oops.Oh(EnumErrorCodeType.s400, "缂哄け鎺у埗鍣ㄧ壒鎬�");
+ var serviceName = resourceControllerAttribute.Service.ToString();
+ var route = resourceAttribute.Route;
+ var method = resourceAttribute.Method;
+ var requestXmlDoc = await requestType.GetXmlDocMemberAsync();
+ if (route.IsNull() || method == EnumResourceMethod.None)
+ {
+ var resource = await Db.GetRepository<Resource>().AsQueryable().AsNoTracking()
+ .Where(it =>
+ it.ServiceName == serviceName
+ && it.ControllerName == resourceControllerAttribute.ControllerName
+ && it.Code == requestXmlDoc.Name)
+ .Select(it => new
+ {
+ it.Route,
+ it.Method
+ })
+ .FirstOrDefaultAsync();
+ if (resource == null) throw Oops.Oh(EnumErrorCodeType.s404, "璧勬簮");
+ route = resource.Route;
+ method = resource.Method;
+ }
+ var responseJson = await request.SendHttpAsync(serviceName, route, method, provider);
+ var response = responseJson.JsonTo<TResponse>();
+ return response;
+ }
+
+ /// <summary>
+ /// 鑾峰彇璇锋眰鏂瑰紡
+ /// </summary>
+ /// <param name="method"></param>
+ /// <returns></returns>
+ public static HttpMethod GetHttpMethod(this EnumResourceMethod method)
+ {
+ switch (method)
+ {
+ case EnumResourceMethod.Get:
+ return HttpMethod.Get;
+ case EnumResourceMethod.Post:
+ return HttpMethod.Post;
+ case EnumResourceMethod.Put:
+ return HttpMethod.Put;
+ case EnumResourceMethod.Delete:
+ return HttpMethod.Delete;
+ default:
+ throw Oops.Oh(EnumErrorCodeType.s400, "涓嶆敮鎸佺殑璇锋眰绫诲瀷");
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇鍋ュ悍鏈嶅姟鍦板潃
+ /// </summary>
+ /// <param name="serviceName"></param>
+ /// <param name="route"></param>
+ /// <returns></returns>
+ public static async Task<string> GetUrl(string serviceName, string route)
+ {
+ var domain = await GetHealthyServiceDomain(serviceName);
+ return $"{domain}{route}";
+ }
+
+ /// <summary>
+ /// 鑾峰彇鍋ュ悍鏈嶅姟鍩熷悕
+ /// </summary>
+ /// <param name="serviceName"></param>
+ /// <returns></returns>
+ public static async Task<string> GetHealthyServiceDomain(string serviceName)
+ {
+ var env = App.GetConfig<string>("Environment");
+ serviceName = $"{env}_{serviceName}";
+
+ var queryResult = await App.GetRequiredService<IConsulClient>().Health.Service(serviceName, null, true);
+ if (queryResult.StatusCode != System.Net.HttpStatusCode.OK)
+ throw Oops.Oh(EnumErrorCodeType.s404, $"寰湇鍔serviceName}");
+
+ var domains = queryResult.Response
+ .Select(s => $"http://{s.Service.Address}:{s.Service.Port}")
+ .ToList();
+ if (domains.IsNull())
+ throw Oops.Oh(EnumErrorCodeType.s404, $"寰湇鍔serviceName}");
+ // 杞閫夋嫨瀹炰緥
+ int randomIndex = new Random().Next(domains.Count);
+ return domains[randomIndex];
+ }
+
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceModel.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceModel.cs
new file mode 100644
index 0000000..2ca23d2
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceModel.cs
@@ -0,0 +1,136 @@
+锘縰sing Furion.FriendlyException;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class ResourceModel
+ {
+ /// <summary>
+ /// 璺熻釜Id
+ /// </summary>
+ public string TraceId { get; set; }
+
+ /// <summary>
+ /// 搴旂敤鍚嶇О
+ /// </summary>
+ public string ApplicationName { get; set; }
+
+ /// <summary>
+ /// 鍔ㄦ�佺▼搴忛泦鍚嶇О
+ /// </summary>
+ public string DynamicAssemblyName { get; set; }
+
+ /// <summary>
+ /// 鏈嶅姟鍚嶇О
+ /// </summary>
+ public string ServiceName { get; set; }
+
+ /// <summary>
+ /// 鎺у埗鍣ㄥ悕绉�
+ /// </summary>
+ public string ControllerName { get; set; }
+
+ /// <summary>
+ /// 鎺у埗鍣ㄦ憳瑕�
+ /// </summary>
+ public string ControllerSummary { get; set; }
+
+ /// <summary>
+ /// 濮旀墭鍚嶇О
+ /// </summary>
+ public string ActionName { get; set; }
+
+ /// <summary>
+ /// 濮旀墭鎽樿
+ /// </summary>
+ public string ActionSummary { get; set; }
+
+ /// <summary>
+ /// 缂栧彿
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// 蹇界暐鏉冮檺
+ /// </summary>
+ public bool AllowAnonymous { get; set; }
+
+ /// <summary>
+ /// 璇锋眰鏂瑰紡
+ /// </summary>
+ public EnumResourceMethod Method { get; set; }
+
+ /// <summary>
+ /// 鏂囦欢涓婁紶
+ /// </summary>
+ public bool FileUpload { get; set; }
+
+ /// <summary>
+ /// 鏄惁鏉ヨ嚜琛ㄥ崟
+ /// </summary>
+ public bool IsFromForm { get; set; }
+
+ /// <summary>
+ /// 鑷畾涔夌粨鏋�
+ /// </summary>
+ public bool CustomResponse { get; set; }
+
+ /// <summary>
+ /// 璺敱鍖哄煙
+ /// </summary>
+ public string RouteArea { get; set; }
+
+ /// <summary>
+ /// 璺敱
+ /// </summary>
+ public string Route { get; set; }
+
+ /// <summary>
+ /// 璇锋眰绫诲瀷鍚嶇О
+ /// </summary>
+ public string RequestTypeName { get; set; }
+
+ /// <summary>
+ /// 璇锋眰绫诲瀷鍏ㄥ悕
+ /// </summary>
+ public string RequestTypeFullName { get; set; }
+
+ /// <summary>
+ /// 鍝嶅簲绫诲瀷鍚嶇О
+ /// </summary>
+ public string ResponseTypeName { get; set; }
+
+ /// <summary>
+ /// 鍝嶅簲绫诲瀷鍏ㄥ悕
+ /// </summary>
+ public string ResponseTypeFullName { get; set; }
+
+ public HttpMethod GetHttpMethod()
+ {
+ switch (Method)
+ {
+ case EnumResourceMethod.Get:
+ return HttpMethod.Get;
+ case EnumResourceMethod.Post:
+ return HttpMethod.Post;
+ case EnumResourceMethod.Put:
+ return HttpMethod.Put;
+ case EnumResourceMethod.Delete:
+ return HttpMethod.Delete;
+ default:
+ throw Oops.Oh(EnumErrorCodeType.s400, "涓嶆敮鎸佺殑璇锋眰绫诲瀷");
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceServiceAttribute.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceServiceAttribute.cs
new file mode 100644
index 0000000..fff6d9a
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceServiceAttribute.cs
@@ -0,0 +1,100 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璧勬簮鐗规��
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class)]
+ public class ResourceAttribute : Attribute
+ {
+ public ResourceAttribute(EnumResourceController[] controllers)
+ {
+ Controllers = controllers;
+ }
+
+ /// <summary>
+ /// 璧勬簮鎺у埗鍣�
+ /// </summary>
+ public EnumResourceController[] Controllers { get; }
+
+ /// <summary>
+ /// 蹇界暐鏉冮檺
+ /// </summary>
+ public bool AllowAnonymous { get; set; }
+
+ /// <summary>
+ /// 璇锋眰鏂瑰紡
+ /// </summary>
+ public EnumResourceMethod Method { get; set; }
+
+ /// <summary>
+ /// 璺敱
+ /// </summary>
+ public string Route { get; set; }
+
+ /// <summary>
+ /// 鏂囦欢涓婁紶
+ /// </summary>
+ public bool FileUpload { get; set; }
+
+ /// <summary>
+ /// 鏉ヨ嚜琛ㄥ崟
+ /// </summary>
+ public bool IsFromForm { get; set; }
+
+ /// <summary>
+ /// 鑷畾涔夌粨鏋�
+ /// </summary>
+ public bool CustomResponse { get; set; }
+ }
+
+ /// <summary>
+ /// 璧勬簮鎺у埗鍣ㄧ壒鎬�
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Field)]
+ public class ResourceControllerAttribute : Attribute
+ {
+ public ResourceControllerAttribute(EnumResourceService service, string controllerName)
+ {
+ Service = service;
+ ControllerName = controllerName;
+ }
+
+ /// <summary>
+ /// 鏈嶅姟
+ /// </summary>
+ public EnumResourceService Service { get; set; }
+
+ /// <summary>
+ /// 鎺у埗鍣ㄥ悕绉�
+ /// </summary>
+ public string ControllerName { get; set; }
+ }
+
+ /// <summary>
+ /// 璧勬簮鏈嶅姟鐗规��
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Field)]
+ public class ResourceServiceAttribute : Attribute
+ {
+ /// <summary>
+ /// 搴旂敤鍚嶇О
+ /// </summary>
+ public string ApplicationName { get; set; }
+
+ /// <summary>
+ /// 璺敱鍖哄煙
+ /// </summary>
+ public string RouteArea { get; set; }
+
+ /// <summary>
+ /// 鏈嶅姟鍚嶇О
+ /// </summary>
+ public string ServiceName { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/ResourceUtils/ResourceUtils.cs b/ApiTools.Core/Utils/ResourceUtils/ResourceUtils.cs
new file mode 100644
index 0000000..eedbec0
--- /dev/null
+++ b/ApiTools.Core/Utils/ResourceUtils/ResourceUtils.cs
@@ -0,0 +1,358 @@
+锘縰sing Consul;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.DistributedIDGenerator;
+using Furion.DynamicApiController;
+using Furion.FriendlyException;
+using Furion.HttpRemote;
+using Furion.Logging;
+using Furion.Logging.Extensions;
+using Mapster;
+using MediatR;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ActionConstraints;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Caching.Distributed;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Reflection;
+using System.Resources;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using static System.Collections.Specialized.BitVector32;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璧勬簮宸ュ叿
+ /// </summary>
+ public static class ResourceUtils
+ {
+ /// <summary>
+ /// 鐢熸垚鍔ㄦ�佹帶鍒跺櫒
+ /// </summary>
+ public static async Task BuildDynamicControllersAsync()
+ {
+ var traceId = App.GetTraceId() ?? IDGen.NextID().ToString();
+ var scopeFactory = App.GetService<IServiceScopeFactory>();
+ var serviceScope = scopeFactory.CreateScope();
+ var provider = serviceScope.ServiceProvider.GetRequiredService<IDynamicApiRuntimeChangeProvider>();
+ var rep = serviceScope.ServiceProvider.GetRequiredService<IRepository<Resource>>();
+ var xmlDoc = await XmlDocUtils.GetXmlDocAsync();
+ var enumWebApiMethods = await EnumUtils.GetModel<EnumResourceMethod>();
+ var resourceControllers = await EnumUtils.GetModel<EnumResourceController>();
+ var requests = App.Assemblies
+ .SelectMany(it => it.GetTypes())
+ .Where(it => !it.IsAbstract && typeof(IBaseRequest).IsAssignableFrom(it))
+ .ToList();
+ var models = new List<ResourceModel>();
+ foreach (var request in requests)
+ {
+ var resourceAttribute = request.GetCustomAttribute<ResourceAttribute>();
+ if (resourceAttribute == null) throw Oops.Oh(EnumErrorCodeType.s404, $"璇风粰璧勬簮{request.Name}鍒嗛厤鏈嶅姟鐗规�esource");
+
+ foreach (var controller in resourceAttribute.Controllers)
+ {
+ var requestXmlDoc = await request.GetXmlDocMemberAsync(xmlDoc);
+ var resourceController = controller.GetCustomAttribute<EnumResourceController, ResourceControllerAttribute>();
+ var resourceService = resourceController.Service.GetCustomAttribute<EnumResourceService, ResourceServiceAttribute>();
+
+ var model = new ResourceModel();
+ model.TraceId = traceId;
+ model.ApplicationName = resourceService.ApplicationName;
+ model.ControllerName = resourceController.ControllerName;
+ model.ControllerSummary = resourceControllers.GetDescription(controller);
+ model.ActionName = Regex.Replace(request.Name, @"(Command|Query)$", "", RegexOptions.None);
+ model.ActionSummary = requestXmlDoc?.Summary;
+ model.ServiceName = resourceService.ServiceName;
+ model.RouteArea = resourceService.RouteArea;
+ model.Route = $"/api/{resourceService.RouteArea ?? "main"}/{model.ControllerName}/{model.ActionName}";
+ model.CustomResponse = resourceAttribute.CustomResponse;
+ model.Method =
+ resourceAttribute.Method != EnumResourceMethod.None
+ ? resourceAttribute.Method
+ : request.BaseType?.IsGenericType == true && request.BaseType.GetGenericTypeDefinition() == typeof(PagedListQuery<,>)
+ ? EnumResourceMethod.Post
+ : new List<string> { "Post", "Add", "Create", "Insert", "Submit" }.Any(it => request.Name.StartsWith(it, StringComparison.OrdinalIgnoreCase))
+ ? EnumResourceMethod.Post
+ : new List<string> { "GetAll", "GetList", "Get", "Find", "Fetch", "Query" }.Any(it => request.Name.StartsWith(it, StringComparison.OrdinalIgnoreCase))
+ ? EnumResourceMethod.Get
+ : new List<string> { "Put", "Update ", "Set" }.Any(it => request.Name.StartsWith(it, StringComparison.OrdinalIgnoreCase))
+ ? EnumResourceMethod.Put
+ : new List<string> { "Delete", "Remove ", "Clear" }.Any(it => request.Name.StartsWith(it, StringComparison.OrdinalIgnoreCase))
+ ? EnumResourceMethod.Delete
+ : EnumResourceMethod.Post;
+ model.FileUpload = resourceAttribute.FileUpload;
+ if (model.FileUpload)
+ {
+ model.IsFromForm = true;
+ }
+ else
+ {
+ model.IsFromForm = resourceAttribute.IsFromForm;
+ }
+ model.Code = requestXmlDoc?.Name;
+ model.Name = $"{model.ControllerSummary}-{model.ActionSummary}";
+ model.AllowAnonymous = resourceAttribute.AllowAnonymous;
+ model.RequestTypeName = request.Name;
+ model.RequestTypeFullName = request.FullName;
+ var iRequestType = request.GetInterface("IRequest`1");
+ if (iRequestType != null && iRequestType.IsGenericType)
+ {
+ var responseType = iRequestType.GenericTypeArguments[0];
+ model.ResponseTypeName = responseType.GetCSharpFriendlyName();
+ model.ResponseTypeFullName = responseType.FullName;
+ }
+ models.Add(model);
+
+ await App.GetRequiredService<IDistributedCache>().SetStringAsync($"ResourceModel|{model.RequestTypeFullName}", model.ToJson());
+ }
+ }
+
+ var resources = await SaveResourcesAsync(models, rep);
+
+ DynamicControllersHotPlug(resources, provider);
+
+ await rep.SaveNowAsync();
+ }
+
+ /// <summary>
+ /// 淇濆瓨璧勬簮
+ /// </summary>
+ /// <param name="models"></param>
+ /// <param name="rep"></param>
+ /// <returns></returns>
+ private static async Task<List<Resource>> SaveResourcesAsync(List<ResourceModel> models, IRepository<Resource> rep = null)
+ {
+ rep = rep ?? Db.GetRepository<Resource>();
+ var resources = await rep.AsQueryable()
+ .Where(it => !it.IsExpired)
+ .ToListAsync();
+ foreach (var model in models)
+ {
+ var resource = resources.FirstOrDefault(it => it.Route == model.Route && it.Method == model.Method);
+ if (resource == null)
+ {
+ resource = new Resource();
+ resource.Id = IDGen.NextID();
+ resource.CreatedTime = DateTimeOffset.Now;
+ model.Adapt(resource);
+ await rep.InsertAsync(resource);
+ resources.Add(resource);
+ }
+ else
+ {
+ var resourceBakModel = new ResourceModel();
+ resource.Adapt(resourceBakModel);
+ resourceBakModel.TraceId = model.TraceId;
+ resourceBakModel.DynamicAssemblyName = model.DynamicAssemblyName;
+ if (resourceBakModel.ToJson() != model.ToJson())
+ {
+ model.Adapt(resource);
+ resource.UpdatedTime = DateTimeOffset.Now;
+ await rep.UpdateAsync(resource);
+ }
+ }
+ }
+
+ var expiredResources = resources.Where(it => !models.Any(m => m.Route == it.Route && m.Method == it.Method)).ToList();
+ foreach (var expiredResource in expiredResources)
+ {
+ resources.Remove(expiredResource);
+ await rep.DeleteAsync(expiredResource);
+ }
+
+ return resources.Where(it => !it.IsExpired).ToList();
+ }
+
+ /// <summary>
+ /// 鍔ㄦ�佹帶鍒跺櫒鐑彃
+ /// </summary>
+ /// <param name="resources"></param>
+ /// <param name="provider"></param>
+ public static void DynamicControllersHotPlug(List<Resource> resources, IDynamicApiRuntimeChangeProvider provider = null)
+ {
+ provider = provider ?? App.GetRequiredService<IDynamicApiRuntimeChangeProvider>();
+ var controllers = resources
+ .GroupBy(it => new
+ {
+ it.ApplicationName,
+ it.ControllerName,
+ it.ControllerSummary,
+ it.RouteArea
+ })
+ .Select(it => new
+ {
+ it.Key,
+ Actions = it.ToList()
+ })
+ .ToList();
+ foreach (var controller in controllers)
+ {
+ var code = $@"
+using ApiTools.Core;
+using Furion.DynamicApiController;
+using Furion.FriendlyException;
+using MediatR;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+
+namespace {controller.Key.ApplicationName}.{controller.Key.ControllerName}
+{{
+ /// <summary>
+ /// {controller.Key.ControllerSummary}
+ /// </summary>
+ [Route(""api/{controller.Key.RouteArea}/[controller]"")]
+ public class {controller.Key.ControllerName}AppService(IMediator mediator) : IDynamicApiController
+ {{
+ private readonly IMediator mediator = mediator;";
+
+ foreach (var action in controller.Actions)
+ {
+ var result = action.ResponseTypeName.IsNull() ? "Task" : $"Task<{action.ResponseTypeName}>";
+ code += @$"
+
+ /// <summary>
+ /// {action.ActionSummary}
+ /// </summary>
+ /// <param name=""request""></param>
+ /// <returns></returns>";
+ if (action.AllowAnonymous)
+ {
+ code += $@"
+ [AllowAnonymous]";
+ }
+ if (action.CustomResponse)
+ {
+ code += $@"
+ [CustomResponse]";
+ }
+ code += $@"
+ [Http{action.Method}]";
+ if (action.FileUpload)
+ {
+ code += @"
+ [Consumes(""multipart/form-data"")]";
+ }
+ code += @$"
+ public {result} {action.ActionName}(";
+ if (action.FileUpload || action.IsFromForm)
+ {
+ code += "[FromForm] ";
+ }
+ code += $@"{action.RequestTypeName} request)
+ {{
+ return mediator.Send(request);
+ }}";
+ }
+
+ code += @"
+ }
+}
+";
+ try
+ {
+ var dynamicAssembly = App.CompileCSharpClassCode(code);
+ provider.AddAssembliesWithNotifyChanges(dynamicAssembly);
+ var dynamicAssemblyName = dynamicAssembly.GetName().Name;
+ foreach (var action in controller.Actions)
+ {
+ action.DynamicAssemblyName = dynamicAssemblyName;
+ }
+ }
+ catch (Exception ex)
+ {
+ code.LogError(ex);
+ throw;
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// 鍔ㄦ�佹帶鍒跺櫒鐑嫈
+ /// </summary>
+ /// <param name="resource"></param>
+ /// <param name="provider"></param>
+ public static void DynamicControllerHotPluck(Resource resource, IDynamicApiRuntimeChangeProvider provider = null)
+ {
+ provider = provider ?? App.GetRequiredService<IDynamicApiRuntimeChangeProvider>();
+ provider.RemoveAssembliesWithNotifyChanges(resource.DynamicAssemblyName);
+ }
+
+ /// <summary>
+ /// 鑾峰彇C#鍙嬪ソ鍚嶇О
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ private static string GetCSharpFriendlyName(this Type type)
+ {
+ // 澶勭悊鍙┖绫诲瀷
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
+ {
+ Type underlyingType = Nullable.GetUnderlyingType(type)!;
+ return $"{GetCSharpFriendlyName(underlyingType)}?";
+ }
+
+ // 澶勭悊鍩虹绫诲瀷
+ if (type.FullName.IsNotNull())
+ {
+ var baseTypes = new Dictionary<string, string>
+ {
+ { "System.Byte", "byte" },
+ { "System.SByte", "sbyte" },
+ { "System.Int16", "short" },
+ { "System.UInt16", "ushort" },
+ { "System.Int32", "int" },
+ { "System.UInt32", "uint" },
+ { "System.Int64", "long" },
+ { "System.UInt64", "ulong" },
+ { "System.Single", "float" },
+ { "System.Double", "double" },
+ { "System.Decimal", "decimal" },
+ { "System.Char", "char" },
+ { "System.Boolean", "bool" },
+ { "System.String", "string" },
+ { "System.Object", "object" }
+ };
+ if (baseTypes.TryGetValue(type.FullName, out string? friendlyName) && friendlyName.IsNotNull())
+ {
+ return friendlyName;
+ }
+ }
+
+ // 澶勭悊闈炴硾鍨嬬被鍨�
+ if (!type.IsGenericType)
+ {
+ return type.Name;
+ }
+
+ // 澶勭悊娉涘瀷绫诲瀷
+ string genericTypeName = type.GetGenericTypeDefinition().Name;
+ if (genericTypeName.Contains('`'))
+ genericTypeName = genericTypeName.Substring(0, genericTypeName.IndexOf('`'));
+
+ string[] genericArgs = type.GetGenericArguments()
+ .Select(GetCSharpFriendlyName)
+ .ToArray();
+
+ return $"{genericTypeName}<{string.Join(", ", genericArgs)}>";
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/ScheduleUtils/DbJobPersistence.cs b/ApiTools.Core/Utils/ScheduleUtils/DbJobPersistence.cs
new file mode 100644
index 0000000..b637fb8
--- /dev/null
+++ b/ApiTools.Core/Utils/ScheduleUtils/DbJobPersistence.cs
@@ -0,0 +1,121 @@
+锘縰sing Furion;
+using Furion.DatabaseAccessor;
+using Furion.Schedule;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 浣滀笟鎸佷箙鍖栵紙鏁版嵁搴擄級
+ /// </summary>
+ public class DbJobPersistence : IJobPersistence, IDisposable
+ {
+ private readonly IServiceScope _serviceScope;
+ private readonly IRepository<ScheduleJobDetail> repScheduleJobDetail;
+ private readonly IRepository<ScheduleJobTrigger> repScheduleJobTrigger;
+ private readonly IRepository<ScheduleJobTriggerTimeline, LogDbContextLocator> repScheduleJobTriggerTimeline;
+
+ public DbJobPersistence(IServiceScopeFactory scopeFactory)
+ {
+ _serviceScope = scopeFactory.CreateScope();
+ var services = _serviceScope.ServiceProvider;
+
+ repScheduleJobDetail = services.GetService<IRepository<ScheduleJobDetail>>();
+ repScheduleJobTrigger = services.GetService<IRepository<ScheduleJobTrigger>>();
+ repScheduleJobTriggerTimeline = services.GetService<IRepository<ScheduleJobTriggerTimeline, LogDbContextLocator>>();
+ }
+
+ /// <summary>
+ /// 浣滀笟璋冨害鏈嶅姟鍚姩鏃�
+ /// </summary>
+ /// <returns></returns>
+ public Task<IEnumerable<SchedulerBuilder>> PreloadAsync(CancellationToken stoppingToken)
+ {
+ return Task.FromResult(App.EffectiveTypes.ScanToBuilders().AsEnumerable());
+ }
+
+ public Task<SchedulerBuilder> OnLoadingAsync(SchedulerBuilder builder, CancellationToken stoppingToken)
+ {
+ // 鏍囪浠庡叾浠栧湴鏂规洿鏂帮紝姣斿鏁版嵁搴�
+ return Task.FromResult(builder);
+ }
+
+ public async Task OnChangedAsync(PersistenceContext context)
+ {
+ switch (context.Behavior)
+ {
+ case PersistenceBehavior.Appended:
+ var insertEntity = new ScheduleJobDetail();
+ context.JobDetail.Adapt(insertEntity);
+ await repScheduleJobDetail.InsertNowAsync(insertEntity);
+ break;
+ case PersistenceBehavior.Updated:
+ var updateEntity = await repScheduleJobDetail.AsQueryable().FirstOrDefaultAsync(it => it.JobId == context.JobId);
+ if (updateEntity != null)
+ {
+ context.JobDetail.Adapt(updateEntity);
+ await repScheduleJobDetail.UpdateNowAsync(updateEntity);
+ }
+ break;
+ case PersistenceBehavior.Removed:
+ var deleteEntity = await repScheduleJobDetail.AsQueryable().FirstOrDefaultAsync(it => it.JobId == context.JobId);
+ if (deleteEntity != null)
+ {
+ await repScheduleJobDetail.DeleteNowAsync(deleteEntity);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task OnTriggerChangedAsync(PersistenceTriggerContext context)
+ {
+ switch (context.Behavior)
+ {
+ case PersistenceBehavior.Appended:
+ var insertEntity = new ScheduleJobTrigger();
+ context.Trigger.Adapt(insertEntity);
+ await repScheduleJobTrigger.InsertNowAsync(insertEntity);
+ break;
+ case PersistenceBehavior.Updated:
+ var updateEntity = await repScheduleJobTrigger.AsQueryable().FirstOrDefaultAsync(it => it.JobId == context.JobId && it.TriggerId == context.TriggerId);
+ if (updateEntity != null)
+ {
+ context.Trigger.Adapt(updateEntity);
+ await repScheduleJobTrigger.UpdateNowAsync(updateEntity);
+ }
+ break;
+ case PersistenceBehavior.Removed:
+ var deleteEntity = await repScheduleJobTrigger.AsQueryable().FirstOrDefaultAsync(it => it.JobId == context.JobId && it.TriggerId == context.TriggerId);
+ if (deleteEntity != null)
+ {
+ await repScheduleJobTrigger.DeleteNowAsync(deleteEntity);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public async Task OnExecutionRecordAsync(PersistenceExecutionRecordContext context)
+ {
+ var entity = new ScheduleJobTriggerTimeline();
+ context.Timeline.Adapt(entity);
+ await repScheduleJobTriggerTimeline.InsertNowAsync(entity);
+ }
+
+ public void Dispose()
+ {
+ _serviceScope?.Dispose();
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsOptions.cs b/ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsOptions.cs
new file mode 100644
index 0000000..0380d51
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsOptions.cs
@@ -0,0 +1,37 @@
+锘縰sing Furion.ConfigurableOptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璇氱珛涓氶厤缃�
+ /// </summary>
+ public class ChengLiYeSmsOptions : IConfigurableOptions
+ {
+ public ChengLiYeSmsOptions()
+ {
+ TemplateCodes = [];
+ }
+
+ /// <summary>
+ /// 绛惧悕鍚嶇О
+ /// </summary>
+ public string SignName { get; set; }
+ /// <summary>
+ /// 鐢ㄦ埛鍚�
+ /// </summary>
+ public string UserName { get; set; }
+ /// <summary>
+ /// 瀵嗙爜
+ /// </summary>
+ public string Password { get; set; }
+ /// <summary>
+ /// 妯℃澘浠g爜
+ /// </summary>
+ public Dictionary<string, string> TemplateCodes { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsSubmitRequest.cs b/ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsSubmitRequest.cs
new file mode 100644
index 0000000..3abe179
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/ChengLiYe/ChengLiYeSmsSubmitRequest.cs
@@ -0,0 +1,99 @@
+锘縰sing Aop.Api.Domain;
+using NetTopologySuite.Mathematics;
+using Newtonsoft.Json;
+using pingan.b2bic.Sign.sign;
+using System;
+using System.Collections.Generic;
+using System.DirectoryServices.Protocols;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 璇氱珛涓氬彂閫佺煭淇�
+ /// </summary>
+ public class ChengLiYeSmsSubmitRequest
+ {
+ //isms Integer 鏄惁鍥介檯鐭俊锛堥�夊~锛夛紝涓嶅~鍒欓粯璁や负0銆�
+
+ /// <summary>
+ /// 鐢ㄦ埛鍚嶏紙蹇呭~锛�
+ /// </summary>
+ [JsonProperty("userName")]
+ public string UserName { get; set; }
+ /// <summary>
+ /// 绛惧悕锛堝繀濉級
+ /// MD5(userName+password+mobile+content)
+ /// password涓烘槑鏂囧瘑鐮�
+ /// </summary>
+ [JsonProperty("sign")]
+ public string Sign { get; set; }
+ /// <summary>
+ /// 鎵嬫満鍙枫�傚涓墜鏈哄彿涓虹敤鍗婅閫楀彿鍒嗗紑锛屽13899999999,13688888888(鏈�澶�1涓囦釜锛屽繀濉�)
+ /// </summary>
+ [JsonProperty("mobile")]
+ public string Mobile { get; set; }
+ /// <summary>
+ /// 鍙戦�佸唴瀹癸紙蹇呭~锛夛紝涓嶈秴杩�1000瀛�
+ /// </summary>
+ [JsonProperty("content")]
+ public string Content { get; set; }
+ /// <summary>
+ /// 瀹氭椂鏃堕棿锛屼负绌烘椂琛ㄧず绔嬪嵆鍙戦�侊紙閫夊~锛�
+ /// 鏍煎紡锛歽yyy-MM-dd HH:mm:ss
+ /// 渚嬪锛�2016-09-10 09:00:00
+ /// </summary>
+ [JsonProperty("dstime")]
+ public string Dstime { get; set; }
+ /// <summary>
+ /// 鐢ㄦ埛鑷畾涔夋墿灞曪紙閫夊~锛夈��106鐮佸彿鍚庨潰鎵╁睍鐨勯儴鍒嗐�傞渶瑕佸拰鍚庡彴浜哄憳纭鏉冮檺
+ /// </summary>
+ [JsonProperty("ext")]
+ public string Ext { get; set; }
+ /// <summary>
+ /// 瀹㈡埛鑷畾涔夋秷鎭痠d锛堥�夊~锛夛紝濡傛灉瀹㈡埛涓嶅~鍒欑敱骞冲彴渚х敓鎴愬敮涓�缂栧彿
+ /// 娉細涓嶈甯瀛楃
+ /// </summary>
+ [JsonProperty("seqid")]
+ public string Seqid { get; set; }
+ /// <summary>
+ /// 鏄惁鍥介檯鐭俊锛堥�夊~锛夛紝涓嶅~鍒欓粯璁や负0銆�
+ /// 0-鍥藉唴鐭俊锛堜笉鍖呭惈娓境鍙帮級
+ /// mobile瀛楁涓嶈甯�86鍥藉鍖哄煙璇嗗埆鐮併��
+ /// 1-鍥介檯鐭俊锛堝寘鍚腐婢冲彴锛�
+ /// mobile瀛楁甯︿笂鍥藉鍖哄煙浠g爜銆傚鏋滃�兼槸1锛屼笉瑕佸彂閫佸浗鍐呭彿鐮�
+ /// </summary>
+ [JsonProperty("isms")]
+ public string Isms { get; set; }
+ }
+
+ /// <summary>
+ /// 璇氱珛涓氬彂閫佺煭淇�
+ /// </summary>
+ public class ChengLiYeSmsSubmitResponse
+ {
+ /// <summary>
+ /// 鍥為敊璇唬鐮併��1-琛ㄧず鎴愬姛锛屽叾浠栧弬鑰冮敊璇唬鐮佹弿杩�
+ /// </summary>
+ [JsonProperty("resultCode")]
+ public string ResultCode { get; set; }
+ /// <summary>
+ /// 閿欒浠g爜鎻忚堪
+ /// </summary>
+ [JsonProperty("resultMsg")]
+ public string ResultMsg { get; set; }
+ /// <summary>
+ /// 绯荤粺鐢熸垚鐨勬秷鎭紪鍙�
+ /// </summary>
+ [JsonProperty("msgid")]
+ public string Msgid { get; set; }
+ /// <summary>
+ /// 鐢ㄦ埛鎸囧畾鐨勬祦姘村彿.濡傛灉娌℃湁鎸囧畾锛屽垯涓簃sgid鍊�
+ /// </summary>
+ [JsonProperty("seqid")]
+ public string Seqid { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/Models/CheckVerifyCodeModel.cs b/ApiTools.Core/Utils/SmsUtils/Models/CheckVerifyCodeModel.cs
new file mode 100644
index 0000000..5b71e6a
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/Models/CheckVerifyCodeModel.cs
@@ -0,0 +1,30 @@
+锘縰sing MediatR;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏍¢獙楠岃瘉鐮�
+ /// </summary>
+ public class CheckVerifyCodeModel
+ {
+ /// <summary>
+ /// 鐭俊妯℃澘缂栧彿
+ /// </summary>
+ public EnumSmsTemplateCode TemplateCode { get; set; }
+
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 楠岃瘉鐮�
+ /// </summary>
+ public string VerifyCode { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/Models/SendSmsModel.cs b/ApiTools.Core/Utils/SmsUtils/Models/SendSmsModel.cs
new file mode 100644
index 0000000..329aba8
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/Models/SendSmsModel.cs
@@ -0,0 +1,39 @@
+锘縰sing Furion.DataValidation;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍙戦�佺煭淇�
+ /// </summary>
+ public class SendSmsModel
+ {
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [Required, DataValidation(ValidationTypes.PhoneNumber)]
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 鐭俊妯℃澘缂栧彿
+ /// </summary>
+ public EnumSmsTemplateCode TemplateCode { get; set; }
+
+ /// <summary>
+ /// 鏈夋晥鏈�
+ /// </summary>
+ public DateTime? Expiry { get; set; }
+
+ /// <summary>
+ /// 娓犻亾鎿嶄綔浜�
+ /// </summary>
+ public Guid? ChannelCreatedUserId { get; set; }
+
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/Models/SendVerifyCodeModel.cs b/ApiTools.Core/Utils/SmsUtils/Models/SendVerifyCodeModel.cs
new file mode 100644
index 0000000..335f221
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/Models/SendVerifyCodeModel.cs
@@ -0,0 +1,28 @@
+锘縰sing Furion.DataValidation;
+using MediatR;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍙戦�侀獙璇佺爜
+ /// </summary>
+ public class SendVerifyCodeModel
+ {
+ /// <summary>
+ /// 鎵嬫満鍙风爜
+ /// </summary>
+ [Required, DataValidation(ValidationTypes.PhoneNumber)]
+ public string PhoneNumber { get; set; }
+
+ /// <summary>
+ /// 鐭俊妯℃澘缂栧彿
+ /// </summary>
+ public EnumSmsTemplateCode TemplateCode { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/Models/SmsResponse.cs b/ApiTools.Core/Utils/SmsUtils/Models/SmsResponse.cs
new file mode 100644
index 0000000..375d29e
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/Models/SmsResponse.cs
@@ -0,0 +1,31 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class SmsResponse
+ {
+ /// <summary>
+ /// 鐭俊鐘舵��
+ /// </summary>
+ public EnumSmsStatus Status { get; set; }
+
+ /// <summary>
+ /// 璇锋眰Id
+ /// </summary>
+ public string RequestId { get; set; }
+
+ /// <summary>
+ /// 鍥炰紶浠g爜
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 鍥炰紶娑堟伅
+ /// </summary>
+ public string Message { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/Services/AliyunSmsService.cs b/ApiTools.Core/Utils/SmsUtils/Services/AliyunSmsService.cs
new file mode 100644
index 0000000..790cb2e
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/Services/AliyunSmsService.cs
@@ -0,0 +1,140 @@
+锘縰sing Aop.Api.Domain;
+using Azure;
+using Furion.DatabaseAccessor;
+using Furion.DependencyInjection;
+using Furion.FriendlyException;
+using Furion.HttpRemote;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using static System.Net.WebRequestMethods;
+
+namespace ApiTools.Core
+{
+ public class AliyunSmsService : ISmsService, ITransient
+ {
+ private readonly IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog;
+ private readonly IOptions<AliyunOptions> options;
+ private readonly IHttpRemoteService httpRemoteService;
+
+ public AliyunSmsService(
+ IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog,
+ IOptions<AliyunOptions> options,
+ IHttpRemoteService httpRemoteService)
+ {
+ this.repThreeResourceLog = repThreeResourceLog;
+ this.options = options;
+ this.httpRemoteService = httpRemoteService;
+ }
+
+ /// <summary>
+ /// 鍙戦�佺煭淇�
+ /// </summary>
+ /// <param name="phoneNumber">鎵嬫満鍙风爜</param>
+ /// <param name="templateCode">妯℃澘浠g爜</param>
+ /// <param name="templateParam">妯℃澘鍙傛暟</param>
+ /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+ /// <returns></returns>
+ /// <exception cref="Oops"></exception>
+ public async Task<SmsResponse> SendAsync(string phoneNumber, EnumSmsTemplateCode templateCode, object templateParam, CancellationToken cancellationToken)
+ {
+ AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config
+ {
+ AccessKeyId = options.Value.SMS.AccessKeyId,
+ AccessKeySecret = options.Value.SMS.AccessSecret,
+ Endpoint = "dysmsapi.aliyuncs.com"
+ };
+ var client = new AlibabaCloud.SDK.Dysmsapi20170525.Client(config);
+ AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest
+ {
+ PhoneNumbers = phoneNumber,
+ SignName = options.Value.SMS.SignName,
+ TemplateCode = options.Value.SMS.TemplateCodes[templateCode.ToString()],
+ TemplateParam = templateParam.ToJson()
+ };
+ var log = new ThreeResourceLog
+ {
+ Method = EnumResourceMethod.Get,
+ Domain = "http://dysmsapi.aliyuncs.com",
+ Request = "SendSms",
+ };
+ await repThreeResourceLog.InsertNowAsync(log);
+ var stopwatch = Stopwatch.StartNew();
+ var response = client.SendSmsWithOptions(sendSmsRequest, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
+ log.UpdatedTime = DateTimeOffset.Now;
+ stopwatch.Stop();
+ log.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
+ log.IsSuccess = response.Body.Code == "OK";
+ await repThreeResourceLog.UpdateNowAsync(log);
+
+ var result = new SmsResponse
+ {
+ Status = log.IsSuccess
+ ? EnumSmsStatus.InProcess
+ : EnumSmsStatus.Fail,
+ Code = response.Body.Code,
+ Message = response.Body.Message,
+ RequestId = response.Body.BizId
+ };
+ if (result.Status == EnumSmsStatus.Fail && result.Message.Contains("娴佹帶"))
+ {
+ result.Message = "鎿嶄綔棰戠箒";
+ }
+
+ //var response2 = client.QuerySendDetailsWithOptions(new AlibabaCloud.SDK.Dysmsapi20170525.Models.QuerySendDetailsRequest
+ //{
+ // PhoneNumber = phoneNumber,
+ // BizId = response1.Body.BizId,
+ // SendDate = DateTime.Now.ToString("yyyyMMdd"),
+ // PageSize = 20,
+ // CurrentPage = 1
+ //}, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
+ //Console.WriteLine();
+
+ return result;
+ }
+
+ /// <summary>
+ /// 鎺掗櫎鏁忔劅瀛楃涓�
+ /// </summary>
+ /// <param name="value">鏂囨湰</param>
+ /// <returns>鎺掗櫎鍚庢枃鏈�</returns>
+ private string PercentEncode(string value)
+ {
+ var stringBuilder = new StringBuilder();
+ var text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
+ var bytes = Encoding.GetEncoding("UTF-8").GetBytes(value);
+ foreach (var b in bytes)
+ {
+ var c = (char)b;
+ if (text.IndexOf(c) >= 0)
+ stringBuilder.Append(c);
+ else
+ stringBuilder.Append("%").Append(
+ string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)c));
+ }
+ return stringBuilder.ToString();
+ }
+
+ /// <summary>
+ /// HMAC-SHA1鍔犲瘑
+ /// </summary>
+ /// <param name="content"></param>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ private static string ToHmacsha1(string content, string key)
+ {
+ var hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(key));
+ var bytes = hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(content));
+ return Convert.ToBase64String(bytes);
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/Services/ChengLiYeSmsService.cs b/ApiTools.Core/Utils/SmsUtils/Services/ChengLiYeSmsService.cs
new file mode 100644
index 0000000..cd47bbc
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/Services/ChengLiYeSmsService.cs
@@ -0,0 +1,76 @@
+锘縰sing Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.DependencyInjection;
+using Furion.HttpRemote;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class ChengLiYeSmsService(
+ IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog,
+ IOptions<ChengLiYeSmsOptions> options,
+ IHttpRemoteService httpRemoteService
+ ) : ISmsService, ITransient
+ {
+ private readonly IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog = repThreeResourceLog;
+ private readonly IOptions<ChengLiYeSmsOptions> options = options;
+ private readonly IHttpRemoteService httpRemoteService = httpRemoteService;
+
+ public async Task<SmsResponse> SendAsync(string phoneNumber, EnumSmsTemplateCode templateCode, object templateParam, CancellationToken cancellationToken)
+ {
+ var content = options.Value.TemplateCodes[templateCode.ToString()];
+ if (templateParam != null)
+ {
+ var jObject = JObject.FromObject(templateParam);
+ var props = jObject.Properties();
+ foreach (var prop in props)
+ {
+ content = content.Replace($"${{{prop.Name}}}", prop.Value.ToString());
+ }
+ }
+
+ var body = new ChengLiYeSmsSubmitRequest
+ {
+ UserName = options.Value.UserName,
+ Sign = MD5Encryption.Encrypt($"{options.Value.UserName}{options.Value.Password}{phoneNumber}銆恵options.Value.SignName}銆憑content}"),
+ Mobile = phoneNumber,
+ Content = $"銆恵options.Value.SignName}銆憑content}",
+ };
+ var log = new ThreeResourceLog
+ {
+ Method = EnumResourceMethod.Get,
+ Domain = "https://www.sms-cly.cn",
+ Path = "/v7/msg/submit.json",
+ Request = body.ToJson(),
+ };
+ await repThreeResourceLog.InsertNowAsync(log);
+ var stopwatch = Stopwatch.StartNew();
+ var result = await httpRemoteService.PostAsAsync<ChengLiYeSmsSubmitResponse>($"{log.Domain}{log.Path}",
+ build => build.SetJsonContent(body));
+ log.UpdatedTime = DateTimeOffset.Now;
+ stopwatch.Stop();
+ log.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
+ log.Response = result.ToJson();
+ log.IsSuccess = result.ResultCode == "1";
+ await repThreeResourceLog.UpdateNowAsync(log);
+
+ return new SmsResponse
+ {
+ Status = log.IsSuccess
+ ? EnumSmsStatus.InProcess
+ : EnumSmsStatus.Fail,
+ Code = result.ResultCode,
+ Message = result.ResultMsg,
+ RequestId = result.Msgid
+ };
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/Services/ISmsService.cs b/ApiTools.Core/Utils/SmsUtils/Services/ISmsService.cs
new file mode 100644
index 0000000..b3671bb
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/Services/ISmsService.cs
@@ -0,0 +1,24 @@
+锘縰sing Furion.FriendlyException;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public interface ISmsService
+ {
+ /// <summary>
+ /// 鍙戦�佺煭淇�
+ /// </summary>
+ /// <param name="phoneNumber">鎵嬫満鍙风爜</param>
+ /// <param name="templateCode">妯℃澘浠g爜</param>
+ /// <param name="templateParam">妯℃澘鍙傛暟</param>
+ /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+ /// <returns></returns>
+ /// <exception cref="Oops"></exception>
+ Task<SmsResponse> SendAsync(string phoneNumber, EnumSmsTemplateCode templateCode, object templateParam, CancellationToken cancellationToken);
+ }
+}
diff --git a/ApiTools.Core/Utils/SmsUtils/SmsUtils.cs b/ApiTools.Core/Utils/SmsUtils/SmsUtils.cs
new file mode 100644
index 0000000..9c1aece
--- /dev/null
+++ b/ApiTools.Core/Utils/SmsUtils/SmsUtils.cs
@@ -0,0 +1,305 @@
+锘縰sing Azure.Core;
+using Furion;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.FriendlyException;
+using Furion.HttpRemote;
+using Furion.UnifyResult;
+using Mapster;
+using MediatR;
+using Microsoft.AspNetCore.Routing.Template;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Options;
+using pingan.openbank.api.sdk.enums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鐭俊宸ュ叿
+ /// </summary>
+ public class SmsUtils
+ {
+ private readonly IRepository<SmsLog> rep;
+ private readonly IRepository<SmsSetting> repSmsSetting;
+ private readonly AliyunSmsService aliyunSmsService;
+ private readonly ChengLiYeSmsService chengLiYeSmsService;
+
+ public SmsUtils(
+ IRepository<SmsLog> rep,
+ IRepository<SmsSetting> repSmsSetting,
+ AliyunSmsService aliyunSmsService,
+ ChengLiYeSmsService chengLiYeSmsService)
+ {
+ this.rep = rep;
+ this.repSmsSetting = repSmsSetting;
+ this.aliyunSmsService = aliyunSmsService;
+ this.chengLiYeSmsService = chengLiYeSmsService;
+ }
+
+ /// <summary>
+ /// 鍙戦�佺煭淇�
+ /// </summary>
+ /// <param name="model"></param>
+ /// <param name="templateParam"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<Guid> Send(SendSmsModel model, object templateParam, CancellationToken cancellationToken = default)
+ {
+ var logier = JwtUtils.GetCurrentLogier();
+ var setting = await repSmsSetting.AsQueryable().AsNoTracking()
+ .Include(it => it.Accesses)
+ .Where(it => it.ChannelId == logier.ChannelId)
+ .FirstOrDefaultAsync();
+ if (setting == null) throw Oops.Oh(EnumErrorCodeType.s401, "鐭俊閰嶇疆");
+ await CheckOperationTooFrequent(logier, setting, model);
+ var entity = await Send(setting, null, model, templateParam, cancellationToken);
+ if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "鐭俊閫氶亾");
+ return entity.Id;
+ }
+
+ /// <summary>
+ /// 鍙戦�侀獙璇佺爜鐭俊
+ /// </summary>
+ /// <param name="model"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task<Guid> SendVerifyCode(SendVerifyCodeModel model, CancellationToken cancellationToken = default)
+ {
+ return await Send(new SendSmsModel
+ {
+ PhoneNumber = model.PhoneNumber,
+ TemplateCode = model.TemplateCode,
+ Expiry = DateTime.Now.AddMinutes(5)
+ },
+ new
+ {
+ code = new Random().Next(100000, 999999).ToString()
+ },
+ cancellationToken);
+ }
+
+ /// <summary>
+ /// 鏍¢獙楠岃瘉鐮�
+ /// </summary>
+ /// <param name="model"></param>
+ /// <param name="cancellationToken"></param>
+ /// <returns></returns>
+ public async Task CheckVerifyCode(CheckVerifyCodeModel model, CancellationToken cancellationToken = default)
+ {
+ var logier = JwtUtils.GetCurrentLogier();
+ var templateCode = model.TemplateCode.ToString();
+ var templateParam = new { code = model.VerifyCode }.ToJson();
+ var now = DateTime.Now;
+ var entity = await rep.AsQueryable().AsNoTracking()
+ .Where(it =>
+ it.ChannelId == logier.ChannelId
+ && it.PhoneNumber == model.PhoneNumber
+ && it.TemplateCode == templateCode
+ && it.TemplateParam == templateParam
+ && (it.Expiry == null || it.Expiry > now)
+ && !it.IsUsed
+ && (it.Status == EnumSmsStatus.InProcess || it.Status == EnumSmsStatus.Success))
+ .FirstOrDefaultAsync(cancellationToken);
+ if (entity == null) throw Oops.Oh(EnumErrorCodeType.s400, "楠岃瘉鐮佹棤鏁�");
+ entity.IsUsed = true;
+ await rep.UpdateAsync(entity);
+ }
+
+ /// <summary>
+ /// 鏍¢獙鎿嶄綔棰戠箒
+ /// </summary>
+ /// <param name="logier"></param>
+ /// <param name="setting"></param>
+ /// <param name="model"></param>
+ /// <returns></returns>
+ private async Task CheckOperationTooFrequent(CurrentLogier logier, SmsSetting setting, SendSmsModel model)
+ {
+ var now = DateTimeOffset.Now;
+ var templateCode = model.TemplateCode.ToString();
+ var times = await rep.AsQueryable().AsNoTracking()
+ .Where(it =>
+ it.ChannelId == logier.ChannelId
+ && it.TemplateCode == templateCode
+ && it.PhoneNumber == model.PhoneNumber
+ && it.CreatedTime.Date == now.Date
+ && (it.Status == EnumSmsStatus.InProcess || it.Status == EnumSmsStatus.Success))
+ .Select(it => it.CreatedTime)
+ .ToListAsync();
+ if (times.Count(it => now.AddMinutes(-1) <= it && it <= now) >= setting.MinutelyMaxCount)
+ {
+ UnifyContext.Fill(new
+ {
+ setting.MinutelyMaxCount
+ });
+ throw Oops.Oh(EnumErrorCodeType.s429);
+ }
+ else if (times.Count(it => now.AddHours(-1) <= it && it <= now) >= setting.HourlyMaxCount)
+ {
+ UnifyContext.Fill(new
+ {
+ setting.HourlyMaxCount
+ });
+ throw Oops.Oh(EnumErrorCodeType.s429);
+ }
+ else if (times.Count >= setting.DailyMaxCount)
+ {
+ UnifyContext.Fill(new
+ {
+ setting.DailyMaxCount
+ });
+ throw Oops.Oh(EnumErrorCodeType.s429);
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇鐭俊閫氶亾
+ /// </summary>
+ /// <param name="setting"></param>
+ /// <param name="fromEntity"></param>
+ /// <returns></returns>
+ private EnumSmsAccess? GetSmsAccess(SmsSetting setting, SmsLog fromEntity)
+ {
+ var accesses = setting.Accesses
+ .OrderBy(it => it.Sort)
+ .Where(it => !it.IsDisabled)
+ .ToList();
+ EnumSmsAccess? access = null;
+ if (fromEntity == null)
+ {
+ access = accesses
+ .FirstOrDefault()
+ ?.Access;
+ }
+ else
+ {
+ var sort = accesses
+ .FirstOrDefault(it => it.Access == fromEntity.Access)
+ ?.Sort;
+ if (sort.HasValue)
+ {
+ access = accesses
+ .Where(it => it.Sort > sort)
+ .FirstOrDefault()
+ ?.Access;
+ }
+ }
+ return access;
+ }
+
+ /// <summary>
+ /// 鑾峰彇鐭俊鏈嶅姟
+ /// </summary>
+ /// <param name="access"></param>
+ /// <returns></returns>
+ private ISmsService GetSmsService(EnumSmsAccess access)
+ {
+ ISmsService smsService;
+ switch (access)
+ {
+ case EnumSmsAccess.AliyunSms:
+ smsService = aliyunSmsService;
+ break;
+ case EnumSmsAccess.ChengLiYe:
+ smsService = chengLiYeSmsService;
+ break;
+ default:
+ throw Oops.Oh(EnumErrorCodeType.s510, "涓嶆敮鎸佺殑鐭俊閫氶亾");
+ }
+ return smsService;
+ }
+
+ /// <summary>
+ /// 鍙戦�佺煭淇�
+ /// </summary>
+ /// <param name="setting"></param>
+ /// <param name="fromEntity"></param>
+ /// <param name="model"></param>
+ /// <param name="templateParam">妯℃澘鍙傛暟</param>
+ /// <param name="cancellationToken">鍙栨秷浠ょ墝</param>
+ /// <returns></returns>
+ /// <exception cref="Oops"></exception>
+ public async Task<SmsLog> Send(
+ SmsSetting setting,
+ SmsLog fromEntity,
+ SendSmsModel model,
+ object templateParam,
+ CancellationToken cancellationToken)
+ {
+ if (setting.IsDisabled)
+ {
+ var entity = new SmsLog
+ {
+ ChannelId = setting.ChannelId,
+ ChannelCreatedUserId = model.ChannelCreatedUserId,
+ Access = EnumSmsAccess.None,
+ PhoneNumber = model.PhoneNumber,
+ TemplateCode = model.TemplateCode.ToString(),
+ TemplateParam = templateParam.ToJson(),
+ Expiry = model.Expiry,
+ Status = EnumSmsStatus.Success,
+ };
+ if (setting.WithoutParams)
+ {
+ UnifyContext.Fill(templateParam);
+ }
+ await rep.InsertNowAsync(entity);
+ return entity;
+ }
+ else
+ {
+ var access = GetSmsAccess(setting, fromEntity);
+ if (access.HasValue)
+ {
+ var smsService = GetSmsService(access.Value);
+ var entity = new SmsLog
+ {
+ ChannelId = setting.ChannelId,
+ ChannelCreatedUserId = model.ChannelCreatedUserId,
+ Access = access.Value,
+ PhoneNumber = model.PhoneNumber,
+ TemplateCode = model.TemplateCode.ToString(),
+ TemplateParam = templateParam.ToJson(),
+ Expiry = model.Expiry,
+ Status = EnumSmsStatus.Wait
+ };
+ await rep.InsertNowAsync(entity);
+ var response = await smsService.SendAsync(model.PhoneNumber, model.TemplateCode, templateParam, cancellationToken);
+ if (response != null)
+ {
+ entity.Status = response.Status;
+ entity.Code = response.Code;
+ entity.Message = response.Message;
+ entity.RequestId = response.RequestId;
+ await rep.UpdateNowAsync(entity);
+
+ if (response.Status == EnumSmsStatus.Fail)
+ {
+ var newEntity = await Send(setting, entity, model, templateParam, cancellationToken);
+ if (newEntity == null) return entity;
+
+ if (setting.WithoutParams)
+ {
+ UnifyContext.Fill(templateParam);
+ }
+ return newEntity;
+ }
+ }
+ if (setting.WithoutParams)
+ {
+ UnifyContext.Fill(templateParam);
+ }
+ return entity;
+ }
+ return null;
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/StringUtils/StringUtils.cs b/ApiTools.Core/Utils/StringUtils/StringUtils.cs
new file mode 100644
index 0000000..76fbf93
--- /dev/null
+++ b/ApiTools.Core/Utils/StringUtils/StringUtils.cs
@@ -0,0 +1,170 @@
+锘縰sing Furion.DataValidation;
+using Furion.FriendlyException;
+using Mapster.Utils;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlTypes;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 瀛楃涓插伐鍏�
+ /// </summary>
+ public static class StringUtils
+ {
+ /// <summary>
+ /// 鏍¢獙瀛楃涓蹭负绌�
+ /// </summary>
+ /// <param name="str"></param>
+ /// <returns></returns>
+ public static bool IsNull([NotNullWhen(false)] this string str)
+ {
+ return string.IsNullOrWhiteSpace(str) || str == "undefined";
+ }
+
+ /// <summary>
+ /// 鏍¢獙瀛楁涓嶄负绌�
+ /// </summary>
+ /// <param name="str"></param>
+ /// <returns></returns>
+ public static bool IsNotNull([NotNullWhen(true)] this string str)
+ {
+ return !str.IsNull();
+ }
+
+ public static Guid? ToGuid(this string str, string requiredMessage = null)
+ {
+ if (str.IsNotNull() && Guid.TryParse(str, out var guid) && guid != Guid.Empty) return guid;
+ if (requiredMessage.IsNotNull()) throw Oops.Oh(EnumErrorCodeType.s400, requiredMessage);
+ return null;
+ }
+
+ public static int? ToInt(this string str)
+ {
+ if (str.IsNotNull() && int.TryParse(str, out var @int)) return @int;
+ return null;
+ }
+
+ public static decimal? ToDecimal(this string str)
+ {
+ if (str.IsNotNull() && decimal.TryParse(str, out var @int)) return @int;
+ return null;
+ }
+
+ public static T? ToEnum<T>(this string str, string requiredMessage = null)
+ where T : struct
+ {
+ if (str.IsNotNull() && Enum.TryParse<T>(str, out var @enum)) return @enum;
+ if (requiredMessage.IsNotNull()) throw Oops.Oh(EnumErrorCodeType.s400, requiredMessage);
+ return null;
+ }
+
+ /// <summary>
+ /// 鑾峰彇澶嶆暟鑻辨枃鍚�
+ /// </summary>
+ /// <param name="singularName"></param>
+ /// <returns></returns>
+ public static string GetPluralizedName(this string singularName)
+ {
+ if (singularName.EndsWith("s") || singularName.EndsWith("x") || singularName.EndsWith("z") ||
+ singularName.EndsWith("ch") || singularName.EndsWith("sh"))
+ {
+ return singularName + "es";
+ }
+ else if (singularName.EndsWith("y") && !"aeiou".Contains(singularName[singularName.Length - 2]))
+ {
+ return singularName.Substring(0, singularName.Length - 1) + "ies";
+ }
+ else
+ {
+ return singularName + "s";
+ }
+ }
+
+ public static bool CheckIsIdentityNumber18(this string identity)
+ {
+ return identity.IsNotNull() && identity.TryValidate(EnumValidationTypes.ValidIdentity).IsValid && identity.Length == 18;
+ }
+
+ /// <summary>
+ /// 鑾峰彇鎬у埆
+ /// </summary>
+ /// <param name="identity"></param>
+ /// <returns></returns>
+ public static EnumUserGender? GetGender(this string identity)
+ {
+ if (identity.CheckIsIdentityNumber18())
+ {
+ return identity[16] % 2 == 0
+ ? EnumUserGender.Female
+ : EnumUserGender.Male;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇鐢熸棩
+ /// </summary>
+ /// <param name="identity"></param>
+ /// <returns></returns>
+ public static DateTime? GetBirthday(this string identity)
+ {
+ if (identity.CheckIsIdentityNumber18())
+ {
+ return new DateTime(
+ identity.Substring(6, 4).ToInt()!.Value,
+ identity.Substring(10, 2).ToInt()!.Value,
+ identity.Substring(12, 2).ToInt()!.Value);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇骞撮緞
+ /// </summary>
+ /// <param name="identity"></param>
+ /// <returns></returns>
+ public static int? GetAge(this string identity)
+ {
+ if (identity.CheckIsIdentityNumber18())
+ {
+ var birthday = identity.GetBirthday();
+ return birthday.GetAge();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// 鐢熸垚闅忔満瀛楃涓�
+ /// </summary>
+ /// <param name="length"></param>
+ /// <returns></returns>
+ public static string GenerateRandomString(int length)
+ {
+ if (length <= 0) return null;
+ var random = new Random();
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ var result = new StringBuilder(length);
+ for (int i = 0; i < length; i++)
+ {
+ // 浠庡瓧绗﹂泦涓殢鏈洪�夋嫨涓�涓瓧绗�
+ int index = random.Next(chars.Length);
+ result.Append(chars[index]);
+ }
+ return result.ToString();
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs b/ApiTools.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs
new file mode 100644
index 0000000..eadf522
--- /dev/null
+++ b/ApiTools.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs
@@ -0,0 +1,57 @@
+锘縰sing Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class CustomOperationIdFilter : IOperationFilter
+ {
+ public void Apply(OpenApiOperation operation, OperationFilterContext context)
+ {
+ // 鑾峰彇鎺у埗鍣ㄥ拰鍔ㄤ綔淇℃伅锛團urion 涓�氳繃 ActionDescriptor 鑾峰彇锛�
+ if (context.ApiDescription.ActionDescriptor is not ControllerActionDescriptor actionDescriptor)
+ return;
+
+ var xmlDoc = XmlDocUtils.GetXmlDocAsync().Result;
+
+ // 鑷畾涔� OperationId 瑙勫垯锛氫緥濡傗�滄帶鍒跺櫒鍚峗鍔ㄤ綔鍚嶁��
+ var controllerName = actionDescriptor.ControllerName;
+ var actionName = actionDescriptor.ActionName;
+
+ // 璁剧疆鏈�缁堢殑 OperationId
+ operation.OperationId = $"{actionName}";
+ var paramenters = actionDescriptor.MethodInfo.GetParameters();
+ if (paramenters.IsNotNull())
+ {
+ operation.Summary = actionDescriptor.MethodInfo.GetParameters()[0].ParameterType.GetXmlDocMemberAsync(xmlDoc).Result?.Summary;
+
+ var returnType = context.MethodInfo.ReturnType;
+
+ if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
+ {
+ returnType = returnType.GetGenericArguments()[0];
+ }
+
+ // 姝ラ 3锛氭浛鎹� Swagger 鍝嶅簲绫诲瀷涓� Data 鐨勭被鍨�
+ operation.Responses.Clear();
+ operation.Responses.Add("200", new OpenApiResponse
+ {
+ Description = "鎿嶄綔鎴愬姛",
+ Content = new Dictionary<string, OpenApiMediaType>
+ {
+ ["application/json"] = new OpenApiMediaType
+ {
+ Schema = context.SchemaGenerator.GenerateSchema(returnType, context.SchemaRepository)
+ }
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/SwaggerUtils/EnumSchemaFilter.cs b/ApiTools.Core/Utils/SwaggerUtils/EnumSchemaFilter.cs
new file mode 100644
index 0000000..1c384ab
--- /dev/null
+++ b/ApiTools.Core/Utils/SwaggerUtils/EnumSchemaFilter.cs
@@ -0,0 +1,29 @@
+锘縰sing Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class EnumSchemaFilter : ISchemaFilter
+ {
+ public void Apply(OpenApiSchema schema, SchemaFilterContext context)
+ {
+ if (context.Type.IsEnum && context.Type.FullName.Contains("ApiTools"))
+ {
+ // 鏋氫妇绫诲瀷鐨勬弿杩帮紙鏉ヨ嚜鏋氫妇鏈韩鐨勬敞閲婏級
+ var model = EnumUtils.GetModel(context.Type).Result;
+ var items = model.Items
+ .Select(it => $"{it.Name ?? it.Value.ToString()}-{it.Value}-{it.Description ?? "娌″啓娉ㄩ噴"}")
+ .SplitJoin(",");
+ schema.Description = $"{model.Description ?? "娌″啓娉ㄩ噴"}|{items}";
+ }
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayEcommerceFundBalance.cs b/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayEcommerceFundBalance.cs
new file mode 100644
index 0000000..8f63a45
--- /dev/null
+++ b/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayEcommerceFundBalance.cs
@@ -0,0 +1,69 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓-璇锋眰-鍦板潃鏍忎紶鍙�
+ /// </summary>
+ public class WeChatPayEcommerceFundBalancePathParamters
+ {
+ /// <summary>
+ /// 鐗圭害鍟嗘埛鍙�
+ /// 鏈嶅姟鍟嗙壒绾﹀晢鎴峰彿锛岀敱寰俊鏀粯鐢熸垚骞朵笅鍙�
+ /// </summary>
+ [JsonProperty("sub_mchid")]
+ public string SubMchid { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓-璇锋眰-鏌ヨ浼犲弬
+ /// </summary>
+ public class WeChatPayEcommerceFundBalanceQueryParamters
+ {
+ /// <summary>
+ /// 鐗圭害鍟嗘埛璐︽埛绫诲瀷
+ /// BASIC: 鍩烘湰璐︽埛
+ /// FEES: 鎵嬬画璐硅处鎴�
+ /// OPERATION: 杩愯惀璐︽埛
+ /// </summary>
+ [JsonProperty("account_type")]
+ public string AccountType { get; set; }
+ }
+
+ /// <summary>
+ /// 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓-鍝嶅簲
+ /// </summary>
+ public class WeChatPayEcommerceFundBalanceResponse : WeChatPayResponse
+ {
+ /// <summary>
+ /// 鐗圭害鍟嗘埛鍙�
+ /// 鏈嶅姟鍟嗙壒绾﹀晢鎴峰彿锛岀敱寰俊鏀粯鐢熸垚骞朵笅鍙�
+ /// </summary>
+ [JsonProperty("sub_mchid")]
+ public string SubMchid { get; set; }
+ /// <summary>
+ /// 鍙敤浣欓锛堝崟浣嶏細鍒嗭級
+ /// 鍙敤浣欓锛堝崟浣嶏細鍒嗭級锛屾浣欓鍙仛鎻愮幇鎿嶄綔
+ /// </summary>
+ [JsonProperty("available_amount")]
+ public string available_amount { get; set; }
+ /// <summary>
+ /// 涓嶅彲鐢ㄤ綑棰濓紙鍗曚綅锛氬垎锛�
+ /// </summary>
+ [JsonProperty("pending_amount")]
+ public string pending_amount { get; set; }
+ /// <summary>
+ /// 鐗圭害鍟嗘埛璐︽埛绫诲瀷
+ /// BASIC: 鍩烘湰璐︽埛
+ /// FEES: 鎵嬬画璐硅处鎴�
+ /// OPERATION: 杩愯惀璐︽埛
+ /// </summary>
+ [JsonProperty("account_type")]
+ public string AccountType { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayPartnerTransferBatches.cs b/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayPartnerTransferBatches.cs
new file mode 100644
index 0000000..429cf0f
--- /dev/null
+++ b/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayPartnerTransferBatches.cs
@@ -0,0 +1,171 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 鍙戣捣鎵归噺杞处-璇锋眰-璇锋眰浣撲紶鍙�
+ /// </summary>
+ public class WeChatPayPartnerTransferBatchesBodyParameters
+ {
+ public WeChatPayPartnerTransferBatchesBodyParameters()
+ {
+ TransferDetailList = [];
+ }
+
+ /// <summary>
+ /// 鐗圭害鍟嗘埛鍙�
+ /// </summary>
+ [JsonProperty("sub_mchid")]
+ public string SubMchId { get; set; }
+ /// <summary>
+ /// 鐗圭害鍟嗘埛appid
+ /// 寰俊鍒嗛厤鐨勭壒绾﹀晢鎴峰叕浼楄处鍙稩D锛岀壒绾﹀晢鎴锋巿鏉冪被鍨嬩负INFORMATION_AUTHORIZATION_TYPE鍜孖NFORMATION_AND_FUND_AUTHORIZATION_TYPE鏃� 闇�瑕佸~鍐�
+ /// </summary>
+ [JsonProperty("sub_appid")]
+ public string SubAppId { get; set; }
+ /// <summary>
+ /// 鐗圭害鍟嗘埛鎺堟潈绫诲瀷
+ /// INFORMATION_AUTHORIZATION_TYPE: 琛ㄧず浣跨敤鐗圭害鍟嗘埛鐢ㄦ埛淇℃伅锛屽嚭娆炬柟鏈嶅姟鍟�
+ /// FUND_AUTHORIZATION_TYPE: 琛ㄧず浣跨敤鐗圭害鍟嗘埛鐨勮祫閲戯紝鍑烘鏂逛负鐗圭害鍟嗘埛锛岀敤鎴蜂俊鎭负鏈嶅姟鍟哸ppid瀵瑰簲鐨刼penid
+ /// INFORMATION_AND_FUND_AUTHORIZATION_TYPE: 琛ㄧず浣跨敤鐗圭害鍟嗘埛鐨勭敤鎴蜂俊鎭笖鍑烘鏂逛负鐗圭害鍟嗘埛
+ /// </summary>
+ [JsonProperty("authorization_type")]
+ public string AuthorizationType { get; set; }
+ /// <summary>
+ /// 鍟嗗鎵规鍗曞彿
+ /// 鍟嗘埛绯荤粺鍐呴儴鐨勫晢瀹舵壒娆″崟鍙凤紝鍦ㄥ晢鎴风郴缁熷唴閮ㄥ敮涓�
+ /// </summary>
+ [JsonProperty("out_batch_no")]
+ public string OutBatchNo { get; set; }
+ /// <summary>
+ /// 鎵规鍚嶇О
+ /// 璇ョ瑪鎵归噺杞处鐨勫悕绉�
+ /// </summary>
+ [JsonProperty("batch_name")]
+ public string BatchName { get; set; }
+ /// <summary>
+ /// 鎵规澶囨敞
+ /// 杞处璇存槑锛孶TF8缂栫爜锛屾渶澶氬厑璁�32涓瓧绗�
+ /// </summary>
+ [JsonProperty("batch_remark")]
+ public string BatchRemark { get; set; }
+ /// <summary>
+ /// 杞处鎬婚噾棰�
+ /// 杞处閲戦鍗曚綅涓衡�滃垎鈥濄�傝浆璐︽�婚噾棰濆繀椤讳笌鎵规鍐呮墍鏈夋槑缁嗚浆璐﹂噾棰濅箣鍜屼繚鎸佷竴鑷达紝鍚﹀垯鏃犳硶鍙戣捣杞处鎿嶄綔
+ /// </summary>
+ [JsonProperty("total_amount")]
+ public int TotalAmount { get; set; }
+ /// <summary>
+ /// 杞处鎬荤瑪鏁�
+ /// 涓�涓浆璐︽壒娆″崟鏈�澶氬彂璧蜂竴鍗冪瑪杞处銆傝浆璐︽�荤瑪鏁板繀椤讳笌鎵规鍐呮墍鏈夋槑缁嗕箣鍜屼繚鎸佷竴鑷达紝鍚﹀垯鏃犳硶鍙戣捣杞处鎿嶄綔
+ /// </summary>
+ [JsonProperty("total_num")]
+ public int TotalNum { get; set; }
+ /// <summary>
+ /// 杞处鏄庣粏鍒楄〃
+ /// </summary>
+ [JsonProperty("transfer_detail_list")]
+ public List<WeChatPayPartnerTransferBatchesBodyParametersDetail> TransferDetailList { get; set; }
+ /// <summary>
+ /// 鏈嶅姟鍟嗙殑appid
+ /// 寰俊鍒嗛厤鐨勬湇鍔″晢鍟嗘埛鍏紬璐﹀彿ID锛岀壒绾﹀晢鎴锋巿鏉冪被鍨嬩负FUND_AUTHORIZATION_TYPE鏃� 闇�瑕佸~鍐�
+ /// </summary>
+ [JsonProperty("sp_appid")]
+ public string SpAppId { get; set; }
+ /// <summary>
+ /// 鎵归噺杞处鐢ㄩ��
+ /// GOODSPAYMENT: 缁欑敤鎴锋敮浠樿揣鐗╅噰璐祫閲�
+ /// COMMISSION: 缁欑敤鎴锋敮浠樹笟鍔℃帹骞夸剑閲�
+ /// REFUND: 缁欑敤鎴锋敮浠樹氦鏄撻��娆�
+ /// REIMBURSEMENT: 浼佷笟缁欏憳宸ユ敮浠樺樊鏃呯瓑鎶ラ攢璧勯噾
+ /// FREIGHT: 缁欏徃鏈烘敮浠樿繍杈撹垂鐢�
+ /// OTHERS: 鍏朵粬
+ /// </summary>
+ [JsonProperty("transfer_purpose")]
+ public string TransferPurpose { get; set; }
+ /// <summary>
+ /// 杞处鍦烘櫙
+ /// ORDINARY_TRANSFER: 鏅�氳浆璐︼紙榛樿锛�
+ /// PAYROLL_CARD_TRANSFER: 缁欎娇鐢ㄥ井淇″姟宸ュ崱鐨勭敤鎴疯繘琛岃浆璐�
+ /// </summary>
+ [JsonProperty("transfer_scene")]
+ public string TransferScene { get; set; }
+ }
+
+ /// <summary>
+ /// 鍙戣捣鎵归噺杞处-璇锋眰-璇锋眰浣撲紶鍙�-杞处鏄庣粏
+ /// </summary>
+ public class WeChatPayPartnerTransferBatchesBodyParametersDetail
+ {
+ /// <summary>
+ /// 鍟嗗鏄庣粏鍗曞彿
+ /// 鍟嗘埛绯荤粺鍐呴儴鍖哄垎杞处鎵规鍗曚笅涓嶅悓杞处鏄庣粏鍗曠殑鍞竴鏍囪瘑
+ /// </summary>
+ [JsonProperty("out_detail_no")]
+ public string OutDetailNo { get; set; }
+ /// <summary>
+ /// 杞处閲戦
+ /// 杞处閲戦鍗曚綅涓衡�滃垎鈥�
+ /// </summary>
+ [JsonProperty("transfer_amount")]
+ public int TransferAmount { get; set; }
+ /// <summary>
+ /// 杞处澶囨敞
+ /// 鍗曟潯杞处澶囨敞锛堝井淇$敤鎴蜂細鏀跺埌璇ュ娉級锛孶TF8缂栫爜锛屾渶澶氬厑璁�32涓瓧绗�
+ /// </summary>
+ [JsonProperty("transfer_remark")]
+ public string TransferRemark { get; set; }
+ /// <summary>
+ /// 鏀舵鐢ㄦ埛openid
+ /// 鏀舵鐢ㄦ埛openid銆傚鏋滆浆璐︾壒绾﹀晢鎴锋巿鏉冪被鍨嬫槸INFORMATION_AUTHORIZATION_TYPE锛屽搴旂殑鏄壒绾﹀晢鎴峰叕浼楀彿涓嬬殑openid銆�
+ /// </summary>
+ [JsonProperty("openid")]
+ public string OpenId { get; set; }
+ /// <summary>
+ /// 鏀舵鐢ㄦ埛濮撳悕
+ /// 鏀舵鐢ㄦ埛濮撳悕銆傞噰鐢ㄦ爣鍑哛SA绠楁硶锛屽叕閽ョ敱寰俊渚ф彁渚�
+ /// 鏄庣粏杞处閲戦 >= 2,000鏃讹紝璇ョ瑪鏄庣粏蹇呴』濉啓鏀舵鐢ㄦ埛濮撳悕
+ /// 鍚屼竴鎵规杞处鏄庣粏涓殑濮撳悕瀛楁浼犲叆瑙勫垯闇�淇濇寔涓�鑷达紝涔熷嵆鍏ㄩ儴濉啓銆佹垨鍏ㄩ儴涓嶅~鍐�
+ /// 鑻ュ晢鎴蜂紶鍏ユ敹娆剧敤鎴峰鍚嶏紝寰俊鏀粯浼氭牎楠岀敤鎴穙penID涓庡鍚嶆槸鍚︿竴鑷达紝骞舵彁渚涚數瀛愬洖鍗�
+ /// </summary>
+ [JsonProperty("user_name")]
+ public string UserName { get; set; }
+ /// <summary>
+ /// 鏀舵鐢ㄦ埛韬唤璇�
+ /// 鏀舵鏂硅韩浠借瘉鍙凤紝鍙笉鐢ㄥ~锛堥噰鐢ㄦ爣鍑哛SA绠楁硶锛屽叕閽ョ敱寰俊渚ф彁渚涳級
+ /// 褰撳~鍏ユ敹娆炬柟韬唤璇佸彿鏃讹紝濮撳悕瀛楁蹇呴』濉叆
+ /// </summary>
+ [JsonProperty("user_id_card")]
+ public string UserIdCard { get; set; }
+ }
+
+ /// <summary>
+ /// 鍙戣捣鎵归噺杞处-鍝嶅簲
+ /// </summary>
+ public class PartnerTransferBatchesResponse : WeChatPayResponse
+ {
+ /// <summary>
+ /// 鍟嗗鎵规鍗曞彿
+ /// 鍟嗘埛绯荤粺鍐呴儴鐨勫晢瀹舵壒娆″崟鍙凤紝鍦ㄥ晢鎴风郴缁熷唴閮ㄥ敮涓�
+ /// </summary>
+ [JsonProperty("out_batch_no")]
+ public string out_batch_no { get; set; }
+ /// <summary>
+ /// 寰俊鏀粯鎵规鍗曞彿
+ /// 寰俊鏀粯鎵规鍗曞彿锛屽井淇″晢瀹惰浆璐︾郴缁熻繑鍥炵殑鍞竴鏍囪瘑
+ /// </summary>
+ [JsonProperty("batch_id")]
+ public string batch_id { get; set; }
+ /// <summary>
+ /// 鎵规鍒涘缓鏃堕棿
+ /// 鎵规鍙楃悊鎴愬姛鏃惰繑鍥烇紝鎸夌収浣跨敤rfc3339鎵�瀹氫箟鐨勬牸寮忥紝鏍煎紡涓篩YYY-MM-DDThh:mm:ss+TIMEZONE
+ /// </summary>
+ [JsonProperty("create_time")]
+ public string create_time { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayRequest.cs b/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayRequest.cs
new file mode 100644
index 0000000..a39349c
--- /dev/null
+++ b/ApiTools.Core/Utils/WeChatPayUtils/Models/WeChatPayRequest.cs
@@ -0,0 +1,44 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 寰俊鏀粯璇锋眰
+ /// </summary>
+ public class WeChatPayRequest<TPathParameters, TQueryParameters, TBodyParameters>
+ {
+ /// <summary>
+ /// 鍦板潃鍙傛暟
+ /// </summary>
+ public TPathParameters PathParameters { get; set; }
+
+ /// <summary>
+ /// 鏌ヨ鍙傛暟
+ /// </summary>
+ public TQueryParameters QueryParamters { get; set; }
+
+ /// <summary>
+ /// 璇锋眰浣撳弬鏁�
+ /// </summary>
+ public TBodyParameters BodyParamters { get; set; }
+ }
+
+ public class WeChatPayResponse
+ {
+ /// <summary>
+ /// 閿欒鐮�
+ /// </summary>
+ [JsonProperty("code")]
+ public string Code { get; set; }
+ /// <summary>
+ /// 閿欒娑堟伅
+ /// </summary>
+ [JsonProperty("message")]
+ public string Message { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/WeChatPayUtils/WeChatPayOptions.cs b/ApiTools.Core/Utils/WeChatPayUtils/WeChatPayOptions.cs
new file mode 100644
index 0000000..fd6bbc8
--- /dev/null
+++ b/ApiTools.Core/Utils/WeChatPayUtils/WeChatPayOptions.cs
@@ -0,0 +1,35 @@
+锘縰sing Furion.ConfigurableOptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 寰俊鏀粯閰嶇疆
+ /// </summary>
+ public class WeChatPayOptions : IConfigurableOptions
+ {
+ /// <summary>
+ /// 鍟嗘埛Id
+ /// </summary>
+ public string MchId { get; set; }
+
+ /// <summary>
+ /// 璇佷功搴忓垪鍙�
+ /// </summary>
+ public string SerialNo { get; set; }
+
+ /// <summary>
+ /// 璇佷功鍏挜
+ /// </summary>
+ public string PublicKey { get; set; }
+
+ /// <summary>
+ /// 璇佷功绉侀挜
+ /// </summary>
+ public string PrivateKey { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/WeChatPayUtils/WeChatPayUtils.cs b/ApiTools.Core/Utils/WeChatPayUtils/WeChatPayUtils.cs
new file mode 100644
index 0000000..9699d9f
--- /dev/null
+++ b/ApiTools.Core/Utils/WeChatPayUtils/WeChatPayUtils.cs
@@ -0,0 +1,274 @@
+锘縰sing Baidu.Aip.BodyAnalysis;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using Furion.DependencyInjection;
+using Furion.HttpRemote;
+using Furion.Logging;
+using log4net;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 寰俊鏀粯宸ュ叿
+ /// </summary>
+ public class WeChatPayUtils(
+ IOptions<WeChatPayOptions> options,
+ IHttpRemoteService httpRemoteService,
+ IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog
+ ) : ITransient
+ {
+ private readonly IOptions<WeChatPayOptions> options = options;
+ private readonly IHttpRemoteService httpRemoteService = httpRemoteService;
+ private readonly IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog = repThreeResourceLog;
+
+ public async Task<TResponse> Send<TPathParameters, TQueryParameters, TBodyParameters, TResponse>(
+ EnumResourceMethod method,
+ string path,
+ WeChatPayRequest<TPathParameters, TQueryParameters, TBodyParameters> request,
+ Func<HttpRequestBuilder, HttpRequestBuilder> build = null)
+ where TResponse : WeChatPayResponse, new()
+ {
+ var log = new ThreeResourceLog
+ {
+ Method = method,
+ Domain = "https://api.mch.weixin.qq.com",
+ Path = path,
+ Request = request.ToJson()
+ };
+ if (request.PathParameters != null)
+ {
+ var properties = typeof(TPathParameters).GetProperties();
+ foreach (var property in properties)
+ {
+ var jsonProperty = property.GetCustomAttribute<JsonPropertyAttribute>();
+ var name = jsonProperty != null ? jsonProperty.PropertyName : property.Name;
+ path = path.Replace($"{{{name}}}", property.GetValue(request.PathParameters).ToString());
+ }
+ }
+ if (request.QueryParamters != null)
+ {
+ var properties = typeof(TQueryParameters).GetProperties();
+ var queries = new Dictionary<string, string>();
+ foreach (var property in properties)
+ {
+ var jsonProperty = property.GetCustomAttribute<JsonPropertyAttribute>();
+ var name = jsonProperty != null ? jsonProperty.PropertyName : property.Name;
+ var value = property.GetValue(request.QueryParamters).ToString();
+ if (value.IsNotNull())
+ {
+ value = UrlEncoder.Default.Encode(value);
+ }
+ queries.Add(name, value);
+ }
+ var queriesString = queries.Select(it => $"{it.Key}={it.Value}").SplitJoin("&");
+ path = $"{path}?{queriesString}";
+ }
+
+ var methodString = method.ToString().ToUpper();
+ var builder = HttpRequestBuilder.Create(methodString, $"{log.Domain}{path}");
+
+ var body = "";
+ if (request.BodyParamters != null)
+ {
+ body = request.BodyParamters.ToJson(new JsonSerializerSettings
+ {
+ NullValueHandling = NullValueHandling.Ignore
+ });
+ builder = builder.SetJsonContent(body);
+ builder = builder.WithHeader("Content-Type", "application/json");
+ }
+ var authorization = GetAuthorization(methodString, path, body, options.Value.MchId, options.Value.SerialNo, options.Value.PrivateKey);
+ builder = builder.WithHeader("Authorization", authorization);
+ builder = builder.WithHeader("Accept", "application/json");
+ if (build != null)
+ {
+ builder = build(builder);
+ }
+
+ await repThreeResourceLog.InsertNowAsync(log);
+ var stopwatch = Stopwatch.StartNew();
+ log.Response = await httpRemoteService.SendAsStringAsync(builder);
+ log.UpdatedTime = DateTimeOffset.Now;
+ stopwatch.Stop();
+ log.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
+ var result = log.Response.JsonTo<TResponse>();
+ log.IsSuccess = false;
+ await repThreeResourceLog.UpdateNowAsync(log);
+ return result;
+ }
+
+ /// <summary>
+ /// 鍙戣捣鎵归噺杞处
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<PartnerTransferBatchesResponse> PartnerTransferBatches(WeChatPayRequest<object, object, WeChatPayPartnerTransferBatchesBodyParameters> request)
+ {
+ foreach (var item in request.BodyParamters.TransferDetailList)
+ {
+ item.UserName = item.UserName.IsNotNull() ? Encrypt(options.Value.PublicKey, item.UserName) : null;
+ item.UserIdCard = item.UserIdCard.IsNotNull() ? Encrypt(options.Value.PublicKey, item.UserIdCard) : null;
+ }
+ return await Send<object, object, WeChatPayPartnerTransferBatchesBodyParameters, PartnerTransferBatchesResponse>(
+ EnumResourceMethod.Post,
+ "/v3/partner-transfer/batches",
+ request,
+ it => it.WithHeader("Wechatpay-Serial", options.Value.SerialNo));
+ }
+
+ /// <summary>
+ /// 鏌ヨ鐗圭害鍟嗘埛璐︽埛瀹炴椂浣欓
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public async Task<WeChatPayEcommerceFundBalanceResponse> EcommerceFundBalance(WeChatPayRequest<WeChatPayEcommerceFundBalancePathParamters, WeChatPayEcommerceFundBalanceQueryParamters, object> request)
+ {
+ return await Send<WeChatPayEcommerceFundBalancePathParamters, WeChatPayEcommerceFundBalanceQueryParamters, object, WeChatPayEcommerceFundBalanceResponse>(
+ EnumResourceMethod.Get,
+ "/v3/ecommerce/fund/balance/{sub_mchid}",
+ request,
+ it => it.WithHeader("Wechatpay-Serial", options.Value.SerialNo));
+ }
+
+ /// <summary>
+ /// 鐢熸垚璁よ瘉淇℃伅
+ /// </summary>
+ /// <param name="method"></param>
+ /// <param name="path"></param>
+ /// <param name="body"></param>
+ /// <param name="mchId"></param>
+ /// <param name="serialNo"></param>
+ /// <param name="privateKey"></param>
+ /// <returns></returns>
+ private string GetAuthorization(string method, string path, string body, string mchId, string serialNo, string privateKey)
+ {
+ var timestamp = DateTime.Now.ToTimeStamp(false);
+ var nonce_str = GetHexDumpRandom();
+ var signature = GetSignature(method, path, body, privateKey, timestamp, nonce_str);
+ return $"WECHATPAY2-SHA256-RSA2048 mchid=\"{mchId}\",nonce_str=\"{nonce_str}\",signature=\"{signature}\",timestamp=\"{timestamp}\",serial_no=\"{serialNo}\"";
+ }
+
+ /// <summary>
+ /// 鍔犲瘑鏁忔劅瀛楁
+ /// </summary>
+ /// <param name="publicKey"></param>
+ /// <param name="data"></param>
+ /// <returns></returns>
+ public string Encrypt(string publicKey, string data)
+ {
+ byte[] dataToEncrypt = Encoding.UTF8.GetBytes(data);
+ using (var rsa = new RSACryptoServiceProvider())
+ {
+ rsa.ImportFromPem(publicKey.ToCharArray());
+ byte[] encryptedBytes = rsa.Encrypt(dataToEncrypt, true);
+ return Convert.ToBase64String(encryptedBytes);
+ }
+ }
+
+ /// <summary>
+ /// 瑙e瘑鏁忔劅瀛楁
+ /// </summary>
+ /// <param name="privareKey"></param>
+ /// <param name="encryptedBase64"></param>
+ /// <returns></returns>
+ public string Decrypt(string privareKey, string encryptedBase64)
+ {
+ byte[] encryptedBytes = Convert.FromBase64String(encryptedBase64);
+ using (var rsa = new RSACryptoServiceProvider())
+ {
+ rsa.ImportFromPem(privareKey.ToCharArray());
+ byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, true);
+ return Encoding.UTF8.GetString(decryptedBytes);
+ }
+ }
+
+ /// <summary>
+ /// 鐢熸垚绛惧悕
+ /// </summary>
+ /// <param name="method"></param>
+ /// <param name="path"></param>
+ /// <param name="body"></param>
+ /// <param name="privateKey"></param>
+ /// <param name="timestamp"></param>
+ /// <param name="nonce_str"></param>
+ /// <returns></returns>
+ private string GetSignature(string method, string path, string body, string privateKey, long timestamp, string nonce_str)
+ {
+ string signString = $"{method}\n{path}\n{timestamp}\n{nonce_str}\n{body}\n";
+ using (var rsa = new RSACryptoServiceProvider())
+ {
+ rsa.ImportFromPem(privateKey.ToCharArray());
+
+ // 灏嗗瓧绗︿覆杞崲涓哄瓧鑺傛暟缁勶紙浣跨敤UTF8缂栫爜锛�
+ byte[] dataBytes = Encoding.UTF8.GetBytes(signString);
+
+ // 鎵ц绛惧悕锛歋HA256鍝堝笇绠楁硶锛孭KCS#1 v1.5濉厖妯″紡
+ byte[] signatureBytes = rsa.SignData(
+ dataBytes,
+ HashAlgorithmName.SHA256,
+ RSASignaturePadding.Pkcs1
+ );
+
+ // 灏嗙鍚嶇粨鏋滆浆鎹负Base64瀛楃涓�
+ var base64 = Convert.ToBase64String(signatureBytes);
+ return base64;
+ }
+ }
+
+ /// <summary>
+ /// 鐢熸垚涓�涓姹傞殢鏈轰覆
+ /// </summary>
+ /// <returns></returns>
+ private string GetHexDumpRandom()
+ {
+ // 16瀛楄妭缂撳啿鍖猴紝涓巋exdump -n 16瀵瑰簲
+ byte[] randomBytes = new byte[16];
+
+ // 浣跨敤鍔犲瘑绾ч殢鏈烘暟鐢熸垚鍣紝绫讳技浜�/dev/random
+ using (var rng = RandomNumberGenerator.Create())
+ {
+ rng.GetBytes(randomBytes);
+ }
+
+ // 鏋勫缓杈撳嚭瀛楃涓�
+ StringBuilder sb = new StringBuilder();
+
+ // 4/4 "%08X" 瀵瑰簲锛氬皢16瀛楄妭鍒嗘垚4涓�4瀛楄妭鏁存暟锛屾瘡涓互8浣嶅崄鍏繘鍒舵樉绀�
+ for (int i = 0; i < 4; i++)
+ {
+ // 浠庡瓧鑺傛暟缁勪腑瑙f瀽32浣嶆暣鏁帮紙澶х瀛楄妭搴忥級
+ uint value = BitConverter.ToUInt32(randomBytes, i * 4);
+ // 濡傛灉绯荤粺鏄皬绔瓧鑺傚簭锛岄渶瑕佽浆鎹负澶х
+ if (BitConverter.IsLittleEndian)
+ {
+ value = ReverseBytes(value);
+ }
+ // 鏍煎紡鍖栦负8浣嶅崄鍏繘鍒跺ぇ鍐欏舰寮�
+ sb.AppendFormat("{0:X8}", value);
+ }
+
+ return sb.ToString();
+ }
+
+ // 鍙嶈浆32浣嶆暣鏁扮殑瀛楄妭搴忥紙灏忕杞ぇ绔級
+ private static uint ReverseBytes(uint value)
+ {
+ return (value << 24) | ((value & 0x0000FF00) << 8) |
+ ((value & 0x00FF0000) >> 8) | (value >> 24);
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/WxmpUtils/WxmpGetAccessTokenRequest.cs b/ApiTools.Core/Utils/WxmpUtils/WxmpGetAccessTokenRequest.cs
new file mode 100644
index 0000000..63ebf05
--- /dev/null
+++ b/ApiTools.Core/Utils/WxmpUtils/WxmpGetAccessTokenRequest.cs
@@ -0,0 +1,50 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core.Utils.WxmpUtils
+{
+ /// <summary>
+ /// 寰俊灏忕▼搴忚幏鍙栨帴鍙h皟鐢ㄥ嚟鎹�
+ /// </summary>
+ public class WxmpGetAccessTokenRequest
+ {
+ /// <summary>
+ /// 濉啓 client_credential
+ /// </summary>
+ [JsonProperty("grant_type")]
+ public string GrantType { get; set; } = "client_credential";
+
+ /// <summary>
+ /// 灏忕▼搴忓敮涓�鍑瘉锛屽嵆 AppID锛屽彲鍦ㄣ�屽井淇″叕浼楀钩鍙� - 璁剧疆 - 寮�鍙戣缃�嶉〉涓幏寰椼�傦紙闇�瑕佸凡缁忔垚涓哄紑鍙戣�咃紝涓斿笎鍙锋病鏈夊紓甯哥姸鎬�
+ /// </summary>
+ [JsonProperty("appid")]
+ public string Appid { get; set; }
+
+ /// <summary>
+ /// 灏忕▼搴忓敮涓�鍑瘉瀵嗛挜锛屽嵆 AppSecret锛岃幏鍙栨柟寮忓悓 appid
+ /// </summary>
+ [JsonProperty("secret")]
+ public string Secret { get; set; }
+ }
+
+ /// <summary>
+ /// 寰俊灏忕▼搴忚幏鍙栨帴鍙h皟鐢ㄥ嚟鎹�-缁撴灉
+ /// </summary>
+ public class WxmpGetAccessTokenResponse
+ {
+ /// <summary>
+ /// 鑾峰彇鍒扮殑鍑瘉
+ /// </summary>
+ [JsonProperty("access_token")]
+ public string AccessToken { get; set; }
+ /// <summary>
+ /// 鍑瘉鏈夋晥鏃堕棿锛屽崟浣嶏細绉掋�傜洰鍓嶆槸7200绉掍箣鍐呯殑鍊笺��
+ /// </summary>
+ [JsonProperty("expires_in")]
+ public int ExpiresIn { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs b/ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs
new file mode 100644
index 0000000..2cf4fdd
--- /dev/null
+++ b/ApiTools.Core/Utils/WxmpUtils/WxmpGetQrCodeRequest.cs
@@ -0,0 +1,109 @@
+锘縰sing Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 灏忕▼搴忚幏鍙栦簩缁寸爜
+ /// </summary>
+ public class WxmpGetQrCodeCommand : WxmpGetQrCodeRequest
+ {
+ /// <summary>
+ /// 灏忕▼搴忕紪鍙�
+ /// </summary>
+ public string WxmpCode { get; set; }
+
+ /// <summary>
+ /// 闃块噷浜慜SS鍦烘櫙
+ /// </summary>
+ public string OssScene { get; set; }
+
+ /// <summary>
+ /// 鏂囦欢鍚�
+ /// </summary>
+ public string OssFileName { get; set; }
+ }
+
+ /// <summary>
+ /// 灏忕▼搴忚幏鍙栦簩缁寸爜
+ /// </summary>
+ public class WxmpGetQrCodeRequest
+ {
+ /// <summary>
+ /// 鏈�澶�32涓彲瑙佸瓧绗︼紝鍙敮鎸佹暟瀛楋紝澶у皬鍐欒嫳鏂囦互鍙婇儴鍒嗙壒娈婂瓧绗︼細!#$&'()*+,/:;=?@-._~锛屽叾瀹冨瓧绗﹁鑷缂栫爜涓哄悎娉曞瓧绗︼紙鍥犱笉鏀寔%锛屼腑鏂囨棤娉曚娇鐢� urlencode 澶勭悊锛岃浣跨敤鍏朵粬缂栫爜鏂瑰紡锛�
+ /// </summary>
+ [JsonProperty("scene")]
+ [Required]
+ public string Scene { get; set; }
+
+ /// <summary>
+ /// 榛樿鏄富椤碉紝椤甸潰 page锛屼緥濡� pages/index/index锛屾牴璺緞鍓嶄笉瑕佸~鍔� /锛屼笉鑳芥惡甯﹀弬鏁帮紙鍙傛暟璇锋斁鍦╯cene瀛楁閲岋級锛屽鏋滀笉濉啓杩欎釜瀛楁锛岄粯璁よ烦涓婚〉闈€�俿cancode_time涓虹郴缁熶繚鐣欏弬鏁帮紝涓嶅厑璁搁厤缃�
+ /// </summary>
+ [JsonProperty("page")]
+ public string Page { get; set; }
+
+ /// <summary>
+ /// 榛樿鏄痶rue锛屾鏌age 鏄惁瀛樺湪锛屼负 true 鏃� page 蹇呴』鏄凡缁忓彂甯冪殑灏忕▼搴忓瓨鍦ㄧ殑椤甸潰锛堝惁鍒欐姤閿欙級锛涗负 false 鏃跺厑璁稿皬绋嬪簭鏈彂甯冩垨鑰� page 涓嶅瓨鍦紝 浣唒age 鏈夋暟閲忎笂闄愶紙60000涓級璇峰嬁婊ョ敤銆�
+ /// </summary>
+ [JsonProperty("check_path")]
+ public bool? CheckPath { get; set; }
+
+ /// <summary>
+ /// 瑕佹墦寮�鐨勫皬绋嬪簭鐗堟湰銆傛寮忕増涓� "release"锛屼綋楠岀増涓� "trial"锛屽紑鍙戠増涓� "develop"銆傞粯璁ゆ槸姝e紡鐗堛��
+ /// </summary>
+ [JsonProperty("env_version")]
+ public string EnvVersion { get; set; }
+
+ /// <summary>
+ /// 榛樿430锛屼簩缁寸爜鐨勫搴︼紝鍗曚綅 px锛屾渶灏� 280px锛屾渶澶� 1280px
+ /// </summary>
+ [JsonProperty("width")]
+ public int? Width { get; set; }
+
+ /// <summary>
+ /// 鑷姩閰嶇疆绾挎潯棰滆壊锛屽鏋滈鑹蹭緷鐒舵槸榛戣壊锛屽垯璇存槑涓嶅缓璁厤缃富鑹茶皟锛岄粯璁� false
+ /// </summary>
+ [JsonProperty("auto_color")]
+ public bool? AutoColor { get; set; }
+
+ /// <summary>
+ /// 榛樿鏄瘂"r":0,"g":0,"b":0} 銆俛uto_color 涓� false 鏃剁敓鏁堬紝浣跨敤 rgb 璁剧疆棰滆壊 渚嬪 {"r":"xxx","g":"xxx","b":"xxx"} 鍗佽繘鍒惰〃绀�
+ /// </summary>
+ [JsonProperty("line_color")]
+ public object LineColor { get; set; }
+
+ /// <summary>
+ /// 榛樿鏄痜alse锛屾槸鍚﹂渶瑕侀�忔槑搴曡壊锛屼负 true 鏃讹紝鐢熸垚閫忔槑搴曡壊鐨勫皬绋嬪簭
+ /// </summary>
+ [JsonProperty("is_hyaline")]
+ public bool? IsHyaline { get; set; }
+ }
+
+ /// <summary>
+ /// 灏忕▼搴忚幏鍙栦簩缁寸爜-缁撴灉
+ /// </summary>
+ public class WxmpGetQrCodeResponse
+ {
+ /// <summary>
+ /// 鍥剧墖 Buffer
+ /// </summary>
+ [JsonProperty("buffer")]
+ public byte[] Buffer { get; set; }
+ /// <summary>
+ /// 閿欒鐮�
+ /// </summary>
+ [JsonProperty("errcode")]
+ public int ErrorCode { get; set; }
+ /// <summary>
+ /// 閿欒淇℃伅
+ /// </summary>
+ [JsonProperty("errmsg")]
+ public string ErrorMessage { get; set; }
+
+ }
+}
diff --git a/ApiTools.Core/Utils/WxmpUtils/WxmpOptions.cs b/ApiTools.Core/Utils/WxmpUtils/WxmpOptions.cs
new file mode 100644
index 0000000..ec1a277
--- /dev/null
+++ b/ApiTools.Core/Utils/WxmpUtils/WxmpOptions.cs
@@ -0,0 +1,45 @@
+锘縰sing Furion.ConfigurableOptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 寰俊灏忕▼搴忛厤缃�
+ /// </summary>
+ public class WxmpOptions : IConfigurableOptions
+ {
+ public WxmpOptions()
+ {
+ Items = [];
+ }
+
+ public List<WxmpOptionsItem> Items { get; set; }
+ }
+
+ public class WxmpOptionsItem
+ {
+ /// <summary>
+ /// 缂栧彿
+ /// </summary>
+ public string Code { get; set; }
+
+ /// <summary>
+ /// 灏忕▼搴廔D
+ /// </summary>
+ public string AppId { get; set; }
+
+ /// <summary>
+ /// 灏忕▼搴忓瘑閽�
+ /// </summary>
+ public string AppSecret { get; set; }
+
+ /// <summary>
+ /// 鐗堟湰
+ /// </summary>
+ public string EnvVersion { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/WxmpUtils/WxmpSnsJscode2sessionResponse.cs b/ApiTools.Core/Utils/WxmpUtils/WxmpSnsJscode2sessionResponse.cs
new file mode 100644
index 0000000..f954aed
--- /dev/null
+++ b/ApiTools.Core/Utils/WxmpUtils/WxmpSnsJscode2sessionResponse.cs
@@ -0,0 +1,17 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class WxmpSnsJscode2sessionResponse
+ {
+ public string session_key { get; set; }
+ public string unionid { get; set; }
+ public string errmsg { get; set; }
+ public string openid { get; set; }
+ public int errcode { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/WxmpUtils/WxmpUtils.cs b/ApiTools.Core/Utils/WxmpUtils/WxmpUtils.cs
new file mode 100644
index 0000000..44f09c0
--- /dev/null
+++ b/ApiTools.Core/Utils/WxmpUtils/WxmpUtils.cs
@@ -0,0 +1,128 @@
+锘縰sing Aliyun.OSS;
+using Azure.Core;
+using ApiTools.Core.Utils.WxmpUtils;
+using Furion.FriendlyException;
+using Furion.HttpRemote;
+using Mapster;
+using Microsoft.Extensions.Caching.Distributed;
+using Microsoft.Extensions.Options;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http.Json;
+using System.Text;
+using System.Text.Json.Nodes;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 寰俊灏忕▼搴忓伐鍏�
+ /// </summary>
+ public class WxmpUtils
+ {
+ private readonly IOptions<WxmpOptions> options;
+ private readonly IHttpRemoteService httpRemoteService;
+ private readonly IDistributedCache distributedCache;
+
+ public WxmpUtils(
+ IOptions<WxmpOptions> options,
+ IHttpRemoteService httpRemoteService,
+ IDistributedCache distributedCache)
+ {
+ this.options = options;
+ this.httpRemoteService = httpRemoteService;
+ this.distributedCache = distributedCache;
+ }
+
+ public async Task<WxmpSnsJscode2sessionResponse> SnsJscode2sessionAsync(string wxmpCode, string code, CancellationToken cancellationToken = default)
+ {
+ var option = options.Value.Items.FirstOrDefault(it => it.Code == wxmpCode);
+ if (option == null || option.AppId.IsNull() || option.AppSecret.IsNull())
+ throw Oops.Oh(EnumErrorCodeType.s400, "鐧诲綍澶辫触锛岀己澶遍厤缃細WxmpOptions");
+ if (code.IsNull())
+ throw Oops.Oh(EnumErrorCodeType.s400, "璇峰~鍐橶xmpCode");
+ var callback = await httpRemoteService.GetAsAsync<WxmpSnsJscode2sessionResponse>("https://api.weixin.qq.com/sns/jscode2session",
+ builder => builder.WithQueryParameters(new Dictionary<string, string>
+ {
+ { "appid", option.AppId },
+ { "secret", option.AppSecret },
+ { "js_code", code },
+ { "grant_type", "authorization_code" }
+ }));
+ if (callback == null || callback.errcode != 0)
+ throw Oops.Oh(EnumErrorCodeType.s510, $"鐧诲綍澶辫触锛歿callback.errmsg}锛岃鑱旂郴绠$悊鍛�");
+ return callback;
+ }
+
+ /// <summary>
+ /// 鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹�
+ /// </summary>
+ /// <param name="wxmpCode"></param>
+ /// <returns></returns>
+ public async Task<string> GetAccessToken(string wxmpCode)
+ {
+ var cacheKey = $"Wxmp|{wxmpCode}|AccessToken";
+ var accessToken = await distributedCache.GetStringAsync(cacheKey);
+ if (accessToken.IsNull())
+ {
+ var option = options.Value.Items.FirstOrDefault(it => it.Code == wxmpCode);
+ if (option == null || option.AppId.IsNull() || option.AppSecret.IsNull())
+ throw Oops.Oh(EnumErrorCodeType.s400, "鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹け璐ワ紝缂哄け閰嶇疆锛歐xmpOptions");
+ var request = new WxmpGetAccessTokenRequest
+ {
+ Appid = option.AppId,
+ Secret = option.AppSecret,
+ };
+ var response = await httpRemoteService.GetAsStringAsync("https://api.weixin.qq.com/cgi-bin/token",
+ builder => builder.WithQueryParameters(JsonObject.Parse(request.ToJson())));
+ var callback = response.JsonTo<WxmpGetAccessTokenResponse>();
+ if (callback == null && callback.AccessToken.IsNull())
+ throw Oops.Oh(EnumErrorCodeType.s510, "鑾峰彇灏忕▼搴忔帴鍙h皟鐢ㄥ嚟鎹け璐�");
+ accessToken = callback.AccessToken;
+ await distributedCache.SetStringAsync(cacheKey, accessToken, new DistributedCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(callback.ExpiresIn - 300)
+ });
+ }
+ return accessToken;
+ }
+
+ /// <summary>
+ /// 鑾峰彇灏忕▼搴忕爜
+ /// </summary>
+ /// <param name="command"></param>
+ /// <returns></returns>
+ public async Task<string> GetQrCodeOssUrl(WxmpGetQrCodeCommand command)
+ {
+ var option = options.Value.Items.FirstOrDefault(it => it.Code == command.WxmpCode);
+ if (option == null || option.AppId.IsNull() || option.AppSecret.IsNull())
+ throw Oops.Oh(EnumErrorCodeType.s400, "鑾峰彇灏忕▼搴忕爜澶辫触锛岀己澶遍厤缃細WxmpOptions");
+ command.EnvVersion = option.EnvVersion;
+ var accessToken = await GetAccessToken(command.WxmpCode);
+ var request = command.Adapt<WxmpGetQrCodeRequest>();
+ var jsonContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings
+ {
+ NullValueHandling = NullValueHandling.Ignore
+ });
+ var response = await httpRemoteService.PostAsync("https://api.weixin.qq.com/wxa/getwxacodeunlimit",
+ builder => builder
+ .WithQueryParameter("access_token", accessToken)
+ .SetJsonContent(jsonContent));
+ response.EnsureSuccessStatusCode();
+ if (response.Content.Headers.ContentType.ToString() == "application/json; charset=UTF-8")
+ {
+ var jsonResult = await response.Content.ReadAsStringAsync();
+ var callback = jsonResult.JsonTo<WxmpGetQrCodeResponse>();
+ if (callback == null || callback.ErrorCode != 0)
+ throw Oops.Oh(EnumErrorCodeType.s510, $"鑾峰彇灏忕▼搴忕爜澶辫触锛歿callback.ErrorMessage}锛岃鑱旂郴绠$悊鍛�");
+ }
+ var stream = await response.Content.ReadAsStreamAsync();
+ var result = AliyunOSSUtils.Upload(command.OssScene, stream, command.OssFileName);
+ return result.Url;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/XmlDocUtils/XmlDoc.cs b/ApiTools.Core/Utils/XmlDocUtils/XmlDoc.cs
new file mode 100644
index 0000000..c453ab6
--- /dev/null
+++ b/ApiTools.Core/Utils/XmlDocUtils/XmlDoc.cs
@@ -0,0 +1,52 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 娉ㄩ噴鏂囨。
+ /// </summary>
+ public class XmlDoc
+ {
+ public XmlDoc()
+ {
+ Members = [];
+ }
+
+ /// <summary>
+ /// 鎴愬憳
+ /// </summary>
+ public List<XmlDocMember> Members { get; set; }
+ }
+
+ /// <summary>
+ /// 娉ㄩ噴鏂囨。鎴愬憳
+ /// </summary>
+ public class XmlDocMember
+ {
+ public XmlDocMember()
+ {
+ Parameters = [];
+ }
+
+ /// <summary>
+ /// 鍚嶇О
+ /// </summary>
+ public string Name { get; set; }
+ /// <summary>
+ /// 娉ㄩ噴
+ /// </summary>
+ public string Summary { get; set; }
+ /// <summary>
+ /// 鍙傛暟
+ /// </summary>
+ public List<XmlDocMember> Parameters { get; set; }
+ /// <summary>
+ /// 杩斿洖鍊�
+ /// </summary>
+ public string Returm { get; set; }
+ }
+}
diff --git a/ApiTools.Core/Utils/XmlDocUtils/XmlDocBuildHostedService.cs b/ApiTools.Core/Utils/XmlDocUtils/XmlDocBuildHostedService.cs
new file mode 100644
index 0000000..9e8bd1c
--- /dev/null
+++ b/ApiTools.Core/Utils/XmlDocUtils/XmlDocBuildHostedService.cs
@@ -0,0 +1,23 @@
+锘縰sing Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ApiTools.Core
+{
+ public class XmlDocBuildHostedService : IHostedService
+ {
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ await XmlDocUtils.BuildXmlDocAsync();
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/ApiTools.Core/Utils/XmlDocUtils/XmlDocUtils.cs b/ApiTools.Core/Utils/XmlDocUtils/XmlDocUtils.cs
new file mode 100644
index 0000000..9ed26db
--- /dev/null
+++ b/ApiTools.Core/Utils/XmlDocUtils/XmlDocUtils.cs
@@ -0,0 +1,193 @@
+锘縰sing Furion;
+using Furion.DatabaseAccessor;
+using Furion.DataEncryption;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.Extensions.Caching.Distributed;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace ApiTools.Core
+{
+ /// <summary>
+ /// 娉ㄩ噴鏂囨。宸ュ叿
+ /// </summary>
+ public static class XmlDocUtils
+ {
+ private const string cacheKey = "XmlDoc";
+
+ public static XmlDoc XmlDoc { get; set; }
+
+ /// <summary>
+ /// 鐢熸垚娉ㄩ噴鏂囨。
+ /// </summary>
+ /// <returns></returns>
+ public static async Task<XmlDoc> BuildXmlDocAsync()
+ {
+ var xmlDoc = new XmlDoc();
+ foreach (var item in App.Assemblies)
+ {
+ var path = item.Location.Replace("dll", "xml");
+ if (File.Exists(path))
+ {
+ var document = new XmlDocument();
+ document.Load(path);
+ var memberNodes = document.SelectNodes("//member");
+ if (memberNodes != null)
+ {
+ foreach (XmlNode memberNode in memberNodes)
+ {
+ var memberName = memberNode.Attributes?["name"]?.Value;
+ if (!string.IsNullOrEmpty(memberName))
+ {
+ var member = new XmlDocMember
+ {
+ Name = memberName,
+ Summary = memberNode.SelectSingleNode("summary")?.InnerText?.Trim(),
+ Returm = memberNode.SelectSingleNode("returns")?.InnerText?.Trim()
+ };
+ var paramNodes = memberNode.SelectNodes("param");
+ if (paramNodes != null)
+ {
+ foreach (XmlNode paramNode in paramNodes)
+ {
+ var paramNodeName = paramNode.Attributes?["name"]?.Value;
+ if (!string.IsNullOrEmpty(paramNodeName))
+ {
+ member.Parameters.Add(new XmlDocMember
+ {
+ Name = paramNodeName,
+ Summary = paramNode.InnerText?.Trim()
+ });
+ }
+ }
+ }
+ xmlDoc.Members.Add(member);
+ }
+ }
+ }
+ }
+ }
+
+ XmlDoc = xmlDoc;
+
+ if (xmlDoc.Members.Any())
+ {
+ var json = JsonConvert.SerializeObject(xmlDoc);
+ await App.GetService<IDistributedCache>().SetStringAsync(cacheKey, json);
+ return xmlDoc;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// 鑾峰彇娉ㄩ噴鏂囨。
+ /// </summary>
+ /// <returns></returns>
+ public static async Task<XmlDoc> GetXmlDocAsync()
+ {
+ if (XmlDoc == null)
+ {
+ var json = await App.GetService<IDistributedCache>().GetStringAsync(cacheKey);
+ if (!string.IsNullOrEmpty(json))
+ {
+ XmlDoc = JsonConvert.DeserializeObject<XmlDoc>(json);
+ }
+ if (XmlDoc == null)
+ {
+ XmlDoc = await BuildXmlDocAsync();
+ }
+ }
+ return XmlDoc;
+ }
+
+ /// <summary>
+ /// 鑾峰彇娉ㄩ噴鏂囨。鎴愬憳
+ /// </summary>
+ /// <param name="memberInfo"></param>
+ /// <param name="xmlDoc"></param>
+ /// <returns></returns>
+ public static async Task<XmlDocMember> GetXmlDocMemberAsync(this MemberInfo memberInfo, XmlDoc xmlDoc = null)
+ {
+ if (xmlDoc == null)
+ {
+ xmlDoc = await GetXmlDocAsync();
+ }
+ if (xmlDoc != null && memberInfo != null)
+ {
+ var memberName = GetXmlDocMemberName(memberInfo);
+ return xmlDoc.Members.FirstOrDefault(it => it.Name == memberName);
+ }
+ return null;
+ }
+
+ public static async Task<string> GetSummary(this MemberInfo memberInfo, XmlDoc xmlDoc = null)
+ {
+ var memberXmlDoc = await memberInfo.GetXmlDocMemberAsync(xmlDoc);
+ return memberXmlDoc?.Summary;
+ }
+
+ private static string GetXmlDocMemberName(MemberInfo memberInfo)
+ {
+ if (memberInfo != null)
+ {
+ if (memberInfo is Type type)
+ {
+ return $"T:{GetTypeName(type)}";
+ }
+ else if (memberInfo is MethodInfo methodInfo && methodInfo.DeclaringType != null)
+ {
+ var methodName = $"M:{GetTypeName(methodInfo.DeclaringType)}.{methodInfo.Name}";
+ var parameters = methodInfo.GetParameters();
+ if (parameters.Length > 0)
+ {
+ methodName += $"({string.Join(",", parameters.Select(p => GetTypeName(p.ParameterType)))})";
+ }
+ return methodName;
+ }
+ else if (memberInfo is FieldInfo fieldInfo && fieldInfo.DeclaringType != null)
+ {
+ return $"F:{GetTypeName(fieldInfo.DeclaringType)}.{fieldInfo.Name}";
+ }
+ else if (memberInfo is PropertyInfo propertyInfo && propertyInfo.DeclaringType != null)
+ {
+ return $"P:{GetTypeName(propertyInfo.DeclaringType)}.{propertyInfo.Name}";
+ }
+ }
+ return string.Empty;
+ }
+
+ private static string GetTypeName(Type type)
+ {
+ if (type.IsGenericType)
+ {
+ var genericTypeDefinition = type.GetGenericTypeDefinition();
+ var genericArguments = type.GetGenericArguments();
+ var baseName = genericTypeDefinition.FullName?.Replace('+', '.') ?? "";
+ baseName = baseName.Substring(0, baseName.IndexOf('`'));
+ return $"{baseName}`{genericArguments.Length}";
+ }
+ else if (type.IsArray)
+ {
+ var elementType = type.GetElementType();
+ if (elementType != null)
+ {
+ return $"{GetTypeName(elementType)}[]";
+ }
+ }
+ else if (type.IsNested && type.DeclaringType != null)
+ {
+ return $"{GetTypeName(type.DeclaringType)}+{type.Name}";
+ }
+ return type.FullName?.Replace('+', '.') ?? "";
+ }
+ }
+}
diff --git a/ApiTools.Core/settings.json b/ApiTools.Core/settings.json
new file mode 100644
index 0000000..6b673c3
--- /dev/null
+++ b/ApiTools.Core/settings.json
@@ -0,0 +1,54 @@
+{
+ "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
+ "SpecificationDocumentSettings": {
+ "DocumentTitle": "鐏垫椿鐢ㄥ伐 | 瑙勮寖鍖栨帴鍙�",
+ "GroupOpenApiInfos": [
+ {
+ "Group": "Default",
+ "Title": "瑙勮寖鍖栨帴鍙f紨绀�",
+ "Version": "1.0.0",
+ "Contact": {
+ "Name": "瀛欓箯椋�"
+ }
+ }
+ ],
+ "EnumToNumber": true
+ },
+ "DynamicApiControllerSettings": {
+ "LowercaseRoute": false,
+ "KeepName": true,
+ "AsLowerCamelCase": true,
+ "ModelToQuery": true
+ },
+ "CorsAccessorSettings": {
+ "WithExposedHeaders": [
+ "access-token",
+ "x-access-token",
+ "environment"
+ ]
+ },
+ "AllowedHosts": "*",
+ "FriendlyExceptionSettings": {
+ "HideErrorCode": true,
+ "DefaultErrorCode": "500",
+ "DefaultErrorMessage": "鏈嶅姟鍣ㄥ紓甯革紝璇疯仈绯荤鐞嗗憳"
+ },
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "Microsoft.EntityFrameworkCore": "Information"
+ },
+ "File": {
+ "FileName": "Logs/logs{0:yyyy}{0:MM}{0:dd}.txt",
+ "Append": true,
+ "MinimumLevel": "Information",
+ "FileSizeLimitBytes": 0,
+ "MaxRollingFiles": 7
+ },
+ "Database": {
+ "MinimumLevel": "Information"
+ }
+ },
+ "SupplierPassword": "qwe321"
+}
\ No newline at end of file
diff --git a/ApiTools.Database.Migrations/ApiTools.Database.Migrations.csproj b/ApiTools.Database.Migrations/ApiTools.Database.Migrations.csproj
new file mode 100644
index 0000000..4dfb99c
--- /dev/null
+++ b/ApiTools.Database.Migrations/ApiTools.Database.Migrations.csproj
@@ -0,0 +1,12 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+
+ <PropertyGroup>
+ <TargetFramework>net9.0</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\ApiTools.EntityFramework.Core\ApiTools.EntityFramework.Core.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/ApiTools.Database.Migrations/Migrations/20250930032645_Init.Designer.cs b/ApiTools.Database.Migrations/Migrations/20250930032645_Init.Designer.cs
new file mode 100644
index 0000000..a7d40d4
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/20250930032645_Init.Designer.cs
@@ -0,0 +1,515 @@
+锘�// <auto-generated />
+using System;
+using ApiTools.EntityFramework.Core;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations
+{
+ [DbContext(typeof(DefaultDbContext))]
+ [Migration("20250930032645_Init")]
+ partial class Init
+ {
+ /// <inheritdoc />
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ApiTools.Core.Channel", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.Resource", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ActionName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ActionSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("AllowAnonymous")
+ .HasColumnType("bit");
+
+ b.Property<string>("ApplicationName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Code")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("CustomResponse")
+ .HasColumnType("bit");
+
+ b.Property<string>("DynamicAssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("FileUpload")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsExpired")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsFromForm")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeFullName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeFullName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Route")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RouteArea")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ServiceName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Resource");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobDetail", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("Concurrent")
+ .HasColumnType("bit");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("GroupName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IncludeAnnotations")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("JobType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Properties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobDetail");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobTrigger", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Args")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedTime")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTime?>("LastRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("MaxNumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("MaxNumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("NextRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("NumRetries")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("ResetOnlyOnce")
+ .HasColumnType("bit");
+
+ b.Property<string>("Result")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("RetryTimeout")
+ .HasColumnType("int");
+
+ b.Property<bool>("RunOnStart")
+ .HasColumnType("bit");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<bool>("StartNow")
+ .HasColumnType("bit");
+
+ b.Property<DateTime?>("StartTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("Status")
+ .HasColumnType("bigint");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobTrigger");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTime?>("Expiry")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsUsed")
+ .HasColumnType("bit");
+
+ b.Property<string>("Message")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("PhoneNumber")
+ .IsRequired()
+ .HasMaxLength(11)
+ .HasColumnType("nvarchar(11)");
+
+ b.Property<string>("RequestId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<int>("Status")
+ .HasColumnType("int");
+
+ b.Property<string>("TemplateCode")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<string>("TemplateParam")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("SmsLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("DailyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("HourlyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<int>("MinutelyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("WithoutParams")
+ .HasColumnType("bit");
+
+ b.HasKey("Id");
+
+ b.ToTable("SmsSetting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<Guid>("SettingId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SettingId");
+
+ b.ToTable("SmsSettingAccess");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.HasOne("ApiTools.Core.SmsSetting", "Setting")
+ .WithMany("Accesses")
+ .HasForeignKey("SettingId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Setting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Navigation("Accesses");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/20250930032645_Init.cs b/ApiTools.Database.Migrations/Migrations/20250930032645_Init.cs
new file mode 100644
index 0000000..a70e272
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/20250930032645_Init.cs
@@ -0,0 +1,255 @@
+锘縰sing System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations
+{
+ /// <inheritdoc />
+ public partial class Init : Migration
+ {
+ /// <inheritdoc />
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Channel",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Code = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Channel", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Resource",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ ApplicationName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ DynamicAssemblyName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ServiceName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ControllerName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ControllerSummary = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ActionName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ActionSummary = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Code = table.Column<string>(type: "nvarchar(max)", nullable: false),
+ Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
+ AllowAnonymous = table.Column<bool>(type: "bit", nullable: false),
+ Method = table.Column<int>(type: "int", nullable: false),
+ FileUpload = table.Column<bool>(type: "bit", nullable: false),
+ IsFromForm = table.Column<bool>(type: "bit", nullable: false),
+ CustomResponse = table.Column<bool>(type: "bit", nullable: false),
+ RouteArea = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Route = table.Column<string>(type: "nvarchar(max)", nullable: false),
+ RequestTypeName = table.Column<string>(type: "nvarchar(max)", nullable: false),
+ RequestTypeFullName = table.Column<string>(type: "nvarchar(max)", nullable: false),
+ ResponseTypeName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ResponseTypeFullName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ IsExpired = table.Column<bool>(type: "bit", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Resource", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ScheduleJobDetail",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ JobId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ GroupName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ JobType = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ AssemblyName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Concurrent = table.Column<bool>(type: "bit", nullable: false),
+ IncludeAnnotations = table.Column<bool>(type: "bit", nullable: false),
+ Properties = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ScheduleJobDetail", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ScheduleJobTrigger",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ TriggerId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ JobId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ TriggerType = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ AssemblyName = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Args = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Status = table.Column<long>(type: "bigint", nullable: false),
+ StartTime = table.Column<DateTime>(type: "datetime2", nullable: true),
+ EndTime = table.Column<DateTime>(type: "datetime2", nullable: true),
+ LastRunTime = table.Column<DateTime>(type: "datetime2", nullable: true),
+ NextRunTime = table.Column<DateTime>(type: "datetime2", nullable: true),
+ NumberOfRuns = table.Column<long>(type: "bigint", nullable: false),
+ MaxNumberOfRuns = table.Column<long>(type: "bigint", nullable: false),
+ NumberOfErrors = table.Column<long>(type: "bigint", nullable: false),
+ MaxNumberOfErrors = table.Column<long>(type: "bigint", nullable: false),
+ NumRetries = table.Column<long>(type: "bigint", nullable: false),
+ RetryTimeout = table.Column<int>(type: "int", nullable: false),
+ StartNow = table.Column<bool>(type: "bit", nullable: false),
+ RunOnStart = table.Column<bool>(type: "bit", nullable: false),
+ ResetOnlyOnce = table.Column<bool>(type: "bit", nullable: false),
+ Result = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ElapsedTime = table.Column<long>(type: "bigint", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ScheduleJobTrigger", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "SmsLog",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Access = table.Column<int>(type: "int", nullable: false),
+ PhoneNumber = table.Column<string>(type: "nvarchar(11)", maxLength: 11, nullable: false),
+ TemplateCode = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
+ TemplateParam = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Expiry = table.Column<DateTime>(type: "datetime2", nullable: true),
+ IsUsed = table.Column<bool>(type: "bit", nullable: false),
+ Status = table.Column<int>(type: "int", nullable: false),
+ RequestId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Code = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Message = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_SmsLog", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "SmsSetting",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ IsDisabled = table.Column<bool>(type: "bit", nullable: false),
+ WithoutParams = table.Column<bool>(type: "bit", nullable: false),
+ MinutelyMaxCount = table.Column<int>(type: "int", nullable: false),
+ HourlyMaxCount = table.Column<int>(type: "int", nullable: false),
+ DailyMaxCount = table.Column<int>(type: "int", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_SmsSetting", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "SmsSettingAccess",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ SettingId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Access = table.Column<int>(type: "int", nullable: false),
+ IsDisabled = table.Column<bool>(type: "bit", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_SmsSettingAccess", x => x.Id);
+ table.ForeignKey(
+ name: "FK_SmsSettingAccess_SmsSetting_SettingId",
+ column: x => x.SettingId,
+ principalTable: "SmsSetting",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_SmsSettingAccess_SettingId",
+ table: "SmsSettingAccess",
+ column: "SettingId");
+ }
+
+ /// <inheritdoc />
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Channel");
+
+ migrationBuilder.DropTable(
+ name: "Resource");
+
+ migrationBuilder.DropTable(
+ name: "ScheduleJobDetail");
+
+ migrationBuilder.DropTable(
+ name: "ScheduleJobTrigger");
+
+ migrationBuilder.DropTable(
+ name: "SmsLog");
+
+ migrationBuilder.DropTable(
+ name: "SmsSettingAccess");
+
+ migrationBuilder.DropTable(
+ name: "SmsSetting");
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.Designer.cs b/ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.Designer.cs
new file mode 100644
index 0000000..59c1744
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.Designer.cs
@@ -0,0 +1,656 @@
+锘�// <auto-generated />
+using System;
+using ApiTools.EntityFramework.Core;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations
+{
+ [DbContext(typeof(DefaultDbContext))]
+ [Migration("20250930060650_CreateUser")]
+ partial class CreateUser
+ {
+ /// <inheritdoc />
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ApiTools.Core.Channel", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<string>("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.Resource", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ActionName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ActionSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("AllowAnonymous")
+ .HasColumnType("bit");
+
+ b.Property<string>("ApplicationName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Code")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("CustomResponse")
+ .HasColumnType("bit");
+
+ b.Property<string>("DynamicAssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("FileUpload")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsExpired")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsFromForm")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeFullName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeFullName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Route")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RouteArea")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ServiceName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Resource");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobDetail", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("Concurrent")
+ .HasColumnType("bit");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("GroupName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IncludeAnnotations")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("JobType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Properties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobDetail");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobTrigger", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Args")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedTime")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTime?>("LastRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("MaxNumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("MaxNumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("NextRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("NumRetries")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("ResetOnlyOnce")
+ .HasColumnType("bit");
+
+ b.Property<string>("Result")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("RetryTimeout")
+ .HasColumnType("int");
+
+ b.Property<bool>("RunOnStart")
+ .HasColumnType("bit");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<bool>("StartNow")
+ .HasColumnType("bit");
+
+ b.Property<DateTime?>("StartTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("Status")
+ .HasColumnType("bigint");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobTrigger");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTime?>("Expiry")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsUsed")
+ .HasColumnType("bit");
+
+ b.Property<string>("Message")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("PhoneNumber")
+ .IsRequired()
+ .HasMaxLength(11)
+ .HasColumnType("nvarchar(11)");
+
+ b.Property<string>("RequestId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<int>("Status")
+ .HasColumnType("int");
+
+ b.Property<string>("TemplateCode")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<string>("TemplateParam")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("SmsLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("DailyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("HourlyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<int>("MinutelyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("WithoutParams")
+ .HasColumnType("bit");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("SmsSetting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<Guid>("SettingId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.HasIndex("SettingId");
+
+ b.ToTable("SmsSettingAccess");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.User", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Avatar")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsCheckPhoneNumber")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<int>("Level")
+ .HasColumnType("int");
+
+ b.Property<string>("Name")
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.Property<string>("Password")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("PhoneNumber")
+ .HasMaxLength(11)
+ .HasColumnType("nvarchar(11)");
+
+ b.Property<string>("Remark")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<int>("Status")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Type")
+ .HasColumnType("int");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("UserName")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("User");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("11111111-1111-1111-1111-111111111111"),
+ CreatedTime = new DateTimeOffset(new DateTime(2000, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 8, 0, 0, 0)),
+ IsCheckPhoneNumber = false,
+ IsDeleted = false,
+ Level = 999,
+ Name = "绠$悊鍛�",
+ Password = "iEYggKrMhQ3ASUGLobra1w==:fn/DsMJUbD9FGpvBvR3moMpMPptdxzZlourPVhU479I=",
+ Sort = 0,
+ Status = 10,
+ Type = 100,
+ UserName = "system"
+ });
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsLog", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.HasOne("ApiTools.Core.SmsSetting", "Setting")
+ .WithMany("Accesses")
+ .HasForeignKey("SettingId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Channel");
+
+ b.Navigation("Setting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.User", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Navigation("Accesses");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.cs b/ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.cs
new file mode 100644
index 0000000..8e3e5b3
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/20250930060650_CreateUser.cs
@@ -0,0 +1,168 @@
+锘縰sing System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations
+{
+ /// <inheritdoc />
+ public partial class CreateUser : Migration
+ {
+ /// <inheritdoc />
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn<Guid>(
+ name: "ChannelId",
+ table: "SmsSettingAccess",
+ type: "uniqueidentifier",
+ nullable: true);
+
+ migrationBuilder.AddColumn<Guid>(
+ name: "ChannelId",
+ table: "SmsSetting",
+ type: "uniqueidentifier",
+ nullable: true);
+
+ migrationBuilder.AddColumn<Guid>(
+ name: "ChannelId",
+ table: "SmsLog",
+ type: "uniqueidentifier",
+ nullable: true);
+
+ migrationBuilder.AddColumn<bool>(
+ name: "IsDisabled",
+ table: "Channel",
+ type: "bit",
+ nullable: false,
+ defaultValue: false);
+
+ migrationBuilder.CreateTable(
+ name: "User",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Type = table.Column<int>(type: "int", nullable: false),
+ ChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ Avatar = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Name = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: true),
+ UserName = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
+ PhoneNumber = table.Column<string>(type: "nvarchar(11)", maxLength: 11, nullable: true),
+ IsCheckPhoneNumber = table.Column<bool>(type: "bit", nullable: false),
+ Password = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Level = table.Column<int>(type: "int", nullable: false),
+ Remark = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Status = table.Column<int>(type: "int", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_User", x => x.Id);
+ table.ForeignKey(
+ name: "FK_User_Channel_ChannelId",
+ column: x => x.ChannelId,
+ principalTable: "Channel",
+ principalColumn: "Id");
+ });
+
+ migrationBuilder.InsertData(
+ table: "User",
+ columns: new[] { "Id", "Avatar", "ChannelId", "CreatedChannelId", "CreatedTime", "CreatedUserId", "IsCheckPhoneNumber", "IsDeleted", "Level", "Name", "Password", "PhoneNumber", "Remark", "Sort", "Status", "TraceId", "Type", "UpdatedTime", "UpdatedUserId", "UserName" },
+ values: new object[] { new Guid("11111111-1111-1111-1111-111111111111"), null, null, null, new DateTimeOffset(new DateTime(2000, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 8, 0, 0, 0)), null, false, false, 999, "绠$悊鍛�", "iEYggKrMhQ3ASUGLobra1w==:fn/DsMJUbD9FGpvBvR3moMpMPptdxzZlourPVhU479I=", null, null, 0, 10, null, 100, null, null, "system" });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_SmsSettingAccess_ChannelId",
+ table: "SmsSettingAccess",
+ column: "ChannelId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_SmsSetting_ChannelId",
+ table: "SmsSetting",
+ column: "ChannelId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_SmsLog_ChannelId",
+ table: "SmsLog",
+ column: "ChannelId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_User_ChannelId",
+ table: "User",
+ column: "ChannelId");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_SmsLog_Channel_ChannelId",
+ table: "SmsLog",
+ column: "ChannelId",
+ principalTable: "Channel",
+ principalColumn: "Id");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_SmsSetting_Channel_ChannelId",
+ table: "SmsSetting",
+ column: "ChannelId",
+ principalTable: "Channel",
+ principalColumn: "Id");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_SmsSettingAccess_Channel_ChannelId",
+ table: "SmsSettingAccess",
+ column: "ChannelId",
+ principalTable: "Channel",
+ principalColumn: "Id");
+ }
+
+ /// <inheritdoc />
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropForeignKey(
+ name: "FK_SmsLog_Channel_ChannelId",
+ table: "SmsLog");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_SmsSetting_Channel_ChannelId",
+ table: "SmsSetting");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_SmsSettingAccess_Channel_ChannelId",
+ table: "SmsSettingAccess");
+
+ migrationBuilder.DropTable(
+ name: "User");
+
+ migrationBuilder.DropIndex(
+ name: "IX_SmsSettingAccess_ChannelId",
+ table: "SmsSettingAccess");
+
+ migrationBuilder.DropIndex(
+ name: "IX_SmsSetting_ChannelId",
+ table: "SmsSetting");
+
+ migrationBuilder.DropIndex(
+ name: "IX_SmsLog_ChannelId",
+ table: "SmsLog");
+
+ migrationBuilder.DropColumn(
+ name: "ChannelId",
+ table: "SmsSettingAccess");
+
+ migrationBuilder.DropColumn(
+ name: "ChannelId",
+ table: "SmsSetting");
+
+ migrationBuilder.DropColumn(
+ name: "ChannelId",
+ table: "SmsLog");
+
+ migrationBuilder.DropColumn(
+ name: "IsDisabled",
+ table: "Channel");
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.Designer.cs b/ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.Designer.cs
new file mode 100644
index 0000000..a11a48e
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.Designer.cs
@@ -0,0 +1,659 @@
+锘�// <auto-generated />
+using System;
+using ApiTools.EntityFramework.Core;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations
+{
+ [DbContext(typeof(DefaultDbContext))]
+ [Migration("20250930074028_UpdateSmsLog")]
+ partial class UpdateSmsLog
+ {
+ /// <inheritdoc />
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ApiTools.Core.Channel", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<string>("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.Resource", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ActionName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ActionSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("AllowAnonymous")
+ .HasColumnType("bit");
+
+ b.Property<string>("ApplicationName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Code")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("CustomResponse")
+ .HasColumnType("bit");
+
+ b.Property<string>("DynamicAssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("FileUpload")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsExpired")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsFromForm")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeFullName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeFullName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Route")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RouteArea")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ServiceName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Resource");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobDetail", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("Concurrent")
+ .HasColumnType("bit");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("GroupName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IncludeAnnotations")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("JobType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Properties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobDetail");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobTrigger", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Args")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedTime")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTime?>("LastRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("MaxNumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("MaxNumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("NextRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("NumRetries")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("ResetOnlyOnce")
+ .HasColumnType("bit");
+
+ b.Property<string>("Result")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("RetryTimeout")
+ .HasColumnType("int");
+
+ b.Property<bool>("RunOnStart")
+ .HasColumnType("bit");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<bool>("StartNow")
+ .HasColumnType("bit");
+
+ b.Property<DateTime?>("StartTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("Status")
+ .HasColumnType("bigint");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobTrigger");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("ChannelCreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTime?>("Expiry")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsUsed")
+ .HasColumnType("bit");
+
+ b.Property<string>("Message")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("PhoneNumber")
+ .IsRequired()
+ .HasMaxLength(11)
+ .HasColumnType("nvarchar(11)");
+
+ b.Property<string>("RequestId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<int>("Status")
+ .HasColumnType("int");
+
+ b.Property<string>("TemplateCode")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<string>("TemplateParam")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("SmsLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("DailyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("HourlyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<int>("MinutelyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("WithoutParams")
+ .HasColumnType("bit");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("SmsSetting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<Guid>("SettingId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.HasIndex("SettingId");
+
+ b.ToTable("SmsSettingAccess");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.User", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Avatar")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsCheckPhoneNumber")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<int>("Level")
+ .HasColumnType("int");
+
+ b.Property<string>("Name")
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.Property<string>("Password")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("PhoneNumber")
+ .HasMaxLength(11)
+ .HasColumnType("nvarchar(11)");
+
+ b.Property<string>("Remark")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<int>("Status")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Type")
+ .HasColumnType("int");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("UserName")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("User");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("11111111-1111-1111-1111-111111111111"),
+ CreatedTime = new DateTimeOffset(new DateTime(2000, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 8, 0, 0, 0)),
+ IsCheckPhoneNumber = false,
+ IsDeleted = false,
+ Level = 999,
+ Name = "绠$悊鍛�",
+ Password = "iEYggKrMhQ3ASUGLobra1w==:fn/DsMJUbD9FGpvBvR3moMpMPptdxzZlourPVhU479I=",
+ Sort = 0,
+ Status = 10,
+ Type = 100,
+ UserName = "system"
+ });
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsLog", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.HasOne("ApiTools.Core.SmsSetting", "Setting")
+ .WithMany("Accesses")
+ .HasForeignKey("SettingId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Channel");
+
+ b.Navigation("Setting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.User", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Navigation("Accesses");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.cs b/ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.cs
new file mode 100644
index 0000000..4647b28
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/20250930074028_UpdateSmsLog.cs
@@ -0,0 +1,29 @@
+锘縰sing System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations
+{
+ /// <inheritdoc />
+ public partial class UpdateSmsLog : Migration
+ {
+ /// <inheritdoc />
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn<Guid>(
+ name: "ChannelCreatedUserId",
+ table: "SmsLog",
+ type: "uniqueidentifier",
+ nullable: true);
+ }
+
+ /// <inheritdoc />
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "ChannelCreatedUserId",
+ table: "SmsLog");
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/DefaultDbContextModelSnapshot.cs b/ApiTools.Database.Migrations/Migrations/DefaultDbContextModelSnapshot.cs
new file mode 100644
index 0000000..95c7e64
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/DefaultDbContextModelSnapshot.cs
@@ -0,0 +1,656 @@
+锘�// <auto-generated />
+using System;
+using ApiTools.EntityFramework.Core;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations
+{
+ [DbContext(typeof(DefaultDbContext))]
+ partial class DefaultDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ApiTools.Core.Channel", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<string>("Name")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.Resource", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ActionName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ActionSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("AllowAnonymous")
+ .HasColumnType("bit");
+
+ b.Property<string>("ApplicationName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Code")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ControllerSummary")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("CustomResponse")
+ .HasColumnType("bit");
+
+ b.Property<string>("DynamicAssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("FileUpload")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsExpired")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsFromForm")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeFullName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestTypeName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeFullName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseTypeName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Route")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RouteArea")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ServiceName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("Resource");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobDetail", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("Concurrent")
+ .HasColumnType("bit");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("GroupName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IncludeAnnotations")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("JobType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Properties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobDetail");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobTrigger", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Args")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("AssemblyName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Description")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedTime")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTime?>("LastRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("MaxNumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("MaxNumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<DateTime?>("NextRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("NumRetries")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfErrors")
+ .HasColumnType("bigint");
+
+ b.Property<long>("NumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("ResetOnlyOnce")
+ .HasColumnType("bit");
+
+ b.Property<string>("Result")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("RetryTimeout")
+ .HasColumnType("int");
+
+ b.Property<bool>("RunOnStart")
+ .HasColumnType("bit");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<bool>("StartNow")
+ .HasColumnType("bit");
+
+ b.Property<DateTime?>("StartTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("Status")
+ .HasColumnType("bigint");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobTrigger");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("ChannelCreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTime?>("Expiry")
+ .HasColumnType("datetime2");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsUsed")
+ .HasColumnType("bit");
+
+ b.Property<string>("Message")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("PhoneNumber")
+ .IsRequired()
+ .HasMaxLength(11)
+ .HasColumnType("nvarchar(11)");
+
+ b.Property<string>("RequestId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<int>("Status")
+ .HasColumnType("int");
+
+ b.Property<string>("TemplateCode")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<string>("TemplateParam")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("SmsLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("DailyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("HourlyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<int>("MinutelyMaxCount")
+ .HasColumnType("int");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("WithoutParams")
+ .HasColumnType("bit");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("SmsSetting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDisabled")
+ .HasColumnType("bit");
+
+ b.Property<Guid>("SettingId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.HasIndex("SettingId");
+
+ b.ToTable("SmsSettingAccess");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.User", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Avatar")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("ChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsCheckPhoneNumber")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<int>("Level")
+ .HasColumnType("int");
+
+ b.Property<string>("Name")
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.Property<string>("Password")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("PhoneNumber")
+ .HasMaxLength(11)
+ .HasColumnType("nvarchar(11)");
+
+ b.Property<string>("Remark")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<int>("Status")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Type")
+ .HasColumnType("int");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("UserName")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChannelId");
+
+ b.ToTable("User");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("11111111-1111-1111-1111-111111111111"),
+ CreatedTime = new DateTimeOffset(new DateTime(2000, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 8, 0, 0, 0)),
+ IsCheckPhoneNumber = false,
+ IsDeleted = false,
+ Level = 999,
+ Name = "绠$悊鍛�",
+ Password = "iEYggKrMhQ3ASUGLobra1w==:fn/DsMJUbD9FGpvBvR3moMpMPptdxzZlourPVhU479I=",
+ Sort = 0,
+ Status = 10,
+ Type = 100,
+ UserName = "system"
+ });
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsLog", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSettingAccess", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.HasOne("ApiTools.Core.SmsSetting", "Setting")
+ .WithMany("Accesses")
+ .HasForeignKey("SettingId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Channel");
+
+ b.Navigation("Setting");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.User", b =>
+ {
+ b.HasOne("ApiTools.Core.Channel", "Channel")
+ .WithMany()
+ .HasForeignKey("ChannelId");
+
+ b.Navigation("Channel");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.SmsSetting", b =>
+ {
+ b.Navigation("Accesses");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.Designer.cs b/ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.Designer.cs
new file mode 100644
index 0000000..94d91c5
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.Designer.cs
@@ -0,0 +1,452 @@
+锘�// <auto-generated />
+using System;
+using ApiTools.EntityFramework.Core;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations.LogDb
+{
+ [DbContext(typeof(LogDbContext))]
+ [Migration("20250930032703_Init")]
+ partial class Init
+ {
+ /// <inheritdoc />
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ApiTools.Core.ConsoleLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<string>("ClientIpAddress")
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.Property<string>("Content")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Ext")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<int>("Level")
+ .HasColumnType("int");
+
+ b.Property<string>("Request")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("StackTrace")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Url")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("ConsoleLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.DbAuditLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("NewValues")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("OldValues")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Operate")
+ .HasColumnType("int");
+
+ b.Property<Guid>("PrimaryKey")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TableName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("DbAuditLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.Entities.Common.ResourceLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ClientIpAddress")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ConsoleLogs")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Domain")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedMilliseconds")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsSuccess")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Path")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RefererUrl")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Request")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Response")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ResourceLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ExceptionLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("Message")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("StackTrace")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Type")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ExceptionLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.QueueLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Data")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedMilliseconds")
+ .HasColumnType("bigint");
+
+ b.Property<string>("EventId")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<bool>("IsConsumOnce")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("QueueLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobTriggerTimeline", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<long>("ElapsedTime")
+ .HasColumnType("bigint");
+
+ b.Property<string>("Exception")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTime?>("LastRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<int>("Mode")
+ .HasColumnType("int");
+
+ b.Property<DateTime?>("NextRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("NumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<string>("Result")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<long>("Status")
+ .HasColumnType("bigint");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobTriggerTimeline");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ThreeResourceLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ClientIpAddress")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ConsoleLogs")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Domain")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedMilliseconds")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsSuccess")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Path")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RefererUrl")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Request")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Response")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ThreeResourceLog");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.cs b/ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.cs
new file mode 100644
index 0000000..1d46e71
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/LogDb/20250930032703_Init.cs
@@ -0,0 +1,229 @@
+锘縰sing System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations.LogDb
+{
+ /// <inheritdoc />
+ public partial class Init : Migration
+ {
+ /// <inheritdoc />
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "ConsoleLog",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Access = table.Column<int>(type: "int", nullable: false),
+ Level = table.Column<int>(type: "int", nullable: false),
+ Content = table.Column<string>(type: "nvarchar(max)", nullable: false),
+ StackTrace = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Url = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Request = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Ext = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ClientIpAddress = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: true),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ConsoleLog", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "DbAuditLog",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ TableName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
+ PrimaryKey = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Operate = table.Column<int>(type: "int", nullable: false),
+ OldValues = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ NewValues = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_DbAuditLog", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ExceptionLog",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Type = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
+ Code = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: true),
+ Message = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ StackTrace = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ExceptionLog", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "QueueLog",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Access = table.Column<int>(type: "int", nullable: false),
+ EventId = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
+ Data = table.Column<string>(type: "nvarchar(max)", nullable: false),
+ IsConsumOnce = table.Column<bool>(type: "bit", nullable: false),
+ ElapsedMilliseconds = table.Column<long>(type: "bigint", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_QueueLog", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ResourceLog",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Method = table.Column<int>(type: "int", nullable: false),
+ Domain = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Path = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ RequestHeaders = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Request = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ResponseHeaders = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Response = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ IsSuccess = table.Column<bool>(type: "bit", nullable: false),
+ ClientIpAddress = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ RefererUrl = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ConsoleLogs = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ElapsedMilliseconds = table.Column<long>(type: "bigint", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ResourceLog", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ScheduleJobTriggerTimeline",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ JobId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ TriggerId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ NumberOfRuns = table.Column<long>(type: "bigint", nullable: false),
+ LastRunTime = table.Column<DateTime>(type: "datetime2", nullable: true),
+ NextRunTime = table.Column<DateTime>(type: "datetime2", nullable: true),
+ Status = table.Column<long>(type: "bigint", nullable: false),
+ Result = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ElapsedTime = table.Column<long>(type: "bigint", nullable: false),
+ Mode = table.Column<int>(type: "int", nullable: false),
+ Exception = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ScheduleJobTriggerTimeline", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ThreeResourceLog",
+ columns: table => new
+ {
+ Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+ Method = table.Column<int>(type: "int", nullable: false),
+ Domain = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Path = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ RequestHeaders = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Request = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ResponseHeaders = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ Response = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ IsSuccess = table.Column<bool>(type: "bit", nullable: false),
+ ClientIpAddress = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ RefererUrl = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ConsoleLogs = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ ElapsedMilliseconds = table.Column<long>(type: "bigint", nullable: false),
+ Sort = table.Column<int>(type: "int", nullable: false),
+ TraceId = table.Column<string>(type: "nvarchar(max)", nullable: true),
+ CreatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
+ CreatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ CreatedChannelId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ UpdatedTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
+ UpdatedUserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
+ IsDeleted = table.Column<bool>(type: "bit", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ThreeResourceLog", x => x.Id);
+ });
+ }
+
+ /// <inheritdoc />
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "ConsoleLog");
+
+ migrationBuilder.DropTable(
+ name: "DbAuditLog");
+
+ migrationBuilder.DropTable(
+ name: "ExceptionLog");
+
+ migrationBuilder.DropTable(
+ name: "QueueLog");
+
+ migrationBuilder.DropTable(
+ name: "ResourceLog");
+
+ migrationBuilder.DropTable(
+ name: "ScheduleJobTriggerTimeline");
+
+ migrationBuilder.DropTable(
+ name: "ThreeResourceLog");
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/Migrations/LogDb/LogDbContextModelSnapshot.cs b/ApiTools.Database.Migrations/Migrations/LogDb/LogDbContextModelSnapshot.cs
new file mode 100644
index 0000000..5037c5d
--- /dev/null
+++ b/ApiTools.Database.Migrations/Migrations/LogDb/LogDbContextModelSnapshot.cs
@@ -0,0 +1,449 @@
+锘�// <auto-generated />
+using System;
+using ApiTools.EntityFramework.Core;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ApiTools.Database.Migrations.Migrations.LogDb
+{
+ [DbContext(typeof(LogDbContext))]
+ partial class LogDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ApiTools.Core.ConsoleLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<string>("ClientIpAddress")
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.Property<string>("Content")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Ext")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<int>("Level")
+ .HasColumnType("int");
+
+ b.Property<string>("Request")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("StackTrace")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Url")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("ConsoleLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.DbAuditLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("NewValues")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("OldValues")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Operate")
+ .HasColumnType("int");
+
+ b.Property<Guid>("PrimaryKey")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TableName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("DbAuditLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.Entities.Common.ResourceLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ClientIpAddress")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ConsoleLogs")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Domain")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedMilliseconds")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsSuccess")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Path")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RefererUrl")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Request")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Response")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ResourceLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ExceptionLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Code")
+ .HasMaxLength(32)
+ .HasColumnType("nvarchar(32)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("Message")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("StackTrace")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Type")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ExceptionLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.QueueLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<int>("Access")
+ .HasColumnType("int");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Data")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedMilliseconds")
+ .HasColumnType("bigint");
+
+ b.Property<string>("EventId")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property<bool>("IsConsumOnce")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("QueueLog");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ScheduleJobTriggerTimeline", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<long>("ElapsedTime")
+ .HasColumnType("bigint");
+
+ b.Property<string>("Exception")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<string>("JobId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTime?>("LastRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<int>("Mode")
+ .HasColumnType("int");
+
+ b.Property<DateTime?>("NextRunTime")
+ .HasColumnType("datetime2");
+
+ b.Property<long>("NumberOfRuns")
+ .HasColumnType("bigint");
+
+ b.Property<string>("Result")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<long>("Status")
+ .HasColumnType("bigint");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("TriggerId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScheduleJobTriggerTimeline");
+ });
+
+ modelBuilder.Entity("ApiTools.Core.ThreeResourceLog", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("ClientIpAddress")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ConsoleLogs")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<Guid?>("CreatedChannelId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<DateTimeOffset>("CreatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("CreatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property<string>("Domain")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<long>("ElapsedMilliseconds")
+ .HasColumnType("bigint");
+
+ b.Property<bool>("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property<bool>("IsSuccess")
+ .HasColumnType("bit");
+
+ b.Property<int>("Method")
+ .HasColumnType("int");
+
+ b.Property<string>("Path")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RefererUrl")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Request")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("RequestHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("Response")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<string>("ResponseHeaders")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<int>("Sort")
+ .HasColumnType("int");
+
+ b.Property<string>("TraceId")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property<DateTimeOffset?>("UpdatedTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property<Guid?>("UpdatedUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.ToTable("ThreeResourceLog");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/ApiTools.Database.Migrations/REDEME.MD b/ApiTools.Database.Migrations/REDEME.MD
new file mode 100644
index 0000000..6211999
--- /dev/null
+++ b/ApiTools.Database.Migrations/REDEME.MD
@@ -0,0 +1,21 @@
+-------------------------------涓绘暟鎹簱---------------------------------------
+
+鏂板杩佺Щ鏂囦欢
+dotnet ef migrations add UpdateSmsLog -s "../ApiTools.Web.Entry" -c DefaultDbContext
+
+鍒犻櫎杩佺Щ鏂囦欢
+dotnet ef migrations remove -s "../ApiTools.Web.Entry" -c DefaultDbContext
+
+鏁版嵁搴撹縼绉�
+dotnet ef database update -s "../ApiTools.Web.Entry" -c DefaultDbContext
+
+-------------------------------鏃ュ織鏁版嵁搴�---------------------------------------
+
+鏂板杩佺Щ鏂囦欢
+dotnet ef migrations add Init -s "../ApiTools.Web.Entry" -c LogDbContext
+
+鍒犻櫎杩佺Щ鏂囦欢
+dotnet ef migrations remove -s "../ApiTools.Web.Entry" -c LogDbContext
+
+鏁版嵁搴撹縼绉�
+dotnet ef database update -s "../ApiTools.Web.Entry" -c LogDbContext
\ No newline at end of file
diff --git a/ApiTools.EntityFramework.Core/ApiTools.EntityFramework.Core.csproj b/ApiTools.EntityFramework.Core/ApiTools.EntityFramework.Core.csproj
new file mode 100644
index 0000000..a217c37
--- /dev/null
+++ b/ApiTools.EntityFramework.Core/ApiTools.EntityFramework.Core.csproj
@@ -0,0 +1,12 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+
+ <PropertyGroup>
+ <TargetFramework>net9.0</TargetFramework>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\ApiTools.Core\ApiTools.Core.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/ApiTools.EntityFramework.Core/DbContexts/DefaultDbContext.cs b/ApiTools.EntityFramework.Core/DbContexts/DefaultDbContext.cs
new file mode 100644
index 0000000..57e774a
--- /dev/null
+++ b/ApiTools.EntityFramework.Core/DbContexts/DefaultDbContext.cs
@@ -0,0 +1,40 @@
+锘縰sing ApiTools.Core;
+using Furion;
+using Furion.DatabaseAccessor;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.Extensions.Configuration;
+
+namespace ApiTools.EntityFramework.Core;
+
+[AppDbContext("ApiTools", DbProvider.SqlServer)]
+public class DefaultDbContext : AppDbContext<DefaultDbContext>
+{
+ public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)
+ {
+ }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ base.OnConfiguring(optionsBuilder);
+ optionsBuilder
+ .UseSqlServer(App.Configuration.GetConnectionString("ApiTools"), options =>
+ {
+ // 鎸囧畾鐩爣鏁版嵁搴撶増鏈负SQL Server 2014
+ options.UseCompatibilityLevel(120); // 120瀵瑰簲SQL Server 2014
+ // 鍙�夛細璁剧疆鎵归噺鎿嶄綔澶у皬锛堟寜闇�璋冩暣锛�
+ options.MaxBatchSize(1000);
+ });
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+ DbUtils.BuildEntity(modelBuilder).Wait();
+ }
+
+ protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)
+ {
+ DbUtils.SavingChangesEvent(eventData, result);
+ }
+}
diff --git a/ApiTools.EntityFramework.Core/DbContexts/LogDbContext.cs b/ApiTools.EntityFramework.Core/DbContexts/LogDbContext.cs
new file mode 100644
index 0000000..0d498c6
--- /dev/null
+++ b/ApiTools.EntityFramework.Core/DbContexts/LogDbContext.cs
@@ -0,0 +1,42 @@
+锘縰sing ApiTools.Core;
+using Furion;
+using Furion.DatabaseAccessor;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.Extensions.Configuration;
+using System;
+
+namespace ApiTools.EntityFramework.Core;
+
+[AppDbContext("ApiToolsLog", DbProvider.SqlServer)]
+public class LogDbContext : AppDbContext<LogDbContext, LogDbContextLocator>
+{
+ public LogDbContext(DbContextOptions<LogDbContext> options) : base(options)
+ {
+ }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ base.OnConfiguring(optionsBuilder);
+ optionsBuilder
+ .UseSqlServer(App.Configuration.GetConnectionString("ApiToolsLog"), options =>
+ {
+ // 鎸囧畾鐩爣鏁版嵁搴撶増鏈负SQL Server 2014
+ options.UseCompatibilityLevel(120); // 120瀵瑰簲SQL Server 2014
+ // 鍙�夛細璁剧疆鎵归噺鎿嶄綔澶у皬锛堟寜闇�璋冩暣锛�
+ options.MaxBatchSize(1000);
+ });
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+ DbUtils.BuildEntity(modelBuilder, typeof(LogDbContextLocator)).Wait();
+ }
+
+ protected override void SavingChangesEvent(DbContextEventData eventData, InterceptionResult<int> result)
+ {
+ DbUtils.SavingChangesEvent(eventData, result);
+ }
+}
diff --git a/ApiTools.EntityFramework.Core/Startup.cs b/ApiTools.EntityFramework.Core/Startup.cs
new file mode 100644
index 0000000..d1bd586
--- /dev/null
+++ b/ApiTools.EntityFramework.Core/Startup.cs
@@ -0,0 +1,18 @@
+锘縰sing ApiTools.Core;
+using ApiTools.EntityFramework.Core;
+using Furion;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace ApiTools.EntityFramework.Core;
+
+public class Startup : AppStartup
+{
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddDatabaseAccessor(options =>
+ {
+ options.AddDbPool<DefaultDbContext>();
+ options.AddDbPool<LogDbContext, LogDbContextLocator>();
+ }, "ApiTools.Database.Migrations");
+ }
+}
diff --git a/ApiTools.Web.Entry/ApiTools.Web.Entry.csproj b/ApiTools.Web.Entry/ApiTools.Web.Entry.csproj
new file mode 100644
index 0000000..617bd5a
--- /dev/null
+++ b/ApiTools.Web.Entry/ApiTools.Web.Entry.csproj
@@ -0,0 +1,30 @@
+锘�<Project Sdk="Microsoft.NET.Sdk.Web">
+
+
+ <PropertyGroup>
+ <TargetFramework>net9.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>
+ <PublishReadyToRunComposite>true</PublishReadyToRunComposite>
+ </PropertyGroup>
+
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <ProjectReference Include="..\ApiTools.Application\ApiTools.Application.csproj" />
+ <ProjectReference Include="..\ApiTools.Database.Migrations\ApiTools.Database.Migrations.csproj" />
+ </ItemGroup>
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties properties_4launchsettings_1json__JsonSchema="" />
+ </VisualStudio>
+ </ProjectExtensions>
+
+</Project>
diff --git a/ApiTools.Web.Entry/Program.cs b/ApiTools.Web.Entry/Program.cs
new file mode 100644
index 0000000..611ed5a
--- /dev/null
+++ b/ApiTools.Web.Entry/Program.cs
@@ -0,0 +1 @@
+Serve.Run(RunOptions.Default.WithArgs(args));
\ No newline at end of file
diff --git a/ApiTools.Web.Entry/Properties/launchSettings.json b/ApiTools.Web.Entry/Properties/launchSettings.json
new file mode 100644
index 0000000..785980f
--- /dev/null
+++ b/ApiTools.Web.Entry/Properties/launchSettings.json
@@ -0,0 +1,31 @@
+锘縶
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53785",
+ "sslPort": 44342
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "ApiTools.Web.Entry": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "",
+ "applicationUrl": "https://localhost:5011;http://localhost:5010",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ApiTools.Web.Entry/Startup.cs b/ApiTools.Web.Entry/Startup.cs
new file mode 100644
index 0000000..8ab551e
--- /dev/null
+++ b/ApiTools.Web.Entry/Startup.cs
@@ -0,0 +1,134 @@
+锘縰sing Consul;
+using ApiTools.Core;
+using Furion;
+using Furion.EventBus;
+using Furion.Schedule;
+using MediatR;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Newtonsoft.Json.Converters;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ApiTools.Web.Entry
+{
+ [AppStartup(2)]
+ public class Startup : AppStartup
+ {
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddHealthChecks();
+
+ services.AddConfigurableOptions<WxmpOptions>();
+ services.AddConfigurableOptions<WeChatPayOptions>();
+ services.AddConfigurableOptions<AlipayOptions>();
+ services.AddConfigurableOptions<PingAnPayOptions>();
+ services.AddConfigurableOptions<ChengLiYeSmsOptions>();
+ services.AddConfigurableOptions<AliyunOptions>();
+ services.AddConfigurableOptions<BaiduOptions>();
+
+ services.AddComponent<LogServiceComponent>();
+
+ services.AddComponent<ConsulServiceComponent>();
+
+ services.AddComponent<EventBusServiceComponent>();
+
+ services.AddComponent<DistributedCacheServiceComponent>();
+
+ services.AddHttpRemote();
+ services.AddSingleton<AlipayUtils>();
+ services.AddSingleton<WxmpUtils>();
+ services.AddScoped<SmsUtils>();
+
+ services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(App.Assemblies.ToArray()));
+
+ services.AddHostedService<XmlDocBuildHostedService>();
+
+ services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
+
+ services.AddCorsAccessor();
+
+ services.AddHostedService<BuildDynamicControllersHostedService>();
+
+ services.AddSchedule(options =>
+ {
+ options.BuildSqlType = SqlTypes.SqlServer;
+ options.JobDetail.LogEnabled = true;
+ //options.AddPersistence<DbJobPersistence>();
+ });
+
+ services.AddSpecificationDocuments(options =>
+ {
+ options.OperationFilter<CustomOperationIdFilter>();
+ options.SchemaFilter<EnumSchemaFilter>();
+ });
+ services.AddSwaggerGenNewtonsoftSupport();
+
+ services.AddMvcFilter<ResourceActionFilter>();
+
+ services.AddControllers()
+ .AddNewtonsoftJson(options =>
+ {
+ options.SerializerSettings.Converters.Add(new EmptyStringToNullConverter());
+ //options.SerializerSettings.Converters.Add(new StringEnumConverter());
+ })
+ .AddFriendlyException()
+ .AddDataValidation()
+ .AddInjectWithUnifyResult<FriendlyResultProvider>();
+
+ }
+
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime)
+ {
+ // 瑙f瀽浜嬩欢鎬荤嚎鍙戝竷鏈嶅姟
+ var eventPublisher = app.ApplicationServices.GetRequiredService<IEventPublisher>();
+
+ // 璁㈤槄
+ eventPublisher.OnExecuted += (sender, args) =>
+ {
+ Console.WriteLine($"浜嬩欢 {args.Source.EventId} 鎵ц鐘舵�侊細{args.Status}锛屽紓甯革細{args.Exception}锛屾墽琛岀粨鏋滐細{args.Result}");
+ };
+
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseUnifyResultStatusCodes();
+
+ //app.UseHttpsRedirection();
+
+ app.UseRouting();
+
+ app.UseCorsAccessor();
+
+ app.UseAuthentication();
+ app.UseAuthorization();
+
+ app.UseInject(string.Empty);
+
+ app.UseStaticFiles();
+ app.UseScheduleUI();
+
+ app.UseSpecificationDocuments();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapHealthChecks("/healthz");
+ });
+
+ app.UseComponent<ConsulApplicationComponent>(env);
+
+ //lifetime.ApplicationStarted.Register(async () =>
+ //{
+ // await ResourceUtils.BuildDynamicControllersAsync();
+ //});
+ }
+ }
+}
diff --git a/ApiTools.Web.Entry/appsettings.Development.json b/ApiTools.Web.Entry/appsettings.Development.json
new file mode 100644
index 0000000..5f187ae
--- /dev/null
+++ b/ApiTools.Web.Entry/appsettings.Development.json
@@ -0,0 +1,10 @@
+{
+ "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "Microsoft.EntityFrameworkCore": "Information"
+ }
+ }
+}
\ No newline at end of file
diff --git a/ApiTools.Web.Entry/appsettings.json b/ApiTools.Web.Entry/appsettings.json
new file mode 100644
index 0000000..46a87d9
--- /dev/null
+++ b/ApiTools.Web.Entry/appsettings.json
@@ -0,0 +1,153 @@
+{
+ "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
+ "Environment": "Local",
+ "ConnectionStrings": {
+
+ "ApiTools": "Server=120.26.58.240; Database=Dev_ApiTools; User=bole;Password=Bole1472589;Encrypt=false;",
+ "ApiToolsLog": "Server=120.26.58.240; Database=Dev_ApiToolsLog; User=bole;Password=Bole1472589;Encrypt=false;"
+
+ //"FlexJobApi": "Server=rm-bp1mt744021h1s6dg4o.sqlserver.rds.aliyuncs.com,2333; Database=Pro_FlexJobApi; User=bole;Password=Blcs20@%27;Encrypt=false;",
+ //"FlexJobApiLog": "Server=rm-bp1mt744021h1s6dg4o.sqlserver.rds.aliyuncs.com,2333; Database=Pro_FlexJobApiLog; User=bole;Password=Blcs20@%27;Encrypt=false;",
+
+ },
+ "Consul": {
+ "Address": "http://localhost:8500/",
+ "ServiceName": "Local_ToolServices",
+ "ServiceIP": "localhost",
+ "ServicePort": 5010,
+ "ServiceHealthCheck": "/api/user/resource/checkHealth"
+ },
+ "ToolServer": {
+ "ServiceName": "ToolServices"
+ },
+ "FlexJobServer": {
+ "ServiceName": "FlexJobServices"
+ },
+ "HumanResourcesServer": {
+ "ServiceName": "HumanResourcesServices"
+ },
+ "ElectronSignServer": {
+ "ServiceName": "HumanResourcesServices",
+ "AppId": "2f31be96-811d-0b3d-d723-3a1bd3b3b55e",
+ "PrivateKey": "QoaFhN5TNmA4EM6JbUrK2IkK5cMVMWr0",
+ "Account": "system",
+ "Password": "qwe321"
+ },
+ "DistributedCache": {
+ "Access": "Redis",
+ "Configuration": "118.178.252.28:5390,password=Bole123!"
+ },
+ "Wxmp": {
+ "Items": [
+ {
+ "Code": "Personal",
+ "AppId": "wxb9e0baf4f87aa0de",
+ "AppSecret": "24abded2cd32b677b1f14ea9ec5767f0",
+ //姝e紡鐗堜负 "release"锛屼綋楠岀増涓� "trial"锛屽紑鍙戠増涓� "develop"
+ "EnvVersion": "trial"
+ },
+ {
+ "Code": "Enterprise",
+ "AppId": "wx3669dd12a0915f7d",
+ "AppSecret": "c03a62ad6822f1c925532c34183e7f7f",
+ "EnvVersion": "trial"
+ }
+ ]
+ },
+ "Task": {
+ "SettlementTime": "T0"
+ },
+ "WeChatPay": {
+ "MchId": "1728403592",
+ "SerialNo": "7A3C3AA2E63D758ED01F7A90DDC61B66D1BF5D4B",
+ "PublicKey": "-----BEGIN PUBLIC KEY-----\r\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxwy0gXOusrM5HS3+N+1L\r\nWzADF3Ic5F9d6x2reLQCKk/aDjurx5t+20oPKInpFdSrOByUWBBST7ig76ODwQIi\r\nX8MO7950JyvpviC5AJ/EFunmQJXsdzRgT0/mIIYlJx21ndhgeDF2f3kcNlVAdaEg\r\nq627Ew+zQVROqP0e+SsI5PfoMOJPn4/jyFNLVRjvH66QLmYg9wOdJeHGEjUbAVri\r\npevQ3Dk00ZGlNchzeo/PciQNe2yK5SuXob75fIa6NrZrQ4d2dXfX1J8+dAbmhaFQ\r\n1w4U7dAZoM6E7nBrFvDkhcDWtEGqw7r+upNBZbAB5UQ9Su9I3/dDT3yMRfvpKJ92\r\nrwIDAQAB\r\n-----END PUBLIC KEY-----\r\n",
+ "PrivateKey": "-----BEGIN PRIVATE KEY-----\r\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHDLSBc66yszkd\r\nLf437UtbMAMXchzkX13rHat4tAIqT9oOO6vHm37bSg8oiekV1Ks4HJRYEFJPuKDv\r\no4PBAiJfww7v3nQnK+m+ILkAn8QW6eZAlex3NGBPT+YghiUnHbWd2GB4MXZ/eRw2\r\nVUB1oSCrrbsTD7NBVE6o/R75Kwjk9+gw4k+fj+PIU0tVGO8frpAuZiD3A50l4cYS\r\nNRsBWuKl69DcOTTRkaU1yHN6j89yJA17bIrlK5ehvvl8hro2tmtDh3Z1d9fUnz50\r\nBuaFoVDXDhTt0BmgzoTucGsW8OSFwNa0QarDuv66k0FlsAHlRD1K70jf90NPfIxF\r\n++kon3avAgMBAAECggEAcmDXnId3/JHGIQFb0pFVuvl03VUiSwyN8FvlO3/cuqmV\r\n+JXLWPD+TU5aNYZB3NyO4rhxecUvN0Y1nF6OiCsMy5BPlgBzKEswjqNJC5XC3RPc\r\nzoIYFkuPiCO2bjwHP1nwEdrTXF235PoX/xSv7KgBGQXEuOhNrh2e8bY5xR44hzD1\r\n11eIOfE/SanF71LNxBNmNegmtWfsU8ctNiavmMIYnkRy9uREPH4FbGYZ07Cugr/s\r\nUhZp5knwZ9wY5LYT0GM3t3VW/vsDmt4cAja289m/AW6ElfP6dwURv9uYBKNVIoFU\r\nlChQKm5SAFVQTyPpCrMCLJimdApz1tIfQSXfr+THIQKBgQDj/aBraiWGDFExhGOK\r\n97pfRYMmxhtyL9iwXaQjgpQpFc1/smVQdkTS6FPz0sQnRHaOuuh5hkkAShHTxYBP\r\nrdo/z82uy6UuflfQgzG2sSZHb/M9BISgnh8l+/hsrSu+zEuTwDBAzPU8a71L3IRu\r\neBMuXNWGOWZAs6IFfQArK5JkUQKBgQDfgN9kxCkClusznoWYURYk80H3WIN+Wi2K\r\nrHGMgfrqiDuDIA7A8QcTgS7fpHYM4rOLc0fVDi6lxNUsuY3W12wpNER3aaM43hTc\r\nc3t+tVW+pwc5hm/N6KVKj5d9Mrt9OjZ9W24SuN/0eLqPN+hE6gGqJCGOoPxuN4EN\r\ngn0lowRq/wKBgHvk8e4tSqLjwqOkC+wS3yaywaiqc3PD6H8/A9mANj91Z60DJudo\r\nvdHXCvgvCwVDwSGjFH4lqToNBk8MvsON+FJA/McGR4dShSn8gWGENwcPISGBeQlH\r\npCmiGcgE+wa+QjvSbuZn+sSQz9ePyC+39MR3ElnUi2qRs3RED3lmPjFhAoGBAJrj\r\nK20gh68UuXBvVfPFlcwLjFaGT7H7en4UnSgbV7C6sktfpvnMzvOUXdB8n5a0cGqe\r\nfFRI3MjiTD0PZh1R8tHnN99tJMEfHmPb3+RidEaIZ/hUkxymMg4mznvj8YyKEAL1\r\nnqV42zMHi3n+64b+iCLJoTu/ktAqxNOA74tqmoAvAoGAUlrwOEHL8LZG2J309nlN\r\nvh2hKOf7+ouxpgiv9QC6Pc9pKbGdsPXnS6NcwOpuCTV4IIsLouzoyeEGiDj05HyB\r\nzRpZd9sRVcG0bmI/UMeRJB9mYU4TYjpP4qwoZl5Ev8uQCfFf7yy0qWc/l9wSRVlP\r\nGvfAjqIq8iptGBcpLVlCNtc=\r\n-----END PRIVATE KEY-----\r\n"
+ },
+ "AliPay": {
+ "ServerUrl": "https://openapi.alipay.com/gateway.do",
+ "AppId": "2021004171602214",
+ "PrivateKey": "MIIEogIBAAKCAQEAoDrOheetqHkE1RYaNhogP/iHVXEtGZW4A/JJnwpJs+6eLXfpXf/ecuywplDpgc/BXSUEnDaktUwceLXO8vdIf8h0y8yqWwYdgzC0xELYpTroK3dlNiShgVkUEeMXi+n3Mhjp9OVrqieggDI3YGzDBLY4UAWsXCcXnD+r/xIpT8keVMtb/LrUmL5XLvBVcn5MkJTAoeFt18EQXOLFN1+ldpaf9k+iyM2fbgXCc6InNSgHGSHZwhzm9t+cGqNd1ju/nQN9lHwKCDQPMn6cor2lsP1nsEfpHp2vdfNEdccVSRZB/kdtFzXEUpTFznz8+zK2D0Ra+B0G1nSxus9xsD3HmwIDAQABAoIBACQYm2X3J1wIx1npvMXrZNCEgJhzAqH85JOfBY7alnf+jYvYs64FcmuZfsI5ACHKV9lP+ZXniXt+Rfu7mX+Kzb5bvlQbK1WOLx/a3R5JoNy4RI1mPFrSLcAh/S96ZVeTwah7jFkrRfHzM2kt5uPGHLj3BACjBo1METmV7n1r7fqXCus/Eihdo5ah8WOUPPMg8MqLadSnKVgnkzDLEa+8bagN/WgNfg9m4nW3IocEtFmKox3xV938eXpzn6KrgCduyK1Xn3d1PViRDT1QFOqhTCg17j8qDD4xZphH32Vbgq+heURmSMfecmC1u0CEpvFq3WBVxir/VOxk88gqkAzwusECgYEA+x/OjjNYaeOTFxCLtcI6EnerwgisF39rSNVAdSziWO3u8tUhzhHxB1cE5im4f9Qsd+r3Mw7Vu26YHgQn9O/A1QGoU3e0W/0Ckz5iIIJdAqBB279lNN+puYo4lIUfZha00i/R3Sj6eXrKGTwqCPRyHvJUC7biAAUgnqDAPLdPpgkCgYEAo1c3P4saxVqPnGheplud+jpEilp92dwHn9nIsaX0A/ohcYQIes+bKEZHHafn7ksDhidcjrbPMK72PP2HOJOL6D8a2w9zdyZ6jlycV5jiFHB6ywmkJ0517HWAJ6Fl3OsltDrxWHnuiyb/G/2fU1uLsO2U/b7zT9s2zXJzN53ZiYMCgYAmVku9T79eovxwl/kMLXOaICTbgWFsUOp6+vtVKB4B/4jsD3eSsxB9014PGS1ubmC/ieJlLA2bCJ42buH+tZ9VpWQiIfMp2+1Jt0tZtS0n2nlTZ9u2f7K0fZJ3sf8CIdNHBz/dqITciM9TnOi55z+I0+vawfeskxvQu6+9VSrWqQKBgD55voUMhMnVsLZnaUSCKHOsU8kDgb2Rnkzy9QOV8TaQNrh/gurOe481CkB6l4iaopdueMWRgMAjO8XqRw1Jyiqj8Ha3ezeovRm0rIwIyvh8aUs9vc7XAN3Xt5Pw9NBCFOLR5LwtryMEYHFpWcZ9bnnW9bT0k4YI1/ZO/2jXdHxXAoGAQLGrsed0HLWRjGU2rAUvA9Kny6wo+ScUas5IhoAhGMYDDQ8lFbndgnIOMjdXllT9IvmVERMTSMmP2m7+aqKNz3x0kTkg0tIQTLPsaWCjI5G4CDASUPo/jPvcd4h3euclhpuhcU9FMme3R5UhMAZy1bt+1VWPRxRB0gzWi4d7AFQ=",
+ "Format": "json",
+ "Charset": "UTF-8",
+ "SignType": "RSA2",
+ "AppCertPath": "AlipayCert/appCertPublicKey_2021004171602214.crt",
+ "AlipayPublicCertPath": "AlipayCert/alipayCertPublicKey_RSA2.crt",
+ "RootCertPath": "AlipayCert/alipayRootCert.crt",
+ "NotifyUrl": "https://testfj.81812333.com",
+ "EncryptKey": "jjy8A7hB/1Bkhg+8FtXyyg==",
+ "AlipayPublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoDrOheetqHkE1RYaNhogP/iHVXEtGZW4A/JJnwpJs+6eLXfpXf/ecuywplDpgc/BXSUEnDaktUwceLXO8vdIf8h0y8yqWwYdgzC0xELYpTroK3dlNiShgVkUEeMXi+n3Mhjp9OVrqieggDI3YGzDBLY4UAWsXCcXnD+r/xIpT8keVMtb/LrUmL5XLvBVcn5MkJTAoeFt18EQXOLFN1+ldpaf9k+iyM2fbgXCc6InNSgHGSHZwhzm9t+cGqNd1ju/nQN9lHwKCDQPMn6cor2lsP1nsEfpHp2vdfNEdccVSRZB/kdtFzXEUpTFznz8+zK2D0Ra+B0G1nSxus9xsD3HmwIDAQAB"
+ },
+ "PingAnPay": {
+ "MrChCode": "0040107980000NBCS000"
+ },
+ "ChengLiYeSms": {
+ "SignName": "818浜哄姏鏃犲咖1",
+ "UserName": "nbcsxx",
+ "Password": "8af9s7",
+ "TemplateCodes": {
+ //818骞冲彴鐧诲綍/娉ㄥ唽
+ "LoginOrRegister": "楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙扮櫥褰�/娉ㄥ唽锛岄獙璇佺爜10鍒嗛挓鍐呮湁鏁堛��",
+ //818鎵嬫満鍙风爜淇敼
+ "UpdateUserPhoneNumber": "楠岃瘉鐮�${code}锛屾偍姝e湪杩涜淇敼鎵嬫満鍙风爜鎿嶄綔锛岃鍕挎硠闇诧紝鑻ラ潪鏈汉鎿嶄綔璇峰拷鐣ャ��",
+ //818閽卞寘寮�閫�
+ "BankWalletAccountOpen": "楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙伴挶鍖呭紑閫氾紝璇ラ獙璇佺爜5鍒嗛挓鍐呮湁鏁堬紝璇峰嬁娉勯湶浜庝粬浜恒��",
+ //鐢靛瓙绛鹃個绾�
+ "InviteElectronSign": "${name}璇锋偍鐐瑰嚮绛剧害http://testwww.81812333.com/sg/${code}",
+ //绛剧害鍦板潃
+ "ElectronSignUrl": "${name}璇锋偍鐐瑰嚮绛剧害https://testwww.81812333.com/sgu/${code}"
+ }
+ },
+ "Aliyun": {
+ "OSS": {
+ "AccessKeyId": "LTAI4GAdJ88mUMMFBHHiyDmS",
+ "AccessSecret": "NX3AmjOcGkJ8bncQfIVxqmifBWkI0E",
+ "RegionId": "cn-hangzhou",
+ "Endpoint": "http://oss-cn-hangzhou.aliyuncs.com",
+ "BucketName": "waterdroptest2",
+ "Url": "https://waterdroptest2.oss-cn-hangzhou.aliyuncs.com/",
+ "RoleArn": "acs:ram::1483797030072898:role/boleoss",
+ "RoleSessionName": "SessionTest",
+ "Policy": "{\"Version\":\"1\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"oss:PutObject\",\"Resource\":[\"acs:oss:*:*:waterdroptest2/*\",\"acs:oss:*:*:parkmanagement/*\",\"acs:oss:*:*:jurenlian/*\"]}]}",
+ "DurationSeconds": 3600
+ },
+
+ //"OSS": {
+ // "AccessKeyId": "LTAI4GAdJ88mUMMFBHHiyDmS",
+ // "AccessSecret": "NX3AmjOcGkJ8bncQfIVxqmifBWkI0E",
+ // "RegionId": "cn-hangzhou",
+ // "Endpoint": "http://oss-cn-hangzhou.aliyuncs.com",
+ // "BucketName": "parkmanagement",
+ // "Url": "https://parkmanagement.oss-cn-hangzhou.aliyuncs.com/",
+ // "RoleArn": "acs:ram::1483797030072898:role/boleoss",
+ // "RoleSessionName": "SessionTest",
+ // "Policy": "{\"Version\":\"1\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"oss:PutObject\",\"Resource\":[\"acs:oss:*:*:waterdroptest2/*\",\"acs:oss:*:*:parkmanagement/*\",\"acs:oss:*:*:jurenlian/*\"]}]}",
+ // "DurationSeconds": 3600
+ //},
+
+ "SMS": {
+ "AccessKeyId": "LTAI5tLzz2jnXrUAAiC2kduH",
+ "AccessSecret": "do1XqrgHJ5gOuFHhO5eku0FyYzZvbQ",
+ "Version": "2017-05-25",
+ "SignName": "818鏁板瓧浜哄姏璧勪骇骞冲彴",
+ "RegionId": "cn-hangzhou",
+ "TemplateCodes": {
+ //818骞冲彴鐧诲綍/娉ㄥ唽 楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙扮櫥褰�/娉ㄥ唽锛岄獙璇佺爜10鍒嗛挓鍐呮湁鏁堛��
+ "LoginOrRegister": "SMS_472170005",
+ //818鎵嬫満鍙风爜淇敼 楠岃瘉鐮�${code}锛屾偍姝e湪杩涜淇敼鎵嬫満鍙风爜鎿嶄綔锛岃鍕挎硠闇诧紝鑻ラ潪鏈汉鎿嶄綔璇峰拷鐣ャ��
+ "UpdateUserPhoneNumber": "SMS_471100097",
+ //818閽卞寘寮�閫� 楠岃瘉鐮�${code}锛岀敤鎴锋偍濂斤紝鎮ㄦ鍦ㄨ繘琛屽钩鍙伴挶鍖呭紑閫氾紝璇ラ獙璇佺爜5鍒嗛挓鍐呮湁鏁堬紝璇峰嬁娉勯湶浜庝粬浜恒��
+ "BankWalletAccountOpen": "SMS_473860301",
+ //鐢靛瓙绛鹃個绾� ${name}璇锋偍鐐瑰嚮绛剧害http://testwww.81812333.com/sg/${code}
+ "InviteElectronSign": "SMS_493755029",
+ //绛剧害鍦板潃 ${name}璇锋偍鐐瑰嚮绛剧害https://testwww.81812333.com/sgu/${code}
+ "ElectronSignUrl": "SMS_493715033"
+ }
+ }
+ },
+ "Baidu": {
+ "Ocr": {
+ "Key": "Htx3y6eFnlW92WvHx9aW44f8",
+ "Secret": "k1rDa3vjVtArrQio9LtR5AjqARSw45WO"
+ }
+ }
+}
\ No newline at end of file
diff --git a/ApiTools.sln b/ApiTools.sln
new file mode 100644
index 0000000..45dbb66
--- /dev/null
+++ b/ApiTools.sln
@@ -0,0 +1,49 @@
+锘�
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36310.24 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTools.Application", "ApiTools.Application\ApiTools.Application.csproj", "{AB699EE9-43A8-46F2-A855-04A26DE63372}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTools.EntityFramework.Core", "ApiTools.EntityFramework.Core\ApiTools.EntityFramework.Core.csproj", "{4BD77E5C-138D-4F2D-B709-F9020F306AF3}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTools.Core", "ApiTools.Core\ApiTools.Core.csproj", "{4FB30091-15C7-4FD9-AB7D-266814F360F5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTools.Database.Migrations", "ApiTools.Database.Migrations\ApiTools.Database.Migrations.csproj", "{EA769D36-9D55-47A6-945F-1687EA95179F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTools.Web.Entry", "ApiTools.Web.Entry\ApiTools.Web.Entry.csproj", "{C8D99F52-EDC7-411F-8300-6DB14BF59E8C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AB699EE9-43A8-46F2-A855-04A26DE63372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AB699EE9-43A8-46F2-A855-04A26DE63372}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AB699EE9-43A8-46F2-A855-04A26DE63372}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AB699EE9-43A8-46F2-A855-04A26DE63372}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4BD77E5C-138D-4F2D-B709-F9020F306AF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4BD77E5C-138D-4F2D-B709-F9020F306AF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4BD77E5C-138D-4F2D-B709-F9020F306AF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4BD77E5C-138D-4F2D-B709-F9020F306AF3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EA769D36-9D55-47A6-945F-1687EA95179F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EA769D36-9D55-47A6-945F-1687EA95179F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EA769D36-9D55-47A6-945F-1687EA95179F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EA769D36-9D55-47A6-945F-1687EA95179F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B2073C2C-0FD3-452B-8047-8134D68E12CE}
+ EndGlobalSection
+EndGlobal
--
Gitblit v1.9.1