diff --git a/Bing.All.sln b/Bing.All.sln
index 0b100e45a..b1cb0a9ee 100644
--- a/Bing.All.sln
+++ b/Bing.All.sln
@@ -50,18 +50,6 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.MiniProfiler", "framework\src\Bing.MiniProfiler\Bing.MiniProfiler.csproj", "{43BE3B85-AA7B-47B5-AC09-EE66B52358EA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_SolutionItems", "_SolutionItems", "{2BA5C677-C0B9-458B-8A6D-D3E74B6F60EA}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- .gitattributes = .gitattributes
- .gitignore = .gitignore
- common.props = common.props
- Directory.Build.targets = Directory.Build.targets
- framework.props = framework.props
- LICENSE = LICENSE
- README.md = README.md
- version.dev.props = version.dev.props
- version.props = version.props
- EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6690993E-6659-451F-907C-A48FE1121D40}"
ProjectSection(SolutionItems) = preProject
@@ -89,9 +77,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-admin", "01-admin", "{BDBABE46-FAAE-459D-BC78-B5BA6503EBBA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-tests", "02-tests", "{5C7976B4-C243-41B9-8303-8E8FAE099D31}"
- ProjectSection(SolutionItems) = preProject
- framework\tests\Directory.Build.props = framework\tests\Directory.Build.props
- EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.AutoMapper.Tests", "framework\tests\Bing.AutoMapper.Tests\Bing.AutoMapper.Tests.csproj", "{741EE94D-5F03-426E-9D34-CBDA41671742}"
EndProject
@@ -111,8 +96,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Ddd.Application", "fra
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Ddd.Application.Contracts", "framework\src\Bing.Ddd.Application.Contracts\Bing.Ddd.Application.Contracts.csproj", "{577D3EA3-5342-4E0D-AE51-39CBEE217089}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Validation.Abstractions", "framework\src\Bing.Validation.Abstractions\Bing.Validation.Abstractions.csproj", "{DB0D25EE-7489-4DD1-8CF9-A8F839B58446}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Auditing", "framework\src\Bing.Auditing\Bing.Auditing.csproj", "{F084AFFB-9136-43CE-874C-777DBA4D5205}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Emailing", "framework\src\Bing.Emailing\Bing.Emailing.csproj", "{5D81881D-FF17-4902-8BEB-A1D58D0EF688}"
@@ -190,6 +173,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "props", "props", "{D77F42E0
ProjectSection(SolutionItems) = preProject
asset\props\misc.props = asset\props\misc.props
asset\props\package.props = asset\props\package.props
+ asset\props\sourcelink.env.props = asset\props\sourcelink.env.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Admin.Data.FreeSQL", "modules\admin\src\Bing.Admin.Data.FreeSQL\Bing.Admin.Data.FreeSQL.csproj", "{05DFA67F-C861-48F9-BBD9-7777972A918F}"
@@ -242,6 +226,45 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Logging.Tests", "frame
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Logging.Serilog.Tests", "framework\tests\Bing.Logging.Serilog.Tests\Bing.Logging.Serilog.Tests.csproj", "{857BF156-74BE-4D71-8814-A1ECAA958C2D}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Validation.Abstractions", "framework\src\Bing.Validation.Abstractions\Bing.Validation.Abstractions.csproj", "{19A3A852-6F7B-4864-8F53-AE91A04D0732}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Aop.AspectCore", "framework\src\Bing.Aop.AspectCore\Bing.Aop.AspectCore.csproj", "{E7D1CB89-9657-44EC-8531-4C1B956D190E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-tests", "02-tests", "{FA7995A9-43C6-405A-B924-E4F182C245C2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bing.Biz.Payments.Tests", "components\tests\Bing.Biz.Payments.Tests\Bing.Biz.Payments.Tests.csproj", "{F41CF4E3-DB29-42C2-8999-39880376D862}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{3EE7B5A9-FF9B-4786-9E0F-AFD2BED68CC2}"
+ ProjectSection(SolutionItems) = preProject
+ asset\images\icon.png = asset\images\icon.png
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{7ABB7FBC-A1B9-432F-BCC5-53B9FD0172D8}"
+ ProjectSection(SolutionItems) = preProject
+ README.md = README.md
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{4A87040E-99A6-4A3F-BD6D-D2A3C3663012}"
+ ProjectSection(SolutionItems) = preProject
+ framework\Publish.bat = framework\Publish.bat
+ framework\UnPublish.bat = framework\UnPublish.bat
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution", "solution", "{B6E2B626-F561-4B47-8CFE-E8A305696522}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ .gitattributes = .gitattributes
+ .gitignore = .gitignore
+ common.props = common.props
+ common.tests.props = common.tests.props
+ framework.props = framework.props
+ LICENSE = LICENSE
+ version.dev.props = version.dev.props
+ version.props = version.props
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bing.Uow", "framework\src\Bing.Uow\Bing.Uow.csproj", "{659C6450-6A39-44A3-A1A5-449ECAA1AFBE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -396,10 +419,6 @@ Global
{577D3EA3-5342-4E0D-AE51-39CBEE217089}.Debug|Any CPU.Build.0 = Debug|Any CPU
{577D3EA3-5342-4E0D-AE51-39CBEE217089}.Release|Any CPU.ActiveCfg = Release|Any CPU
{577D3EA3-5342-4E0D-AE51-39CBEE217089}.Release|Any CPU.Build.0 = Release|Any CPU
- {DB0D25EE-7489-4DD1-8CF9-A8F839B58446}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {DB0D25EE-7489-4DD1-8CF9-A8F839B58446}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {DB0D25EE-7489-4DD1-8CF9-A8F839B58446}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {DB0D25EE-7489-4DD1-8CF9-A8F839B58446}.Release|Any CPU.Build.0 = Release|Any CPU
{F084AFFB-9136-43CE-874C-777DBA4D5205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F084AFFB-9136-43CE-874C-777DBA4D5205}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F084AFFB-9136-43CE-874C-777DBA4D5205}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -552,6 +571,22 @@ Global
{857BF156-74BE-4D71-8814-A1ECAA958C2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{857BF156-74BE-4D71-8814-A1ECAA958C2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{857BF156-74BE-4D71-8814-A1ECAA958C2D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19A3A852-6F7B-4864-8F53-AE91A04D0732}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19A3A852-6F7B-4864-8F53-AE91A04D0732}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19A3A852-6F7B-4864-8F53-AE91A04D0732}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19A3A852-6F7B-4864-8F53-AE91A04D0732}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E7D1CB89-9657-44EC-8531-4C1B956D190E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E7D1CB89-9657-44EC-8531-4C1B956D190E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E7D1CB89-9657-44EC-8531-4C1B956D190E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E7D1CB89-9657-44EC-8531-4C1B956D190E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F41CF4E3-DB29-42C2-8999-39880376D862}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F41CF4E3-DB29-42C2-8999-39880376D862}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F41CF4E3-DB29-42C2-8999-39880376D862}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F41CF4E3-DB29-42C2-8999-39880376D862}.Release|Any CPU.Build.0 = Release|Any CPU
+ {659C6450-6A39-44A3-A1A5-449ECAA1AFBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {659C6450-6A39-44A3-A1A5-449ECAA1AFBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {659C6450-6A39-44A3-A1A5-449ECAA1AFBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {659C6450-6A39-44A3-A1A5-449ECAA1AFBE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -599,7 +634,6 @@ Global
{25107D91-1E7D-422C-8B03-B1C94EE3A1B5} = {AED4D92B-5196-47E9-BD2C-84D4077F5A70}
{CAC738F2-8F95-4940-90D2-76DABF403581} = {AED4D92B-5196-47E9-BD2C-84D4077F5A70}
{577D3EA3-5342-4E0D-AE51-39CBEE217089} = {AED4D92B-5196-47E9-BD2C-84D4077F5A70}
- {DB0D25EE-7489-4DD1-8CF9-A8F839B58446} = {472FFE79-B8B1-41A1-91F2-CFA0F8406BC9}
{F084AFFB-9136-43CE-874C-777DBA4D5205} = {AED4D92B-5196-47E9-BD2C-84D4077F5A70}
{5D81881D-FF17-4902-8BEB-A1D58D0EF688} = {B8142AAE-3792-44C0-9197-0F14A9749E33}
{256EB128-60DC-406C-BED0-9D0013A6B49A} = {052D4342-8B65-4836-A9B6-681A7812760E}
@@ -659,6 +693,15 @@ Global
{C7E17279-AAEB-4A58-BBBB-AF443F924D9E} = {33F6CAB3-FD8A-4B91-9B94-A1E2DBC2759B}
{73871EF9-9CF6-479F-BC1C-AD443CE037AE} = {5C7976B4-C243-41B9-8303-8E8FAE099D31}
{857BF156-74BE-4D71-8814-A1ECAA958C2D} = {5C7976B4-C243-41B9-8303-8E8FAE099D31}
+ {19A3A852-6F7B-4864-8F53-AE91A04D0732} = {C6B2743E-B7EE-418C-9F9B-79976B71C46B}
+ {E7D1CB89-9657-44EC-8531-4C1B956D190E} = {C6B2743E-B7EE-418C-9F9B-79976B71C46B}
+ {FA7995A9-43C6-405A-B924-E4F182C245C2} = {8E2070BF-F6CF-47CC-8DB8-56B74EDFA7EB}
+ {F41CF4E3-DB29-42C2-8999-39880376D862} = {FA7995A9-43C6-405A-B924-E4F182C245C2}
+ {3EE7B5A9-FF9B-4786-9E0F-AFD2BED68CC2} = {F40A8736-2FEC-446A-99FD-3660729893FC}
+ {7ABB7FBC-A1B9-432F-BCC5-53B9FD0172D8} = {2BA5C677-C0B9-458B-8A6D-D3E74B6F60EA}
+ {4A87040E-99A6-4A3F-BD6D-D2A3C3663012} = {2BA5C677-C0B9-458B-8A6D-D3E74B6F60EA}
+ {B6E2B626-F561-4B47-8CFE-E8A305696522} = {2BA5C677-C0B9-458B-8A6D-D3E74B6F60EA}
+ {659C6450-6A39-44A3-A1A5-449ECAA1AFBE} = {AED4D92B-5196-47E9-BD2C-84D4077F5A70}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C1202A0F-83CC-4602-BCE5-20CB640BCAD4}
diff --git a/Directory.Build.targets b/Directory.Build.targets
deleted file mode 100644
index 564bbc920..000000000
--- a/Directory.Build.targets
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- true
- latest
-
- NU5125;$(NoWarn)
-
-
-
-
-
-
-
diff --git a/asset/props/sourcelink.env.props b/asset/props/sourcelink.env.props
new file mode 100644
index 000000000..ac94a6d78
--- /dev/null
+++ b/asset/props/sourcelink.env.props
@@ -0,0 +1,17 @@
+
+
+
+
+ 2.2.0
+ 2.2.0
+ 2.2.0
+ 2.2.0
+ 2.2.0
+ 2.2.0
+ 3.1.0
+ 3.1.0
+ 3.1.0
+
+
+
+
\ No newline at end of file
diff --git a/common.props b/common.props
index 6ea08493b..9bd180eac 100644
--- a/common.props
+++ b/common.props
@@ -1,9 +1,9 @@
-
latest
- $(NoWarn);CS1591
+ $(NoWarn);NETSDK1138
+ $(NoWarn);CS1591;NETSDK1138
@@ -22,6 +22,8 @@
$(AssemblyName).xml
+
+
diff --git a/common.tests.props b/common.tests.props
new file mode 100644
index 000000000..6745a5ea3
--- /dev/null
+++ b/common.tests.props
@@ -0,0 +1,23 @@
+
+
+ latest
+ $(NoWarn);CS1591
+ false
+
+
+
+
+
+
+
+ 2.4.5
+ 2.4.3
+ 2.4.3
+ 2.4.3
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
diff --git a/components/src/Bing.Biz.OAuthLogin/Bing.Biz.OAuthLogin.csproj b/components/src/Bing.Biz.OAuthLogin/Bing.Biz.OAuthLogin.csproj
index 480e0e4a0..2e5ae873c 100644
--- a/components/src/Bing.Biz.OAuthLogin/Bing.Biz.OAuthLogin.csproj
+++ b/components/src/Bing.Biz.OAuthLogin/Bing.Biz.OAuthLogin.csproj
@@ -7,12 +7,13 @@ Bing是一个.net core平台下的应用框架,旨在于提升小型团队的
-
+
+
diff --git a/components/src/Bing.Biz.OAuthLogin/Core/AccessTokenParam.cs b/components/src/Bing.Biz.OAuthLogin/Core/AccessTokenParam.cs
index 8de6bc553..11c26db03 100644
--- a/components/src/Bing.Biz.OAuthLogin/Core/AccessTokenParam.cs
+++ b/components/src/Bing.Biz.OAuthLogin/Core/AccessTokenParam.cs
@@ -1,14 +1,14 @@
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Bing.Exceptions;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.OAuthLogin.Core
{
///
/// 访问令牌参数
///
- public class AccessTokenParam : IValidation
+ public class AccessTokenParam : IVerifyModel
{
///
/// 授权类型
@@ -31,7 +31,7 @@ public class AccessTokenParam : IValidation
///
/// 验证
///
- public virtual ValidationResultCollection Validate()
+ public virtual IValidationResult Validate()
{
var result = DataAnnotationValidation.Validate(this);
if (result.IsValid)
diff --git a/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationConfigBase.cs b/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationConfigBase.cs
index 3ea3930a2..10734ff43 100644
--- a/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationConfigBase.cs
+++ b/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationConfigBase.cs
@@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Bing.Exceptions;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.OAuthLogin.Core
{
diff --git a/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationParamBase.cs b/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationParamBase.cs
index 83ec53c1e..1fe6dde43 100644
--- a/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationParamBase.cs
+++ b/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationParamBase.cs
@@ -3,14 +3,14 @@
using System.Linq;
using Bing.Exceptions;
using Bing.ObjectMapping;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.OAuthLogin.Core
{
///
/// 授权参数基类
///
- public class AuthorizationParamBase : IValidation
+ public class AuthorizationParamBase : IVerifyModel
{
///
/// 授权类型
@@ -45,7 +45,7 @@ private void InitState()
///
/// 验证
///
- public virtual ValidationResultCollection Validate()
+ public virtual IValidationResult Validate()
{
var result = DataAnnotationValidation.Validate(this);
if (result.IsValid)
diff --git a/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationUserParamBase.cs b/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationUserParamBase.cs
index 285fb2563..3ca6749ba 100644
--- a/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationUserParamBase.cs
+++ b/components/src/Bing.Biz.OAuthLogin/Core/AuthorizationUserParamBase.cs
@@ -2,14 +2,14 @@
using System.Linq;
using Bing.Exceptions;
using Bing.ObjectMapping;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.OAuthLogin.Core
{
///
/// 授权用户参数基类
///
- public class AuthorizationUserParamBase : IValidation
+ public class AuthorizationUserParamBase : IVerifyModel
{
///
/// 访问令牌
@@ -20,7 +20,7 @@ public class AuthorizationUserParamBase : IValidation
///
/// 验证
///
- public ValidationResultCollection Validate()
+ public IValidationResult Validate()
{
var result = DataAnnotationValidation.Validate(this);
if (result.IsValid)
diff --git a/components/src/Bing.Biz.OAuthLogin/MeiliShuo/Configs/MeiliShuoAuthorizationConfig.cs b/components/src/Bing.Biz.OAuthLogin/MeiliShuo/Configs/MeiliShuoAuthorizationConfig.cs
index cfdddcd3f..3c44e66c2 100644
--- a/components/src/Bing.Biz.OAuthLogin/MeiliShuo/Configs/MeiliShuoAuthorizationConfig.cs
+++ b/components/src/Bing.Biz.OAuthLogin/MeiliShuo/Configs/MeiliShuoAuthorizationConfig.cs
@@ -12,18 +12,18 @@ public class MeiliShuoAuthorizationConfig : AuthorizationConfigBase
/// 应用标识
///
[Required(ErrorMessage = "应用标识[AppId]不能为空")]
- public string AppId { get; set; }
+ public override string AppId { get; set; }
///
/// 应用密钥
///
[Required(ErrorMessage = "应用密钥[AppKey]不能为空")]
- public string AppKey { get; set; }
+ public override string AppKey { get; set; }
///
/// 回调地址
///
[Required(ErrorMessage = "回调地址[CallbackUrl]不能为空")]
- public string CallbackUrl { get; set; }
+ public override string CallbackUrl { get; set; }
}
}
diff --git a/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayAppPayService.cs b/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayAppPayService.cs
index 72c83dcbb..46943a784 100644
--- a/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayAppPayService.cs
+++ b/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayAppPayService.cs
@@ -12,7 +12,6 @@ public interface IAlipayAppPayService
/// 支付
///
/// 支付参数
- ///
Task PayAsync(AlipayAppPayRequest request);
}
}
diff --git a/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayReturnService.cs b/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayReturnService.cs
index 2ada0f423..225c26160 100644
--- a/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayReturnService.cs
+++ b/components/src/Bing.Biz.Payments/Alipay/Abstractions/IAlipayReturnService.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.Payments.Alipay.Abstractions
{
diff --git a/components/src/Bing.Biz.Payments/Alipay/Configs/AlipayConfig.cs b/components/src/Bing.Biz.Payments/Alipay/Configs/AlipayConfig.cs
index aab8a9b8c..5f2f23ec0 100644
--- a/components/src/Bing.Biz.Payments/Alipay/Configs/AlipayConfig.cs
+++ b/components/src/Bing.Biz.Payments/Alipay/Configs/AlipayConfig.cs
@@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Bing.Exceptions;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.Payments.Alipay.Configs
{
@@ -19,7 +19,7 @@ public class AlipayConfig
///
/// 应用标识
///
- [Required(ErrorMessage = "应用标识[AppId]不能为空")]
+ [Required(ErrorMessage = "应用标识[GetAppId]不能为空")]
public string AppId { get; set; }
///
diff --git a/components/src/Bing.Biz.Payments/Alipay/Services/AlipayNotifyService.cs b/components/src/Bing.Biz.Payments/Alipay/Services/AlipayNotifyService.cs
index adbd8b417..ba4c6c1bf 100644
--- a/components/src/Bing.Biz.Payments/Alipay/Services/AlipayNotifyService.cs
+++ b/components/src/Bing.Biz.Payments/Alipay/Services/AlipayNotifyService.cs
@@ -5,6 +5,7 @@
using Bing.Extensions;
using Bing.Parameters;
using Bing.Utils.Parameters;
+using Bing.Validation;
using Bing.Validations;
namespace Bing.Biz.Payments.Alipay.Services
diff --git a/components/src/Bing.Biz.Payments/Alipay/Services/Base/AlipayNotifyServiceBase.cs b/components/src/Bing.Biz.Payments/Alipay/Services/Base/AlipayNotifyServiceBase.cs
index 681e0a0e2..6c0fdafba 100644
--- a/components/src/Bing.Biz.Payments/Alipay/Services/Base/AlipayNotifyServiceBase.cs
+++ b/components/src/Bing.Biz.Payments/Alipay/Services/Base/AlipayNotifyServiceBase.cs
@@ -7,7 +7,7 @@
using Bing.Logs;
using Bing.Utils.Parameters;
using Bing.Utils.Signatures;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.Payments.Alipay.Services.Base
{
diff --git a/components/src/Bing.Biz.Payments/Bing.Biz.Payments.csproj b/components/src/Bing.Biz.Payments/Bing.Biz.Payments.csproj
index 45967cd5c..0031726b5 100644
--- a/components/src/Bing.Biz.Payments/Bing.Biz.Payments.csproj
+++ b/components/src/Bing.Biz.Payments/Bing.Biz.Payments.csproj
@@ -1,35 +1,14 @@
-
-
- netstandard2.0
- Bing.Biz.Payments是Bing应用框架的支付操作类库。
-Bing是一个.net core平台下的应用框架,旨在于提升小型团队的开发能力,由常用公共操作类、架构基类、第三方组件封装、第三方业务接口封装等组成。
-
-
+
-
-
-
+
-
-
-
-
-
+
True
- True
- PayResource.resx
-
-
- ResXFileCodeGenerator
- PayResource.Designer.cs
-
-
-
diff --git a/components/src/Bing.Biz.Payments/Core/DownloadBillParam.cs b/components/src/Bing.Biz.Payments/Core/DownloadBillParam.cs
new file mode 100644
index 000000000..195466d86
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Core/DownloadBillParam.cs
@@ -0,0 +1,23 @@
+namespace Bing.Biz.Payments.Core
+{
+ ///
+ /// 下载账单参数
+ ///
+ public class DownloadBillParam: DownloadBillParamBase
+ {
+ ///
+ /// 账单类型
+ ///
+ public string BillType { get; set; }
+
+ ///
+ /// 资金账户类型
+ ///
+ public string AccountType { get; set; }
+
+ ///
+ /// 压缩账单
+ ///
+ public string TarType { get; set; }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Core/DownloadBillParamBase.cs b/components/src/Bing.Biz.Payments/Core/DownloadBillParamBase.cs
new file mode 100644
index 000000000..aa6755f1c
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Core/DownloadBillParamBase.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Linq;
+using Bing.Exceptions;
+using Bing.ObjectMapping;
+using Bing.Validation;
+
+namespace Bing.Biz.Payments.Core
+{
+ ///
+ /// 下载账单参数基类
+ ///
+ public class DownloadBillParamBase : IVerifyModel
+ {
+ ///
+ /// 账单日期
+ ///
+ public DateTime BillDate { get; set; }
+
+ ///
+ /// 验证
+ ///
+ public virtual IValidationResult Validate()
+ {
+ var result = DataAnnotationValidation.Validate(this);
+ if (result.IsValid)
+ return ValidationResultCollection.Success;
+ throw new Warning(result.First().ErrorMessage);
+ }
+
+ ///
+ /// 转换为下载账单参数
+ ///
+ public virtual DownloadBillParam ToParam() => this.MapTo();
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Core/DownloadBillWay.cs b/components/src/Bing.Biz.Payments/Core/DownloadBillWay.cs
new file mode 100644
index 000000000..09f24d2a0
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Core/DownloadBillWay.cs
@@ -0,0 +1,13 @@
+namespace Bing.Biz.Payments.Core
+{
+ ///
+ /// 下载对账单方式
+ ///
+ public enum DownloadBillWay
+ {
+ WechatAllBill,
+ WechatSuccessBill,
+ WechatRefundBill,
+ WechatRechargeRefund,
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Core/INotifyService.cs b/components/src/Bing.Biz.Payments/Core/INotifyService.cs
index bcaa32997..7895f046c 100644
--- a/components/src/Bing.Biz.Payments/Core/INotifyService.cs
+++ b/components/src/Bing.Biz.Payments/Core/INotifyService.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.Payments.Core
{
@@ -28,7 +28,6 @@ public interface INotifyService
/// 获取参数
///
/// 参数名
- ///
string GetParam(string name);
///
@@ -36,31 +35,26 @@ public interface INotifyService
///
/// 类型
/// 参数名
- ///
T GetParam(string name);
///
/// 获取参数集合
///
- ///
IDictionary GetParams();
///
/// 验证
///
- ///
Task ValidateAsync();
///
/// 返回成功消息
///
- ///
string Success();
///
/// 返回失败消息
///
- ///
string Fail();
}
}
diff --git a/components/src/Bing.Biz.Payments/Core/PayParamBase.cs b/components/src/Bing.Biz.Payments/Core/PayParamBase.cs
index 81d72f2f6..9ae1b76a9 100644
--- a/components/src/Bing.Biz.Payments/Core/PayParamBase.cs
+++ b/components/src/Bing.Biz.Payments/Core/PayParamBase.cs
@@ -4,14 +4,14 @@
using Bing.Exceptions;
using Bing.Extensions;
using Bing.ObjectMapping;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.Payments.Core
{
///
/// 支付参数基类
///
- public class PayParamBase : IValidation
+ public class PayParamBase : IVerifyModel
{
///
/// 订单标题
@@ -51,7 +51,7 @@ private void InitSubject()
///
/// 验证
///
- public virtual ValidationResultCollection Validate()
+ public virtual IValidationResult Validate()
{
ValidateMoney();
var result = DataAnnotationValidation.Validate(this);
diff --git a/components/src/Bing.Biz.Payments/Core/PayResult.cs b/components/src/Bing.Biz.Payments/Core/PayResult.cs
index 21083e60d..3855b663d 100644
--- a/components/src/Bing.Biz.Payments/Core/PayResult.cs
+++ b/components/src/Bing.Biz.Payments/Core/PayResult.cs
@@ -5,6 +5,24 @@
///
public class PayResult
{
+ ///
+ /// 初始化一个类型的实例
+ ///
+ public PayResult() { }
+
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 是否成功
+ /// 交易编号
+ /// 支付接口返回的原始消息
+ public PayResult(bool success, string tradeId, string raw)
+ {
+ Success = success;
+ TradeId = tradeId;
+ Raw = raw;
+ }
+
///
/// 是否成功
///
@@ -34,23 +52,5 @@ public class PayResult
/// 请求参数
///
public string Parameter { get; set; }
-
- ///
- /// 初始化一个类型的实例
- ///
- public PayResult() { }
-
- ///
- /// 初始化一个类型的实例
- ///
- /// 是否成功
- /// 交易编号
- /// 支付接口返回的原始消息
- public PayResult(bool success, string tradeId, string raw)
- {
- Success = success;
- TradeId = tradeId;
- Raw = raw;
- }
}
}
diff --git a/components/src/Bing.Biz.Payments/Core/PayWay.cs b/components/src/Bing.Biz.Payments/Core/PayWay.cs
index bed4ca8fc..fd333a99d 100644
--- a/components/src/Bing.Biz.Payments/Core/PayWay.cs
+++ b/components/src/Bing.Biz.Payments/Core/PayWay.cs
@@ -38,39 +38,57 @@ public enum PayWay
AlipayAppPay,
///
- /// 微信App支付
+ /// 微信付款码支付
///
- [Description("微信App支付")]
- WechatpayAppPay,
+ ///
+ /// 用户打开微信钱包-付款码的界面,商户扫码后提交完成支付
+ ///
+ [Description("微信付款码支付")]
+ WechatpayPaymentCodePay,
///
- /// 微信小程序支付
+ /// 微信JsApi支付
///
- [Description("微信小程序支付")]
- WechatpayMiniProgramPay,
+ ///
+ /// 用户通过微信扫码,关注公众号等方式进入商家H5页面,并在微信内调用JsSdk完成支付
+ ///
+ [Description("微信JsApi支付")]
+ WechatpayJsApiPay,
///
- /// 微信电脑网站支付
+ /// 微信Native支付
///
- [Description("微信电脑网站支付")]
- WechatpayPagePay,
+ ///
+ /// 用户打开“微信扫一扫”,扫描商户的二维码后完成付款
+ ///
+ [Description("微信Native支付")]
+ WechatpayNativePay,
///
- /// 微信手机网站支付
+ /// 微信App支付
///
- [Description("微信手机网站支付")]
- WechatpayWapPay,
+ ///
+ /// 商户APP中集成微信SDK,用户点击后跳转到微信内完成支付
+ ///
+ [Description("微信App支付")]
+ WechatpayAppPay,
///
- /// 微信公众号支付
+ /// 微信H5支付
///
- [Description("微信公众号支付")]
- WechatpayPublicPay,
+ ///
+ /// 用户在微信以外的手机浏览器请求微信支付的场景唤醒微信支付
+ ///
+ [Description("微信H5支付")]
+ WechatpayH5Pay,
///
- /// 微信条码支付
+ /// 微信小程序支付
///
- [Description("微信条码支付")]
- WechatpayBarcodePay,
+ ///
+ /// 用户在微信小程序中使用微信支付的场景
+ ///
+ [Description("微信小程序支付")]
+ WechatpayMiniProgramPay,
}
}
diff --git a/components/src/Bing.Biz.Payments/Core/RefundResult.cs b/components/src/Bing.Biz.Payments/Core/RefundResult.cs
new file mode 100644
index 000000000..f0c6bbe74
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Core/RefundResult.cs
@@ -0,0 +1,58 @@
+namespace Bing.Biz.Payments.Core
+{
+ ///
+ /// 退款结果
+ ///
+ public class RefundResult
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ public RefundResult()
+ {
+ }
+
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 是否成功
+ /// 交易编号
+ /// 支付接口返回的原始消息
+ public RefundResult(bool success, string tradeId, string raw)
+ {
+ Success = success;
+ TradeId = tradeId;
+ Raw = raw;
+ }
+
+ ///
+ /// 是否成功
+ ///
+ public bool Success { get; }
+
+ ///
+ /// 交易编号,外部支付系统的交易流水号
+ ///
+ public string TradeId { get; }
+
+ ///
+ /// 支付接口返回的原始消息
+ ///
+ public string Raw { get; }
+
+ ///
+ /// 结果
+ ///
+ public string Result { get; set; }
+
+ ///
+ /// 消息
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// 请求参数
+ ///
+ public string Parameter { get; set; }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Factories/PayFactory.cs b/components/src/Bing.Biz.Payments/Factories/PayFactory.cs
index 80ccb5178..b136a48d6 100644
--- a/components/src/Bing.Biz.Payments/Factories/PayFactory.cs
+++ b/components/src/Bing.Biz.Payments/Factories/PayFactory.cs
@@ -40,7 +40,6 @@ public PayFactory(IAlipayConfigProvider alipayConfigProvider, IWechatpayConfigPr
/// 创建支付服务
///
/// 支付方式
- ///
public IPayService CreatePayService(PayWay way)
{
switch (way)
@@ -60,23 +59,23 @@ public IPayService CreatePayService(PayWay way)
case PayWay.AlipayWapPay:
return new AlipayWapPayService(_alipayConfigProvider);
+ case PayWay.WechatpayPaymentCodePay:
+ return new WechatpayPaymentCodePayService(_wechatpayConfigProvider);
+
+ case PayWay.WechatpayJsApiPay:
+ return new WechatpayJsApiPayService(_wechatpayConfigProvider);
+
+ case PayWay.WechatpayNativePay:
+ return new WechatpayNativePayService(_wechatpayConfigProvider);
+
case PayWay.WechatpayAppPay:
return new WechatpayAppPayService(_wechatpayConfigProvider);
case PayWay.WechatpayMiniProgramPay:
return new WechatpayMiniProgramPayService(_wechatpayConfigProvider);
- case PayWay.WechatpayPagePay:
- return new WechatpayPagePayService(_wechatpayConfigProvider);
-
- case PayWay.WechatpayWapPay:
- return new WechatpayWapPayService(_wechatpayConfigProvider);
-
- case PayWay.WechatpayPublicPay:
- return new WechatpayPublicPayService(_wechatpayConfigProvider);
-
- case PayWay.WechatpayBarcodePay:
- return new WechatpayBarcodePayService(_wechatpayConfigProvider);
+ case PayWay.WechatpayH5Pay:
+ return new WechatpayH5PayService(_wechatpayConfigProvider);
}
throw new NotImplementedException(way.Description());
@@ -148,64 +147,36 @@ public IAlipayWapPayService CreateAlipayWapPayService()
///
/// 创建微信回调通知服务
///
- ///
- public IWechatpayNotifyService CreateWechatpayNotifyService()
- {
- return new WechatpayNotifyService(_wechatpayConfigProvider);
- }
+ public IWechatpayNotifyService CreateWechatpayNotifyService() => new WechatpayNotifyService(_wechatpayConfigProvider);
///
- /// 创建微信App支付服务
+ /// 创建微信下载交易账单服务
///
- ///
- public IWechatpayAppPayService CreateWechatpayAppPayService()
- {
- return new WechatpayAppPayService(_wechatpayConfigProvider);
- }
+ public IWechatpayDownloadBillService CreateWechatpayDownloadBillService() => new WechatpayDownloadBillService(_wechatpayConfigProvider);
///
- /// 创建微信小程序支付服务
+ /// 创建微信付款码支付服务
///
- ///
- public IWechatpayMiniProgramPayService CreateWechatpayMiniProgramPayService()
- {
- return new WechatpayMiniProgramPayService(_wechatpayConfigProvider);
- }
+ public IWechatpayPaymentCodePayService CreateWechatpayBarcodePayService() => new WechatpayPaymentCodePayService(_wechatpayConfigProvider);
///
- /// 创建微信电脑网站支付服务
+ /// 创建微信JsApi支付服务
///
- ///
- public IWechatpayPagePayService CreateWechatpayPagePayService()
- {
- return new WechatpayPagePayService(_wechatpayConfigProvider);
- }
+ public IWechatpayJsApiPayService CreateWechatpayJsApiPayService() => new WechatpayJsApiPayService(_wechatpayConfigProvider);
///
- /// 创建微信手机网站支付服务
+ /// 创建微信App支付服务
///
- ///
- public IWechatpayWapPayService CreateWechatpayWapPayService()
- {
- return new WechatpayWapPayService(_wechatpayConfigProvider);
- }
+ public IWechatpayAppPayService CreateWechatpayAppPayService() => new WechatpayAppPayService(_wechatpayConfigProvider);
///
- /// 创建微信公众号支付服务
+ /// 创建微信H5支付服务
///
- ///
- public IWechatpayPublicPayService CreateWechatpayPublicPayService()
- {
- return new WechatpayPublicPayService(_wechatpayConfigProvider);
- }
+ public IWechatpayH5PayService CreateH5PayService() => new WechatpayH5PayService(_wechatpayConfigProvider);
///
- /// 创建微信条码支付服务
+ /// 创建微信小程序支付服务
///
- ///
- public IWechatpayBarcodePayService CreateWechatpayBarcodePayService()
- {
- return new WechatpayBarcodePayService(_wechatpayConfigProvider);
- }
+ public IWechatpayMiniProgramPayService CreateWechatpayMiniProgramPayService() => new WechatpayMiniProgramPayService(_wechatpayConfigProvider);
}
}
diff --git a/components/src/Bing.Biz.Payments/IPayFactory.cs b/components/src/Bing.Biz.Payments/IPayFactory.cs
index 4c91ebec2..14d0834f8 100644
--- a/components/src/Bing.Biz.Payments/IPayFactory.cs
+++ b/components/src/Bing.Biz.Payments/IPayFactory.cs
@@ -13,91 +13,76 @@ public interface IPayFactory
/// 创建支付服务
///
/// 支付方式
- ///
IPayService CreatePayService(PayWay way);
///
/// 创建支付宝回调通知服务
///
- ///
IAlipayNotifyService CreateAlipayNotifyService();
///
/// 创建支付宝返回服务
///
- ///
IAlipayReturnService CreateAlipayReturnService();
///
/// 创建支付宝条码支付服务
///
- ///
IAlipayBarcodePayService CreateAlipayBarcodePayService();
///
/// 创建支付宝二维码支付服务
///
- ///
IAlipayQrCodePayService CreateAlipayQrCodePayService();
///
/// 创建支付宝App支付服务
///
- ///
IAlipayAppPayService CreateAlipayAppPayService();
///
/// 创建支付宝电脑网站支付服务
///
- ///
IAlipayPagePayService CreateAlipayPagePayService();
///
/// 创建支付宝手机网站支付服务
///
- ///
IAlipayWapPayService CreateAlipayWapPayService();
///
/// 创建微信回调通知服务
///
- ///
IWechatpayNotifyService CreateWechatpayNotifyService();
///
- /// 创建微信App支付服务
+ /// 创建微信下载交易账单服务
///
- ///
- IWechatpayAppPayService CreateWechatpayAppPayService();
+ IWechatpayDownloadBillService CreateWechatpayDownloadBillService();
///
- /// 创建微信小程序支付服务
+ /// 创建微信付款码支付服务
///
- ///
- IWechatpayMiniProgramPayService CreateWechatpayMiniProgramPayService();
+ IWechatpayPaymentCodePayService CreateWechatpayBarcodePayService();
///
- /// 创建微信电脑网站支付服务
+ /// 创建微信JsApi支付服务
///
- ///
- IWechatpayPagePayService CreateWechatpayPagePayService();
+ IWechatpayJsApiPayService CreateWechatpayJsApiPayService();
///
- /// 创建微信手机网站支付服务
+ /// 创建微信App支付服务
///
- ///
- IWechatpayWapPayService CreateWechatpayWapPayService();
+ IWechatpayAppPayService CreateWechatpayAppPayService();
///
- /// 创建微信公众号支付服务
+ /// 创建微信H5支付服务
///
- ///
- IWechatpayPublicPayService CreateWechatpayPublicPayService();
+ IWechatpayH5PayService CreateH5PayService();
///
- /// 创建微信条码支付服务
+ /// 创建微信小程序支付服务
///
- ///
- IWechatpayBarcodePayService CreateWechatpayBarcodePayService();
+ IWechatpayMiniProgramPayService CreateWechatpayMiniProgramPayService();
}
}
diff --git a/components/src/Bing.Biz.Payments/Properties/PayResource.Designer.cs b/components/src/Bing.Biz.Payments/Properties/PayResource.Designer.cs
index f92eb0b9f..0107521be 100644
--- a/components/src/Bing.Biz.Payments/Properties/PayResource.Designer.cs
+++ b/components/src/Bing.Biz.Payments/Properties/PayResource.Designer.cs
@@ -19,7 +19,7 @@ namespace Bing.Biz.Payments.Properties {
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class PayResource {
@@ -39,7 +39,7 @@ internal PayResource() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Bing.Biz.Payments.Properties.PayResource", typeof(PayResource).Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Properties.PayResource", typeof(PayResource).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -47,8 +47,8 @@ internal PayResource() {
}
///
- /// 重写当前线程的 CurrentUICulture 属性
- /// 重写当前线程的 CurrentUICulture 属性。
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayAppPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayAppPayService.cs
index 2ceb9a4b2..77f069da9 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayAppPayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayAppPayService.cs
@@ -13,7 +13,6 @@ public interface IWechatpayAppPayService
/// 支付
///
/// 支付参数
- ///
Task PayAsync(WechatpayAppPayRequest request);
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayDownloadBillService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayDownloadBillService.cs
new file mode 100644
index 000000000..667848a9b
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayDownloadBillService.cs
@@ -0,0 +1,18 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+using Bing.Biz.Payments.Wechatpay.Results;
+
+namespace Bing.Biz.Payments.Wechatpay.Abstractions
+{
+ ///
+ /// 微信支付下载交易账单服务
+ ///
+ public interface IWechatpayDownloadBillService
+ {
+ ///
+ /// 下载对账单
+ ///
+ /// 下载对账单参数
+ Task DownloadAsync(WechatpayDownloadBillRequest request);
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayWapPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayH5PayService.cs
similarity index 65%
rename from components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayWapPayService.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayH5PayService.cs
index 5812a3771..24ab44f8b 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayWapPayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayH5PayService.cs
@@ -5,15 +5,14 @@
namespace Bing.Biz.Payments.Wechatpay.Abstractions
{
///
- /// 微信手机网站支付服务
+ /// 微信H5支付服务
///
- public interface IWechatpayWapPayService
+ public interface IWechatpayH5PayService
{
///
/// 支付
///
/// 支付参数
- ///
- Task PayAsync(WechatpayWapPayRequest request);
+ Task PayAsync(WechatpayH5PayRequest request);
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayBarcodePayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayJsApiPayService.cs
similarity index 65%
rename from components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayBarcodePayService.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayJsApiPayService.cs
index 78205ce43..f78a17fd3 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayBarcodePayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayJsApiPayService.cs
@@ -5,15 +5,14 @@
namespace Bing.Biz.Payments.Wechatpay.Abstractions
{
///
- /// 微信条码支付服务
+ /// 微信JsApi支付服务
///
- public interface IWechatpayBarcodePayService
+ public interface IWechatpayJsApiPayService
{
///
/// 支付
///
/// 支付参数
- ///
- Task PayAsync(WechatpayBarcodePayRequest request);
+ Task PayAsync(WechatpayJsApiPayRequest request);
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayMiniProgramPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayMiniProgramPayService.cs
index 657590bc7..339065355 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayMiniProgramPayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayMiniProgramPayService.cs
@@ -13,7 +13,6 @@ public interface IWechatpayMiniProgramPayService
/// 支付
///
/// 支付参数
- ///
Task PayAsync(WechatpayMiniProgramPayRequest request);
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPublicPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayNativePayService.cs
similarity index 65%
rename from components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPublicPayService.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayNativePayService.cs
index 427556087..805c89f22 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPublicPayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayNativePayService.cs
@@ -5,15 +5,14 @@
namespace Bing.Biz.Payments.Wechatpay.Abstractions
{
///
- /// 微信公众号支付服务
+ /// 微信扫码支付服务
///
- public interface IWechatpayPublicPayService
+ public interface IWechatpayNativePayService
{
///
/// 支付
///
/// 支付参数
- ///
- Task PayAsync(WechatpayPublicPayRequest request);
+ Task PayAsync(WechatpayNativePayRequest request);
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPagePayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPaymentCodePayService.cs
similarity index 65%
rename from components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPagePayService.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPaymentCodePayService.cs
index efd2890e3..ab94ad81f 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPagePayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayPaymentCodePayService.cs
@@ -5,15 +5,14 @@
namespace Bing.Biz.Payments.Wechatpay.Abstractions
{
///
- /// 微信电脑网站支付服务
+ /// 创建微信付款码支付服务
///
- public interface IWechatpayPagePayService
+ public interface IWechatpayPaymentCodePayService
{
///
/// 支付
///
/// 支付参数
- ///
- Task PayAsync(WechatpayPagePayRequest request);
+ Task PayAsync(WechatpayPaymentCodePayRequest request);
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayRefundService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayRefundService.cs
new file mode 100644
index 000000000..fccea226c
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Abstractions/IWechatpayRefundService.cs
@@ -0,0 +1,18 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Core;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+
+namespace Bing.Biz.Payments.Wechatpay.Abstractions
+{
+ ///
+ /// 微信退款服务
+ ///
+ public interface IWechatpayRefundService
+ {
+ ///
+ /// 退款
+ ///
+ /// 退款参数
+ Task RefundAsync(WechatRefundRequest request);
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Configs/IWechatpayConfigProvider.cs b/components/src/Bing.Biz.Payments/Wechatpay/Configs/IWechatpayConfigProvider.cs
index f7c83bc54..85485b3b8 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Configs/IWechatpayConfigProvider.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Configs/IWechatpayConfigProvider.cs
@@ -1,18 +1,16 @@
using System.Threading.Tasks;
-using Bing.Utils.Parameters;
namespace Bing.Biz.Payments.Wechatpay.Configs
{
///
- /// 微信支付配置提供器
+ /// 微信支付配置提供程序
///
public interface IWechatpayConfigProvider
{
///
/// 获取配置
///
- /// 参数管理器
- ///
- Task GetConfigAsync(IParameterManager parameterManager = null);
+ /// 参数
+ Task GetConfigAsync(object parameter = null);
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfig.cs b/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfig.cs
index f78b094fd..96399e2e7 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfig.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfig.cs
@@ -3,7 +3,7 @@
using Bing.Biz.Payments.Wechatpay.Enums;
using Bing.Exceptions;
using Bing.Helpers;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Biz.Payments.Wechatpay.Configs
{
@@ -21,7 +21,7 @@ public class WechatpayConfig
///
/// 应用标识
///
- [Required(ErrorMessage = "应用标识[AppId]不能为空")]
+ [Required(ErrorMessage = "应用标识[GetAppId]不能为空")]
public string AppId { get; set; }
///
@@ -46,6 +46,16 @@ public class WechatpayConfig
///
public string NotifyUrl { get; set; }
+ ///
+ /// 证书绝对路径
+ ///
+ public string Certificate { get; set; }
+
+ ///
+ /// 证书密码
+ ///
+ public string CertificatePassword { get; set; }
+
///
/// 验证
///
@@ -53,18 +63,32 @@ public void Validate()
{
var result = DataAnnotationValidation.Validate(this);
if (result.IsValid == false)
- {
throw new Warning(result.First().ErrorMessage);
- }
}
///
/// 获取统一下单地址
///
- ///
- public string GetOrderUrl()
- {
- return Url.Combine(GatewayUrl, "pay/unifiedorder");
- }
+ public string GetOrderUrl() => Url.Combine(GatewayUrl, "pay/unifiedorder");
+
+ ///
+ /// 获取付款码支付地址
+ ///
+ public string GetPaymentCodePayUrl() => Url.Combine(GatewayUrl, "pay/micropay");
+
+ ///
+ /// 获取关闭订单地址
+ ///
+ public string GetCloseOrderUrl() => Url.Combine(GatewayUrl, "pay/closeorder");
+
+ ///
+ /// 获取退款地址
+ ///
+ public string GetRefundUrl() => Url.Combine(GatewayUrl, "secapi/pay/refund");
+
+ ///
+ /// 获取下载对账单地址
+ ///
+ public string GetDownloadBillUrl() => Url.Combine(GatewayUrl, "pay/downloadbill");
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfigProvider.cs b/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfigProvider.cs
index a7091ae52..5ba3d4b67 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfigProvider.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConfigProvider.cs
@@ -1,5 +1,4 @@
using System.Threading.Tasks;
-using Bing.Utils.Parameters;
namespace Bing.Biz.Payments.Wechatpay.Configs
{
@@ -25,9 +24,8 @@ public WechatpayConfigProvider(WechatpayConfig config)
///
/// 获取配置
///
- /// 参数管理器
- ///
- public Task GetConfigAsync(IParameterManager parameterManager = null)
+ /// 参数
+ public Task GetConfigAsync(object parameter = null)
{
return Task.FromResult(_config);
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConst.cs b/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConst.cs
index fe5a893ac..146864514 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConst.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Configs/WechatpayConst.cs
@@ -139,5 +139,30 @@ public static class WechatpayConst
/// 用户授权码
///
public const string AuthCode = "auth_code";
+
+ ///
+ /// 对账单日期
+ ///
+ public const string BillDate = "bill_date";
+
+ ///
+ /// 账单类型
+ ///
+ public const string BillType = "bill_type";
+
+ ///
+ /// 压缩账单
+ ///
+ public const string TarType = "tar_type";
+
+ ///
+ /// 资金账户类型
+ ///
+ public const string AccountType = "account_type";
+
+ ///
+ /// 随机字符串
+ ///
+ public const string NonceStr = "nonce_str";
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Enums/WechatpayAccountType.cs b/components/src/Bing.Biz.Payments/Wechatpay/Enums/WechatpayAccountType.cs
new file mode 100644
index 000000000..134a86e54
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Enums/WechatpayAccountType.cs
@@ -0,0 +1,28 @@
+using System.ComponentModel;
+
+namespace Bing.Biz.Payments.Wechatpay.Enums
+{
+ ///
+ /// 微信支付资金账户类型
+ ///
+ public enum WechatpayAccountType
+ {
+ ///
+ /// 基本账户
+ ///
+ [Description("Basic")]
+ Basic,
+
+ ///
+ /// 运营账户
+ ///
+ [Description("Operation")]
+ Operation,
+
+ ///
+ /// 手续费账户
+ ///
+ [Description("Fees")]
+ Fees,
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Enums/WechatpayBillType.cs b/components/src/Bing.Biz.Payments/Wechatpay/Enums/WechatpayBillType.cs
new file mode 100644
index 000000000..4afaa0555
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Enums/WechatpayBillType.cs
@@ -0,0 +1,34 @@
+using System.ComponentModel;
+
+namespace Bing.Biz.Payments.Wechatpay.Enums
+{
+ ///
+ /// 微信支付账单类型
+ ///
+ public enum WechatpayBillType
+ {
+ ///
+ /// 所有订单信息,不含充值退款订单
+ ///
+ [Description("ALL")]
+ All,
+
+ ///
+ /// 成功支付订单,不含充值退款订单
+ ///
+ [Description("SUCCESS")]
+ Success,
+
+ ///
+ /// 退款订单,不含充值退款订单
+ ///
+ [Description("REFUND")]
+ Refund,
+
+ ///
+ /// 充值退款订单
+ ///
+ [Description("RECHARGE_REFUND")]
+ RechargeRefund,
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/IWechatpayParameterBuilder.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/IWechatpayParameterBuilder.cs
new file mode 100644
index 000000000..9d51abdfa
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/IWechatpayParameterBuilder.cs
@@ -0,0 +1,48 @@
+namespace Bing.Biz.Payments.Wechatpay.Parameters
+{
+ ///
+ /// 微信支付参数生成器
+ ///
+ public interface IWechatpayParameterBuilder
+ {
+ ///
+ /// 获取签名
+ ///
+ string GetSign();
+
+ ///
+ /// 获取Xml结果,包含签名
+ ///
+ string ToXml();
+
+ ///
+ /// 获取Xml结果,不包含签名
+ ///
+ string ToXmlNoContainsSign();
+
+ ///
+ /// 获取Json结果,包含签名
+ ///
+ string ToJson();
+ }
+
+ ///
+ /// 微信支付参数生成器
+ ///
+ public interface IWechatpayParameterBuilder : IWechatpayParameterBuilder
+ where TParameterBuilder : IWechatpayParameterBuilder
+ {
+ ///
+ /// 添加参数
+ ///
+ /// 参数名
+ /// 参数值
+ TParameterBuilder Add(string name, object value);
+
+ ///
+ /// 设置签名参数名称
+ ///
+ /// 参数名
+ TParameterBuilder SignParamName(string name);
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatRefundRequest.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatRefundRequest.cs
new file mode 100644
index 000000000..91043d226
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatRefundRequest.cs
@@ -0,0 +1,30 @@
+using Bing.Biz.Payments.Core;
+
+namespace Bing.Biz.Payments.Wechatpay.Parameters.Requests
+{
+ ///
+ /// 微信支付退款参数
+ ///
+ public class WechatRefundRequest : PayParamBase
+ {
+ ///
+ /// 退款原因
+ ///
+ public string RefundDescription { get; set; }
+
+ ///
+ /// 退款金额。单位:元
+ ///
+ public decimal RefundFee { get; set; }
+
+ ///
+ /// 商户退款单号
+ ///
+ public string RefundId { get; set; }
+
+ ///
+ /// 微信订单号或商户订单号
+ ///
+ public string TransactionId { get; set; }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayDownloadBillRequest.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayDownloadBillRequest.cs
new file mode 100644
index 000000000..199a6840a
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayDownloadBillRequest.cs
@@ -0,0 +1,42 @@
+using System;
+using Bing.Biz.Payments.Wechatpay.Enums;
+using Bing.Exceptions;
+using Bing.Extensions;
+using Bing.Validation;
+
+namespace Bing.Biz.Payments.Wechatpay.Parameters.Requests
+{
+ ///
+ /// 微信支付下载对账单接口参数
+ ///
+ public class WechatpayDownloadBillRequest : IVerifyModel
+ {
+ ///
+ /// 对账单日期
+ ///
+ public DateTime? BillDate { get; set; }
+
+ ///
+ /// 账单类型
+ ///
+ public WechatpayBillType BillType { get; set; } = WechatpayBillType.All;
+
+ ///
+ /// 验证
+ ///
+ public IValidationResult Validate()
+ {
+ if (BillDate == null)
+ throw new Warning("必须设置账单日期");
+ return ValidationResultCollection.Success;
+ }
+
+ ///
+ /// 获取账单日期
+ ///
+ public string GetBillDate()
+ {
+ return BillDate.SafeValue().ToString("yyyyMMdd");
+ }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayWapPayRequest.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayH5PayRequest.cs
similarity index 74%
rename from components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayWapPayRequest.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayH5PayRequest.cs
index 778bae0af..bddfcfa30 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayWapPayRequest.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayH5PayRequest.cs
@@ -3,9 +3,9 @@
namespace Bing.Biz.Payments.Wechatpay.Parameters.Requests
{
///
- /// 微信手机网站支付参数
+ /// 微信H5支付参数
///
- public class WechatpayWapPayRequest : PayParamBase
+ public class WechatpayH5PayRequest : PayParamBase
{
///
/// 附加数据,通知原样返回
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPublicPayRequest.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayJsApiPayRequest.cs
similarity index 80%
rename from components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPublicPayRequest.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayJsApiPayRequest.cs
index 12ab31475..83c6d733e 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPublicPayRequest.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayJsApiPayRequest.cs
@@ -3,9 +3,9 @@
namespace Bing.Biz.Payments.Wechatpay.Parameters.Requests
{
///
- /// 微信公众号支付参数
+ /// 微信JsApi支付参数
///
- public class WechatpayPublicPayRequest : PayParamBase
+ public class WechatpayJsApiPayRequest : PayParamBase
{
///
/// 用户标识
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPagePayRequest.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayNativePayRequest.cs
similarity index 74%
rename from components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPagePayRequest.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayNativePayRequest.cs
index af03c50bc..5baa57fb5 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPagePayRequest.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayNativePayRequest.cs
@@ -3,9 +3,9 @@
namespace Bing.Biz.Payments.Wechatpay.Parameters.Requests
{
///
- /// 微信电脑网站支付参数
+ /// 微信扫码支付参数
///
- public class WechatpayPagePayRequest : PayParamBase
+ public class WechatpayNativePayRequest : PayParamBase
{
///
/// 附加数据,通知时原样返回
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayBarcodePayRequest.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPaymentCodePayRequest.cs
similarity index 82%
rename from components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayBarcodePayRequest.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPaymentCodePayRequest.cs
index c617ff3bb..53e27154d 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayBarcodePayRequest.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/Requests/WechatpayPaymentCodePayRequest.cs
@@ -5,7 +5,7 @@ namespace Bing.Biz.Payments.Wechatpay.Parameters.Requests
///
/// 微信条码支付参数
///
- public class WechatpayBarcodePayRequest : PayParamBase
+ public class WechatpayPaymentCodePayRequest : PayParamBase
{
///
/// 用户付款授权码
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilder.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilder.cs
index 5079a7969..c08d67f39 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilder.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilder.cs
@@ -1,103 +1,57 @@
-using System.Xml;
-using Bing.Biz.Payments.Core;
+using Bing.Biz.Payments.Core;
using Bing.Biz.Payments.Wechatpay.Configs;
-using Bing.Biz.Payments.Wechatpay.Signatures;
using Bing.Extensions;
using Bing.Helpers;
-using Bing.Utils.Parameters;
-using Xml = Bing.Helpers.Xml;
namespace Bing.Biz.Payments.Wechatpay.Parameters
{
///
/// 微信支付参数生成器
///
- public class WechatpayParameterBuilder
+ public class WechatpayParameterBuilder : WechatpayParameterBuilderBase, IWechatpayParameterBuilder
{
///
- /// 参数生成器
- ///
- private readonly ParameterBuilder _builder;
-
- ///
- /// 微信支付配置
+ /// 初始化一个类型的实例
///
- public WechatpayConfig Config { get; }
+ /// 微信支付配置
+ public WechatpayParameterBuilder(WechatpayConfig config) : base(config)
+ {
+ }
///
- /// 初始化一个类型的实例
+ /// 初始化
///
- /// 微信支付配置
- public WechatpayParameterBuilder(WechatpayConfig config)
+ public void Init()
{
- config.CheckNotNull(nameof(config));
- Config = config;
- _builder = new ParameterBuilder();
+ this.AppId(Config.AppId)
+ .MerchantId(Config.MerchantId)
+ .SignType(Config.SignType.Description())
+ .NonceStr();
}
///
- /// 初始化
+ /// 初始化支付参数
///
/// 支付参数
public void Init(PayParam param)
{
- param.CheckNotNull(nameof(param));
+ param.CheckNull(nameof(param));
param.Init();
- AppId(Config.AppId)
- .MerchantId(Config.MerchantId)
- .SignType(Config.SignType.Description())
- .Add("nonce_str", Id.Guid())
- .SpbillCreateIp(Web.IP)
+ SpbillCreateIp(Web.IP)
.Body(param.Subject)
.OutTradeNo(param.OrderId)
.TotalFee(param.Money)
.NotifyUrl(param.NotifyUrl)
- .Attach(param.Attach)
- .OpenId(param.OpenId);
- }
-
- ///
- /// 添加参数
- ///
- /// 参数名
- /// 参数值
- ///
- public WechatpayParameterBuilder Add(string name, string value)
- {
- _builder.Add(name, value);
- return this;
- }
-
- ///
- /// 设置应用标识
- ///
- /// 应用标识
- ///
- public WechatpayParameterBuilder AppId(string appId)
- {
- _builder.Add(WechatpayConst.AppId, appId);
- return this;
- }
-
- ///
- /// 设置商户号
- ///
- /// 商户号
- ///
- public WechatpayParameterBuilder MerchantId(string merchantId)
- {
- _builder.Add(WechatpayConst.MerchantId, merchantId);
- return this;
+ .Attach(param.Attach);
}
///
/// 设置标题
///
/// 标题
- ///
public WechatpayParameterBuilder Body(string body)
{
- _builder.Add(WechatpayConst.Body, body);
+ Add(WechatpayConst.Body, body);
return this;
}
@@ -105,10 +59,9 @@ public WechatpayParameterBuilder Body(string body)
/// 设置商户订单号
///
/// 商户订单号
- ///
public WechatpayParameterBuilder OutTradeNo(string orderId)
{
- _builder.Add(WechatpayConst.OutTradeNo, orderId);
+ Add(WechatpayConst.OutTradeNo, orderId);
return this;
}
@@ -116,10 +69,9 @@ public WechatpayParameterBuilder OutTradeNo(string orderId)
/// 设置货币类型
///
/// 货币类型
- ///
public WechatpayParameterBuilder FeeType(string feeType)
{
- _builder.Add(WechatpayConst.FeeType, feeType);
+ Add(WechatpayConst.FeeType, feeType);
return this;
}
@@ -127,10 +79,9 @@ public WechatpayParameterBuilder FeeType(string feeType)
/// 设置总金额
///
/// 总金额。单位:元
- ///
public WechatpayParameterBuilder TotalFee(decimal totalFee)
{
- _builder.Add(WechatpayConst.TotalFee, Conv.ToInt(totalFee * 100));
+ Add(WechatpayConst.TotalFee, Conv.ToInt(totalFee * 100));
return this;
}
@@ -138,10 +89,9 @@ public WechatpayParameterBuilder TotalFee(decimal totalFee)
/// 设置回调通知地址
///
/// 回调通知地址
- ///
public WechatpayParameterBuilder NotifyUrl(string notifyUrl)
{
- _builder.Add(WechatpayConst.NotifyUrl, GetNotifyUrl(notifyUrl));
+ Add(WechatpayConst.NotifyUrl, GetNotifyUrl(notifyUrl));
return this;
}
@@ -149,24 +99,15 @@ public WechatpayParameterBuilder NotifyUrl(string notifyUrl)
/// 获取回调通知地址
///
/// 回调通知地址
- ///
- private string GetNotifyUrl(string notifyUrl)
- {
- if (notifyUrl.IsEmpty())
- {
- return Config.NotifyUrl;
- }
- return notifyUrl;
- }
+ private string GetNotifyUrl(string notifyUrl) => notifyUrl.IsEmpty() ? Config.NotifyUrl : notifyUrl;
///
/// 设置终端IP
///
/// 终端IP
- ///
public WechatpayParameterBuilder SpbillCreateIp(string ip)
{
- _builder.Add(WechatpayConst.SpbillCreateIp, ip);
+ Add(WechatpayConst.SpbillCreateIp, ip);
return this;
}
@@ -174,21 +115,9 @@ public WechatpayParameterBuilder SpbillCreateIp(string ip)
/// 设置交易类型
///
/// 交易类型
- ///
public WechatpayParameterBuilder TradeType(string type)
{
- _builder.Add(WechatpayConst.TradeType, type);
- return this;
- }
-
- ///
- /// 设置签名类型
- ///
- /// 签名类型
- ///
- public WechatpayParameterBuilder SignType(string type)
- {
- _builder.Add(WechatpayConst.SignType, type);
+ Add(WechatpayConst.TradeType, type);
return this;
}
@@ -196,10 +125,9 @@ public WechatpayParameterBuilder SignType(string type)
/// 设置伙伴标识
///
/// 伙伴标识
- ///
public WechatpayParameterBuilder PartnerId(string partnerId)
{
- _builder.Add(WechatpayConst.PartnerId, partnerId);
+ Add(WechatpayConst.PartnerId, partnerId);
return this;
}
@@ -207,10 +135,9 @@ public WechatpayParameterBuilder PartnerId(string partnerId)
/// 设置时间戳
///
/// 时间戳
- ///
public WechatpayParameterBuilder Timestamp(long timestamp = 0)
{
- _builder.Add(WechatpayConst.Timestamp, timestamp == 0 ? Time.GetUnixTimestamp() : timestamp);
+ Add(WechatpayConst.Timestamp, timestamp == 0 ? Time.GetUnixTimestamp() : timestamp);
return this;
}
@@ -218,10 +145,9 @@ public WechatpayParameterBuilder Timestamp(long timestamp = 0)
/// 设置包
///
/// 包。默认值:"Sign=WXPay"
- ///
public WechatpayParameterBuilder Package(string package = "Sign=WXPay")
{
- _builder.Add(WechatpayConst.Package, package);
+ Add(WechatpayConst.Package, package);
return this;
}
@@ -229,10 +155,9 @@ public WechatpayParameterBuilder Package(string package = "Sign=WXPay")
/// 设置附加数据
///
/// 附加数据
- ///
public WechatpayParameterBuilder Attach(string attach)
{
- _builder.Add(WechatpayConst.Attach, attach);
+ Add(WechatpayConst.Attach, attach);
return this;
}
@@ -240,10 +165,9 @@ public WechatpayParameterBuilder Attach(string attach)
/// 设置用户标识
///
/// 用户标识
- ///
public WechatpayParameterBuilder OpenId(string openId)
{
- _builder.Add(WechatpayConst.OpenId, openId);
+ Add(WechatpayConst.OpenId, openId);
return this;
}
@@ -251,99 +175,11 @@ public WechatpayParameterBuilder OpenId(string openId)
/// 设置用户授权码
///
/// 用户授权码
- ///
public WechatpayParameterBuilder AuthCode(string code)
{
- _builder.Add(WechatpayConst.AuthCode, code);
+ Add(WechatpayConst.AuthCode, code);
return this;
}
- ///
- /// 获取Xml结果,包含签名
- ///
- ///
- public string ToXml()
- {
- return ToXmlDocument(GetSignBuilder()).OuterXml;
- }
-
- ///
- /// 获取Xml文档
- ///
- /// 参数生成器
- ///
- private XmlDocument ToXmlDocument(ParameterBuilder builder)
- {
- var xml = new Xml();
- foreach (var param in builder.GetDictionary())
- {
- AddNode(xml, param.Key, param.Value);
- }
- return xml.Document;
- }
-
- ///
- /// 添加Xml节点
- ///
- /// Xml操作
- /// 键
- /// 值
- private void AddNode(Xml xml, string key, object value)
- {
- if (key.SafeString().ToLower() == WechatpayConst.TotalFee)
- {
- xml.AddNode(key, value);
- return;
- }
-
- xml.AddCDataNode(value, key);
- }
-
- ///
- /// 获取签名的参数生成器
- ///
- ///
- private ParameterBuilder GetSignBuilder()
- {
- var builder = new ParameterBuilder(_builder);
- builder.Add(WechatpayConst.Sign, GetSign());
- return builder;
- }
-
- ///
- /// 获取签名
- ///
- ///
- public string GetSign()
- {
- return SignManagerFactory.Create(Config, _builder).Sign();
- }
-
- ///
- /// 获取Xml结果,不包含签名
- ///
- ///
- public string ToXmlNoContainsSign()
- {
- return ToXmlDocument(_builder).OuterXml;
- }
-
- ///
- /// 获取Json结果,包含签名
- ///
- ///
- public string ToJson()
- {
- return GetSignBuilder().ToJson();
- }
-
- ///
- /// 输出结果
- ///
- ///
- public override string ToString()
- {
- return ToXml();
- }
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilderBase.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilderBase.cs
new file mode 100644
index 000000000..2c5f0ceaa
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilderBase.cs
@@ -0,0 +1,138 @@
+using System.Xml;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Signatures;
+using Bing.Extensions;
+using Bing.Helpers;
+using Bing.Utils.Parameters;
+
+namespace Bing.Biz.Payments.Wechatpay.Parameters
+{
+ ///
+ /// 微信支付参数生成器基类
+ ///
+ /// 微信支付参数生成器
+ public abstract class WechatpayParameterBuilderBase
+ where TParameterBuilder : IWechatpayParameterBuilder
+ {
+ ///
+ /// 参数生成器
+ ///
+ private readonly ParameterBuilder _builder;
+
+ ///
+ /// 签名参数名称
+ ///
+ private string _signName;
+
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置
+ protected WechatpayParameterBuilderBase(WechatpayConfig config)
+ {
+ config.CheckNull(nameof(config));
+ Config = config;
+ _builder = new ParameterBuilder();
+ }
+
+ ///
+ /// 微信支付配置
+ ///
+ public WechatpayConfig Config { get; }
+
+ ///
+ /// 添加参数
+ ///
+ /// 参数名
+ /// 参数值
+ public virtual TParameterBuilder Add(string name, object value)
+ {
+ _builder.Add(name, value);
+ return This();
+ }
+
+ ///
+ /// 获取签名
+ ///
+ public virtual string GetSign() => SignManagerFactory.Create(Config, _builder).Sign();
+
+ ///
+ /// 设置签名参数名称
+ ///
+ /// 参数名
+ public virtual TParameterBuilder SignParamName(string name)
+ {
+ _signName = name;
+ return This();
+ }
+
+ ///
+ /// 获取Xml结果,包含签名
+ ///
+ public virtual string ToXml() => ToXmlDocument(GetSignBuilder()).OuterXml;
+
+ ///
+ /// 获取Xml文档
+ ///
+ /// 参数生成器
+ private XmlDocument ToXmlDocument(ParameterBuilder builder)
+ {
+ var xml = new Xml();
+ foreach (var param in builder.GetDictionary())
+ AddNode(xml, param.Key, param.Value);
+ return xml.Document;
+ }
+
+ ///
+ /// 添加Xml节点
+ ///
+ /// Xml操作
+ /// 键
+ /// 值
+ private void AddNode(Xml xml, string key, object value)
+ {
+ if (key.SafeString().ToLower() == WechatpayConst.TotalFee)
+ {
+ xml.AddNode(key, value);
+ return;
+ }
+
+ xml.AddCDataNode(value, key);
+ }
+
+ ///
+ /// 获取签名的参数生成器
+ ///
+ private ParameterBuilder GetSignBuilder()
+ {
+ var builder = new ParameterBuilder(_builder);
+ builder.Add(GetSingName(), GetSign());
+ return builder;
+ }
+
+ ///
+ /// 获取签名参数名称
+ ///
+ private string GetSingName() => _signName.IsEmpty() ? WechatpayConst.Sign : _signName;
+
+ ///
+ /// 获取Xml结果,不包含签名
+ ///
+ public virtual string ToXmlNoContainsSign() => ToXmlDocument(_builder).OuterXml;
+
+ ///
+ /// 获取Json结果,包含签名
+ ///
+ public virtual string ToJson() => GetSignBuilder().ToJson();
+
+ ///
+ /// 输出结果
+ ///
+ public override string ToString() => ToXml();
+
+ ///
+ /// 返回自身
+ ///
+ private TParameterBuilder This() => (TParameterBuilder)(object)this;
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilderExtensions.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilderExtensions.cs
new file mode 100644
index 000000000..adc088d82
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayParameterBuilderExtensions.cs
@@ -0,0 +1,91 @@
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Helpers;
+
+namespace Bing.Biz.Payments.Wechatpay.Parameters
+{
+ ///
+ /// 微信支付参数生成器() 扩展
+ ///
+ public static class WechatpayParameterBuilderExtensions
+ {
+ #region AppId(设置应用标识)
+
+ ///
+ /// 设置应用标识
+ ///
+ /// 微信支付参数生成器
+ /// 微信支付参数生成器
+ /// 应用标识
+ public static TParameterBuilder AppId(this TParameterBuilder builder, string appId)
+ where TParameterBuilder : IWechatpayParameterBuilder
+ {
+ builder.Add(WechatpayConst.AppId, appId);
+ return builder;
+ }
+
+ #endregion
+
+ #region MerchantId(设置商户号)
+
+ ///
+ /// 设置商户号
+ ///
+ /// 微信支付参数生成器
+ /// 微信支付参数生成器
+ /// 商户号
+ public static TParameterBuilder MerchantId(this TParameterBuilder builder, string merchantId)
+ where TParameterBuilder : IWechatpayParameterBuilder
+ {
+ builder.Add(WechatpayConst.MerchantId, merchantId);
+ return builder;
+ }
+
+ #endregion
+
+ #region NonceStr(设置随机字符串)
+
+ ///
+ /// 设置随机字符串
+ ///
+ /// 微信支付参数生成器
+ /// 微信支付参数生成器
+ public static TParameterBuilder NonceStr(this TParameterBuilder builder)
+ where TParameterBuilder : IWechatpayParameterBuilder
+ {
+ builder.Add(WechatpayConst.NonceStr, Id.Guid());
+ return builder;
+ }
+
+ ///
+ /// 设置随机字符串
+ ///
+ /// 微信支付参数生成器
+ /// 微信支付参数生成器
+ /// 随机字符串
+ public static TParameterBuilder NonceStr(this TParameterBuilder builder, string nonceStr)
+ where TParameterBuilder : IWechatpayParameterBuilder
+ {
+ builder.Add(WechatpayConst.NonceStr, nonceStr);
+ return builder;
+ }
+
+ #endregion
+
+ #region SignType(设置签名类型)
+
+ ///
+ /// 设置签名类型
+ ///
+ /// 微信支付参数生成器
+ /// 微信支付参数生成器
+ /// 签名类型
+ public static TParameterBuilder SignType(this TParameterBuilder builder, string type)
+ where TParameterBuilder : IWechatpayParameterBuilder
+ {
+ builder.Add(WechatpayConst.SignType, type);
+ return builder;
+ }
+
+ #endregion
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayRefundParameterBuilder.cs b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayRefundParameterBuilder.cs
new file mode 100644
index 000000000..46677ced6
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Parameters/WechatpayRefundParameterBuilder.cs
@@ -0,0 +1,77 @@
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+using Bing.Extensions;
+using Bing.Helpers;
+
+namespace Bing.Biz.Payments.Wechatpay.Parameters
+{
+ ///
+ /// 微信支付退款参数生成器
+ ///
+ public class WechatpayRefundParameterBuilder : WechatpayParameterBuilder
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置
+ public WechatpayRefundParameterBuilder(WechatpayConfig config) : base(config)
+ {
+ }
+
+ ///
+ /// 初始化退款参数
+ ///
+ /// 退款参数
+ public void Init(WechatRefundRequest param)
+ {
+ param.CheckNull(nameof(param));
+ RefundFee(param.RefundFee)
+ .Description(param.RefundDescription)
+ .RefundId(param.RefundId)
+ .TransactionId(param.TransactionId)
+ .NotifyUrl(param.NotifyUrl)
+ .OutTradeNo(param.OrderId)
+ .TotalFee(param.Money);
+ }
+
+ ///
+ /// 设置退款金额
+ ///
+ /// 退款金额。单位:元
+ public WechatpayRefundParameterBuilder RefundFee(decimal refundFee)
+ {
+ Add("refund_fee", Conv.ToInt(refundFee * 100));
+ return this;
+ }
+
+ ///
+ /// 设置微信订单号
+ ///
+ /// 微信订单号
+ public WechatpayRefundParameterBuilder TransactionId(string transactionId)
+ {
+ Add("transaction_id", transactionId);
+ return this;
+ }
+
+ ///
+ /// 设置商户退款单号
+ ///
+ /// 商户退款单号
+ public WechatpayRefundParameterBuilder RefundId(string refundId)
+ {
+ Add("out_refund_no", refundId);
+ return this;
+ }
+
+ ///
+ /// 设置退款原因
+ ///
+ /// 退款原因
+ public WechatpayRefundParameterBuilder Description(string description)
+ {
+ Add("refund_desc", description);
+ return this;
+ }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayBillInfo.cs b/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayBillInfo.cs
new file mode 100644
index 000000000..c4d38116c
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayBillInfo.cs
@@ -0,0 +1,165 @@
+namespace Bing.Biz.Payments.Wechatpay.Results
+{
+ ///
+ /// 微信对账单信息
+ ///
+ public class WechatpayBillInfo
+ {
+ ///
+ /// 交易时间
+ ///
+ public string TransactionTime { get; set; }
+
+ ///
+ /// 公众账号ID
+ ///
+ public string AppId { get; set; }
+
+ ///
+ /// 商户号
+ ///
+ public string MerchantId { get; set; }
+
+ ///
+ /// 子商户号/特约商户号
+ ///
+ public string SubMerchantId { get; set; }
+
+ ///
+ /// 设备号
+ ///
+ public string DeviceNumber { get; set; }
+
+ ///
+ /// 微信订单号
+ ///
+ public string TradeId { get; set; }
+
+ ///
+ /// 商户订单号
+ ///
+ public string OrderId { get; set; }
+
+ ///
+ /// 用户标识
+ ///
+ public string OpenId { get; set; }
+
+ ///
+ /// 交易类型
+ ///
+ ///
+ /// MICROPAY:付款码支付
+ /// JSAPI:JSAPI支付、小程序支付
+ /// NATIVE:Native支付
+ /// APP:APP支付
+ /// FACE:刷脸支付
+ ///
+ public string TradeType { get; set; }
+
+ ///
+ /// 交易状态
+ ///
+ ///
+ /// SUCCESS:支付成功,说明该行数据为一笔支付成功的订单
+ /// REFUND:转入退款,说明该行数据为一笔发起退款成功的退款单
+ /// REVOKED:已撤销,说明该行数据为一笔用户支付成功后发起撤销的退款单
+ ///
+ public string TradeStatus { get; set; }
+
+ ///
+ /// 付款银行
+ ///
+ public string Bank { get; set; }
+
+ ///
+ /// 货币种类
+ ///
+ public string CurrencyType { get; set; }
+
+ ///
+ /// 总金额/应结订单金额(元)
+ ///
+ public decimal TotalAmount { get; set; }
+
+ ///
+ /// 代金券或立减优惠金额(元)
+ ///
+ public decimal CouponAmount { get; set; }
+
+ ///
+ /// 退款申请时间
+ ///
+ public string RefundApplyTime { get; set; }
+
+ ///
+ /// 退款成功时间
+ ///
+ public string RefundTime { get; set; }
+
+ ///
+ /// 微信退款单号
+ ///
+ public string WechatpayRefundId { get; set; }
+
+ ///
+ /// 商户退款单号
+ ///
+ public string MerchantRefundId { get; set; }
+
+ ///
+ /// 退款金额(元)
+ ///
+ public decimal RefundAmount { get; set; }
+
+ ///
+ /// 代金券或立减优惠退款金额/充值券退款金额(元)
+ ///
+ public decimal CouponRefundAmount { get; set; }
+
+ ///
+ /// 退款类型
+ ///
+ public string RefundType { get; set; }
+
+ ///
+ /// 退款状态
+ ///
+ public string RefundStatus { get; set; }
+
+ ///
+ /// 商品名称
+ ///
+ public string TradeName { get; set; }
+
+ ///
+ /// 商户数据包
+ ///
+ public string MerchantAttach { get; set; }
+
+ ///
+ /// 手续费(元)
+ ///
+ public decimal Commission { get; set; }
+
+ ///
+ /// 费率
+ ///
+ public string Rate { get; set; }
+
+ ///
+ /// 订单金额(元)
+ ///
+ public decimal OrderAmount { get; set; }
+
+ ///
+ /// 申请退款金额(元)
+ ///
+ public decimal ApplyRefundAmount { get; set; }
+
+ ///
+ /// 费率备注
+ ///
+ public string RateRemark { get; set; }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayDownloadBillResult.cs b/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayDownloadBillResult.cs
new file mode 100644
index 000000000..7c5c285c3
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayDownloadBillResult.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+
+namespace Bing.Biz.Payments.Wechatpay.Results
+{
+ ///
+ /// 微信支付下载对账单结果
+ ///
+ public class WechatpayDownloadBillResult
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 是否成功
+ /// 请求结果
+ public WechatpayDownloadBillResult(bool success, WechatpayResult result)
+ {
+ Success = success;
+ ErrorCode = result.GetErrorCode();
+ ErrorMessage = result.GetErrorCodeDescription();
+ Raw = result.Raw;
+ Parameter = result.Builder.ToString();
+ Bills = new List();
+ }
+
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 是否成功
+ /// 请求参数
+ /// 对账单信息列表
+ public WechatpayDownloadBillResult(bool success, string parameter, List bills)
+ {
+ Success = success;
+ Parameter = parameter;
+ Bills = bills ?? new List();
+ }
+
+ ///
+ /// 是否成功
+ ///
+ public bool Success { get; }
+
+ ///
+ /// 错误码
+ ///
+ public string ErrorCode { get; }
+
+ ///
+ /// 错误消息
+ ///
+ public string ErrorMessage { get; }
+
+ ///
+ /// 支付结果返回的原始消息
+ ///
+ public string Raw { get; }
+
+ ///
+ /// 请求参数
+ ///
+ public string Parameter { get; set; }
+
+ ///
+ /// 对账单信息列表
+ ///
+ public List Bills { get; set; }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayResult.cs b/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayResult.cs
index 3ec8d388d..a887ca543 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayResult.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Results/WechatpayResult.cs
@@ -2,11 +2,12 @@
using System.Linq;
using System.Threading.Tasks;
using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters;
using Bing.Biz.Payments.Wechatpay.Signatures;
using Bing.Extensions;
using Bing.Logs;
using Bing.Utils.Parameters;
-using Bing.Validations;
+using Bing.Validation;
using Xml = Bing.Helpers.Xml;
namespace Bing.Biz.Payments.Wechatpay.Results
@@ -16,11 +17,6 @@ namespace Bing.Biz.Payments.Wechatpay.Results
///
public class WechatpayResult
{
- ///
- /// 配置提供者
- ///
- private readonly IWechatpayConfigProvider _configProvider;
-
///
/// 响应结果
///
@@ -31,25 +27,44 @@ public class WechatpayResult
///
private string _sign;
- ///
- /// 微信支付原始响应
- ///
- public string Raw { get; }
-
///
/// 初始化一个类型的实例
///
- /// 配置提供器
+ /// 微信支付配置提供程序
/// xml响应消息
- public WechatpayResult(IWechatpayConfigProvider configProvider, string response)
+ /// 微信支付配置
+ /// 微信支付参数生成器
+ public WechatpayResult(IWechatpayConfigProvider configProvider, string response, WechatpayConfig config = null, IWechatpayParameterBuilder parameterBuilder = null)
{
- configProvider.CheckNotNull(nameof(configProvider));
- _configProvider = configProvider;
+ configProvider.CheckNull(nameof(configProvider));
+ ConfigProvider = configProvider;
Raw = response;
+ Config = config;
+ Builder = parameterBuilder;
_builder = new ParameterBuilder();
Resolve(response);
}
+ ///
+ /// 微信支付原始响应
+ ///
+ public string Raw { get; }
+
+ ///
+ /// 微信支付配置提供程序
+ ///
+ public IWechatpayConfigProvider ConfigProvider { get; }
+
+ ///
+ /// 配置
+ ///
+ public WechatpayConfig Config { get; }
+
+ ///
+ /// 微信支付参数生成器
+ ///
+ public IWechatpayParameterBuilder Builder { get; }
+
///
/// 解析响应
///
@@ -110,7 +125,7 @@ protected void WriteLog()
///
/// 获取业务结果代码
///
- public string GetResultCode() => GetParam(WechatpayConst.ReturnCode);
+ public string GetResultCode() => GetParam(WechatpayConst.ResultCode);
///
/// 获取返回消息
@@ -120,7 +135,7 @@ protected void WriteLog()
///
/// 获取应用标识
///
- public string AppId() => GetParam(WechatpayConst.AppId);
+ public string GetAppId() => GetParam(WechatpayConst.AppId);
///
/// 获取商户号
@@ -147,6 +162,11 @@ protected void WriteLog()
///
public string GetMWebUrl() => GetParam("mweb_url");
+ ///
+ /// 获取微信退款单号
+ ///
+ public string GetRefundId() => GetParam("refund_id");
+
///
/// 获取交易类型
///
@@ -155,12 +175,27 @@ protected void WriteLog()
///
/// 获取错误码
///
- public string GetErrorCode() => GetParam(WechatpayConst.ErrorCode);
+ public string GetErrorCode()
+ {
+ var result = GetParam(WechatpayConst.ErrorCode);
+ if (string.IsNullOrWhiteSpace(result) == false)
+ return result;
+ return GetParam("error_code");
+ }
///
/// 获取错误码和描述
///
- public string GetErrorCodeDesciption() => GetParam(WechatpayConst.ErrorCodeDescription);
+ public string GetErrorCodeDescription()
+ {
+ var result = GetParam(WechatpayConst.ErrorCodeDescription);
+ if (string.IsNullOrWhiteSpace(result) == false)
+ return result;
+ result = GetParam("return_msg");
+ if (string.IsNullOrWhiteSpace(result) == false)
+ return result;
+ return GetErrorCode();
+ }
///
/// 获取签名
@@ -183,7 +218,7 @@ public IDictionary GetParams()
public async Task ValidateAsync()
{
if (GetReturnCode() != WechatpayConst.Success || GetResultCode() != WechatpayConst.Success)
- return new ValidationResultCollection(GetErrorCodeDesciption());
+ return new ValidationResultCollection(GetErrorCodeDescription());
var isValid = await VerifySign();
if (isValid == false)
return new ValidationResultCollection("签名失败");
@@ -195,7 +230,7 @@ public async Task ValidateAsync()
///
public async Task VerifySign()
{
- var config = await _configProvider.GetConfigAsync(_builder);
+ var config = Config ?? await ConfigProvider.GetConfigAsync(_builder);
return SignManagerFactory.Create(config, _builder).Verify(GetSign());
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/Base/WechatpayPayServiceBase.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/Base/WechatpayPayServiceBase.cs
new file mode 100644
index 000000000..502341181
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/Base/WechatpayPayServiceBase.cs
@@ -0,0 +1,90 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Core;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters;
+using Bing.Biz.Payments.Wechatpay.Results;
+
+namespace Bing.Biz.Payments.Wechatpay.Services.Base
+{
+ ///
+ /// 微信支付服务
+ ///
+ public abstract class WechatpayPayServiceBase : WechatpayServiceBase, IPayService
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置提供器
+ protected WechatpayPayServiceBase(IWechatpayConfigProvider configProvider) : base(configProvider)
+ {
+ }
+
+ ///
+ /// 支付
+ ///
+ /// 支付参数
+ public virtual async Task PayAsync(PayParam param)
+ {
+ var result = await Request(param);
+ return await CreateResult(result);
+ }
+
+ ///
+ /// 创建参数生成器
+ ///
+ /// 微信支付配置
+ protected override WechatpayParameterBuilder CreateParameterBuilder(WechatpayConfig config) => new WechatpayParameterBuilder(config);
+
+ ///
+ /// 配置参数生成器
+ ///
+ /// 微信支付参数生成器
+ /// 请求参数
+ protected override void ConfigBuilder(WechatpayParameterBuilder builder, PayParam param)
+ {
+ builder.Init();
+ builder.Init(param);
+ builder.TradeType(GetTradeType());
+ InitBuilder(builder, param);
+ }
+
+ ///
+ /// 获取交易类型
+ ///
+ protected abstract string GetTradeType();
+
+ ///
+ /// 初始化参数生成器
+ ///
+ /// 微信支付参数生成器
+ /// 支付参数
+ protected virtual void InitBuilder(WechatpayParameterBuilder builder, PayParam param) { }
+
+ ///
+ /// 获取接口地址
+ ///
+ /// 微信支付配置
+ protected override string GetUrl(WechatpayConfig config) => config.GetOrderUrl();
+
+ ///
+ /// 创建支付结果
+ ///
+ /// 微信支付结果
+ protected virtual async Task CreateResult(WechatpayResult result)
+ {
+ var success = (await result.ValidateAsync()).IsValid;
+ return new PayResult(success, result.GetPrepayId(), result.Raw)
+ {
+ Parameter = result.Builder.ToString(),
+ Message = result.GetReturnMessage(),
+ Result = success ? GetResult(result) : null
+ };
+ }
+
+ ///
+ /// 获取结果
+ ///
+ /// 微信支付结果
+ protected virtual string GetResult(WechatpayResult result) => result.GetPrepayId();
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/Base/WechatpayServiceBase.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/Base/WechatpayServiceBase.cs
index a202ad9ee..033692de7 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/Base/WechatpayServiceBase.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/Base/WechatpayServiceBase.cs
@@ -1,49 +1,53 @@
using System.Threading.Tasks;
-using Bing.Biz.Payments.Core;
using Bing.Biz.Payments.Wechatpay.Configs;
using Bing.Biz.Payments.Wechatpay.Parameters;
using Bing.Biz.Payments.Wechatpay.Results;
using Bing.Extensions;
using Bing.Helpers;
using Bing.Logs;
+using Bing.Validation;
namespace Bing.Biz.Payments.Wechatpay.Services.Base
{
///
/// 微信支付服务
///
- public abstract class WechatpayServiceBase : IPayService
+ /// 请求参数类型
+ /// 微信支付参数生成器
+ public abstract class WechatpayServiceBase
+ where TRequest : IVerifyModel
+ where TParameterBuilder : IWechatpayParameterBuilder
{
///
- /// 配置提供器
+ /// 微信支付配置提供程序
///
protected readonly IWechatpayConfigProvider ConfigProvider;
///
- /// 是否发送请求
- ///
- public bool IsSend { get; set; } = true;
-
- ///
- /// 初始化一个类型的实例
+ /// 初始化一个类型的实例
///
- /// 微信支付配置提供器
+ /// 微信支付配置提供程序
protected WechatpayServiceBase(IWechatpayConfigProvider configProvider)
{
- configProvider.CheckNotNull(nameof(configProvider));
+ configProvider.CheckNull(nameof(configProvider));
ConfigProvider = configProvider;
}
///
- /// 支付
+ /// 是否发送请求
///
- /// 支付参数
- public virtual async Task PayAsync(PayParam param)
+ public bool IsSend { get; set; } = true;
+
+ ///
+ /// 请求
+ ///
+ /// 请求参数
+ protected virtual async Task Request(TRequest param)
{
- var config = await ConfigProvider.GetConfigAsync();
+ var config = await ConfigProvider.GetConfigAsync(param);
Validate(config, param);
- var builder = new WechatpayParameterBuilder(config);
- Config(builder, param);
+ var builder = CreateParameterBuilder(config);
+ ConfigBuilder(builder, param);
return await RequestResult(config, builder);
}
@@ -51,11 +55,11 @@ public virtual async Task PayAsync(PayParam param)
/// 验证
///
/// 微信支付配置
- /// 支付参数
- protected void Validate(WechatpayConfig config, PayParam param)
+ /// 请求参数
+ protected void Validate(WechatpayConfig config, TRequest param)
{
- config.CheckNotNull(nameof(config));
- param.CheckNotNull(nameof(param));
+ config.CheckNull(nameof(config));
+ param.CheckNull(nameof(param));
config.Validate();
param.Validate();
ValidateParam(param);
@@ -64,65 +68,57 @@ protected void Validate(WechatpayConfig config, PayParam param)
///
/// 验证参数
///
- /// 支付参数
- protected virtual void ValidateParam(PayParam param) { }
-
- ///
- /// 配置
- ///
- /// 微信支付参数生成器
- /// 支付参数
- protected void Config(WechatpayParameterBuilder builder, PayParam param)
+ /// 请求参数
+ protected virtual void ValidateParam(TRequest param)
{
- builder.Init(param);
- builder.TradeType(GetTradeType());
- InitBuilder(builder, param);
}
///
- /// 获取交易类型
+ /// 创建参数生成器
///
- protected abstract string GetTradeType();
+ /// 微信支付配置
+ protected abstract TParameterBuilder CreateParameterBuilder(WechatpayConfig config);
///
- /// 初始化参数生成器
+ /// 配置参数生成器
///
/// 微信支付参数生成器
- /// 支付参数
- protected virtual void InitBuilder(WechatpayParameterBuilder builder, PayParam param) { }
+ /// 请求参数
+ protected abstract void ConfigBuilder(TParameterBuilder builder, TRequest param);
///
/// 请求结果
///
/// 微信支付配置
/// 微信支付参数生成器
- ///
- protected virtual async Task RequestResult(WechatpayConfig config, WechatpayParameterBuilder builder)
+ protected virtual async Task RequestResult(WechatpayConfig config, TParameterBuilder builder)
{
- var result = new WechatpayResult(ConfigProvider, await Request(config, builder));
+ var response = await SendRequest(config, builder);
+ var result = new WechatpayResult(ConfigProvider, response, config, builder);
WriteLog(config, builder, result);
- return await CreateResult(config, builder, result);
+ return result;
}
///
/// 发送请求
///
/// 微信支付配置
- /// 微信支付参数生辰器
- protected virtual async Task Request(WechatpayConfig config, WechatpayParameterBuilder builder)
+ /// 微信支付参数生成器
+ protected virtual async Task SendRequest(WechatpayConfig config, TParameterBuilder builder)
{
if (IsSend == false)
return string.Empty;
return await Web.Client()
- .Post(string.IsNullOrWhiteSpace(GetOrderUrl()) ? config.GetOrderUrl() : GetOrderUrl())
+ .Post(GetUrl(config))
.XmlData(builder.ToXml())
.ResultAsync();
}
///
- /// 获取统一下单地址
+ /// 获取接口地址
///
- protected virtual string GetOrderUrl() => string.Empty;
+ /// 微信支付配置
+ protected abstract string GetUrl(WechatpayConfig config);
///
/// 写日志
@@ -130,19 +126,18 @@ protected virtual async Task Request(WechatpayConfig config, WechatpayPa
/// 微信支付配置
/// 微信支付参数生成器
/// 微信支付结果
- protected void WriteLog(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayResult result)
+ protected void WriteLog(WechatpayConfig config, TParameterBuilder builder, WechatpayResult result)
{
var log = GetLog();
if (log.IsTraceEnabled == false)
return;
log.Class(GetType().FullName)
.Caption("微信支付")
- .Content($"支付方式 : {GetPayWay().Description()}")
- .Content($"支付网关 : {config.GetOrderUrl()}")
- .Content("请求参数:")
+ .Content($"支付网关: {GetUrl(config)}")
+ .Content("请求参数: ")
.Content(builder.ToXml())
.Content()
- .Content("返回结果:")
+ .Content("返回结果: ")
.Content(result.GetParams())
.Content()
.Content("原始响应: ")
@@ -153,39 +148,16 @@ protected void WriteLog(WechatpayConfig config, WechatpayParameterBuilder builde
///
/// 获取日志操作
///
- private ILog GetLog() => Log.GetLog(WechatpayConst.TraceLogName);
-
- ///
- /// 获取支付方式
- ///
- protected abstract PayWay GetPayWay();
-
- ///
- /// 创建支付结果
- ///
- /// 微信支付配置
- /// 微信支付参数生成器
- /// 微信支付结果
- protected virtual async Task CreateResult(WechatpayConfig config, WechatpayParameterBuilder builder,
- WechatpayResult result)
+ private ILog GetLog()
{
- var success = (await result.ValidateAsync()).IsValid;
- return new PayResult(success, result.GetPrepayId(), result.Raw)
+ try
+ {
+ return Log.GetLog(WechatpayConst.TraceLogName);
+ }
+ catch
{
- Parameter = builder.ToString(),
- Message = result.GetReturnMessage(),
- Result = success ? GetResult(config, builder, result) : null
- };
+ return Log.Null;
+ }
}
-
- ///
- /// 获取结果
- ///
- /// 微信支付配置
- /// 微信支付参数生成器
- /// 微信支付结果
- protected virtual string GetResult(WechatpayConfig config, WechatpayParameterBuilder builder,
- WechatpayResult result) =>
- result.GetPrepayId();
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/RemovePrefixDecimalConvert.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/RemovePrefixDecimalConvert.cs
new file mode 100644
index 000000000..15237dde7
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/RemovePrefixDecimalConvert.cs
@@ -0,0 +1,26 @@
+using System;
+using Bing.Extensions;
+using TinyCsvParser.TypeConverter;
+
+namespace Bing.Biz.Payments.Wechatpay.Services.CsvMappings
+{
+ ///
+ /// 移除前缀`字符的decimal列转换器
+ ///
+ internal class RemovePrefixDecimalConvert : ITypeConverter
+ {
+ ///
+ /// 转换
+ ///
+ public bool TryConvert(string value, out decimal result)
+ {
+ result = string.IsNullOrWhiteSpace(value) ? 0 : value.TrimStart('`').ToDecimal();
+ return true;
+ }
+
+ ///
+ /// 目标类型
+ ///
+ public Type TargetType => typeof(decimal);
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/RemovePrefixStringConvert.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/RemovePrefixStringConvert.cs
new file mode 100644
index 000000000..22e617dab
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/RemovePrefixStringConvert.cs
@@ -0,0 +1,25 @@
+using System;
+using TinyCsvParser.TypeConverter;
+
+namespace Bing.Biz.Payments.Wechatpay.Services.CsvMappings
+{
+ ///
+ /// 移除前缀`字符的字符串列转换器
+ ///
+ internal class RemovePrefixStringConvert : ITypeConverter
+ {
+ ///
+ /// 转换
+ ///
+ public bool TryConvert(string value, out string result)
+ {
+ result = string.IsNullOrWhiteSpace(value) ? "" : value.TrimStart('`');
+ return true;
+ }
+
+ ///
+ /// 目标类型
+ ///
+ public Type TargetType => typeof(string);
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpayAllBillInfoMapping.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpayAllBillInfoMapping.cs
new file mode 100644
index 000000000..ca51fb3b1
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpayAllBillInfoMapping.cs
@@ -0,0 +1,45 @@
+using Bing.Biz.Payments.Wechatpay.Results;
+using TinyCsvParser.Mapping;
+
+namespace Bing.Biz.Payments.Wechatpay.Services.CsvMappings
+{
+ ///
+ /// 微信支付所有对账单信息CSV映射
+ ///
+ internal class WechatpayAllBillInfoMapping : CsvMapping
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ public WechatpayAllBillInfoMapping()
+ {
+ MapProperty(0, t => t.TransactionTime, new RemovePrefixStringConvert());
+ MapProperty(1, t => t.AppId, new RemovePrefixStringConvert());
+ MapProperty(2, t => t.MerchantId, new RemovePrefixStringConvert());
+ MapProperty(3, t => t.SubMerchantId, new RemovePrefixStringConvert());
+ MapProperty(4, t => t.DeviceNumber, new RemovePrefixStringConvert());
+ MapProperty(5, t => t.TradeId, new RemovePrefixStringConvert());
+ MapProperty(6, t => t.OrderId, new RemovePrefixStringConvert());
+ MapProperty(7, t => t.OpenId, new RemovePrefixStringConvert());
+ MapProperty(8, t => t.TradeType, new RemovePrefixStringConvert());
+ MapProperty(9, t => t.TradeStatus, new RemovePrefixStringConvert());
+ MapProperty(10, t => t.Bank, new RemovePrefixStringConvert());
+ MapProperty(11, t => t.CurrencyType, new RemovePrefixStringConvert());
+ MapProperty(12, t => t.TotalAmount, new RemovePrefixDecimalConvert());
+ MapProperty(13, t => t.CouponAmount, new RemovePrefixDecimalConvert());
+ MapProperty(14, t => t.WechatpayRefundId, new RemovePrefixStringConvert());
+ MapProperty(15, t => t.MerchantRefundId, new RemovePrefixStringConvert());
+ MapProperty(16, t => t.RefundAmount, new RemovePrefixDecimalConvert());
+ MapProperty(17, t => t.CouponRefundAmount, new RemovePrefixDecimalConvert());
+ MapProperty(18, t => t.RefundType, new RemovePrefixStringConvert());
+ MapProperty(19, t => t.RefundStatus, new RemovePrefixStringConvert());
+ MapProperty(20, t => t.TradeName, new RemovePrefixStringConvert());
+ MapProperty(21, t => t.MerchantAttach, new RemovePrefixStringConvert());
+ MapProperty(22, t => t.Commission, new RemovePrefixDecimalConvert());
+ MapProperty(23, t => t.Rate, new RemovePrefixStringConvert());
+ MapProperty(24, t => t.OrderAmount, new RemovePrefixDecimalConvert());
+ MapProperty(25, t => t.ApplyRefundAmount, new RemovePrefixDecimalConvert());
+ MapProperty(26, t => t.RateRemark, new RemovePrefixStringConvert());
+ }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpayRefundBillInfoMapping.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpayRefundBillInfoMapping.cs
new file mode 100644
index 000000000..2758a30f3
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpayRefundBillInfoMapping.cs
@@ -0,0 +1,47 @@
+using Bing.Biz.Payments.Wechatpay.Results;
+using TinyCsvParser.Mapping;
+
+namespace Bing.Biz.Payments.Wechatpay.Services.CsvMappings
+{
+ ///
+ /// 微信支付退款对账单信息Csv映射
+ ///
+ internal class WechatpayRefundBillInfoMapping : CsvMapping
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ public WechatpayRefundBillInfoMapping()
+ {
+ MapProperty(0, t => t.TransactionTime, new RemovePrefixStringConvert());
+ MapProperty(1, t => t.AppId, new RemovePrefixStringConvert());
+ MapProperty(2, t => t.MerchantId, new RemovePrefixStringConvert());
+ MapProperty(3, t => t.SubMerchantId, new RemovePrefixStringConvert());
+ MapProperty(4, t => t.DeviceNumber, new RemovePrefixStringConvert());
+ MapProperty(5, t => t.TradeId, new RemovePrefixStringConvert());
+ MapProperty(6, t => t.OrderId, new RemovePrefixStringConvert());
+ MapProperty(7, t => t.OpenId, new RemovePrefixStringConvert());
+ MapProperty(8, t => t.TradeType, new RemovePrefixStringConvert());
+ MapProperty(9, t => t.TradeStatus, new RemovePrefixStringConvert());
+ MapProperty(10, t => t.Bank, new RemovePrefixStringConvert());
+ MapProperty(11, t => t.CurrencyType, new RemovePrefixStringConvert());
+ MapProperty(12, t => t.TotalAmount, new RemovePrefixDecimalConvert());
+ MapProperty(13, t => t.CouponAmount, new RemovePrefixDecimalConvert());
+ MapProperty(14, t => t.RefundApplyTime, new RemovePrefixStringConvert());
+ MapProperty(15, t => t.RefundTime, new RemovePrefixStringConvert());
+ MapProperty(16, t => t.WechatpayRefundId, new RemovePrefixStringConvert());
+ MapProperty(17, t => t.MerchantRefundId, new RemovePrefixStringConvert());
+ MapProperty(18, t => t.RefundAmount, new RemovePrefixDecimalConvert());
+ MapProperty(19, t => t.CouponRefundAmount, new RemovePrefixDecimalConvert());
+ MapProperty(20, t => t.RefundType, new RemovePrefixStringConvert());
+ MapProperty(21, t => t.RefundStatus, new RemovePrefixStringConvert());
+ MapProperty(22, t => t.TradeName, new RemovePrefixStringConvert());
+ MapProperty(23, t => t.MerchantAttach, new RemovePrefixStringConvert());
+ MapProperty(24, t => t.Commission, new RemovePrefixDecimalConvert());
+ MapProperty(25, t => t.Rate, new RemovePrefixStringConvert());
+ MapProperty(26, t => t.OrderAmount, new RemovePrefixDecimalConvert());
+ MapProperty(27, t => t.ApplyRefundAmount, new RemovePrefixDecimalConvert());
+ MapProperty(28, t => t.RateRemark, new RemovePrefixStringConvert());
+ }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpaySuccessBillInfoMapping.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpaySuccessBillInfoMapping.cs
new file mode 100644
index 000000000..cdae09ac4
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/CsvMappings/WechatpaySuccessBillInfoMapping.cs
@@ -0,0 +1,36 @@
+using Bing.Biz.Payments.Wechatpay.Results;
+using TinyCsvParser.Mapping;
+
+namespace Bing.Biz.Payments.Wechatpay.Services.CsvMappings
+{
+ ///
+ /// 微信支付成功支付对账单信息Csv映射
+ ///
+ internal class WechatpaySuccessBillInfoMapping : CsvMapping
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ public WechatpaySuccessBillInfoMapping()
+ {
+ MapProperty(0, t => t.TransactionTime, new RemovePrefixStringConvert());
+ MapProperty(1, t => t.AppId, new RemovePrefixStringConvert());
+ MapProperty(2, t => t.MerchantId, new RemovePrefixStringConvert());
+ MapProperty(3, t => t.SubMerchantId, new RemovePrefixStringConvert());
+ MapProperty(4, t => t.DeviceNumber, new RemovePrefixStringConvert());
+ MapProperty(5, t => t.TradeId, new RemovePrefixStringConvert());
+ MapProperty(6, t => t.OrderId, new RemovePrefixStringConvert());
+ MapProperty(7, t => t.OpenId, new RemovePrefixStringConvert());
+ MapProperty(8, t => t.TradeType, new RemovePrefixStringConvert());
+ MapProperty(9, t => t.TradeStatus, new RemovePrefixStringConvert());
+ MapProperty(10, t => t.Bank, new RemovePrefixStringConvert());
+ MapProperty(11, t => t.CurrencyType, new RemovePrefixStringConvert());
+ MapProperty(12, t => t.TotalAmount, new RemovePrefixDecimalConvert());
+ MapProperty(13, t => t.CouponAmount, new RemovePrefixDecimalConvert());
+ MapProperty(14, t => t.TradeName, new RemovePrefixStringConvert());
+ MapProperty(15, t => t.MerchantAttach, new RemovePrefixStringConvert());
+ MapProperty(16, t => t.Commission, new RemovePrefixDecimalConvert());
+ MapProperty(17, t => t.Rate, new RemovePrefixStringConvert());
+ }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayAppPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayAppPayService.cs
index c628776c7..b803f1c6b 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayAppPayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayAppPayService.cs
@@ -13,7 +13,7 @@ namespace Bing.Biz.Payments.Wechatpay.Services
///
/// 微信App支付服务
///
- public class WechatpayAppPayService : WechatpayServiceBase, IWechatpayAppPayService
+ public class WechatpayAppPayService : WechatpayPayServiceBase, IWechatpayAppPayService
{
///
/// 初始化一个类型的实例
@@ -24,45 +24,25 @@ public WechatpayAppPayService(IWechatpayConfigProvider configProvider) : base(co
}
///
- /// 获取交易类型
- ///
- ///
- protected override string GetTradeType()
- {
- return "APP";
- }
-
- ///
- /// 获取支付方式
+ /// 支付
///
- ///
- protected override PayWay GetPayWay()
- {
- return PayWay.WechatpayAppPay;
- }
+ /// 支付参数
+ public async Task PayAsync(WechatpayAppPayRequest request) => await PayAsync(request.ToParam());
///
- /// 支付
+ /// 获取交易类型
///
- /// 支付参数
- ///
- public async Task PayAsync(WechatpayAppPayRequest request)
- {
- return await PayAsync(request.ToParam());
- }
+ protected override string GetTradeType() => "APP";
///
/// 获取结果
///
- /// 微信支付配置
- /// 微信支付参数生成器
/// 微信支付结果
- ///
- protected override string GetResult(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayResult result)
+ protected override string GetResult( WechatpayResult result)
{
- return new WechatpayParameterBuilder(config)
- .AppId(config.AppId)
- .PartnerId(config.MerchantId)
+ return new WechatpayParameterBuilder(result.Config)
+ .AppId(result.Config.AppId)
+ .PartnerId(result.Config.MerchantId)
.Add("prepayid", result.GetPrepayId())
.Add("noncestr", Id.Guid())
.Timestamp()
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayDownloadBillService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayDownloadBillService.cs
new file mode 100644
index 000000000..8ae5cb357
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayDownloadBillService.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Wechatpay.Abstractions;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Enums;
+using Bing.Biz.Payments.Wechatpay.Parameters;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+using Bing.Biz.Payments.Wechatpay.Results;
+using Bing.Biz.Payments.Wechatpay.Services.Base;
+using Bing.Biz.Payments.Wechatpay.Services.CsvMappings;
+using Bing.Extensions;
+using TinyCsvParser;
+using TinyCsvParser.Mapping;
+using TinyCsvParser.Tokenizer;
+
+namespace Bing.Biz.Payments.Wechatpay.Services
+{
+ ///
+ /// 微信支付下载交易账单服务
+ ///
+ public class WechatpayDownloadBillService : WechatpayServiceBase, IWechatpayDownloadBillService
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置提供程序
+ public WechatpayDownloadBillService(IWechatpayConfigProvider configProvider) : base(configProvider)
+ {
+ }
+
+ ///
+ /// 下载对账单
+ ///
+ /// 下载对账单参数
+ public async Task DownloadAsync(WechatpayDownloadBillRequest request)
+ {
+ var config = await ConfigProvider.GetConfigAsync(request);
+ Validate(config, request);
+ var builder = new WechatpayParameterBuilder(config);
+ ConfigBuilder(builder, request);
+ return await RequestAsync(config, builder, request);
+ }
+
+ ///
+ /// 创建参数生成器
+ ///
+ /// 微信支付配置
+ protected override WechatpayParameterBuilder CreateParameterBuilder(WechatpayConfig config) => new WechatpayParameterBuilder(config);
+
+ ///
+ /// 配置参数生成器
+ ///
+ /// 微信支付参数生成器
+ /// 请求参数
+ protected override void ConfigBuilder(WechatpayParameterBuilder builder, WechatpayDownloadBillRequest param)
+ {
+ builder.Init();
+ builder.Add("bill_date", param.GetBillDate());
+ builder.Add("bill_type", param.BillType.Description());
+ }
+
+ ///
+ /// 请求结果
+ ///
+ /// 微信支付配置
+ /// 微信支付参数生成器
+ /// 请求参数
+ protected async Task RequestAsync(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayDownloadBillRequest request)
+ {
+ var response = await SendRequest(config, builder);
+ if (response.StartsWith("交易时间"))
+ return Success(response, builder, request);
+ return await Fail(response, config, builder);
+ }
+
+ ///
+ /// 请求成功
+ ///
+ /// 响应内容
+ /// 微信支付参数生成器
+ /// 请求参数
+ private WechatpayDownloadBillResult Success(string response, WechatpayParameterBuilder builder, WechatpayDownloadBillRequest request)
+ {
+ var bills = GetBills(response, request);
+ return new WechatpayDownloadBillResult(true, builder.ToString(), bills);
+ }
+
+ ///
+ /// 获取对账单
+ ///
+ /// 响应内容
+ /// 请求参数
+ private List GetBills(string response, WechatpayDownloadBillRequest request)
+ {
+ var result = new List();
+ var tokenizer = new QuotedStringTokenizer(',');
+ var options = new CsvParserOptions(true, tokenizer);
+ var parser = new CsvParser(options, GetCsvMapping(request));
+ var readerOptions = new CsvReaderOptions(new[] { Environment.NewLine });
+ var records = parser.ReadFromString(readerOptions, response);
+ foreach (var record in records)
+ {
+ if (record.IsValid == false)
+ continue;
+ if (record.Result.TransactionTime == "交易时间")
+ continue;
+ if (record.Result.TransactionTime == "总交易单数")
+ break;
+ result.Add(record.Result);
+ }
+ return result;
+ }
+
+ ///
+ /// 获取Csv映射
+ ///
+ /// 请求参数
+ private ICsvMapping GetCsvMapping(WechatpayDownloadBillRequest request)
+ {
+ switch (request.BillType)
+ {
+ case WechatpayBillType.Success:
+ return new WechatpaySuccessBillInfoMapping();
+ case WechatpayBillType.RechargeRefund:
+ return new WechatpayRefundBillInfoMapping();
+ default:
+ return new WechatpayAllBillInfoMapping();
+ }
+ }
+
+ ///
+ /// 请求失败
+ ///
+ /// 响应内容
+ /// 微信支付配置
+ /// 微信支付参数生成器
+ private async Task Fail(string response, WechatpayConfig config, WechatpayParameterBuilder builder)
+ {
+ var result = new WechatpayResult(ConfigProvider, response, config, builder);
+ WriteLog(config, builder, result);
+ var success = (await result.ValidateAsync()).IsValid;
+ return new WechatpayDownloadBillResult(success, result);
+ }
+
+ ///
+ /// 获取接口地址
+ ///
+ /// 微信支付配置
+ protected override string GetUrl(WechatpayConfig config) => config.GetDownloadBillUrl();
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayH5PayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayH5PayService.cs
new file mode 100644
index 000000000..710a72d64
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayH5PayService.cs
@@ -0,0 +1,44 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Core;
+using Bing.Biz.Payments.Wechatpay.Abstractions;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+using Bing.Biz.Payments.Wechatpay.Results;
+using Bing.Biz.Payments.Wechatpay.Services.Base;
+
+namespace Bing.Biz.Payments.Wechatpay.Services
+{
+ ///
+ /// 微信H5支付服务
+ ///
+ public class WechatpayH5PayService : WechatpayPayServiceBase, IWechatpayH5PayService
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置提供器
+ public WechatpayH5PayService(IWechatpayConfigProvider configProvider) : base(configProvider)
+ {
+ }
+
+ ///
+ /// 支付
+ ///
+ /// 支付参数
+ public async Task PayAsync(WechatpayH5PayRequest request) => await PayAsync(request.ToParam());
+
+ ///
+ /// 获取交易类型
+ ///
+ protected override string GetTradeType() => "MWEB";
+
+ ///
+ /// 获取结果
+ ///
+ /// 微信支付结果
+ protected override string GetResult(WechatpayResult result)
+ {
+ return result.GetMWebUrl();
+ }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPublicPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayJsApiPayService.cs
similarity index 56%
rename from components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPublicPayService.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayJsApiPayService.cs
index 1c3d502a5..d711e9fbb 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPublicPayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayJsApiPayService.cs
@@ -13,15 +13,15 @@
namespace Bing.Biz.Payments.Wechatpay.Services
{
///
- /// 微信公众号支付服务
+ /// 微信JsApi支付服务
///
- public class WechatpayPublicPayService : WechatpayServiceBase, IWechatpayPublicPayService
+ public class WechatpayJsApiPayService : WechatpayPayServiceBase, IWechatpayJsApiPayService
{
///
- /// 初始化一个类型的实例
+ /// 初始化一个类型的实例
///
/// 微信支付配置提供器
- public WechatpayPublicPayService(IWechatpayConfigProvider configProvider) : base(configProvider)
+ public WechatpayJsApiPayService(IWechatpayConfigProvider configProvider) : base(configProvider)
{
}
@@ -29,57 +29,45 @@ public WechatpayPublicPayService(IWechatpayConfigProvider configProvider) : base
/// 支付
///
/// 支付参数
- ///
- public async Task PayAsync(WechatpayPublicPayRequest request)
- {
- return await PayAsync(request.ToParam());
- }
+ public async Task PayAsync(WechatpayJsApiPayRequest request) => await PayAsync(request.ToParam());
///
/// 获取交易类型
///
- ///
- protected override string GetTradeType()
- {
- return "JSAPI";
- }
+ protected override string GetTradeType() => "JSAPI";
///
/// 验证参数
///
- /// 支付参数
+ /// 请求参数
protected override void ValidateParam(PayParam param)
{
if (param.OpenId.IsEmpty())
- {
- throw new Warning("公众号支付必须设置OpenId");
- }
+ throw new Warning("必须设置OpenId");
}
///
- /// 获取支付方式
+ /// 初始化参数生成器
///
- ///
- protected override PayWay GetPayWay()
+ /// 微信支付参数生成器
+ /// 支付参数
+ protected override void InitBuilder(WechatpayParameterBuilder builder, PayParam param)
{
- return PayWay.WechatpayPublicPay;
+ builder.OpenId(param.OpenId);
}
///
/// 获取结果
///
- /// 微信支付配置
- /// 微信支付参数生成器
/// 微信支付结果
- ///
- protected override string GetResult(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayResult result)
+ protected override string GetResult(WechatpayResult result)
{
- return new WechatpayParameterBuilder(config)
- .Add("appId", config.AppId)
+ return new WechatpayParameterBuilder(result.Config)
+ .Add("appId", result.Config.AppId)
.Add("timeStamp", Time.GetUnixTimestamp().SafeString())
.Add("nonceStr", Id.Guid())
.Package($"prepay_id{result.GetPrepayId()}")
- .Add("signType", config.SignType.Description())
+ .Add("signType", result.Config.SignType.Description())
.Add("paySign", result.GetSign())
.ToJson();
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayMiniProgramPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayMiniProgramPayService.cs
index 83f8f39a5..6fa86d726 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayMiniProgramPayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayMiniProgramPayService.cs
@@ -15,7 +15,7 @@ namespace Bing.Biz.Payments.Wechatpay.Services
///
/// 微信小程序支付服务
///
- public class WechatpayMiniProgramPayService : WechatpayServiceBase, IWechatpayMiniProgramPayService
+ public class WechatpayMiniProgramPayService : WechatpayPayServiceBase, IWechatpayMiniProgramPayService
{
///
/// 初始化一个类型的实例
@@ -26,22 +26,15 @@ public WechatpayMiniProgramPayService(IWechatpayConfigProvider configProvider) :
}
///
- /// 获取交易类型
+ /// 支付
///
- ///
- protected override string GetTradeType()
- {
- return "JSAPI";
- }
+ /// 微信小程序支付参数
+ public async Task PayAsync(WechatpayMiniProgramPayRequest request) => await PayAsync(request.ToParam());
///
- /// 获取支付方式
+ /// 获取交易类型
///
- ///
- protected override PayWay GetPayWay()
- {
- return PayWay.WechatpayMiniProgramPay;
- }
+ protected override string GetTradeType() => "JSAPI";
///
/// 验证参数
@@ -50,36 +43,31 @@ protected override PayWay GetPayWay()
protected override void ValidateParam(PayParam param)
{
if (param.OpenId.IsEmpty())
- {
throw new Warning("小程序支付必须设置OpenId");
- }
}
///
- /// 支付
+ /// 初始化参数生成器
///
- /// 微信小程序支付参数
- ///
- public async Task PayAsync(WechatpayMiniProgramPayRequest request)
+ /// 微信支付参数生成器
+ /// 支付参数
+ protected override void InitBuilder(WechatpayParameterBuilder builder, PayParam param)
{
- return await PayAsync(request.ToParam());
+ builder.OpenId(param.OpenId);
}
///
/// 获取结果
///
- /// 微信支付配置
- /// 微信支付参数生成器
/// 微信支付结果
- ///
- protected override string GetResult(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayResult result)
+ protected override string GetResult(WechatpayResult result)
{
- return new WechatpayParameterBuilder(config)
- .Add("appId", config.AppId)
+ return new WechatpayParameterBuilder(result.Config)
+ .Add("appId", result.Config.AppId)
.Add("timeStamp", Time.GetUnixTimestamp().SafeString())
.Add("nonceStr", Id.Guid())
.Package($"prepay_id={result.GetPrepayId()}")
- .Add("signType", config.SignType.Description())
+ .Add("signType", result.Config.SignType.Description())
.ToJson();
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayNativePayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayNativePayService.cs
new file mode 100644
index 000000000..0cb7f7686
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayNativePayService.cs
@@ -0,0 +1,44 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Core;
+using Bing.Biz.Payments.Wechatpay.Abstractions;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+using Bing.Biz.Payments.Wechatpay.Results;
+using Bing.Biz.Payments.Wechatpay.Services.Base;
+
+namespace Bing.Biz.Payments.Wechatpay.Services
+{
+ ///
+ /// 微信扫码支付服务
+ ///
+ public class WechatpayNativePayService : WechatpayPayServiceBase, IWechatpayNativePayService
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置提供器
+ public WechatpayNativePayService(IWechatpayConfigProvider configProvider) : base(configProvider)
+ {
+ }
+
+ ///
+ /// 支付
+ ///
+ /// 支付参数
+ public async Task PayAsync(WechatpayNativePayRequest request) => await PayAsync(request.ToParam());
+
+ ///
+ /// 获取交易类型
+ ///
+ protected override string GetTradeType() => "NATIVE";
+
+ ///
+ /// 获取结果
+ ///
+ /// 微信支付结果
+ protected override string GetResult(WechatpayResult result)
+ {
+ return result.GetCodeUrl();
+ }
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayNotifyService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayNotifyService.cs
index 1ed923f15..b811cc26b 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayNotifyService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayNotifyService.cs
@@ -6,7 +6,7 @@
using Bing.Biz.Payments.Wechatpay.Results;
using Bing.Extensions;
using Bing.Helpers;
-using Bing.Validations;
+using Bing.Validation;
using Xml = Bing.Helpers.Xml;
namespace Bing.Biz.Payments.Wechatpay.Services
@@ -31,6 +31,17 @@ public class WechatpayNotifyService : IWechatpayNotifyService
///
private bool _isLoad;
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置提供器
+ public WechatpayNotifyService(IWechatpayConfigProvider configProvider)
+ {
+ configProvider.CheckNotNull(nameof(configProvider));
+ _configProvider = configProvider;
+ _isLoad = false;
+ }
+
///
/// 商户订单号
///
@@ -46,22 +57,10 @@ public class WechatpayNotifyService : IWechatpayNotifyService
///
public decimal Money => GetParam(WechatpayConst.TotalFee).ToDecimal() / 100M;
- ///
- /// 初始化一个类型的实例
- ///
- /// 微信支付配置提供器
- public WechatpayNotifyService(IWechatpayConfigProvider configProvider)
- {
- configProvider.CheckNotNull(nameof(configProvider));
- _configProvider = configProvider;
- _isLoad = false;
- }
-
///
/// 获取参数
///
/// 参数名
- ///
public string GetParam(string name)
{
Init();
@@ -73,16 +72,11 @@ public string GetParam(string name)
///
/// 类型
/// 参数名
- ///
- public T GetParam(string name)
- {
- return Conv.To(GetParam(name));
- }
+ public T GetParam(string name) => Conv.To(GetParam(name));
///
/// 获取参数集合
///
- ///
public IDictionary GetParams()
{
Init();
@@ -95,9 +89,7 @@ public IDictionary GetParams()
private void Init()
{
if (_isLoad)
- {
return;
- }
InitResult();
_isLoad = true;
}
@@ -105,50 +97,34 @@ private void Init()
///
/// 初始化支付结果
///
- private void InitResult()
- {
- _result = new WechatpayResult(_configProvider, Web.Body);
- }
+ private void InitResult() => _result = new WechatpayResult(_configProvider, Web.Body);
///
/// 验证
///
- ///
public async Task ValidateAsync()
{
Init();
if (Money <= 0)
- {
return new ValidationResultCollection(PayResource.InvalidMoney);
- }
-
return await _result.ValidateAsync();
}
///
/// 返回成功消息
///
- ///
- public string Success()
- {
- return Return(WechatpayConst.Success, WechatpayConst.Ok);
- }
+ public string Success() => Return(WechatpayConst.Success, WechatpayConst.Ok);
///
/// 返回失败消息
///
- ///
- public string Fail()
- {
- return Return(WechatpayConst.Fail, WechatpayConst.Fail);
- }
+ public string Fail() => Return(WechatpayConst.Fail, WechatpayConst.Fail);
///
/// 返回消息
///
/// 编码
/// 消息
- ///
private string Return(string code, string message)
{
var xml = new Xml();
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPagePayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPagePayService.cs
deleted file mode 100644
index 6523cda61..000000000
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPagePayService.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Threading.Tasks;
-using Bing.Biz.Payments.Core;
-using Bing.Biz.Payments.Wechatpay.Abstractions;
-using Bing.Biz.Payments.Wechatpay.Configs;
-using Bing.Biz.Payments.Wechatpay.Parameters;
-using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
-using Bing.Biz.Payments.Wechatpay.Results;
-using Bing.Biz.Payments.Wechatpay.Services.Base;
-
-namespace Bing.Biz.Payments.Wechatpay.Services
-{
- ///
- /// 微信电脑网站支付服务
- ///
- public class WechatpayPagePayService : WechatpayServiceBase, IWechatpayPagePayService
- {
- ///
- /// 初始化一个类型的实例
- ///
- /// 微信支付配置提供器
- public WechatpayPagePayService(IWechatpayConfigProvider configProvider) : base(configProvider)
- {
- }
-
- ///
- /// 支付
- ///
- /// 支付参数
- ///
- public async Task PayAsync(WechatpayPagePayRequest request)
- {
- return await PayAsync(request.ToParam());
- }
-
- ///
- /// 获取交易类型
- ///
- ///
- protected override string GetTradeType()
- {
- return "NATIVE";
- }
-
- ///
- /// 获取支付方式
- ///
- ///
- protected override PayWay GetPayWay()
- {
- return PayWay.WechatpayPagePay;
- }
-
- ///
- /// 获取结果
- ///
- /// 微信支付配置
- /// 微信支付参数生成器
- /// 微信支付结果
- ///
- protected override string GetResult(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayResult result)
- {
- return result.GetCodeUrl();
- }
- }
-}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayBarcodePayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPaymentCodePayService.cs
similarity index 64%
rename from components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayBarcodePayService.cs
rename to components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPaymentCodePayService.cs
index 550653dd0..8a505d4e4 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayBarcodePayService.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayPaymentCodePayService.cs
@@ -16,13 +16,13 @@ namespace Bing.Biz.Payments.Wechatpay.Services
///
/// 微信条码支付服务
///
- public class WechatpayBarcodePayService : WechatpayServiceBase, IWechatpayBarcodePayService
+ public class WechatpayPaymentCodePayService : WechatpayPayServiceBase, IWechatpayPaymentCodePayService
{
///
- /// 初始化一个类型的实例
+ /// 初始化一个类型的实例
///
/// 微信支付配置提供器
- public WechatpayBarcodePayService(IWechatpayConfigProvider configProvider) : base(configProvider)
+ public WechatpayPaymentCodePayService(IWechatpayConfigProvider configProvider) : base(configProvider)
{
}
@@ -30,29 +30,12 @@ public WechatpayBarcodePayService(IWechatpayConfigProvider configProvider) : bas
/// 支付
///
/// 支付参数
- ///
- public async Task PayAsync(WechatpayBarcodePayRequest request)
- {
- return await PayAsync(request.ToParam());
- }
+ public async Task PayAsync(WechatpayPaymentCodePayRequest request) => await PayAsync(request.ToParam());
///
/// 获取交易类型
///
- ///
- protected override string GetTradeType()
- {
- return string.Empty;
- }
-
- ///
- /// 获取支付方式
- ///
- ///
- protected override PayWay GetPayWay()
- {
- return PayWay.WechatpayBarcodePay;
- }
+ protected override string GetTradeType() => string.Empty;
///
/// 验证参数
@@ -61,9 +44,7 @@ protected override PayWay GetPayWay()
protected override void ValidateParam(PayParam param)
{
if (param.AuthCode.IsEmpty())
- {
throw new Warning(PayResource.AuthCodeIsEmpty);
- }
}
///
@@ -77,13 +58,16 @@ protected override void InitBuilder(WechatpayParameterBuilder builder, PayParam
}
///
- /// 获取结果
+ /// 获取接口地址
///
/// 微信支付配置
- /// 微信支付参数生成器
+ protected override string GetUrl(WechatpayConfig config) => config.GetPaymentCodePayUrl();
+
+ ///
+ /// 获取结果
+ ///
/// 微信支付结果
- ///
- protected override string GetResult(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayResult result)
+ protected override string GetResult(WechatpayResult result)
{
return result.GetParams().ToJson();
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayRefundService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayRefundService.cs
new file mode 100644
index 000000000..81a997fb2
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayRefundService.cs
@@ -0,0 +1,59 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Core;
+using Bing.Biz.Payments.Wechatpay.Abstractions;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+using Bing.Biz.Payments.Wechatpay.Services.Base;
+using Bing.Helpers;
+
+namespace Bing.Biz.Payments.Wechatpay.Services
+{
+ ///
+ /// 微信退款服务
+ ///
+ public class WechatpayRefundService : WechatpayServiceBase, IWechatpayRefundService
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 微信支付配置提供程序
+ public WechatpayRefundService(IWechatpayConfigProvider configProvider) : base(configProvider)
+ {
+ }
+
+ ///
+ /// 退款
+ ///
+ /// 退款参数
+ public Task RefundAsync(WechatRefundRequest request)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ ///
+ /// 创建参数生成器
+ ///
+ /// 微信支付配置
+ protected override WechatpayRefundParameterBuilder CreateParameterBuilder(WechatpayConfig config) => new WechatpayRefundParameterBuilder(config);
+
+ ///
+ /// 配置参数生成器
+ ///
+ /// 微信支付参数生成器
+ /// 请求参数
+ protected override void ConfigBuilder(WechatpayRefundParameterBuilder builder, WechatRefundRequest param)
+ {
+ builder.Init(param);
+ builder.Add(WechatpayConst.AppId, builder.Config.AppId)
+ .Add(WechatpayConst.MerchantId, builder.Config.MerchantId)
+ .Add(WechatpayConst.NonceStr, Id.Guid());
+ }
+
+ ///
+ /// 获取接口地址
+ ///
+ /// 微信支付配置
+ protected override string GetUrl(WechatpayConfig config) => config.GetRefundUrl();
+ }
+}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayWapPayService.cs b/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayWapPayService.cs
deleted file mode 100644
index 804002aca..000000000
--- a/components/src/Bing.Biz.Payments/Wechatpay/Services/WechatpayWapPayService.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Threading.Tasks;
-using Bing.Biz.Payments.Core;
-using Bing.Biz.Payments.Wechatpay.Abstractions;
-using Bing.Biz.Payments.Wechatpay.Configs;
-using Bing.Biz.Payments.Wechatpay.Parameters;
-using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
-using Bing.Biz.Payments.Wechatpay.Results;
-using Bing.Biz.Payments.Wechatpay.Services.Base;
-
-namespace Bing.Biz.Payments.Wechatpay.Services
-{
- ///
- /// 微信手机网站支付服务
- ///
- public class WechatpayWapPayService : WechatpayServiceBase, IWechatpayWapPayService
- {
- ///
- /// 初始化一个类型的实例
- ///
- /// 微信支付配置提供器
- public WechatpayWapPayService(IWechatpayConfigProvider configProvider) : base(configProvider)
- {
- }
-
- ///
- /// 支付
- ///
- /// 支付参数
- ///
- public async Task PayAsync(WechatpayWapPayRequest request)
- {
- return await PayAsync(request.ToParam());
- }
-
- ///
- /// 获取交易类型
- ///
- ///
- protected override string GetTradeType()
- {
- return "MWEB";
- }
-
- ///
- /// 获取支付方式
- ///
- ///
- protected override PayWay GetPayWay()
- {
- return PayWay.WechatpayWapPay;
- }
-
- ///
- /// 获取结果
- ///
- /// 微信支付配置
- /// 微信支付参数生成器
- /// 微信支付结果
- ///
- protected override string GetResult(WechatpayConfig config, WechatpayParameterBuilder builder, WechatpayResult result)
- {
- return result.GetMWebUrl();
- }
- }
-}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Signatures/HmacSha256SignManager.cs b/components/src/Bing.Biz.Payments/Wechatpay/Signatures/HmacSha256SignManager.cs
index 404e369b2..f8858e4fd 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Signatures/HmacSha256SignManager.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Signatures/HmacSha256SignManager.cs
@@ -37,7 +37,6 @@ public HmacSha256SignManager(ISignKey key, ParameterBuilder builder = null)
///
/// 键
/// 值
- ///
public ISignManager Add(string key, object value)
{
_builder.Add(key, value);
@@ -47,7 +46,6 @@ public ISignManager Add(string key, object value)
///
/// 签名
///
- ///
public string Sign()
{
var value = $"{_builder.Result(true)}&key={_key.GetKey()}";
@@ -58,13 +56,10 @@ public string Sign()
/// 验证签名
///
/// 签名
- ///
public bool Verify(string sign)
{
if (sign.IsEmpty())
- {
return false;
- }
return sign == Sign();
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Signatures/Md5SignManager.cs b/components/src/Bing.Biz.Payments/Wechatpay/Signatures/Md5SignManager.cs
index c99621193..144d4b2a4 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Signatures/Md5SignManager.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Signatures/Md5SignManager.cs
@@ -37,7 +37,6 @@ public Md5SignManager(ISignKey key, ParameterBuilder builder = null)
///
/// 键
/// 值
- ///
public ISignManager Add(string key, object value)
{
_builder.Add(key, value);
@@ -47,7 +46,6 @@ public ISignManager Add(string key, object value)
///
/// 签名
///
- ///
public string Sign()
{
var value = $"{_builder.Result(true)}&key={_key.GetKey()}";
@@ -58,14 +56,10 @@ public string Sign()
/// 验证签名
///
/// 签名
- ///
public bool Verify(string sign)
{
if (sign.IsEmpty())
- {
return false;
- }
-
return sign == Sign();
}
}
diff --git a/components/src/Bing.Biz.Payments/Wechatpay/Signatures/SignManagerFactory.cs b/components/src/Bing.Biz.Payments/Wechatpay/Signatures/SignManagerFactory.cs
index 43385054a..aabb4fca7 100644
--- a/components/src/Bing.Biz.Payments/Wechatpay/Signatures/SignManagerFactory.cs
+++ b/components/src/Bing.Biz.Payments/Wechatpay/Signatures/SignManagerFactory.cs
@@ -17,19 +17,12 @@ public class SignManagerFactory
///
/// 微信支付配置
/// 参数生成器
- ///
public static ISignManager Create(WechatpayConfig config, ParameterBuilder builder)
{
if (config.SignType == WechatpaySignType.Md5)
- {
return new Md5SignManager(new SignKey(config.PrivateKey), builder);
- }
-
if (config.SignType == WechatpaySignType.HmacSha256)
- {
return new HmacSha256SignManager(new SignKey(config.PrivateKey), builder);
- }
-
throw new NotImplementedException($"未实现签名算法:{config.SignType.Description()}");
}
}
diff --git a/components/src/Bing.Biz.Payments/project.dependency.props b/components/src/Bing.Biz.Payments/project.dependency.props
new file mode 100644
index 000000000..cc901947c
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/project.dependency.props
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/src/Bing.Biz.Payments/project.props b/components/src/Bing.Biz.Payments/project.props
new file mode 100644
index 000000000..9ecb980a1
--- /dev/null
+++ b/components/src/Bing.Biz.Payments/project.props
@@ -0,0 +1,25 @@
+
+
+ Bing.Biz.Payments
+ Bing.Biz.Payments
+ Bing.Biz.Payments是Bing应用框架的支付操作类库。
+Bing是一个.net core平台下的应用框架,旨在于提升小型团队的开发能力,由常用公共操作类、架构基类、第三方组件封装、第三方业务接口封装等组成。
+
+
+
+
+
+ True
+ True
+ PayResource.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ PayResource.Designer.cs
+
+
+
+
\ No newline at end of file
diff --git a/components/tests/Bing.Biz.Payments.Tests/Bing.Biz.Payments.Tests.csproj b/components/tests/Bing.Biz.Payments.Tests/Bing.Biz.Payments.Tests.csproj
new file mode 100644
index 000000000..a4cb08793
--- /dev/null
+++ b/components/tests/Bing.Biz.Payments.Tests/Bing.Biz.Payments.Tests.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netcoreapp3.1
+ false
+
+
+
+
+
+
+
diff --git a/components/tests/Bing.Biz.Payments.Tests/TestConst.cs b/components/tests/Bing.Biz.Payments.Tests/TestConst.cs
new file mode 100644
index 000000000..9c7c47a14
--- /dev/null
+++ b/components/tests/Bing.Biz.Payments.Tests/TestConst.cs
@@ -0,0 +1,13 @@
+namespace Bing.Biz.Payments.Tests
+{
+ ///
+ /// 测试常量
+ ///
+ public class TestConst
+ {
+ ///
+ /// 测试时间
+ ///
+ public const string Time = "2010-10-10 10:10:10:10";
+ }
+}
diff --git a/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Configs/TestConfigProvider.cs b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Configs/TestConfigProvider.cs
new file mode 100644
index 000000000..489d5e602
--- /dev/null
+++ b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Configs/TestConfigProvider.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Wechatpay.Configs;
+
+namespace Bing.Biz.Payments.Tests.Wechatpay.Configs
+{
+ ///
+ /// 微信支付测试配置提供器
+ ///
+ public class TestConfigProvider : IWechatpayConfigProvider
+ {
+ ///
+ /// 获取配置
+ ///
+ /// 参数
+ public Task GetConfigAsync(object parameter = null)
+ {
+ var config = new WechatpayConfig { AppId = "", MerchantId = "", PrivateKey = "", NotifyUrl = "" };
+ return Task.FromResult(config);
+ }
+ }
+}
diff --git a/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Parameters/WechatpayParameterBuilderTest.cs b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Parameters/WechatpayParameterBuilderTest.cs
new file mode 100644
index 000000000..972cdec0e
--- /dev/null
+++ b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Parameters/WechatpayParameterBuilderTest.cs
@@ -0,0 +1,241 @@
+using System;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters;
+using Bing.Helpers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Bing.Biz.Payments.Tests.Wechatpay.Parameters
+{
+ ///
+ /// 微信支付参数生成器测试
+ ///
+ public class WechatpayParameterBuilderTest : IDisposable
+ {
+ ///
+ /// 输出
+ ///
+ private readonly ITestOutputHelper _output;
+
+ ///
+ /// 微信支付参数生成器
+ ///
+ private readonly WechatpayParameterBuilder _builder;
+
+ ///
+ /// 测试初始化
+ ///
+ public WechatpayParameterBuilderTest(ITestOutputHelper output)
+ {
+ _output = output;
+ Time.SetTime(TestConst.Time);
+ _builder = new WechatpayParameterBuilder(new WechatpayConfig());
+ }
+
+ ///
+ /// 释放资源
+ ///
+ public void Dispose()
+ {
+ Time.Reset();
+ }
+
+ ///
+ /// 测试 - 设置应用标识
+ ///
+ [Fact]
+ public void Test_AppId()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.AppId("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置商户号
+ ///
+ [Fact]
+ public void Test_MerchantId()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.MerchantId("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置签名类型
+ ///
+ [Fact]
+ public void Test_SignType()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.SignType("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置标题
+ ///
+ [Fact]
+ public void Test_Body()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.Body("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置商户订单号
+ ///
+ [Fact]
+ public void Test_OutTradeNo()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.OutTradeNo("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置总金额
+ ///
+ [Fact]
+ public void Test_TotalFee()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("123");
+ result.Append("");
+
+ // 操作
+ _builder.TotalFee(1.23M);
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置回调通知地址
+ ///
+ [Fact]
+ public void Test_NotifyUrl()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.NotifyUrl("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置终端IP
+ ///
+ [Fact]
+ public void Test_SpbillCreateIp()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.SpbillCreateIp("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+
+ ///
+ /// 测试 - 设置交易类型
+ ///
+ [Fact]
+ public void Test_TradeType()
+ {
+ // 结果
+ var result = new Str();
+ result.Append("");
+ result.Append("");
+ result.Append("");
+
+ // 操作
+ _builder.TradeType("a");
+
+ // 验证
+ Assert.Equal(result.ToString(), _builder.ToXmlNoContainsSign());
+
+ // 输出结果
+ _output.WriteLine(_builder.ToString());
+ }
+ }
+}
diff --git a/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Results/WechatpayResultTest.cs b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Results/WechatpayResultTest.cs
new file mode 100644
index 000000000..1fd47d8a4
--- /dev/null
+++ b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Results/WechatpayResultTest.cs
@@ -0,0 +1,70 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Enums;
+using Bing.Biz.Payments.Wechatpay.Results;
+using Xunit;
+
+namespace Bing.Biz.Payments.Tests.Wechatpay.Results
+{
+ ///
+ /// 微信支付结果测试
+ ///
+ public class WechatpayResultTest
+ {
+ ///
+ /// 测试 - 校验响应内容
+ ///
+ [Fact]
+ public async Task Test_VerifyResponse()
+ {
+ // 设置响应内容
+ var response = @"
+
+
+
+
+
+
+
+
+
+ ";
+
+ // 操作
+ var result = new WechatpayResult(new TestConfigProvider(), response);
+
+ // 验证
+ Assert.Equal("SUCCESS", result.GetReturnCode());
+ Assert.Equal("OK", result.GetReturnMessage());
+ Assert.Equal("wx9b90e1788b39fec6", result.GetAppId());
+ Assert.Equal("1985518532", result.GetMerchantId());
+ Assert.Equal("wrKodsjUFk34qYno", result.GetNonce());
+ Assert.Equal("5F721ADF22DD2C60B4E171228F8DA36E", result.GetSign());
+ Assert.Equal("SUCCESS", result.GetResultCode());
+ Assert.Equal("wx141217433636466fe2c3b2a10139084028", result.GetPrepayId());
+ Assert.Equal("APP", result.GetTradeType());
+ var isValid = (await result.ValidateAsync()).IsValid;
+ Assert.True(isValid);
+ }
+ }
+
+ ///
+ /// 微信支付测试配置提供器
+ ///
+ public class TestConfigProvider : IWechatpayConfigProvider
+ {
+ ///
+ /// 获取配置
+ ///
+ /// 参数
+ public Task GetConfigAsync(object parameter = null)
+ {
+ var config = new WechatpayConfig
+ {
+ SignType = WechatpaySignType.Md5,
+ PrivateKey = "VVHZOaJEj44WbX0f3Lj7DHkfwEqvlURA"
+ };
+ return Task.FromResult(config);
+ }
+ }
+}
diff --git a/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Services/WechatpayDownloadBillServiceTest.cs b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Services/WechatpayDownloadBillServiceTest.cs
new file mode 100644
index 000000000..4ad3c6b13
--- /dev/null
+++ b/components/tests/Bing.Biz.Payments.Tests/Wechatpay/Services/WechatpayDownloadBillServiceTest.cs
@@ -0,0 +1,28 @@
+using System.Threading.Tasks;
+using Bing.Biz.Payments.Tests.Wechatpay.Configs;
+using Bing.Biz.Payments.Wechatpay.Parameters.Requests;
+using Bing.Biz.Payments.Wechatpay.Services;
+using Bing.Extensions;
+using Xunit;
+
+namespace Bing.Biz.Payments.Tests.Wechatpay.Services
+{
+ ///
+ /// 微信支付 - 下载交易账单服务
+ ///
+ public class WechatpayDownloadBillServiceTest
+ {
+ ///
+ /// 测试 - 下载交易账单
+ ///
+ //[Fact]
+ [Fact(Skip = "更改支付配置后测试")]
+ public async Task Test_DownloadAsync()
+ {
+ var service = new WechatpayDownloadBillService(new TestConfigProvider());
+ var request = new WechatpayDownloadBillRequest { BillDate = "2022-06-10".ToDate() };
+ var result = await service.DownloadAsync(request);
+ Assert.NotEmpty(result.Bills);
+ }
+ }
+}
diff --git a/framework/Publish.bat b/framework/Publish.bat
index c10f5b0d8..ebffe8767 100644
--- a/framework/Publish.bat
+++ b/framework/Publish.bat
@@ -14,6 +14,13 @@ for /R "nuget_pub" %%s in (*) do (
dotnet pack src/Bing -c Release -o nuget_pub
dotnet pack src/Bing.AspNetCore -c Release -o nuget_pub
+::AOP
+dotnet pack src/Bing.Aop.AspectCore -c Release -o nuget_pub
+
+::Validation
+dotnet pack src/Bing.Validation.Abstractions -c Release -o nuget_pub
+dotnet pack src/Bing.Validation -c Release -o nuget_pub
+
::Security
dotnet pack src/Bing.Security -c Release -o nuget_pub
@@ -34,6 +41,7 @@ dotnet pack src/Bing.Data -c Release -o nuget_pub
dotnet pack src/Bing.Data.Sql -c Release -o nuget_pub
::Domain
+dotnet pack src/Bing.Uow -c Release -o nuget_pub
dotnet pack src/Bing.Auditing -c Release -o nuget_pub
dotnet pack src/Bing.Ddd.Domain -c Release -o nuget_pub
diff --git a/framework/UnPublish.bat b/framework/UnPublish.bat
index be3ee9edb..04f94629e 100644
--- a/framework/UnPublish.bat
+++ b/framework/UnPublish.bat
@@ -19,6 +19,10 @@ dotnet nuget delete Bing.AspNetCore %version% -s %source% -k %key% --non-interac
::Security
dotnet nuget delete Bing.Security %version% -s %source% -k %key% --non-interactive
+::Validation
+dotnet nuget delete Bing.Validation.Abstractions %version% -s %source% -k %key% --non-interactive
+dotnet nuget delete Bing.Validation %version% -s %source% -k %key% --non-interactive
+
::Logs
dotnet nuget delete Bing.Logs %version% -s %source% -k %key% --non-interactive
dotnet nuget delete Bing.Logs.Exceptionless %version% -s %source% -k %key% --non-interactive
diff --git a/framework/src/Bing.Aop.AspectCore/Bing.Aop.AspectCore.csproj b/framework/src/Bing.Aop.AspectCore/Bing.Aop.AspectCore.csproj
new file mode 100644
index 000000000..4b0e705e9
--- /dev/null
+++ b/framework/src/Bing.Aop.AspectCore/Bing.Aop.AspectCore.csproj
@@ -0,0 +1,14 @@
+
+
+ Bing.Aop.AspectCore
+ Bing.Aop.AspectCore
+ Bing.Aop.AspectCore是Bing应用框架基于 AspectCore 实现AOP拦截功能的库。
+
+
+
+
+
+
+
+
+
diff --git a/framework/src/Bing/Bing/Aspects/AutowiredAttribute.cs b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/AutowiredAttribute.cs
similarity index 100%
rename from framework/src/Bing/Bing/Aspects/AutowiredAttribute.cs
rename to framework/src/Bing.Aop.AspectCore/Bing/Aspects/AutowiredAttribute.cs
diff --git a/framework/src/Bing/Bing/Aspects/IgnoreAttribute.cs b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/IgnoreAttribute.cs
similarity index 100%
rename from framework/src/Bing/Bing/Aspects/IgnoreAttribute.cs
rename to framework/src/Bing.Aop.AspectCore/Bing/Aspects/IgnoreAttribute.cs
diff --git a/framework/src/Bing.Aop.AspectCore/Bing/Aspects/InterceptorBase.cs b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/InterceptorBase.cs
new file mode 100644
index 000000000..1a5c26c73
--- /dev/null
+++ b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/InterceptorBase.cs
@@ -0,0 +1,9 @@
+namespace Bing.Aspects
+{
+ ///
+ /// 拦截器基类
+ ///
+ public abstract class InterceptorBase : AspectCore.DynamicProxy.AbstractInterceptorAttribute
+ {
+ }
+}
diff --git a/framework/src/Bing/Bing/Aspects/NotEmptyAttribute.cs b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/NotEmptyAttribute.cs
similarity index 96%
rename from framework/src/Bing/Bing/Aspects/NotEmptyAttribute.cs
rename to framework/src/Bing.Aop.AspectCore/Bing/Aspects/NotEmptyAttribute.cs
index 8e0edd455..f42f2b707 100644
--- a/framework/src/Bing/Bing/Aspects/NotEmptyAttribute.cs
+++ b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/NotEmptyAttribute.cs
@@ -1,7 +1,6 @@
using System;
using System.Threading.Tasks;
using AspectCore.DynamicProxy.Parameters;
-using Bing.Aspects.Base;
using Bing.Extensions;
namespace Bing.Aspects
diff --git a/framework/src/Bing/Bing/Aspects/NotNullAttribute.cs b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/NotNullAttribute.cs
similarity index 96%
rename from framework/src/Bing/Bing/Aspects/NotNullAttribute.cs
rename to framework/src/Bing.Aop.AspectCore/Bing/Aspects/NotNullAttribute.cs
index 8acf26ae3..ca637a62f 100644
--- a/framework/src/Bing/Bing/Aspects/NotNullAttribute.cs
+++ b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/NotNullAttribute.cs
@@ -1,7 +1,6 @@
using System;
using System.Threading.Tasks;
using AspectCore.DynamicProxy.Parameters;
-using Bing.Aspects.Base;
namespace Bing.Aspects
{
diff --git a/framework/src/Bing.Aop.AspectCore/Bing/Aspects/ParameterInterceptorBase.cs b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/ParameterInterceptorBase.cs
new file mode 100644
index 000000000..d59049ed0
--- /dev/null
+++ b/framework/src/Bing.Aop.AspectCore/Bing/Aspects/ParameterInterceptorBase.cs
@@ -0,0 +1,9 @@
+namespace Bing.Aspects
+{
+ ///
+ /// 参数拦截器基类
+ ///
+ public abstract class ParameterInterceptorBase : AspectCore.DynamicProxy.Parameters.ParameterInterceptorAttribute
+ {
+ }
+}
diff --git a/framework/src/Bing/Bing/DependencyInjection/Extensions.Aop.cs b/framework/src/Bing.Aop.AspectCore/Bing/DependencyInjection/AspectCoreExtensions.cs
similarity index 81%
rename from framework/src/Bing/Bing/DependencyInjection/Extensions.Aop.cs
rename to framework/src/Bing.Aop.AspectCore/Bing/DependencyInjection/AspectCoreExtensions.cs
index f5db14550..aac736396 100644
--- a/framework/src/Bing/Bing/DependencyInjection/Extensions.Aop.cs
+++ b/framework/src/Bing.Aop.AspectCore/Bing/DependencyInjection/AspectCoreExtensions.cs
@@ -1,8 +1,10 @@
using System;
using AspectCore.Configuration;
using AspectCore.DynamicProxy;
+using AspectCore.DynamicProxy.Parameters;
using AspectCore.Extensions.AspectScope;
using AspectCore.Extensions.DependencyInjection;
+using Bing.Exceptions.Prompts;
using Bing.Extensions;
using Bing.Reflection;
using Microsoft.Extensions.DependencyInjection;
@@ -10,9 +12,9 @@
namespace Bing.DependencyInjection
{
///
- /// AspectCore扩展
+ /// AspectCore 扩展
///
- public static partial class Extensions
+ public static class AspectCoreExtensions
{
///
/// 启用Aop
@@ -24,12 +26,11 @@ public static partial class Extensions
///
public static void EnableAop(this IServiceCollection services, Action configAction = null)
{
+ ExceptionPrompt.AddPrompt(new AspectExceptionPrompt());
services.ConfigureDynamicProxy(config =>
{
//config.EnableParameterAspect();// 启用参数拦截,会导致异常不能很好的定位
- config.NonAspectPredicates.Add(t =>
- Reflections.GetTopBaseType(t.DeclaringType).SafeString() ==
- "Microsoft.EntityFrameworkCore.DbContext");
+ config.NonAspectPredicates.Add(t => Reflections.GetTopBaseType(t.DeclaringType).SafeString() == "Microsoft.EntityFrameworkCore.DbContext");
configAction?.Invoke(config);
});
services.EnableAspectScoped();
diff --git a/framework/src/Bing.Aop.AspectCore/Bing/Exceptions/Prompts/AspectExceptionPrompt.cs b/framework/src/Bing.Aop.AspectCore/Bing/Exceptions/Prompts/AspectExceptionPrompt.cs
new file mode 100644
index 000000000..687eac130
--- /dev/null
+++ b/framework/src/Bing.Aop.AspectCore/Bing/Exceptions/Prompts/AspectExceptionPrompt.cs
@@ -0,0 +1,42 @@
+using System;
+
+namespace Bing.Exceptions.Prompts
+{
+ ///
+ /// AOP 异常提示
+ ///
+ public class AspectExceptionPrompt : IExceptionPrompt
+ {
+ ///
+ /// 获取异常提示
+ ///
+ /// 异常
+ public string GetPrompt(Exception exception)
+ {
+ if (exception == null)
+ return null;
+ if (exception is AspectCore.DynamicProxy.AspectInvocationException aspectInvocationException)
+ {
+ return aspectInvocationException.InnerException is null
+ ? aspectInvocationException.Message
+ : GetRawException(aspectInvocationException.InnerException).Message;
+ }
+ return string.Empty;
+ }
+
+ ///
+ /// 获取原始异常
+ ///
+ /// 异常
+ public Exception GetRawException(Exception exception)
+ {
+ if (exception is AspectCore.DynamicProxy.AspectInvocationException aspectInvocationException)
+ {
+ if (aspectInvocationException.InnerException == null)
+ return aspectInvocationException;
+ return GetRawException(aspectInvocationException.InnerException);
+ }
+ return exception;
+ }
+ }
+}
diff --git a/framework/src/Bing.Aop.AspectCore/dependency.props b/framework/src/Bing.Aop.AspectCore/dependency.props
new file mode 100644
index 000000000..04554f27f
--- /dev/null
+++ b/framework/src/Bing.Aop.AspectCore/dependency.props
@@ -0,0 +1,11 @@
+
+
+ 2.2.0
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Bing.Aop.AspectCore/references.props b/framework/src/Bing.Aop.AspectCore/references.props
new file mode 100644
index 000000000..a4ddeda5d
--- /dev/null
+++ b/framework/src/Bing.Aop.AspectCore/references.props
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/IModelStateValidator.cs b/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/IModelStateValidator.cs
index 43533adc1..d227a0cec 100644
--- a/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/IModelStateValidator.cs
+++ b/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/IModelStateValidator.cs
@@ -1,4 +1,4 @@
-using Bing.Validations.Abstractions;
+using Bing.Validation;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Bing.AspNetCore.Mvc.Validation
diff --git a/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/ModelStateValidator.cs b/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/ModelStateValidator.cs
index e56698ab9..91475fd89 100644
--- a/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/ModelStateValidator.cs
+++ b/framework/src/Bing.AspNetCore.Mvc/Bing/AspNetCore/Mvc/Validation/ModelStateValidator.cs
@@ -1,6 +1,5 @@
using System.ComponentModel.DataAnnotations;
-using Bing.Validations;
-using Bing.Validations.Abstractions;
+using Bing.Validation;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Bing.AspNetCore.Mvc.Validation
diff --git a/framework/src/Bing.AspNetCore/Bing.AspNetCore.csproj b/framework/src/Bing.AspNetCore/Bing.AspNetCore.csproj
index 20006af65..3a1960359 100644
--- a/framework/src/Bing.AspNetCore/Bing.AspNetCore.csproj
+++ b/framework/src/Bing.AspNetCore/Bing.AspNetCore.csproj
@@ -4,4 +4,19 @@
+
+
+
+ True
+ True
+ MvcModelBindingResource.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ MvcModelBindingResource.Designer.cs
+
+
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ApplicationBuilder.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ApplicationBuilder.cs
index 6808cf0d3..d84d367e7 100644
--- a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ApplicationBuilder.cs
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ApplicationBuilder.cs
@@ -52,5 +52,12 @@ public static IWebHostBuilder UseRealIp(this IWebHostBuilder hostBuilder, string
return hostBuilder;
}
+
+ ///
+ /// 注册请求响应日志中间件。必须调用 services.AddRequestResponseLog 方法方可正常使用
+ ///
+ /// 应用程序生成器
+ ///
+ public static IApplicationBuilder UseRequestResponseLog(this IApplicationBuilder builder) => builder.UseMiddleware();
}
}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ServiceCollection.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ServiceCollection.cs
index 5f0bff0e8..50a429c48 100644
--- a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ServiceCollection.cs
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Extensions/Extensions.ServiceCollection.cs
@@ -1,4 +1,6 @@
-using Bing.AspNetCore.Mvc;
+using System;
+using Bing.AspNetCore.Logs;
+using Bing.AspNetCore.Mvc;
using Bing.AspNetCore.Uploads;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -36,5 +38,17 @@ public static class BingServiceCollectionExtensions
/// 服务集合
public static void AddApiInterfaceService(this IServiceCollection services) where TApiInterfaceService : class, IApiInterfaceService =>
services.TryAddSingleton();
+
+ ///
+ /// 注册请求响应日志服务
+ ///
+ /// 服务集合
+ /// 配置操作
+ public static void AddRequestResponseLog(this IServiceCollection services, Action setupAction)
+ {
+ services.Configure(setupAction);
+ services.AddSingleton();
+ services.AddScoped();
+ }
}
}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/DefaultRequestResponseLogCreator.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/DefaultRequestResponseLogCreator.cs
new file mode 100644
index 000000000..4f73a6edf
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/DefaultRequestResponseLogCreator.cs
@@ -0,0 +1,30 @@
+using Bing.Utils.Json;
+
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应日志创建者
+ ///
+ public class DefaultRequestResponseLogCreator : IRequestResponseLogCreator
+ {
+ ///
+ /// 初始化一个类型的实例s
+ ///
+ public DefaultRequestResponseLogCreator() => Log = new RequestResponseLog();
+
+ ///
+ /// 请求响应日志
+ ///
+ public RequestResponseLog Log { get; private set; }
+
+ ///
+ /// 输出Json字符串
+ ///
+ public string ToJsonString()
+ {
+ var jsonString = JsonHelper.ToJson(Log);
+ return jsonString;
+ }
+
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/DefaultRequestResponseLogger.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/DefaultRequestResponseLogger.cs
new file mode 100644
index 000000000..49924ace2
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/DefaultRequestResponseLogger.cs
@@ -0,0 +1,27 @@
+using Microsoft.Extensions.Logging;
+
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应记录器
+ ///
+ public class DefaultRequestResponseLogger : IRequestResponseLogger
+ {
+ ///
+ /// 日志记录器
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 日志记录器
+ public DefaultRequestResponseLogger(ILogger logger) => _logger = logger;
+
+ ///
+ /// 写入日志
+ ///
+ /// 请求响应日志创建者
+ public void Log(IRequestResponseLogCreator logCreator) => _logger.LogDebug(logCreator.ToJsonString());
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/IRequestResponseLogCreator.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/IRequestResponseLogCreator.cs
new file mode 100644
index 000000000..23192472d
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/IRequestResponseLogCreator.cs
@@ -0,0 +1,18 @@
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应日志创建者
+ ///
+ public interface IRequestResponseLogCreator
+ {
+ ///
+ /// 请求响应日志
+ ///
+ RequestResponseLog Log { get; }
+
+ ///
+ /// 输出Json字符串
+ ///
+ string ToJsonString();
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/IRequestResponseLogger.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/IRequestResponseLogger.cs
new file mode 100644
index 000000000..176827768
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/IRequestResponseLogger.cs
@@ -0,0 +1,14 @@
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应记录器
+ ///
+ public interface IRequestResponseLogger
+ {
+ ///
+ /// 写入日志
+ ///
+ /// 请求响应日志创建者
+ void Log(IRequestResponseLogCreator logCreator);
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestLogMiddleware.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestLogMiddleware.cs
index fd2173e90..6d846d41c 100644
--- a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestLogMiddleware.cs
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestLogMiddleware.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
@@ -12,6 +13,7 @@ namespace Bing.AspNetCore.Logs
///
/// 请求日志中间件
///
+ [Obsolete("请使用 RequestResponseLoggerMiddleware 中间件")]
public class RequestLogMiddleware : IMiddleware
{
///
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLog.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLog.cs
new file mode 100644
index 000000000..de77f2db5
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLog.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应日志
+ ///
+ public class RequestResponseLog
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ public RequestResponseLog() => LogId = Guid.NewGuid().ToString();
+
+ ///
+ /// 日志标识
+ ///
+ /// 默认:Guid.NewGuid().ToString()
+ public string LogId { get; set; }
+
+ ///
+ /// 节点(项目名称)
+ ///
+ public string Node { get; set; }
+
+ ///
+ /// 客户端IP
+ ///
+ public string ClientIp { get; set; }
+
+ ///
+ /// 跟踪标识
+ ///
+ /// 默认:HttpContext.TraceIdentifier
+ public string TraceId { get; set; }
+
+ ///
+ /// 请求时间(UTC)
+ ///
+ public DateTime? RequestDateTimeUtc { get; set; }
+
+ ///
+ /// 请求时间(UTC)操作层面
+ ///
+ public DateTime? RequestDateTimeUtcActionLevel { get; set; }
+
+ ///
+ /// 请求路径
+ ///
+ public string RequestPath { get; set; }
+
+ ///
+ /// 请求查询
+ ///
+ public string RequestQuery { get; set; }
+
+ ///
+ /// 请求查询列表
+ ///
+ public List> RequestQueries { get; set; }
+
+ ///
+ /// 请求方法
+ ///
+ public string RequestMethod { get; set; }
+
+ ///
+ /// 请求格式
+ ///
+ public string RequestScheme { get; set; }
+
+ ///
+ /// 请求主机
+ ///
+ public string RequestHost { get; set; }
+
+ ///
+ /// 请求头
+ ///
+ public Dictionary RequestHeaders { get; set; }
+
+ ///
+ /// 请求Cookie
+ ///
+ public Dictionary RequestCookies { get; set; }
+
+ ///
+ /// 请求正文
+ ///
+ public string RequestBody { get; set; }
+
+ ///
+ /// 请求内容类型
+ ///
+ public string RequestContentType { get; set; }
+
+ ///
+ /// 响应时间(UTC)
+ ///
+ public DateTime? ResponseDateTimeUtc { get; set; }
+
+ ///
+ /// 响应时间(UTC)操作层面
+ ///
+ public DateTime? ResponseDateTimeUtcActionLevel { get; set; }
+
+ ///
+ /// 响应状态
+ ///
+ public string ResponseStatus { get; set; }
+
+ ///
+ /// 响应头
+ ///
+ public Dictionary ResponseHeaders { get; set; }
+
+ ///
+ /// 响应正文
+ ///
+ public string ResponseBody { get; set; }
+
+ ///
+ /// 响应内容类型
+ ///
+ public string ResponseContentType { get; set; }
+
+ ///
+ /// 是否异常操作层面
+ ///
+ public bool? IsExceptionActionLevel { get; set; }
+
+ ///
+ /// 异常消息
+ ///
+ public string ExceptionMessage { get; set; }
+
+ ///
+ /// 异常堆栈跟踪
+ ///
+ public string ExceptionStackTrace { get; set; }
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerActionFilter.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerActionFilter.cs
new file mode 100644
index 000000000..36cdd9e67
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerActionFilter.cs
@@ -0,0 +1,43 @@
+using System;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应记录器 操作过滤器
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
+ public class RequestResponseLoggerActionFilter : Attribute, IActionFilter
+ {
+ ///
+ /// 获取请求响应日志
+ ///
+ /// Http上下文
+ private RequestResponseLog GetLog(HttpContext context)
+ {
+ return context.RequestServices.GetRequiredService().Log;
+ }
+
+ ///
+ /// 执行操作之前。在模型绑定完成之后,在执行操作之前调用。
+ ///
+ /// 操作执行上下文
+ public void OnActionExecuting(ActionExecutingContext context)
+ {
+ var log = GetLog(context.HttpContext);
+ log.RequestDateTimeUtcActionLevel = DateTime.UtcNow;
+ }
+
+ ///
+ /// 执行操作之后。在操作执行之后,操作结果执行之前调用。
+ ///
+ /// 已执行操作上下文
+ public void OnActionExecuted(ActionExecutedContext context)
+ {
+ var log = GetLog(context.HttpContext);
+ log.ResponseDateTimeUtcActionLevel = DateTime.UtcNow;
+ }
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerErrorFilter.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerErrorFilter.cs
new file mode 100644
index 000000000..761e292e3
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerErrorFilter.cs
@@ -0,0 +1,34 @@
+using System;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应记录器 错误过滤器
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
+ public class RequestResponseLoggerErrorFilter : Attribute, IExceptionFilter
+ {
+ ///
+ /// 获取请求响应日志
+ ///
+ /// Http上下文
+ private RequestResponseLog GetLog(HttpContext context)
+ {
+ return context.RequestServices.GetRequiredService().Log;
+ }
+
+ ///
+ /// 执行操作异常
+ ///
+ /// 异常上下文
+ public void OnException(ExceptionContext context)
+ {
+ var log = GetLog(context.HttpContext);
+ log.IsExceptionActionLevel = true;
+ log.RequestDateTimeUtcActionLevel ??= DateTime.UtcNow;
+ }
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerMiddleware.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerMiddleware.cs
new file mode 100644
index 000000000..c392fe179
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerMiddleware.cs
@@ -0,0 +1,290 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Bing.Helpers;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应记录器中间件
+ ///
+ public class RequestResponseLoggerMiddleware : IMiddleware
+ {
+ ///
+ /// 方法
+ ///
+ private readonly RequestDelegate _next;
+
+ ///
+ /// 请求响应记录器选项
+ ///
+ private readonly RequestResponseLoggerOptions _options;
+
+ ///
+ /// 请求响应记录器
+ ///
+ private readonly IRequestResponseLogger _logger;
+
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 方法
+ /// 请求响应记录器选项
+ /// 请求响应记录器
+ public RequestResponseLoggerMiddleware(RequestDelegate next, IOptions options, IRequestResponseLogger logger)
+ {
+ _next = next;
+ _options = options.Value;
+ _logger = logger;
+ }
+
+ ///
+ /// 执行中间件拦截逻辑
+ ///
+ /// Http上下文
+ public async Task InvokeAsync(HttpContext context)
+ {
+ if (_options == null || !_options.IsEnabled || FilterRequest(context))
+ {
+ await _next(context);
+ return;
+ }
+ var logCreator = context?.RequestServices?.GetRequiredService();
+ var log = logCreator?.Log;
+ if (log == null)
+ {
+ await _next(context);
+ return;
+ }
+
+ log.RequestDateTimeUtc = DateTime.UtcNow;
+ var request = context.Request;
+
+ // log
+ log.LogId = Guid.NewGuid().ToString();
+ log.TraceId = context.TraceIdentifier;
+ var ip = request.HttpContext.Connection.RemoteIpAddress;
+ log.ClientIp = ip?.ToString();
+ log.Node = _options.Name;
+
+ // request
+ log.RequestMethod = request.Method;
+ log.RequestPath = request.Path;
+ log.RequestQuery = request.QueryString.ToString();
+ log.RequestQueries = FormatQueries(request.QueryString.ToString());
+ log.RequestHeaders = _options.WithHeader ? FormatHeaders(request.Headers) : null;
+ log.RequestCookies = _options.WithCookie ? FormatCookies(request.Cookies) : null;
+ log.RequestBody = await ReadBodyFromRequest(request);
+ log.RequestScheme = request.Scheme;
+ log.RequestHost = request.Host.ToString();
+ log.RequestContentType = request.ContentType;
+
+ // 暂时用 MemoryStream 替换 HttpResponseStream,用于获取其运行中的值
+ var response = context.Response;
+ var originalResponseBody = response.Body;
+ using var newResponseBody = new MemoryStream();
+ response.Body = newResponseBody;
+
+ // 调用管道中的下一个中间件
+ try
+ {
+ await _next(context);
+ }
+ catch (Exception e)
+ {
+ // 异常:app.UseExceptionHandler() 或者 中间件
+ LogError(log, e);
+ }
+
+ newResponseBody.Seek(0, SeekOrigin.Begin);
+ var responseBodyText = await ReadBodyFromResponse(context);
+ newResponseBody.Seek(0, SeekOrigin.Begin);
+
+ await newResponseBody.CopyToAsync(originalResponseBody);
+
+ // response
+ log.ResponseContentType = response.ContentType;
+ log.ResponseStatus = response.StatusCode.ToString();
+ log.ResponseHeaders = _options.WithHeader ? FormatHeaders(response.Headers) : null;
+ log.ResponseBody = _options.WithResponse ? responseBodyText : null;
+ log.ResponseDateTimeUtc = DateTime.UtcNow;
+
+#if NETCOREAPP3_1_OR_GREATER
+ var contextFeature = context.Features.Get();
+ if (contextFeature != null && contextFeature.Error != null)
+ {
+ var exception = contextFeature.Error;
+ LogError(log, exception);
+ }
+#endif
+
+ _logger.Log(logCreator);
+ }
+
+ ///
+ /// 记录错误
+ ///
+ /// 请求响应日志
+ /// 异常
+ private void LogError(RequestResponseLog log, Exception exception)
+ {
+ log.ExceptionMessage = exception.Message;
+ log.ExceptionStackTrace = exception.StackTrace;
+ }
+
+ ///
+ /// 格式化请求头
+ ///
+ /// 请求头
+ private Dictionary FormatHeaders(IHeaderDictionary headers)
+ {
+ var pairs = new Dictionary();
+ foreach (var header in headers)
+ pairs.Add(header.Key, header.Value);
+ return pairs;
+ }
+
+ ///
+ /// 格式化Cookies
+ ///
+ /// Cookie集合
+ private Dictionary FormatCookies(IRequestCookieCollection cookies)
+ {
+ var pairs = new Dictionary();
+ foreach (var cookie in cookies)
+ pairs.Add(cookie.Key, cookie.Value);
+ return pairs;
+ }
+
+ ///
+ /// 格式化查询字符串
+ ///
+ /// 查询字符串
+ private List> FormatQueries(string queryString)
+ {
+ var pairs = new List>();
+ foreach (var query in queryString.TrimStart('?').Split('&'))
+ {
+ var items = query.Split('=');
+ var key = items.Any() ? items[0] : string.Empty;
+ var value = items.Length >= 2 ? items[1] : string.Empty;
+ if (!string.IsNullOrEmpty(key))
+ pairs.Add(new KeyValuePair(key, value));
+ }
+ return pairs;
+ }
+
+ ///
+ /// 从请求中读取正文内容
+ ///
+ /// Http请求
+ private async Task ReadBodyFromRequest(HttpRequest request)
+ {
+ // 确保可以多次读取请求的正文,用于管道中的下一个中间件
+ request.EnableBuffering();
+#if NETCOREAPP3_1_OR_GREATER
+ using var streamReader = new StreamReader(request.Body, leaveOpen: true);
+#else
+ using var streamReader = new StreamReader(request.Body, System.Text.Encoding.UTF8, true, 1024, true);
+#endif
+ var requestBody = await streamReader.ReadToEndAsync();
+ // 重置请求的主体流位置,用于管道中的下一个中间件
+ request.Body.Position = 0;
+ return requestBody;
+ }
+
+ ///
+ /// 从响应中读取正文内容
+ ///
+ /// Http上下文
+ private async Task ReadBodyFromResponse(HttpContext context)
+ {
+ if (string.IsNullOrWhiteSpace(context.Response.ContentType) || !_options.WithResponse)
+ {
+ if (context.Response.Body.CanSeek)
+ context.Response.Body.Seek(0, SeekOrigin.Begin);
+ return string.Empty;
+ }
+
+ if (FilterStaticFiles(context))
+ {
+ if (context.Response.Body.CanSeek)
+ context.Response.Body.Seek(0, SeekOrigin.Begin);
+ return string.Empty;
+ }
+
+ var result = string.Empty;
+ context.Response.Body.Seek(0, SeekOrigin.Begin);
+
+ Stream source = null;
+ if (context.Response.Headers.ContainsKey("Content-Encoding"))
+ {
+ var contentEncoding = context.Response.Headers["Content-Encoding"].ToString();
+ switch (contentEncoding)
+ {
+ case "gzip":
+ source = new GZipStream(context.Response.Body, CompressionMode.Decompress);
+ break;
+ case "deflate":
+ source = new DeflateStream(context.Response.Body, CompressionMode.Decompress);
+ break;
+#if NETCOREAPP3_1_OR_GREATER
+ case "br":
+ source = new BrotliStream(context.Response.Body, CompressionMode.Decompress);
+ break;
+#endif
+ }
+ }
+
+ source ??= context.Response.Body;
+
+ var responseBodyText = await new StreamReader(source, Encoding.UTF8).ReadToEndAsync();
+ context.Response.Body.Seek(0, SeekOrigin.Begin);
+ return responseBodyText;
+ }
+
+ ///
+ /// 过滤静态文件
+ ///
+ /// Http上下文
+ private bool FilterStaticFiles(HttpContext context)
+ {
+ if (!string.IsNullOrWhiteSpace(context.Request.ContentType) && context.Request.ContentType.Contains("application/grpc"))
+ return false;
+ if (context.Request.Method.ToLowerInvariant() == "options")
+ return true;
+ if (context.Request.Path.HasValue && context.Request.Path.Value.Contains("."))
+ return true;
+ return false;
+ }
+
+ ///
+ /// 过滤请求
+ ///
+ /// Http上下文
+ private bool FilterRequest(HttpContext context)
+ {
+ // 过滤上传文件请求
+ if (context.Request.HasFormContentType && context.Request.Form != null && context.Request.Form.Files != null && context.Request.Form.Files.Any())
+ return true;
+ // 过滤请求数据
+ if (_options.RequestFilter == null || _options.RequestFilter.Count == 0)
+ return false;
+ // 请求路径 - 规则匹配
+ var path = context.Request.Path.Value.ToLowerInvariant();
+ foreach (var item in _options.RequestFilter)
+ {
+ if (FastPathMatcher.Match(item, path))
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerOptions.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerOptions.cs
new file mode 100644
index 000000000..2aab91c7e
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/RequestResponseLoggerOptions.cs
@@ -0,0 +1,50 @@
+using System.Collections.Generic;
+
+namespace Bing.AspNetCore.Logs
+{
+ ///
+ /// 请求响应记录器选项
+ ///
+ public class RequestResponseLoggerOptions
+ {
+ ///
+ /// 是否开启收集数据
+ ///
+ public bool IsEnabled { get; set; }
+
+ ///
+ /// 名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 是否记录接口的入参
+ ///
+ public bool WithRequest { get; set; } = false;
+
+ ///
+ /// 是否记录接口的出参
+ ///
+ public bool WithResponse { get; set; } = false;
+
+ ///
+ /// 是否记录Cookie信息
+ ///
+ public bool WithCookie { get; set; } = false;
+
+ ///
+ /// 是否记录请求头信息
+ ///
+ public bool WithHeader { get; set; } = false;
+
+ ///
+ /// 请求数据过滤,用 * 来模糊匹配
+ ///
+ public List RequestFilter { get; set; } = new();
+
+ ///
+ /// 日期时间格式
+ ///
+ public string DateTimeFormat { get; set; }
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/RealIp/RealIpMiddleware.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/RealIp/RealIpMiddleware.cs
index 9c4bcaaff..903086bbd 100644
--- a/framework/src/Bing.AspNetCore/Bing/AspNetCore/RealIp/RealIpMiddleware.cs
+++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/RealIp/RealIpMiddleware.cs
@@ -52,20 +52,44 @@ public async Task InvokeAsync(HttpContext context)
var headers = context.Request.Headers;
try
{
- if (headers.ContainsKey(_options.HeaderKey))
- {
- context.Connection.RemoteIpAddress = IPAddress.Parse(
- _options.HeaderKey.Equals("x-forwarded-for", StringComparison.CurrentCultureIgnoreCase)
- ? headers["X-Forwarded-For"].ToString().Split(',')[0]
- : headers[_options.HeaderKey].ToString());
- _logger.LogDebug($"解析真实IP成功: {context.Connection.RemoteIpAddress}");
- }
+ var ip = TryGetIpAddress(headers, _options.HeaderKey) ?? TryGetIpAddress(headers, "x-forwarded-for") ?? TryGetIpAddress(headers, "X-Forwarded-For");
+ if (ip != null)
+ context.Connection.RemoteIpAddress = ip;
}
finally
{
await _next(context);
}
}
+
+ ///
+ /// 尝试获取IP地址
+ ///
+ /// 请求头字典
+ /// 请求头
+ private IPAddress TryGetIpAddress(IHeaderDictionary headers, string key)
+ {
+ if (headers.ContainsKey(key))
+ {
+ headers.TryGetValue(key, out var ip);
+ _logger.LogDebug($"解析真实IP地址: {ip}");
+ if (string.IsNullOrEmpty(ip) == false && ip.ToString().ToLower() != "unknown")
+ {
+ var tmpIp = key.Equals("x-forwarded-for", StringComparison.CurrentCultureIgnoreCase)
+ ? ip.ToString().Split(',')[0]
+ : ip.ToString();
+ if (IPAddress.TryParse(tmpIp, out var ipAddress))
+ {
+ _logger.LogDebug($"解析真实IP成功: {ipAddress}");
+ return ipAddress;
+ }
+
+ _logger.LogError($"解析真实IP失败: {tmpIp}");
+ }
+ }
+
+ return null;
+ }
}
///
diff --git a/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/MvcModelBindingResource.Designer.cs b/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/MvcModelBindingResource.Designer.cs
new file mode 100644
index 000000000..85a07fed7
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/MvcModelBindingResource.Designer.cs
@@ -0,0 +1,162 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本:4.0.30319.42000
+//
+// 对此文件的更改可能会导致不正确的行为,并且如果
+// 重新生成代码,这些更改将会丢失。
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata {
+ using System;
+
+
+ ///
+ /// 一个强类型的资源类,用于查找本地化的字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class MvcModelBindingResource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal MvcModelBindingResource() {
+ }
+
+ ///
+ /// 返回此类使用的缓存的 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.MvcModelBindingResource", typeof(MvcModelBindingResource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// 查找类似 '{0}' 不能作为 {1} 的值 的本地化字符串。
+ ///
+ internal static string AttemptedValueIsInvalidAccessor {
+ get {
+ return ResourceManager.GetString("AttemptedValueIsInvalidAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 没有为属性 '{0}' 指定值 的本地化字符串。
+ ///
+ internal static string MissingBindRequiredValueAccessor {
+ get {
+ return ResourceManager.GetString("MissingBindRequiredValueAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 必须指定值 的本地化字符串。
+ ///
+ internal static string MissingKeyOrValueAccessor {
+ get {
+ return ResourceManager.GetString("MissingKeyOrValueAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 请求正文不能为空 的本地化字符串。
+ ///
+ internal static string MissingRequestBodyRequiredValueAccessor {
+ get {
+ return ResourceManager.GetString("MissingRequestBodyRequiredValueAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 '{0}' 是无效的值 的本地化字符串。
+ ///
+ internal static string NonPropertyAttemptedValueIsInvalidAccessor {
+ get {
+ return ResourceManager.GetString("NonPropertyAttemptedValueIsInvalidAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 指定的值无效 的本地化字符串。
+ ///
+ internal static string NonPropertyUnknownValueIsInvalidAccessor {
+ get {
+ return ResourceManager.GetString("NonPropertyUnknownValueIsInvalidAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 字段的值应该是数字 的本地化字符串。
+ ///
+ internal static string NonPropertyValueMustBeANumberAccessor {
+ get {
+ return ResourceManager.GetString("NonPropertyValueMustBeANumberAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 为 {0} 指定的值无效 的本地化字符串。
+ ///
+ internal static string UnknownValueIsInvalidAccessor {
+ get {
+ return ResourceManager.GetString("UnknownValueIsInvalidAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 '{0}' 是无效的值 的本地化字符串。
+ ///
+ internal static string ValueIsInvalidAccessor {
+ get {
+ return ResourceManager.GetString("ValueIsInvalidAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 字段 {0} 的值应该是数字 的本地化字符串。
+ ///
+ internal static string ValueMustBeANumberAccessor {
+ get {
+ return ResourceManager.GetString("ValueMustBeANumberAccessor", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 '{0}' 是无效的值 的本地化字符串。
+ ///
+ internal static string ValueMustNotBeNullAccessor {
+ get {
+ return ResourceManager.GetString("ValueMustNotBeNullAccessor", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/MvcModelBindingResource.resx b/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/MvcModelBindingResource.resx
new file mode 100644
index 000000000..34c800ce4
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/MvcModelBindingResource.resx
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ '{0}' 不能作为 {1} 的值
+ The value '{0}' is not valid for {1}.
+
+
+ 没有为属性 '{0}' 指定值
+ A value for the '{0}' parameter or property was not provided.
+
+
+ 必须指定值
+ A value is required.
+
+
+ 请求正文不能为空
+ A non-empty request body is required.
+
+
+ '{0}' 是无效的值
+ The value '{0}' is not valid.
+
+
+ 指定的值无效
+ The supplied value is invalid.
+
+
+ 字段的值应该是数字
+ The field must be a number.
+
+
+ 为 {0} 指定的值无效
+ The supplied value is invalid for {0}.
+
+
+ '{0}' 是无效的值
+ The value '{0}' is invalid.
+
+
+ 字段 {0} 的值应该是数字
+ The field {0} must be a number.
+
+
+ '{0}' 是无效的值
+ The value '{0}' is invalid.
+
+
\ No newline at end of file
diff --git a/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/ResourceModelBindingMessageProviderExtensions.cs b/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/ResourceModelBindingMessageProviderExtensions.cs
new file mode 100644
index 000000000..872040127
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Microsoft/AspNetCore/Mvc/ModelBinding/Metadata/ResourceModelBindingMessageProviderExtensions.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
+{
+ ///
+ /// 模型绑定消息提供程序()扩展
+ ///
+ public static class ResourceModelBindingMessageProviderExtensions
+ {
+ ///
+ /// 应用翻译资源
+ ///
+ /// 模型绑定消息提供程序
+ public static void UseTranslatedResources(this DefaultModelBindingMessageProvider messageProvider)
+ {
+ messageProvider.SetMissingBindRequiredValueAccessor(One(MvcModelBindingResource.MissingBindRequiredValueAccessor));
+ messageProvider.SetMissingKeyOrValueAccessor(Zero(MvcModelBindingResource.MissingKeyOrValueAccessor));
+ messageProvider.SetMissingRequestBodyRequiredValueAccessor(Zero(MvcModelBindingResource.MissingRequestBodyRequiredValueAccessor));
+ messageProvider.SetValueMustNotBeNullAccessor(One(MvcModelBindingResource.ValueMustNotBeNullAccessor));
+ messageProvider.SetAttemptedValueIsInvalidAccessor(Two(MvcModelBindingResource.AttemptedValueIsInvalidAccessor));
+ messageProvider.SetNonPropertyAttemptedValueIsInvalidAccessor(One(MvcModelBindingResource.NonPropertyAttemptedValueIsInvalidAccessor));
+ messageProvider.SetUnknownValueIsInvalidAccessor(One(MvcModelBindingResource.UnknownValueIsInvalidAccessor));
+ messageProvider.SetNonPropertyUnknownValueIsInvalidAccessor(Zero(MvcModelBindingResource.NonPropertyUnknownValueIsInvalidAccessor));
+ messageProvider.SetValueIsInvalidAccessor(One(MvcModelBindingResource.ValueIsInvalidAccessor));
+ messageProvider.SetValueMustBeANumberAccessor(One(MvcModelBindingResource.ValueMustBeANumberAccessor));
+ messageProvider.SetNonPropertyValueMustBeANumberAccessor(Zero(MvcModelBindingResource.NonPropertyValueMustBeANumberAccessor));
+ }
+
+ ///
+ /// 0个参字符串格式化
+ ///
+ private static Func Zero(string resource) => () => resource;
+
+ ///
+ /// 1个参数字符串格式化
+ ///
+ private static Func One(string resource) => arg => string.Format(resource, arg);
+
+ ///
+ /// 2个参数字符串格式化
+ ///
+ private static Func Two(string resource) => (arg1, arg2) => string.Format(resource, arg1, arg2);
+ }
+}
diff --git a/framework/src/Bing.AspNetCore/Microsoft/Extensions/DependencyInjection/BingAspNetCoreServiceCollectionExtensions.cs b/framework/src/Bing.AspNetCore/Microsoft/Extensions/DependencyInjection/BingAspNetCoreServiceCollectionExtensions.cs
index 9405d21f3..c6661622f 100644
--- a/framework/src/Bing.AspNetCore/Microsoft/Extensions/DependencyInjection/BingAspNetCoreServiceCollectionExtensions.cs
+++ b/framework/src/Bing.AspNetCore/Microsoft/Extensions/DependencyInjection/BingAspNetCoreServiceCollectionExtensions.cs
@@ -12,7 +12,11 @@ public static class BingAspNetCoreServiceCollectionExtensions
/// 获取环境信息
///
/// 服务集合
- public static IWebHostEnvironment GetWebHostEnvironment(this IServiceCollection services) => services.GetSingletonInstance();
+ public static IWebHostEnvironment GetWebHostEnvironment(this IServiceCollection services)
+ {
+ var hostingEnvironment = services.GetSingletonInstanceOrNull();
+ return hostingEnvironment ?? new EmptyHostingEnvironment { EnvironmentName = Microsoft.Extensions.Hosting.Environments.Development };
+ }
#elif NETSTANDARD2_0
///
/// 获取环境信息
diff --git a/framework/src/Bing.AspNetCore/Microsoft/Extensions/DependencyInjection/EmptyHostingEnvironment.cs b/framework/src/Bing.AspNetCore/Microsoft/Extensions/DependencyInjection/EmptyHostingEnvironment.cs
new file mode 100644
index 000000000..c56c6730a
--- /dev/null
+++ b/framework/src/Bing.AspNetCore/Microsoft/Extensions/DependencyInjection/EmptyHostingEnvironment.cs
@@ -0,0 +1,43 @@
+using Microsoft.Extensions.FileProviders;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+#if NETCOREAPP3_0 || NETCOREAPP3_1 || NET5_0
+ ///
+ /// 空主机环境变量
+ ///
+ internal class EmptyHostingEnvironment : Microsoft.AspNetCore.Hosting.IWebHostEnvironment
+ {
+ ///
+ /// 环境名称
+ ///
+ public string EnvironmentName { get; set; }
+
+ ///
+ /// 应用程序名称
+ ///
+ public string ApplicationName { get; set; }
+
+ ///
+ /// Web根路径,即wwwroot
+ ///
+ public string WebRootPath { get; set; }
+
+ ///
+ /// Web根路径文件提供程序
+ ///
+ public IFileProvider WebRootFileProvider { get; set; }
+
+ ///
+ /// 根路径
+ ///
+ public string ContentRootPath { get; set; }
+
+ ///
+ /// 根路径文件提供程序
+ ///
+ public IFileProvider ContentRootFileProvider { get; set; }
+
+ }
+#endif
+}
diff --git a/framework/src/Bing.Auditing/Bing.Auditing.csproj b/framework/src/Bing.Auditing/Bing.Auditing.csproj
index e9503931b..e5971f447 100644
--- a/framework/src/Bing.Auditing/Bing.Auditing.csproj
+++ b/framework/src/Bing.Auditing/Bing.Auditing.csproj
@@ -5,4 +5,8 @@
+
+
+
+
diff --git a/framework/src/Bing.Auditing/Bing/Auditing/AuditPropertySetter.cs b/framework/src/Bing.Auditing/Bing/Auditing/AuditPropertySetter.cs
new file mode 100644
index 000000000..a0314d081
--- /dev/null
+++ b/framework/src/Bing.Auditing/Bing/Auditing/AuditPropertySetter.cs
@@ -0,0 +1,301 @@
+using System;
+using Bing.DependencyInjection;
+using Bing.Extensions;
+using Bing.Users;
+
+namespace Bing.Auditing
+{
+ ///
+ /// 设计属性设置其
+ ///
+ public class AuditPropertySetter : IAuditPropertySetter, ITransientDependency
+ {
+ ///
+ /// 初始化一个类型的实例
+ ///
+ /// 当前用户
+ public AuditPropertySetter(ICurrentUser currentUser)
+ {
+ CurrentUser = currentUser;
+ }
+
+ ///
+ /// 当前用户
+ ///
+ protected ICurrentUser CurrentUser { get; }
+
+ ///
+ /// 设置创建属性
+ ///
+ /// 目标对象
+ public virtual void SetCreationProperties(object targetObject)
+ {
+ if (targetObject == null)
+ return;
+ SetCreationTime(targetObject);
+ SetCreatorId(targetObject);
+ SetCreator(targetObject);
+ }
+
+ ///
+ /// 设置修改属性
+ ///
+ /// 目标对象
+ public virtual void SetModificationProperties(object targetObject)
+ {
+ if (targetObject == null)
+ return;
+ SetLastModificationTime(targetObject);
+ SetLastModifierId(targetObject);
+ SetLastModifier(targetObject);
+ }
+
+ ///
+ /// 设置删除属性
+ ///
+ /// 目标对象
+ public virtual void SetDeletionProperties(object targetObject)
+ {
+ if (targetObject == null)
+ return;
+ SetDeletionTime(targetObject);
+ SetDeleterId(targetObject);
+ SetDeleter(targetObject);
+ }
+
+ ///
+ /// 设置创建时间
+ ///
+ /// 目标对象
+ protected virtual void SetCreationTime(object targetObject)
+ {
+ if (targetObject is not IHasCreationTime objectWithCreationTime)
+ return;
+ objectWithCreationTime.CreationTime ??= DateTime.Now;
+ }
+
+ ///
+ /// 设置创建人标识
+ ///
+ /// 目标对象
+ protected virtual void SetCreatorId(object targetObject)
+ {
+ if (string.IsNullOrWhiteSpace(CurrentUser.UserId))
+ return;
+ switch (targetObject)
+ {
+ case ICreationAuditedObject userIdWithGuid:
+ if (userIdWithGuid.CreatorId != default && userIdWithGuid.CreatorId != Guid.Empty)
+ return;
+ userIdWithGuid.CreatorId = CurrentUser.UserId.ToGuid();
+ return;
+
+ case ICreationAuditedObject userIdWithNullableGuid:
+ if (userIdWithNullableGuid.CreatorId.HasValue
+ && userIdWithNullableGuid.CreatorId.Value != default
+ && userIdWithNullableGuid.CreatorId.Value != Guid.Empty)
+ return;
+ userIdWithNullableGuid.CreatorId = CurrentUser.UserId.ToGuidOrNull();
+ return;
+
+ case ICreationAuditedObject userIdWithInt:
+ if (userIdWithInt.CreatorId != default)
+ return;
+ userIdWithInt.CreatorId = CurrentUser.UserId.ToInt();
+ return;
+
+ case ICreationAuditedObject userIdWithNullableInt:
+ if (userIdWithNullableInt.CreatorId.HasValue
+ && userIdWithNullableInt.CreatorId.Value != default)
+ return;
+ userIdWithNullableInt.CreatorId = CurrentUser.UserId.ToIntOrNull();
+ return;
+
+ case ICreationAuditedObject userIdWithString:
+ if (!string.IsNullOrWhiteSpace(userIdWithString.CreatorId) && userIdWithString.CreatorId != default)
+ return;
+ userIdWithString.CreatorId = CurrentUser.UserId.SafeString();
+ return;
+
+ case ICreationAuditedObject userIdWithLong:
+ if (userIdWithLong.CreatorId != default)
+ return;
+ userIdWithLong.CreatorId = CurrentUser.UserId.ToLong();
+ return;
+
+ case ICreationAuditedObject userIdWithNullableLong:
+ if (userIdWithNullableLong.CreatorId.HasValue
+ && userIdWithNullableLong.CreatorId.Value != default)
+ return;
+ userIdWithNullableLong.CreatorId = CurrentUser.UserId.ToLongOrNull();
+ return;
+ }
+ }
+
+ ///
+ /// 设置创建人
+ ///
+ /// 目标对象
+ protected virtual void SetCreator(object targetObject)
+ {
+ var userName = GetUserName();
+ if (string.IsNullOrWhiteSpace(userName))
+ return;
+ if (targetObject is IHasCreator objectWithCreator)
+ objectWithCreator.Creator = userName;
+ }
+
+ ///
+ /// 设置修改时间
+ ///
+ /// 目标对象
+ protected virtual void SetLastModificationTime(object targetObject)
+ {
+ if (targetObject is IHasModificationTime objectWithModificationTime)
+ objectWithModificationTime.LastModificationTime = DateTime.Now;
+ }
+
+ ///
+ /// 设置修改人标识
+ ///
+ /// 目标对象
+ protected virtual void SetLastModifierId(object targetObject)
+ {
+ if (string.IsNullOrWhiteSpace(CurrentUser.UserId))
+ return;
+ switch (targetObject)
+ {
+ case IModificationAuditedObject userIdWithGuid:
+ userIdWithGuid.LastModifierId = CurrentUser.UserId.ToGuid();
+ return;
+
+ case IModificationAuditedObject userIdWithNullableGuid:
+ userIdWithNullableGuid.LastModifierId = CurrentUser.UserId.ToGuidOrNull();
+ return;
+
+ case IModificationAuditedObject userIdWithInt:
+ userIdWithInt.LastModifierId = CurrentUser.UserId.ToInt();
+ return;
+
+ case IModificationAuditedObject userIdWithNullableInt:
+ userIdWithNullableInt.LastModifierId = CurrentUser.UserId.ToIntOrNull();
+ return;
+
+ case IModificationAuditedObject userIdWithString:
+ userIdWithString.LastModifierId = CurrentUser.UserId.SafeString();
+ return;
+
+ case IModificationAuditedObject userIdWithLong:
+ userIdWithLong.LastModifierId = CurrentUser.UserId.ToLong();
+ return;
+
+ case IModificationAuditedObject userIdWithNullableLong:
+ userIdWithNullableLong.LastModifierId = CurrentUser.UserId.ToLongOrNull();
+ return;
+ }
+ }
+
+ ///
+ /// 设置修改人
+ ///
+ /// 目标对象
+ protected virtual void SetLastModifier(object targetObject)
+ {
+ var userName = GetUserName();
+ if (string.IsNullOrWhiteSpace(userName))
+ return;
+ if (targetObject is IHasModifier objectWithModifier)
+ objectWithModifier.LastModifier = userName;
+ }
+
+ ///
+ /// 设置删除时间
+ ///
+ /// 目标对象
+ protected virtual void SetDeletionTime(object targetObject)
+ {
+ if (targetObject is IHasDeletionTime objectWithDeletionTime)
+ objectWithDeletionTime.DeletionTime = DateTime.Now;
+ }
+
+ ///
+ /// 设置删除人标识
+ ///
+ /// 目标对象
+ protected virtual void SetDeleterId(object targetObject)
+ {
+ if (string.IsNullOrWhiteSpace(CurrentUser.UserId))
+ return;
+ switch (targetObject)
+ {
+ case IDeletionAuditedObject userIdWithGuid:
+ if (userIdWithGuid.DeleterId != default && userIdWithGuid.DeleterId != Guid.Empty)
+ return;
+ userIdWithGuid.DeleterId = CurrentUser.UserId.ToGuid();
+ return;
+
+ case IDeletionAuditedObject userIdWithNullableGuid:
+ if (userIdWithNullableGuid.DeleterId.HasValue
+ && userIdWithNullableGuid.DeleterId.Value != default
+ && userIdWithNullableGuid.DeleterId.Value != Guid.Empty)
+ return;
+ userIdWithNullableGuid.DeleterId = CurrentUser.UserId.ToGuidOrNull();
+ return;
+
+ case IDeletionAuditedObject userIdWithInt:
+ if (userIdWithInt.DeleterId != default)
+ return;
+ userIdWithInt.DeleterId = CurrentUser.UserId.ToInt();
+ return;
+
+ case IDeletionAuditedObject userIdWithNullableInt:
+ if (userIdWithNullableInt.DeleterId.HasValue
+ && userIdWithNullableInt.DeleterId.Value != default)
+ return;
+ userIdWithNullableInt.DeleterId = CurrentUser.UserId.ToIntOrNull();
+ return;
+
+ case IDeletionAuditedObject userIdWithString:
+ if (!string.IsNullOrWhiteSpace(userIdWithString.DeleterId) && userIdWithString.DeleterId != default)
+ return;
+ userIdWithString.DeleterId = CurrentUser.UserId.SafeString();
+ return;
+
+ case IDeletionAuditedObject userIdWithLong:
+ if (userIdWithLong.DeleterId != default)
+ return;
+ userIdWithLong.DeleterId = CurrentUser.UserId.ToLong();
+ return;
+
+ case IDeletionAuditedObject userIdWithNullableLong:
+ if (userIdWithNullableLong.DeleterId.HasValue
+ && userIdWithNullableLong.DeleterId.Value != default)
+ return;
+ userIdWithNullableLong.DeleterId = CurrentUser.UserId.ToLongOrNull();
+ return;
+ }
+ }
+
+ ///
+ /// 设置删除人
+ ///
+ /// 目标对象
+ protected virtual void SetDeleter(object targetObject)
+ {
+ var userName = GetUserName();
+ if (string.IsNullOrWhiteSpace(userName))
+ return;
+ if (targetObject is IHasDeleter objectWithDeleter)
+ objectWithDeleter.Deleter = userName;
+ }
+
+ ///
+ /// 获取用户名称
+ ///
+ protected virtual string GetUserName()
+ {
+ var name = CurrentUser.GetFullName();
+ return string.IsNullOrEmpty(name) ? CurrentUser.GetUserName() : name;
+ }
+ }
+}
diff --git a/framework/src/Bing.AutoMapper/Bing/AutoMapper/AutoMapperObjectMapper.cs b/framework/src/Bing.AutoMapper/Bing/AutoMapper/AutoMapperObjectMapper.cs
index e2a29ba1a..f632f33a7 100644
--- a/framework/src/Bing.AutoMapper/Bing/AutoMapper/AutoMapperObjectMapper.cs
+++ b/framework/src/Bing.AutoMapper/Bing/AutoMapper/AutoMapperObjectMapper.cs
@@ -17,7 +17,7 @@ public class AutoMapperObjectMapper : Bing.ObjectMapping.IObjectMapper
/// 同步锁
///
// ReSharper disable once InconsistentNaming
- private static readonly object Sync = new object();
+ private static readonly object Sync = new();
///
/// 配置提供程序
@@ -44,7 +44,7 @@ public AutoMapperObjectMapper(IConfigurationProvider configuration, IReadOnlyCol
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
_profiles = profiles;
_mapper = _configuration.CreateMapper();
-
+
}
#region Map(将源对象映射到目标对象)
@@ -76,7 +76,9 @@ public TDestination Map(TSource source, TDestination dest
}
catch (AutoMapperMappingException e)
{
- return GetResult(GetType(e.MemberMap.SourceType), GetType(e.MemberMap.DestinationType), source, destination);
+ if (e.InnerException != null && e.InnerException.Message.StartsWith("Missing type map configuration"))
+ return GetResult(GetType(e.MemberMap.SourceType), GetType(e.MemberMap.DestinationType), source, destination);
+ throw;
}
}
@@ -140,7 +142,7 @@ private void ConfigMap(Type sourceType, Type destinationType)
_configuration = new MapperConfiguration(t =>
{
t.CreateMap(sourceType, destinationType);
- foreach (var map in maps)
+ foreach (var map in maps)
t.CreateMap(map.SourceType, map.DestinationType);
foreach (var profile in _profiles)
t.AddProfile(profile as Profile);
diff --git a/framework/src/Bing.Data.Sql/project.dependency.props b/framework/src/Bing.Data.Sql/project.dependency.props
index 5285b56bf..605bf0dfe 100644
--- a/framework/src/Bing.Data.Sql/project.dependency.props
+++ b/framework/src/Bing.Data.Sql/project.dependency.props
@@ -2,4 +2,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/framework/src/Bing.Data/Bing.Data.csproj b/framework/src/Bing.Data/Bing.Data.csproj
index e9503931b..4723aa7b4 100644
--- a/framework/src/Bing.Data/Bing.Data.csproj
+++ b/framework/src/Bing.Data/Bing.Data.csproj
@@ -5,4 +5,8 @@
+
+
+
+
diff --git a/framework/src/Bing.Datas.EntityFramework/Core/TreeCompactRepositoryBase.cs b/framework/src/Bing.Datas.EntityFramework/Core/TreeCompactRepositoryBase.cs
index 8cc16ea84..29e0d28d8 100644
--- a/framework/src/Bing.Datas.EntityFramework/Core/TreeCompactRepositoryBase.cs
+++ b/framework/src/Bing.Datas.EntityFramework/Core/TreeCompactRepositoryBase.cs
@@ -8,7 +8,7 @@
using Bing.Domain.Repositories;
using Bing.Extensions;
using Bing.Trees;
-using Bing.Validations.Abstractions;
+using Bing.Validation;
using Microsoft.EntityFrameworkCore;
namespace Bing.Datas.EntityFramework.Core
@@ -19,7 +19,7 @@ namespace Bing.Datas.EntityFramework.Core
/// 实体类型
/// 持久化对象类型
public abstract class TreeCompactRepositoryBase : TreeCompactRepositoryBase, ITreeCompactRepository
- where TEntity : class, ITreeEntity, IValidatable
+ where TEntity : class, ITreeEntity, IVerifyModel
where TPo : class, IKey, IVersion, IPath, IParentId, ISortId
{
///
@@ -52,7 +52,7 @@ public override async Task GenerateSortIdAsync(Guid? parentId)
/// 实体标识类型
/// 父标识类型
public abstract class TreeCompactRepositoryBase : CompactRepositoryBase, ITreeCompactRepository
- where TEntity : class, ITreeEntity, IValidatable
+ where TEntity : class, ITreeEntity, IVerifyModel
where TPo : class, IKey, IVersion, IPath
{
///
diff --git a/framework/src/Bing.Datas.EntityFramework/Core/UnitOfWorkBase.cs b/framework/src/Bing.Datas.EntityFramework/Core/UnitOfWorkBase.cs
index 3d6be04da..9cfcd66c0 100644
--- a/framework/src/Bing.Datas.EntityFramework/Core/UnitOfWorkBase.cs
+++ b/framework/src/Bing.Datas.EntityFramework/Core/UnitOfWorkBase.cs
@@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
+using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -79,6 +80,11 @@ public abstract class UnitOfWorkBase : DbContext, IUnitOfWork, IDatabase, IEntit
///
protected ICurrentUser CurrentUser => LazyServiceProvider.LazyGetRequiredService();
+ ///
+ /// 审计属性设置器
+ ///
+ protected IAuditPropertySetter AuditPropertySetter => LazyServiceProvider.LazyGetRequiredService();
+
#endregion
#region 静态构造函数
@@ -169,7 +175,7 @@ protected void EnableLog(DbContextOptionsBuilder builder)
return;
builder.EnableSensitiveDataLogging();
builder.EnableDetailedErrors();
- builder.UseLoggerFactory(LoggerFactory);
+ //builder.UseLoggerFactory(LoggerFactory);
}
///
@@ -446,8 +452,10 @@ protected virtual void SaveChangesBefore()
/// 输入实体
protected virtual void ApplyInterceptForAddedEntity(EntityEntry entry)
{
- SetCreationAudited(entry);
- SetModificationAudited(entry);
+ AuditPropertySetter?.SetCreationProperties(entry.Entity);
+ AuditPropertySetter?.SetModificationProperties(entry.Entity);
+ //SetCreationAudited(entry);
+ //SetModificationAudited(entry);
SetVersion(entry);
}
@@ -461,7 +469,8 @@ protected virtual void ApplyInterceptForAddedEntity(EntityEntry entry)
/// 输入实体
protected virtual void ApplyInterceptForModifiedEntity(EntityEntry entry)
{
- SetModificationAudited(entry);
+ AuditPropertySetter?.SetModificationProperties(entry.Entity);
+ //SetModificationAudited(entry);
SetVersion(entry);
}
@@ -475,7 +484,10 @@ protected virtual void ApplyInterceptForModifiedEntity(EntityEntry entry)
/// 输入实体
protected virtual void ApplyInterceptForDeletedEntity(EntityEntry entry)
{
- SetModificationAudited(entry);
+ AuditPropertySetter?.SetDeletionProperties(entry.Entity);
+ AuditPropertySetter?.SetModificationProperties(entry.Entity);
+ SetVersion(entry);
+ //SetModificationAudited(entry);
}
#endregion
diff --git a/framework/src/Bing.Ddd.Application.Contracts/Bing.Ddd.Application.Contracts.csproj b/framework/src/Bing.Ddd.Application.Contracts/Bing.Ddd.Application.Contracts.csproj
index e9503931b..cdbd4b5f9 100644
--- a/framework/src/Bing.Ddd.Application.Contracts/Bing.Ddd.Application.Contracts.csproj
+++ b/framework/src/Bing.Ddd.Application.Contracts/Bing.Ddd.Application.Contracts.csproj
@@ -5,4 +5,9 @@
+
+
+
+
+
diff --git a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Aspects/UnitOfWorkAttribute.cs b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Aspects/UnitOfWorkAttribute.cs
index 3cdf5fc19..b67cfe7ed 100644
--- a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Aspects/UnitOfWorkAttribute.cs
+++ b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Aspects/UnitOfWorkAttribute.cs
@@ -1,7 +1,7 @@
using System.Threading.Tasks;
using AspectCore.DynamicProxy;
using AspectCore.Extensions.AspectScope;
-using Bing.Aspects.Base;
+using Bing.Aspects;
using Bing.Uow;
using Microsoft.Extensions.DependencyInjection;
diff --git a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/IRequest.cs b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/IRequest.cs
index df59cbd17..5e82fc92e 100644
--- a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/IRequest.cs
+++ b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/IRequest.cs
@@ -1,11 +1,11 @@
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Application.Dtos
{
///
/// 请求对象
///
- public interface IRequest : IValidation
+ public interface IRequest : IVerifyModel
{
}
}
diff --git a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/RequestBase.cs b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/RequestBase.cs
index 41d3c61b2..7cce6e973 100644
--- a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/RequestBase.cs
+++ b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Dtos/RequestBase.cs
@@ -1,6 +1,6 @@
using System.Linq;
using Bing.Exceptions;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Application.Dtos
{
@@ -12,7 +12,7 @@ public abstract class RequestBase : IRequest
///
/// 验证
///
- public virtual ValidationResultCollection Validate()
+ public virtual IValidationResult Validate()
{
var result = DataAnnotationValidation.Validate(this);
if (result.IsValid)
diff --git a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/ICrudAppService.cs b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/ICrudAppService.cs
index 40cf6a887..2634621b7 100644
--- a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/ICrudAppService.cs
+++ b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/ICrudAppService.cs
@@ -3,7 +3,7 @@
using Bing.Application.Aspects;
using Bing.Application.Dtos;
using Bing.Data.Queries;
-using Bing.Validations.Aspects;
+using Bing.Validation;
namespace Bing.Application.Services
{
@@ -44,13 +44,6 @@ public interface ICrudAppService
- /// 创建
- ///
- /// 请求参数
- [UnitOfWork]
- string Create([Valid] TCreateRequest request);
-
///
/// 创建
///
@@ -58,13 +51,6 @@ public interface ICrudAppService CreateAsync([Valid] TCreateRequest request);
- ///
- /// 修改
- ///
- /// 请求参数
- [UnitOfWork]
- void Update([Valid] TUpdateRequest request);
-
///
/// 修改
///
@@ -88,13 +74,6 @@ public interface ICrudAppService
- /// 保存
- ///
- /// 请求参数
- [UnitOfWork]
- void Save([Valid] TRequest request);
-
///
/// 保存
///
@@ -102,14 +81,6 @@ public interface ICrudAppService
- /// 批量保存
- ///
- /// 新增列表
- /// 修改列表
- /// 删除列表
- List Save(List addList, List updateList, List deleteList);
-
///
/// 批量保存
///
diff --git a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IDeleteAppService.cs b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IDeleteAppService.cs
index 81f88c0e4..c19efb557 100644
--- a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IDeleteAppService.cs
+++ b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IDeleteAppService.cs
@@ -12,12 +12,6 @@ public interface IDeleteAppService : IQueryAppService<
where TDto : new()
where TQueryParameter : IQueryParameter
{
- ///
- /// 删除
- ///
- /// 用逗号分隔的Id列表,范例:"1,2"
- void Delete(string ids);
-
///
/// 删除
///
diff --git a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IQueryAppService.cs b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IQueryAppService.cs
index 5a409c053..9405d813c 100644
--- a/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IQueryAppService.cs
+++ b/framework/src/Bing.Ddd.Application.Contracts/Bing/Application/Services/IQueryAppService.cs
@@ -14,58 +14,29 @@ public interface IQueryAppService : IAppService
where TDto : new()
where TQueryParameter : IQueryParameter
{
- ///
- /// 通过编号获取
- ///
- /// 实体编号
- TDto GetById(object id);
-
///
/// 通过编号获取
///
/// 实体编号
Task GetByIdAsync(object id);
- ///
- /// 通过编号列表获取
- ///
- /// 用逗号分隔的Id列表,范例:"1,2"
- List GetByIds(string ids);
-
///
/// 通过编号列表获取
///
/// 用逗号分隔带额Id列表,范例:"1,2"
Task> GetByIdsAsync(string ids);
- ///
- /// 获取全部
- ///
- List GetAll();
-
///
/// 获取全部
///
Task> GetAllAsync();
- ///
- /// 查询
- ///
- /// 查询参数
- List Query(TQueryParameter parameter);
-
///
/// 查询
///
/// 查询参数
Task> QueryAsync(TQueryParameter parameter);
- ///
- /// 分页查询
- ///
- /// 查询参数
- PagerList PagerQuery(TQueryParameter parameter);
-
///
/// 分页查询
///
diff --git a/framework/src/Bing.Ddd.Application/Bing/Application/Services/CrudAppServiceBase.cs b/framework/src/Bing.Ddd.Application/Bing/Application/Services/CrudAppServiceBase.cs
index 733bdc52c..a05a18346 100644
--- a/framework/src/Bing.Ddd.Application/Bing/Application/Services/CrudAppServiceBase.cs
+++ b/framework/src/Bing.Ddd.Application/Bing/Application/Services/CrudAppServiceBase.cs
@@ -153,30 +153,6 @@ protected CrudAppServiceBase(IUnitOfWork unitOfWork, IRepository
#region Save(保存)
- ///
- /// 保存
- ///
- /// 请求参数
- ///
- public virtual void Save(TRequest request)
- {
- if (request == null)
- throw new ArgumentNullException(nameof(request));
- SaveBefore(request);
- var entity = ToEntity(request);
- if (entity == null)
- throw new ArgumentNullException(nameof(entity));
- if (IsNew(request, entity))
- {
- Create(entity);
- request.Id = entity.Id.ToString();
- }
- else
- {
- Update(entity);
- }
- }
-
///
/// 保存
///
@@ -230,32 +206,6 @@ protected virtual void SaveBefore(TRequest request)
#region BatchSave(批量保存)
- ///
- /// 批量保存
- ///
- /// 新增列表
- /// 修改列表
- /// 删除列表
- public virtual List Save(List addList, List updateList, List deleteList)
- {
- if (addList == null && updateList == null && deleteList == null)
- return new List();
- addList ??= new List();
- updateList ??= new List();
- deleteList ??= new List();
- FilterList(addList, updateList, deleteList);
- var addEntities = ToEntities(addList);
- var updateEntities = ToEntities(updateList);
- var deleteEntities = ToEntities(deleteList);
- SaveBefore(addEntities, updateEntities, deleteEntities);
- AddList(addEntities);
- UpdateList(updateEntities);
- DeleteList(deleteEntities);
- Commit();
- SaveAfter(addEntities, updateEntities, deleteEntities);
- return GetResult(addEntities, updateEntities);
- }
-
///
/// 批量保存
///
@@ -325,18 +275,6 @@ protected virtual void SaveBefore(List addList, List updateLis
{
}
- ///
- /// 添加列表
- ///
- /// 新增列表
- private void AddList(List list)
- {
- if (list.Count == 0)
- return;
- Log.Content("创建实体:");
- list.ForEach(Create);
- }
-
///
/// 添加列表
///
@@ -350,18 +288,6 @@ private async Task AddListAsync(List list)
await CreateAsync(entity);
}
- ///
- /// 更新列表
- ///
- /// 修改列表
- private void UpdateList(List list)
- {
- if (list.Count == 0)
- return;
- Log.Content("修改实体:");
- list.ForEach(Update);
- }
-
///
/// 更新列表
///
@@ -375,18 +301,6 @@ private async Task UpdateListAsync(List list)
await UpdateAsync(entity);
}
- ///
- /// 删除列表
- ///
- /// 删除列表
- private void DeleteList(List list)
- {
- if (list.Count == 0)
- return;
- Log.Content("删除实体:");
- list.ForEach(DeleteChilds);
- }
-
///
/// 删除列表
///
@@ -400,28 +314,12 @@ private async Task DeleteListAsync(List list)
await DeleteChildsAsync(entity);
}
- ///
- /// 删除子节点集合
- ///
- /// 父节点
- protected virtual void DeleteChilds(TEntity parent) => DeleteEntity(parent);
-
///
/// 删除子节点集合
///
/// 父节点
protected virtual async Task DeleteChildsAsync(TEntity parent) => await DeleteEntityAsync(parent);
- ///
- /// 删除实体
- ///
- /// 实体
- protected void DeleteEntity(TEntity entity)
- {
- _repository.Remove(entity.Id);
- AddLog(entity);
- }
-
///
/// 删除实体
///
@@ -432,11 +330,6 @@ protected async Task DeleteEntityAsync(TEntity entity)
AddLog(entity);
}
- ///
- /// 提交
- ///
- private void Commit() => _unitOfWork.Commit();
-
///
/// 提交
///
@@ -517,22 +410,6 @@ protected CrudAppServiceBase(IUnitOfWork unitOfWork, IRepository
#region Create(创建)
- ///
- /// 创建
- ///
- /// 创建参数
- ///
- public virtual string Create(TCreateRequest request)
- {
- if (request == null)
- throw new ArgumentNullException(nameof(request));
- var entity = ToEntityFromCreateRequest(request);
- if (entity == null)
- throw new ArgumentNullException(nameof(entity));
- Create(entity);
- return entity.Id.ToString();
- }
-
///
/// 创建实体
///
@@ -605,21 +482,6 @@ protected async Task CreateAsync(TEntity entity)
#region Update(修改)
- ///
- /// 修改
- ///
- /// 修改参数
- ///
- public virtual void Update(TUpdateRequest request)
- {
- if (request == null)
- throw new ArgumentNullException(nameof(request));
- var entity = ToEntityFromUpdateRequest(request);
- if (entity == null)
- throw new ArgumentNullException(nameof(entity));
- Update(entity);
- }
-
///
/// 修改实体
///
diff --git a/framework/src/Bing.Ddd.Application/Bing/Application/Services/DeleteAppServiceBase.cs b/framework/src/Bing.Ddd.Application/Bing/Application/Services/DeleteAppServiceBase.cs
index 270b5aa55..331698d4b 100644
--- a/framework/src/Bing.Ddd.Application/Bing/Application/Services/DeleteAppServiceBase.cs
+++ b/framework/src/Bing.Ddd.Application/Bing/Application/Services/DeleteAppServiceBase.cs
@@ -132,23 +132,6 @@ protected void AddLog(IList entities)
#endregion
- ///
- /// 删除
- ///
- /// 用逗号分隔的Id列表,范例:"1,2"
- public virtual void Delete(string ids)
- {
- if (string.IsNullOrWhiteSpace(ids))
- return;
- var entities = _store.FindByIds(ids);
- if (entities?.Count == 0)
- return;
- DeleteBefore(entities);
- _store.Remove(entities);
- _unitOfWork.Commit();
- DeleteAfter(entities);
- }
-
///
/// 删除
///
diff --git a/framework/src/Bing.Ddd.Application/Bing/Application/Services/QueryAppServiceBase.cs b/framework/src/Bing.Ddd.Application/Bing/Application/Services/QueryAppServiceBase.cs
index be92afe34..cac96e746 100644
--- a/framework/src/Bing.Ddd.Application/Bing/Application/Services/QueryAppServiceBase.cs
+++ b/framework/src/Bing.Ddd.Application/Bing/Application/Services/QueryAppServiceBase.cs
@@ -65,17 +65,7 @@ public abstract class QueryAppServiceBase
/// 实体
protected virtual TDto ToDto(TEntity entity) => entity.MapTo();
- #region GetById(通过编号获取)
-
- ///
- /// 通过编号获取
- ///
- /// 实体编号
- public virtual TDto GetById(object id)
- {
- var key = Conv.To(id);
- return ToDto(_store.Find(key));
- }
+ #region GetByIdAsync(通过编号获取)
///
/// 通过编号获取
@@ -89,13 +79,7 @@ public virtual async Task GetByIdAsync(object id)
#endregion
- #region GetByIds(通过编号列表获取)
-
- ///
- /// 通过编号列表获取
- ///
- /// 用逗号分隔的Id列表,范例:"1,2"
- public virtual List GetByIds(string ids) => _store.FindByIds(ids).Select(ToDto).ToList();
+ #region GetByIdsAsync(通过编号列表获取)
///
/// 通过编号列表获取
@@ -111,11 +95,6 @@ public virtual async Task> GetByIdsAsync(string ids)
#region GetAll(获取全部)
- ///
- /// 获取全部
- ///
- public virtual List GetAll() => _store.FindAll().Select(ToDto).ToList();
-
///
/// 获取全部
///
diff --git a/framework/src/Bing.Ddd.Domain/Bing.Ddd.Domain.csproj b/framework/src/Bing.Ddd.Domain/Bing.Ddd.Domain.csproj
index e9503931b..85e8937e2 100644
--- a/framework/src/Bing.Ddd.Domain/Bing.Ddd.Domain.csproj
+++ b/framework/src/Bing.Ddd.Domain/Bing.Ddd.Domain.csproj
@@ -5,4 +5,10 @@
+
+
+
+
+
+
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Data/IStore.cs b/framework/src/Bing.Ddd.Domain/Bing/Data/IStore.cs
index 24c4b48ed..5f2b99be8 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Data/IStore.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Data/IStore.cs
@@ -3,7 +3,7 @@
using System.Threading;
using System.Threading.Tasks;
using Bing.Domain.Entities;
-using Bing.Validations.Aspects;
+using Bing.Validation;
namespace Bing.Data
{
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/AggregateRoot.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/AggregateRoot.cs
index ad7872e71..d2cb74b47 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/AggregateRoot.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/AggregateRoot.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using Bing.Auditing;
using Bing.Domain.Entities.Events;
+using Bing.Validation;
namespace Bing.Domain.Entities
{
@@ -10,7 +11,7 @@ namespace Bing.Domain.Entities
///
/// 实体类型
public abstract class AggregateRoot : AggregateRoot
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 初始化一个类型的实例
@@ -34,7 +35,7 @@ protected AggregateRoot(Guid id) : base(id)
/// 实体类型
/// 标识类型
public abstract class AggregateRoot : EntityBase, IAggregateRoot
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 领域事件列表
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRoot.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRoot.cs
index 8f1f8ead2..01c422ece 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRoot.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRoot.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class AuditedAggregateRoot : CreationAuditedAggregateRoot, IAuditedObject
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 最后修改时间
@@ -29,7 +30,7 @@ public abstract class AuditedAggregateRoot : CreationAuditedAggregateRo
/// 标识类型
[Serializable]
public abstract class AuditedAggregateRoot : CreationAuditedAggregateRoot, IAuditedObject
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 最后修改时间
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRootWithName.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRootWithName.cs
index 4aeaa111b..455f958a2 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRootWithName.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedAggregateRootWithName.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class AuditedAggregateRootWithName : AuditedAggregateRoot, IAuditedObjectWithName
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建人
@@ -29,7 +30,7 @@ public abstract class AuditedAggregateRootWithName : AuditedAggregateRo
/// 标识类型
[Serializable]
public abstract class AuditedAggregateRootWithName : AuditedAggregateRoot, IAuditedObjectWithName
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建人
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntity.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntity.cs
index 9ce317dc6..ebfee8289 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntity.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntity.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class AuditedEntity : CreationAuditedEntity, IAuditedObject
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 最后修改时间
@@ -29,7 +30,7 @@ public abstract class AuditedEntity : CreationAuditedEntity, I
/// 标识类型
[Serializable]
public abstract class AuditedEntity : CreationAuditedEntity, IAuditedObject
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 最后修改时间
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntityWithName.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntityWithName.cs
index aa193bace..8bc38a178 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntityWithName.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/AuditedEntityWithName.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class AuditedEntityWithName : AuditedEntity, IAuditedObjectWithName
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建人
@@ -29,7 +30,7 @@ public abstract class AuditedEntityWithName : AuditedEntity, I
/// 标识类型
[Serializable]
public abstract class AuditedEntityWithName : AuditedEntity, IAuditedObjectWithName
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建人
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs
index 7645912a5..889cf8dc6 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class CreationAuditedAggregateRoot : AggregateRoot, ICreationAuditedObject
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建时间
@@ -30,7 +31,7 @@ public abstract class CreationAuditedAggregateRoot : AggregateRoot标识类型
[Serializable]
public abstract class CreationAuditedAggregateRoot : AggregateRoot, ICreationAuditedObject
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建时间
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRootWithName.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRootWithName.cs
index 61b455cac..d58629c65 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRootWithName.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedAggregateRootWithName.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class CreationAuditedAggregateRootWithName : CreationAuditedAggregateRoot, ICreationAuditedObjectWithName
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建人
@@ -24,7 +25,7 @@ public abstract class CreationAuditedAggregateRootWithName : CreationAu
/// 标识类型
[Serializable]
public abstract class CreationAuditedAggregateRootWithName : CreationAuditedAggregateRoot, ICreationAuditedObjectWithName
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建人
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntity.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntity.cs
index 8b0b461ac..b5fc2a457 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntity.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntity.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class CreationAuditedEntity : EntityBase, ICreationAuditedObject
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建时间
@@ -29,7 +30,7 @@ public abstract class CreationAuditedEntity : EntityBase, ICre
/// 标识类型
[Serializable]
public abstract class CreationAuditedEntity : EntityBase, ICreationAuditedObject
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建时间
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntityWithName.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntityWithName.cs
index bc231b913..4ec5e81c6 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntityWithName.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/CreationAuditedEntityWithName.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class CreationAuditedEntityWithName : CreationAuditedEntity, ICreationAuditedObjectWithName
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建人
@@ -24,7 +25,7 @@ public abstract class CreationAuditedEntityWithName : CreationAuditedEn
/// 标识类型
[Serializable]
public abstract class CreationAuditedEntityWithName : CreationAuditedEntity, ICreationAuditedObjectWithName
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建人
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs
index 4ada05958..ba346dfb5 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot, IFullAuditedObject
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 是否已删除
@@ -34,7 +35,7 @@ public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot标识类型
[Serializable]
public abstract class FullAuditedAggregateRoot : AuditedAggregateRoot, IFullAuditedObject
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 是否已删除
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRootWithName.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRootWithName.cs
index 77efaac1d..e08f89f85 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRootWithName.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedAggregateRootWithName.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class FullAuditedAggregateRootWithName : FullAuditedAggregateRoot, IFullAuditedObjectWithName
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建人
@@ -34,7 +35,7 @@ public abstract class FullAuditedAggregateRootWithName : FullAuditedAgg
/// 标识类型
[Serializable]
public abstract class FullAuditedAggregateRootWithName : FullAuditedAggregateRoot, IFullAuditedObjectWithName
- where TEntity : class, IAggregateRoot
+ where TEntity : class, IAggregateRoot, IVerifyModel
{
///
/// 创建人
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntity.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntity.cs
index 0019303c1..6b3ee893f 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntity.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntity.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class FullAuditedEntity : AuditedEntity, IFullAuditedObject
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 是否已删除
@@ -34,7 +35,7 @@ public abstract class FullAuditedEntity : AuditedEntity, IFull
/// 标识类型
[Serializable]
public abstract class FullAuditedEntity : AuditedEntity, IFullAuditedObject
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 是否已删除
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntityWithName.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntityWithName.cs
index 64ba6bca8..d77947c07 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntityWithName.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/Auditing/FullAuditedEntityWithName.cs
@@ -1,5 +1,6 @@
using System;
using Bing.Auditing;
+using Bing.Validation;
namespace Bing.Domain.Entities.Auditing
{
@@ -9,7 +10,7 @@ namespace Bing.Domain.Entities.Auditing
/// 实体类型
[Serializable]
public abstract class FullAuditedEntityWithName : FullAuditedEntity, IFullAuditedObjectWithName
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建人
@@ -34,7 +35,7 @@ public abstract class FullAuditedEntityWithName : FullAuditedEntity标识类型
[Serializable]
public abstract class FullAuditedEntityWithName : FullAuditedEntity, IFullAuditedObjectWithName
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 创建人
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/DomainObjectBase.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/DomainObjectBase.cs
index 9f93e23f4..21cac8586 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/DomainObjectBase.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/DomainObjectBase.cs
@@ -2,8 +2,8 @@
using System.Collections.Generic;
using System.Linq.Expressions;
using Bing.Domain.ChangeTracking;
-using Bing.Validations;
-using Bing.Validations.Abstractions;
+using Bing.Validation;
+using Bing.Validation.Strategies;
namespace Bing.Domain.Entities
{
@@ -11,8 +11,8 @@ namespace Bing.Domain.Entities
/// 领域对象基类
///
/// 领域对象
- public abstract class DomainObjectBase : IDomainObject, IValidatable, IChangeTrackable
- where TObject : class, IDomainObject
+ public abstract class DomainObjectBase : IDomainObject, IVerifyModel, IChangeTrackable
+ where TObject : class, IDomainObject, IVerifyModel
{
///
/// 验证上下文
@@ -45,24 +45,32 @@ protected DomainObjectBase()
/// 设置验证处理器
///
/// 验证处理器
- public void SetValidateHandler(IValidationHandler handler) => _validationContext.SetHandler(op => op.HandleAll(handler));
+ public void SetValidationCallback(IValidationCallbackHandler handler) => _validationContext.SetHandler(op => op.HandleAll(handler));
///
- /// 添加验证策略
+ /// 使用全局验证规则
+ ///
+ public void UseValidationRules()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// 使用验证策略
///
/// 验证策略
- public void AddStrategy(IValidateStrategy strategy) => _validationContext.AddStrategy(strategy);
+ public void UseStrategy(IValidationStrategy strategy) => _validationContext.AddStrategy(strategy);
///
- /// 添加验证策略集合
+ /// 使用验证策略集合
///
/// 验证策略集合
- public void AddStrategyList(IEnumerable> strategies) => _validationContext.AddStrategyList(strategies);
+ public void UseStrategyList(IEnumerable> strategies) =>_validationContext.AddStrategyList(strategies);
///
/// 验证
///
- public virtual ValidationResultCollection Validate()
+ public virtual IValidationResult Validate()
{
_validationContext.Validate(Validate);
return _validationContext.GetValidationResultCollection();
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/EntityBase.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/EntityBase.cs
index 06f7f461b..e154d841c 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/EntityBase.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/EntityBase.cs
@@ -3,7 +3,7 @@
using Bing.Extensions;
using Bing.Helpers;
using Bing.Properties;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Domain.Entities
{
@@ -16,7 +16,7 @@ public abstract class EntityBase : IEntity
///
/// 验证
///
- public abstract ValidationResultCollection Validate();
+ public abstract IValidationResult Validate();
///
/// 初始化
@@ -39,7 +39,7 @@ public abstract class EntityBase : IEntity
///
/// 实体类型
[Serializable]
- public abstract class EntityBase : EntityBase where TEntity : class, IEntity
+ public abstract class EntityBase : EntityBase where TEntity : class, IEntity, IVerifyModel
{
///
/// 初始化一个类型的实例
@@ -60,7 +60,7 @@ protected EntityBase(Guid id) : base(id) { }
/// 标识类型
[Serializable]
public abstract class EntityBase : DomainObjectBase, IEntity
- where TEntity : class, IEntity
+ where TEntity : class, IEntity, IVerifyModel
{
///
/// 标识
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/IDomainObject.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/IDomainObject.cs
index 9ecdf470c..ea17999ed 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/IDomainObject.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/IDomainObject.cs
@@ -1,11 +1,11 @@
-using Bing.Validations.Abstractions;
+using Bing.Validation;
namespace Bing.Domain.Entities
{
///
/// 领域对象
///
- public interface IDomainObject : IValidatable
+ public interface IDomainObject : IVerifyModel
{
}
}
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/TreeEntityBase.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/TreeEntityBase.cs
index 57094b4dd..b61a269fe 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/TreeEntityBase.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Entities/TreeEntityBase.cs
@@ -3,7 +3,7 @@
using System.Linq;
using Bing.Extensions;
using Bing.Helpers;
-using Bing.Validations.Abstractions;
+using Bing.Validation;
namespace Bing.Domain.Entities
{
@@ -12,7 +12,7 @@ namespace Bing.Domain.Entities
///
/// 树型实体类型
public abstract class TreeEntityBase : TreeEntityBase
- where TEntity : class, ITreeEntity, IValidatable
+ where TEntity : class, ITreeEntity, IVerifyModel
{
///
/// 初始化一个类型的实例
@@ -33,7 +33,7 @@ protected TreeEntityBase(Guid id, string path, int level) : base(id, path, level
/// 父编号类型
public abstract class TreeEntityBase : AggregateRoot,
ITreeEntity
- where TEntity : class, ITreeEntity, IValidatable
+ where TEntity : class, ITreeEntity, IVerifyModel
{
///
/// 父标识
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Repositories/ICompactRepository.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Repositories/ICompactRepository.cs
index 76df51621..69179cae7 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Repositories/ICompactRepository.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Repositories/ICompactRepository.cs
@@ -4,7 +4,7 @@
using System.Threading.Tasks;
using Bing.DependencyInjection;
using Bing.Domain.Entities;
-using Bing.Validations.Aspects;
+using Bing.Validation;
namespace Bing.Domain.Repositories
{
diff --git a/framework/src/Bing.Ddd.Domain/Bing/Domain/Services/ParameterBase.cs b/framework/src/Bing.Ddd.Domain/Bing/Domain/Services/ParameterBase.cs
index 77f7a82d8..549aa1440 100644
--- a/framework/src/Bing.Ddd.Domain/Bing/Domain/Services/ParameterBase.cs
+++ b/framework/src/Bing.Ddd.Domain/Bing/Domain/Services/ParameterBase.cs
@@ -1,18 +1,18 @@
using System.Linq;
using Bing.Exceptions;
-using Bing.Validations;
+using Bing.Validation;
namespace Bing.Domain.Services
{
///
/// 参数基类
///
- public abstract class ParameterBase : IValidation
+ public abstract class ParameterBase : IVerifyModel
{
///
/// 验证
///
- public virtual ValidationResultCollection Validate()
+ public virtual IValidationResult Validate()
{
var result = DataAnnotationValidation.Validate(this);
if (result.IsValid)
diff --git a/framework/src/Bing.EventBus/Bing/EventBus/Local/LocalEventBus.cs b/framework/src/Bing.EventBus/Bing/EventBus/Local/LocalEventBus.cs
index 6dc0c8f78..462d89f31 100644
--- a/framework/src/Bing.EventBus/Bing/EventBus/Local/LocalEventBus.cs
+++ b/framework/src/Bing.EventBus/Bing/EventBus/Local/LocalEventBus.cs
@@ -3,8 +3,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using Bing.Extensions;
using Bing.Helpers;
+using Bing.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@@ -55,7 +55,7 @@ public LocalEventBus(
/// 事件处理器工厂
public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
{
- GetOrCreateHandlerFactories(eventType).Locking(factories =>
+ GetOrCreateHandlerFactories(eventType).LockAndRun(factories =>
{
if (!factory.IsInFactories(factories))
factories.Add(factory);
@@ -73,7 +73,7 @@ public override void Unsubscribe(Func action)
Check.NotNull(action, nameof(action));
GetOrCreateHandlerFactories(typeof(TEvent))
- .Locking(factories =>
+ .LockAndRun(factories =>
{
factories.RemoveAll(factory =>
{
@@ -96,7 +96,7 @@ public override void Unsubscribe(Func action)
public override void Unsubscribe(Type eventType, IEventHandler handler)
{
GetOrCreateHandlerFactories(eventType)
- .Locking(factories =>
+ .LockAndRun(factories =>
{
factories.RemoveAll(factory =>
factory is SingleInstanceHandlerFactory &&
@@ -111,7 +111,7 @@ factory is SingleInstanceHandlerFactory &&
/// 事件处理器工厂
public override void Unsubscribe(Type eventType, IEventHandlerFactory factory)
{
- GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Remove(factory));
+ GetOrCreateHandlerFactories(eventType).LockAndRun(factories => factories.Remove(factory));
}
///
@@ -120,7 +120,7 @@ public override void Unsubscribe(Type eventType, IEventHandlerFactory factory)
/// 事件类型
public override void UnsubscribeAll(Type eventType)
{
- GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear());
+ GetOrCreateHandlerFactories(eventType).LockAndRun(factories => factories.Clear());
}
///
diff --git a/framework/src/Bing.EventBus/project.dependency.props b/framework/src/Bing.EventBus/project.dependency.props
index 8d37a8e3d..a36ae83c8 100644
--- a/framework/src/Bing.EventBus/project.dependency.props
+++ b/framework/src/Bing.EventBus/project.dependency.props
@@ -1,4 +1,8 @@
+
+
+
+
diff --git a/framework/src/Bing.Events/Cap/CapTraceAttribute.cs b/framework/src/Bing.Events/Cap/CapTraceAttribute.cs
index a64b8eda9..7fdc68b50 100644
--- a/framework/src/Bing.Events/Cap/CapTraceAttribute.cs
+++ b/framework/src/Bing.Events/Cap/CapTraceAttribute.cs
@@ -4,7 +4,7 @@
using System.Threading.Tasks;
using AspectCore.DynamicProxy;
using AspectCore.DynamicProxy.Parameters;
-using Bing.Aspects.Base;
+using Bing.Aspects;
using Bing.Tracing;
using DotNetCore.CAP;
diff --git a/framework/src/Bing.Events/Cap/MessageEventBus.cs b/framework/src/Bing.Events/Cap/MessageEventBus.cs
index b7de9a40f..2a6992627 100644
--- a/framework/src/Bing.Events/Cap/MessageEventBus.cs
+++ b/framework/src/Bing.Events/Cap/MessageEventBus.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
using Bing.Data.Transaction;
using Bing.Events.Messages;
@@ -36,7 +37,7 @@ public class MessageEventBus : IMessageEventBus
/// 事件发布器
/// 事务操作管理器
/// 日志操作
- public MessageEventBus(ICapPublisher publisher,
+ public MessageEventBus(ICapPublisher publisher,
ITransactionActionManager transactionActionManager,
ILog log)
{
@@ -50,7 +51,10 @@ public MessageEventBus(ICapPublisher publisher,
///
/// 事件类型
/// 事件
- public Task PublishAsync(TEvent @event) where TEvent : IMessageEvent => PublishAsync(@event.Name, @event.Data, @event.Callback, @event.Send);
+ /// 取消令牌
+ public Task PublishAsync(TEvent @event, CancellationToken cancellationToken = default)
+ where TEvent : IMessageEvent =>
+ PublishAsync(@event.Name, @event.Data, @event.Callback, @event.Send, cancellationToken);
///
/// 发布事件
@@ -59,18 +63,19 @@ public MessageEventBus(ICapPublisher publisher,
/// 事件数据
/// 回调名称
/// 是否立即发送消息
- public async Task PublishAsync(string name, object data, string callback = null, bool send = false)
+ /// 取消令牌
+ public async Task PublishAsync(string name, object data, string callback = null, bool send = false, CancellationToken cancellationToken = default)
{
- var headers = new Dictionary {{DotNetCore.CAP.Messages.Headers.CallbackName, callback}};
+ var headers = new Dictionary { { DotNetCore.CAP.Messages.Headers.CallbackName, callback } };
InitTraceIdContext(headers);
if (send)
{
- await InternalPublishAsync(name, data, headers, callback);
+ await InternalPublishAsync(name, data, headers, callback, cancellationToken);
return;
}
TransactionActionManager.Register(async transaction =>
{
- await InternalPublishAsync(name, data, headers, callback);
+ await InternalPublishAsync(name, data, headers, callback, cancellationToken);
});
}
@@ -81,9 +86,10 @@ public async Task PublishAsync(string name, object data, string callback = null,
/// 事件数据
/// 数据投
/// 回调名称
- private async Task InternalPublishAsync(string name, object data, IDictionary headers, string callback)
+ /// 取消令牌
+ private async Task InternalPublishAsync(string name, object data, IDictionary headers, string callback, CancellationToken cancellationToken = default)
{
- await Publisher.PublishAsync(name, data, headers);
+ await Publisher.PublishAsync(name, data, headers, cancellationToken);
WriteLog(name, data, callback);
}
@@ -112,7 +118,7 @@ private static void InitTraceIdContext(IDictionary headers)
{
if (TraceIdContext.Current == null)
TraceIdContext.Current = new TraceIdContext(string.Empty);
- if(!headers.ContainsKey(Headers.TraceId))
+ if (!headers.ContainsKey(Headers.TraceId))
headers[Headers.TraceId] = TraceIdContext.Current.TraceId;
}
}
diff --git a/framework/src/Bing.FreeSQL.MySql/Bing/FreeSQL/Extensions.Services.cs b/framework/src/Bing.FreeSQL.MySql/Bing/FreeSQL/Extensions.Services.cs
index 9ad1adbc5..bdc25dbef 100644
--- a/framework/src/Bing.FreeSQL.MySql/Bing/FreeSQL/Extensions.Services.cs
+++ b/framework/src/Bing.FreeSQL.MySql/Bing/FreeSQL/Extensions.Services.cs
@@ -21,79 +21,85 @@ public static partial class Extensions
///
/// 注册MySql工作单元服务
///
- /// 工作单元接口类型
+ /// 工作单元接口类型
/// 工作单元实现类型
/// 服务集合
/// 连接字符串
/// 配置操作
/// FreeSql配置操作
- public static IServiceCollection AddMySqlUnitOfWork(this IServiceCollection services
+ public static IServiceCollection AddMySqlUnitOfWork