diff --git a/Directory.Build.props b/Directory.Build.props index ac13c100..e8eefd47 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ 6.0.1 - 1.10.2 + 2.1.0 \ No newline at end of file diff --git a/common.props b/common.props index 4603b51d..cfa1ee01 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ latest - 2.1.0 + 2.2.0 $(NoWarn);CS1591 true EasyAbp Team diff --git a/docs/Prepayment/README.md b/docs/Prepayment/README.md index d94211f9..dfb6beb6 100644 --- a/docs/Prepayment/README.md +++ b/docs/Prepayment/README.md @@ -56,38 +56,23 @@ We have launched an online demo for this module: [https://pay.samples.easyabp.io ``` > please refer to the `ConfigurePaymentServicePrepayment` method in the [Web module](https://github.com/EasyAbp/PaymentService/blob/master/samples/PaymentServiceSample/aspnet-core/src/PaymentServiceSample.Web/PaymentServiceSampleWebModule.cs) of the sample app. -3. Access the API `/api/paymentService/prepayment/account` (with the request param `UserId`), then the account will be created automatically. +3. Use the API `/api/payment-service/prepayment/account` (with the request param `UserId`), then the account will be created automatically. 4. Top up your account: - 1. Use the API `/api/paymentService/prepayment/account/topUp` to start top-up. + 1. Use the API `/api/payment-service/prepayment/account/top-up` to start top-up. - 2. Use the API `/api/paymentService/prepayment/account/{id}` to get the `ExtraProperties.PendingTopUpPaymentId`. + 2. Use the API `/api/payment-service/prepayment/account/{id}` to get the `ExtraProperties.PendingTopUpPaymentId`. - 3. Use the API `/api/paymentService/payment/{id}/pay` to finish the payment. (for example you can use WeChatPay to top up your prepayment account, please refer to the document of the payment method you want) + 3. Use the API `/api/payment-service/payment/{id}/pay` to finish the payment. (for example you can use WeChatPay to top up your prepayment account, please refer to the document of the payment method you want) - 4. If you want to cancel an ongoing payment, please use the API `/api/paymentService/payment/{id}/cancel`. + 4. If you want to cancel an ongoing payment, please use the API `/api/payment-service/payment/{id}/cancel`. > Or just change the balance directly with the management pages if you have the account management permission. 5. Pay with prepayment account. - 1. Users can use the API `/api/paymentService/payment/{id}/pay` to finish the payment, please put the necessary params in the `ExtraProperties`: - - ``` - { - "extraProperties": { - "AccountId": "82D49C17-9282-4822-9EE9-A0685529D707" // Id of the prepayment account that you use to pay - } - } - ``` - - > Skip the following steps if you are using the [EasyAbp.EShop](https://github.com/EasyAbp/EShop). - -
- See more steps - - 2. Create a payment with the payment method `Prepayment`. - > Other modules or apps that depend on PaymentService module should create payments via distributed events. + 1. Create a payment with the payment method `Prepayment`. + > Other modules or apps should create payments via distributed events. Skip this step if you are using the [EasyAbp.EShop](https://github.com/EasyAbp/EShop).
See sample code @@ -107,9 +92,24 @@ We have launched an online demo for this module: [https://pay.samples.easyabp.io }).ToList() }); ``` - > please refer to the [usage in EShop](https://github.com/EasyAbp/EShop/blob/dev/modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application/EasyAbp/EShop/Payments/Payments/PaymentAppService.cs) + > please refer to the [usage in EShop](https://github.com/EasyAbp/EShop/blob/dev/modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application/EasyAbp/EShop/Payments/Payments/PaymentAppService.cs)
+ 2. Use the API `/api/payment-service/payment/{id}/pay` to finish the payment, please put the necessary params in the `ExtraProperties`: + + ``` + { + "extraProperties": { + "AccountId": "82D49C17-9282-4822-9EE9-A0685529D707" // Id of the prepayment account that you use to pay + } + } + ``` + + > Skip the following steps if you are using the [EasyAbp.EShop](https://github.com/EasyAbp/EShop). + +
+ See more steps + 3. Handle the payment created distributed event to get and remember the `PaymentId`.
See sample code diff --git a/docs/WeChatPay/README.md b/docs/WeChatPay/README.md index 07a29e97..dc9da9fa 100644 --- a/docs/WeChatPay/README.md +++ b/docs/WeChatPay/README.md @@ -48,24 +48,8 @@ We have launched an online demo for this module: [https://pay.samples.easyabp.io > See the [demo](https://github.com/EasyAbp/PaymentService/blob/master/samples/PaymentServiceSample/aspnet-core/src/PaymentServiceSample.Web/appsettings.json), it is also according to the [document](https://github.com/EasyAbp/Abp.WeChat/blob/master/doc/WeChatPay.md) of the EasyAbp.Abp.WeChat module. 3. Pay with WeChatPay. - 1. Users can use the API `/api/paymentService/payment/{id}/pay` to finish the payment, please put the necessary params in the `ExtraProperties`: - - ``` - { - "extraProperties": { - "trade_type": "JSAPI", - "appid": "wx81a2956875268fk8" // You can specify an appid or get it from the input from the client. - } - } - ``` - - > Skip the following steps if you are using the [EasyAbp.EShop](https://github.com/EasyAbp/EShop). - -
- See more steps - - 2. Create a payment with the payment method `WeChatPay`. - > Other modules or apps that depend on PaymentService module should create payments via distributed events. + 1. Create a payment with the payment method `WeChatPay`. + > Other modules or apps should create payments via distributed events. Skip this step if you are using the [EasyAbp.EShop](https://github.com/EasyAbp/EShop).
See sample code @@ -85,9 +69,26 @@ We have launched an online demo for this module: [https://pay.samples.easyabp.io }).ToList() }); ``` - > please refer to the [usage in EShop](https://github.com/EasyAbp/EShop/blob/dev/modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application/EasyAbp/EShop/Payments/Payments/PaymentAppService.cs) + > please refer to the [usage in EShop](https://github.com/EasyAbp/EShop/blob/dev/modules/EasyAbp.EShop.Payments/src/EasyAbp.EShop.Payments.Application/EasyAbp/EShop/Payments/Payments/PaymentAppService.cs)
+ 2. Users can use the API `/api/payment-service/payment/{id}/pay` (POST) to finish the payment, please put the necessary params in the `ExtraProperties`: + + ``` + { + "extraProperties": { + "trade_type": "JSAPI", + "appid": "wx81a2956875268fk8" // You can specify an appid or get it from the input from the client. + "mch_id": "10000100" // If it's null, use the default settings/options value you configured in the Abp.WeChat.Pay module. + } + } + ``` + + > Skip the following steps if you are using the [EasyAbp.EShop](https://github.com/EasyAbp/EShop). + +
+ See more steps + 3. Handle the payment created distributed event to get and remember the `PaymentId`.
See sample code diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/CloseWeChatPayOrderJob.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/CloseWeChatPayOrderJob.cs index 5ad66734..6f4cb3c5 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/CloseWeChatPayOrderJob.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/CloseWeChatPayOrderJob.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using EasyAbp.Abp.WeChat.Pay.Services; using EasyAbp.Abp.WeChat.Pay.Services.Pay; using Volo.Abp.BackgroundJobs; using Volo.Abp.DependencyInjection; @@ -11,28 +12,31 @@ namespace EasyAbp.PaymentService.WeChatPay.Background; public class CloseWeChatPayOrderJob : IAsyncBackgroundJob, ITransientDependency { private readonly ICurrentTenant _currentTenant; - private readonly ServiceProviderPayService _serviceProviderPayService; + private readonly IAbpWeChatPayServiceFactory _abpWeChatPayServiceFactory; public CloseWeChatPayOrderJob( ICurrentTenant currentTenant, - ServiceProviderPayService serviceProviderPayService) + IAbpWeChatPayServiceFactory abpWeChatPayServiceFactory) { _currentTenant = currentTenant; - _serviceProviderPayService = serviceProviderPayService; + _abpWeChatPayServiceFactory = abpWeChatPayServiceFactory; } - + public virtual async Task ExecuteAsync(CloseWeChatPayOrderJobArgs args) { using var change = _currentTenant.Change(args.TenantId); - var orderQueryResult = await _serviceProviderPayService.CloseOrderAsync( + var serviceProviderPayService = + await _abpWeChatPayServiceFactory.CreateAsync(args.MchId); + + var orderQueryResult = await serviceProviderPayService.CloseOrderAsync( appId: args.AppId, mchId: args.MchId, subAppId: null, subMchId: null, outTradeNo: args.OutTradeNo ); - + var dict = orderQueryResult.SelectSingleNode("xml").ToDictionary() ?? throw new NullReferenceException(); var resultCode = dict.GetOrDefault("result_code"); var errCode = dict.GetOrDefault("err_code"); diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/WeChatPayRefundJob.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/WeChatPayRefundJob.cs index aea721df..654a9fa1 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/WeChatPayRefundJob.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Background/WeChatPayRefundJob.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using EasyAbp.Abp.WeChat.Pay.Services; using EasyAbp.Abp.WeChat.Pay.Services.Pay; using EasyAbp.PaymentService.Payments; using EasyAbp.PaymentService.Refunds; @@ -28,7 +29,7 @@ public class WeChatPayRefundJob : IAsyncBackgroundJob, I private readonly IPaymentRecordRepository _paymentRecordRepository; private readonly IRefundRecordRepository _refundRecordRepository; private readonly IWeChatPayFeeConverter _weChatPayFeeConverter; - private readonly ServiceProviderPayService _serviceProviderPayService; + private readonly IAbpWeChatPayServiceFactory _abpWeChatPayServiceFactory; public WeChatPayRefundJob( IGuidGenerator guidGenerator, @@ -40,7 +41,7 @@ public WeChatPayRefundJob( IPaymentRecordRepository paymentRecordRepository, IRefundRecordRepository refundRecordRepository, IWeChatPayFeeConverter weChatPayFeeConverter, - ServiceProviderPayService serviceProviderPayService) + IAbpWeChatPayServiceFactory abpWeChatPayServiceFactory) { _guidGenerator = guidGenerator; _currentTenant = currentTenant; @@ -51,7 +52,7 @@ public WeChatPayRefundJob( _paymentRecordRepository = paymentRecordRepository; _refundRecordRepository = refundRecordRepository; _weChatPayFeeConverter = weChatPayFeeConverter; - _serviceProviderPayService = serviceProviderPayService; + _abpWeChatPayServiceFactory = abpWeChatPayServiceFactory; } [UnitOfWork(true)] @@ -167,9 +168,14 @@ private async Task> RequestWeChatPayRefundAsync(Payme PaymentRecord paymentRecord, decimal refundAmount, [NotNull] string outRefundNo, [CanBeNull] string displayReason) { - var result = await _serviceProviderPayService.RefundAsync( + var mchId = payment.PayeeAccount; + + var serviceProviderPayService = + await _abpWeChatPayServiceFactory.CreateAsync(mchId); + + var result = await serviceProviderPayService.RefundAsync( appId: payment.GetProperty("appid"), - mchId: payment.PayeeAccount, + mchId: mchId, subAppId: null, subMchId: null, transactionId: paymentRecord.TransactionId, diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayHandler.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaidWeChatPayEventHandler.cs similarity index 85% rename from modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayHandler.cs rename to modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaidWeChatPayEventHandler.cs index 55975334..bbcc39c1 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayHandler.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaidWeChatPayEventHandler.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using EasyAbp.Abp.WeChat.Pay.Infrastructure; -using EasyAbp.Abp.WeChat.Pay.Infrastructure.OptionResolve; +using EasyAbp.Abp.WeChat.Common.RequestHandling; +using EasyAbp.Abp.WeChat.Pay.RequestHandling; using EasyAbp.PaymentService.Payments; using EasyAbp.PaymentService.WeChatPay.Background; using EasyAbp.PaymentService.WeChatPay.PaymentRecords; @@ -15,9 +15,9 @@ namespace EasyAbp.PaymentService.WeChatPay { - public class PaymentServiceWeChatPayHandler : IWeChatPayHandler, ITransientDependency + public class PaidWeChatPayEventHandler : IWeChatPayEventHandler, ITransientDependency { - public WeChatHandlerType Type { get; } = WeChatHandlerType.Normal; + public WeChatHandlerType Type => WeChatHandlerType.Paid; private readonly IDataFilter _dataFilter; private readonly IServiceProvider _serviceProvider; @@ -27,7 +27,7 @@ public class PaymentServiceWeChatPayHandler : IWeChatPayHandler, ITransientDepen private readonly IPaymentRecordRepository _paymentRecordRepository; private readonly IPaymentRepository _paymentRepository; - public PaymentServiceWeChatPayHandler( + public PaidWeChatPayEventHandler( IDataFilter dataFilter, IServiceProvider serviceProvider, IUnitOfWorkManager unitOfWorkManager, @@ -46,17 +46,23 @@ public PaymentServiceWeChatPayHandler( } [UnitOfWork(true)] - public virtual async Task HandleAsync(WeChatPayHandlerContext context) + public virtual async Task HandleAsync(WeChatPayEventModel model) { - var dict = context.WeChatRequestXmlData.SelectSingleNode("xml").ToDictionary() ?? + var dict = model.WeChatRequestXmlData.SelectSingleNode("xml").ToDictionary() ?? throw new NullReferenceException(); - if (dict.GetOrDefault("return_code") != "SUCCESS" || - dict.GetOrDefault("device_info") != PaymentServiceWeChatPayConsts.DeviceInfo) + var returnCode = dict.GetOrDefault("return_code"); + var deviceInfo = dict.GetOrDefault("device_info"); + + if (returnCode != "SUCCESS") { - context.IsSuccess = false; + return new WeChatRequestHandlingResult(false, $"Unexpected return_code:{returnCode}"); + } - return; + if (deviceInfo != PaymentServiceWeChatPayConsts.DeviceInfo) + { + // skip handling + return new WeChatRequestHandlingResult(true); } using var disabledDataFilter = _dataFilter.Disable(); @@ -96,7 +102,10 @@ public virtual async Task HandleAsync(WeChatPayHandlerContext context) // Enqueue an empty job to ensure the background job worker is alive. await _backgroundJobManager.EnqueueAsync(new EmptyJobArgs(payment.TenantId)); - _unitOfWorkManager.Current.OnCompleted(async () => { await _backgroundJobManager.EnqueueAsync(args); }); + _unitOfWorkManager.Current.OnCompleted(async () => + { + await _backgroundJobManager.EnqueueAsync(args); + }); } else { @@ -108,8 +117,8 @@ public virtual async Task HandleAsync(WeChatPayHandlerContext context) }); } } - - context.IsSuccess = true; + + return new WeChatRequestHandlingResult(true); } protected virtual async Task RecordPaymentResultAsync(Dictionary dict, diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayDomainModule.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayDomainModule.cs index 0d45549d..2b3d2477 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayDomainModule.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayDomainModule.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using EasyAbp.Abp.WeChat.Pay; -using EasyAbp.Abp.WeChat.Pay.Infrastructure.OptionResolve; +using EasyAbp.Abp.WeChat.Pay; using EasyAbp.PaymentService.WeChatPay.ObjectExtending; using Volo.Abp.BackgroundJobs; using Volo.Abp.Modularity; @@ -19,13 +17,5 @@ public override void PreConfigureServices(ServiceConfigurationContext context) { PaymentServiceWeChatPayDomainObjectExtensions.Configure(); } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.Contributors.AddFirst(new SettingOptionsResolveContributor()); - }); - } } -} +} \ No newline at end of file diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayRefundHandler.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/RefundWeChatPayEventHandler.cs similarity index 71% rename from modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayRefundHandler.cs rename to modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/RefundWeChatPayEventHandler.cs index 07f863d2..0bd3c045 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayRefundHandler.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/RefundWeChatPayEventHandler.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using EasyAbp.Abp.WeChat.Pay.Infrastructure; -using EasyAbp.Abp.WeChat.Pay.Infrastructure.OptionResolve; +using EasyAbp.Abp.WeChat.Common.RequestHandling; +using EasyAbp.Abp.WeChat.Pay.RequestHandling; using EasyAbp.PaymentService.Payments; using EasyAbp.PaymentService.Refunds; using EasyAbp.PaymentService.WeChatPay.RefundRecords; @@ -13,10 +13,9 @@ namespace EasyAbp.PaymentService.WeChatPay { - [ExposeServices(typeof(IWeChatPayHandler), IncludeSelf = true)] - public class PaymentServiceWeChatPayRefundHandler : IWeChatPayHandler, ITransientDependency + public class RefundWeChatPayEventHandler : IWeChatPayEventHandler, ITransientDependency { - public WeChatHandlerType Type { get; } = WeChatHandlerType.Refund; + public WeChatHandlerType Type => WeChatHandlerType.Refund; private readonly IDataFilter _dataFilter; private readonly IPaymentManager _paymentManager; @@ -24,7 +23,7 @@ public class PaymentServiceWeChatPayRefundHandler : IWeChatPayHandler, ITransien private readonly IRefundRepository _refundRepository; private readonly IPaymentRepository _paymentRepository; - public PaymentServiceWeChatPayRefundHandler( + public RefundWeChatPayEventHandler( IDataFilter dataFilter, IPaymentManager paymentManager, IRefundRecordRepository refundRecordRepository, @@ -39,25 +38,30 @@ public PaymentServiceWeChatPayRefundHandler( } [UnitOfWork(true)] - public virtual async Task HandleAsync(WeChatPayHandlerContext context) + public virtual async Task HandleAsync(WeChatPayEventModel model) { - var dict = context.WeChatRequestXmlData.SelectSingleNode("xml").ToDictionary() ?? + var outerDict = model.WeChatRequestXmlData.SelectSingleNode("xml").ToDictionary() ?? throw new NullReferenceException(); - if (dict.GetOrDefault("return_code") != "SUCCESS") + var dict = model.DecryptedXmlData.SelectSingleNode("root").ToDictionary() ?? + throw new NullReferenceException(); + + var returnCode = outerDict.GetOrDefault("return_code"); + var outRefundNo = dict.GetOrDefault("out_refund_no"); + + if (returnCode != "SUCCESS") { - context.IsSuccess = true; - return; + return new WeChatRequestHandlingResult(false, $"Unexpected return_code:{returnCode}"); } using var disabledDataFilter = _dataFilter.Disable(); - var record = await _refundRecordRepository.FindByOutRefundNoAsync(dict.GetOrDefault("out_refund_no")); + var record = await _refundRecordRepository.FindByOutRefundNoAsync(outRefundNo); if (record is null) { - context.IsSuccess = false; - return; + // skip handling + return new WeChatRequestHandlingResult(true); } var payment = await _paymentRepository.FindAsync(record.PaymentId); @@ -66,8 +70,7 @@ public virtual async Task HandleAsync(WeChatPayHandlerContext context) if (payment is null) { - context.IsSuccess = false; - return; + return new WeChatRequestHandlingResult(false, $"Payment entity not found, id: {record.PaymentId}"); } record.SetInformationInNotify( @@ -92,7 +95,7 @@ public virtual async Task HandleAsync(WeChatPayHandlerContext context) } } - context.IsSuccess = true; + return new WeChatRequestHandlingResult(true); } protected virtual async Task HandleSuccessfulRefundAsync(Payment payment, Refund refund) diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/SettingOptionsResolveContributor.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/SettingOptionsResolveContributor.cs deleted file mode 100644 index 9a335076..00000000 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/SettingOptionsResolveContributor.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Threading.Tasks; -using EasyAbp.Abp.WeChat.Pay; -using EasyAbp.Abp.WeChat.Pay.Infrastructure.OptionResolve; -using EasyAbp.PaymentService.WeChatPay.Settings; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Settings; - -namespace EasyAbp.PaymentService.WeChatPay -{ - public class SettingOptionsResolveContributor : IWeChatPayOptionsResolveContributor - { - public const string ContributorName = "Setting"; - - public string Name => ContributorName; - - public virtual async Task ResolveAsync(WeChatPayOptionsResolverContext context) - { - var settingProvider = context.ServiceProvider.GetRequiredService(); - - context.Options = new AbpWeChatPayOptions - { - ApiKey = await settingProvider.GetOrNullAsync(WeChatPaySettings.ApiKey), - MchId = await settingProvider.GetOrNullAsync(WeChatPaySettings.MchId), - IsSandBox = Convert.ToBoolean(await settingProvider.GetOrNullAsync(WeChatPaySettings.IsSandBox)), - NotifyUrl = await settingProvider.GetOrNullAsync(WeChatPaySettings.NotifyUrl), - RefundNotifyUrl = await settingProvider.GetOrNullAsync(WeChatPaySettings.RefundNotifyUrl), - CertificateBlobContainerName = await settingProvider.GetOrNullAsync(WeChatPaySettings.CertificateBlobContainerName), - CertificateBlobName = await settingProvider.GetOrNullAsync(WeChatPaySettings.CertificateBlobName), - CertificateSecret = await settingProvider.GetOrNullAsync(WeChatPaySettings.CertificateSecret) - }; - } - } -} \ No newline at end of file diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettingDefinitionProvider.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettingDefinitionProvider.cs index 37589c78..254ba7dc 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettingDefinitionProvider.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettingDefinitionProvider.cs @@ -1,5 +1,4 @@ -using System; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Volo.Abp.Settings; namespace EasyAbp.PaymentService.WeChatPay.Settings @@ -18,19 +17,6 @@ public override void Define(ISettingDefinitionContext context) /* Define module settings here. * Use names from WeChatPaySettings class. */ - - context.Add( - new SettingDefinition(WeChatPaySettings.MchId), - new SettingDefinition(WeChatPaySettings.ApiKey), - new SettingDefinition(WeChatPaySettings.IsSandBox, "false"), - new SettingDefinition(WeChatPaySettings.NotifyUrl, - _configuration["App:SelfUrl"]?.EnsureEndsWith('/') + "wechat-pay/notify"), - new SettingDefinition(WeChatPaySettings.RefundNotifyUrl, - _configuration["App:SelfUrl"]?.EnsureEndsWith('/') + "wechat-pay/refund-notify"), - new SettingDefinition(WeChatPaySettings.CertificateBlobContainerName), - new SettingDefinition(WeChatPaySettings.CertificateBlobName), - new SettingDefinition(WeChatPaySettings.CertificateSecret) - ); } } } \ No newline at end of file diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettings.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettings.cs index 614e0d83..a6b7ffe6 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettings.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/Settings/WeChatPaySettings.cs @@ -7,14 +7,5 @@ public static class WeChatPaySettings /* Add constants for setting names. Example: * public const string MySettingName = GroupName + ".MySettingName"; */ - - public const string MchId = GroupName + ".MchId"; - public const string ApiKey = GroupName + ".ApiKey"; - public const string IsSandBox = GroupName + ".IsSandBox"; - public const string NotifyUrl = GroupName + ".NotifyUrl"; - public const string RefundNotifyUrl = GroupName + ".RefundNotifyUrl"; - public const string CertificateBlobContainerName = GroupName + ".CertificateBlobContainerName"; - public const string CertificateBlobName = GroupName + ".CertificateBlobName"; - public const string CertificateSecret = GroupName + ".CertificateSecret"; } } \ No newline at end of file diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/WeChatPayPaymentServiceProvider.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/WeChatPayPaymentServiceProvider.cs index f17aa8eb..08c7f9e5 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/WeChatPayPaymentServiceProvider.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.Domain/EasyAbp/PaymentService/WeChatPay/WeChatPayPaymentServiceProvider.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using EasyAbp.Abp.WeChat.Pay.Services; using EasyAbp.Abp.WeChat.Pay.Services.Pay; +using EasyAbp.Abp.WeChat.Pay.Settings; using EasyAbp.PaymentService.Payments; using EasyAbp.PaymentService.Refunds; using EasyAbp.PaymentService.WeChatPay.Background; @@ -11,8 +13,6 @@ using Volo.Abp; using Volo.Abp.BackgroundJobs; using Volo.Abp.Data; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.EventBus.Local; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Settings; @@ -22,7 +22,6 @@ namespace EasyAbp.PaymentService.WeChatPay { public class WeChatPayPaymentServiceProvider : PaymentServiceProvider { - private readonly ServiceProviderPayService _serviceProviderPayService; private readonly ISettingProvider _settingProvider; private readonly IServiceProvider _serviceProvider; private readonly IGuidGenerator _guidGenerator; @@ -34,11 +33,11 @@ public class WeChatPayPaymentServiceProvider : PaymentServiceProvider private readonly IPaymentRecordRepository _paymentRecordRepository; private readonly IPaymentOpenIdProvider _paymentOpenIdProvider; private readonly IPaymentRepository _paymentRepository; + private readonly IAbpWeChatPayServiceFactory _abpWeChatPayServiceFactory; public const string PaymentMethod = "WeChatPay"; public WeChatPayPaymentServiceProvider( - ServiceProviderPayService serviceProviderPayService, ISettingProvider settingProvider, IServiceProvider serviceProvider, IGuidGenerator guidGenerator, @@ -49,9 +48,9 @@ public WeChatPayPaymentServiceProvider( IPaymentManager paymentManager, IPaymentRecordRepository paymentRecordRepository, IPaymentOpenIdProvider paymentOpenIdProvider, - IPaymentRepository paymentRepository) + IPaymentRepository paymentRepository, + IAbpWeChatPayServiceFactory abpWeChatPayServiceFactory) { - _serviceProviderPayService = serviceProviderPayService; _settingProvider = settingProvider; _serviceProvider = serviceProvider; _guidGenerator = guidGenerator; @@ -63,6 +62,7 @@ public WeChatPayPaymentServiceProvider( _paymentRecordRepository = paymentRecordRepository; _paymentOpenIdProvider = paymentOpenIdProvider; _paymentRepository = paymentRepository; + _abpWeChatPayServiceFactory = abpWeChatPayServiceFactory; } [UnitOfWork(true)] @@ -78,12 +78,13 @@ public override async Task OnPaymentStartedAsync(Payment payment, ExtraPropertyD throw new PaymentAmountInvalidException(payment.ActualPaymentAmount, payment.PaymentMethod); } - var payeeAccount = configurations.GetOrDefault("PayeeAccount") as string ?? - await _settingProvider.GetOrNullAsync(WeChatPaySettings.MchId); + var mchId = configurations.GetOrDefault("mch_id") as string ?? + configurations.GetOrDefault("PayeeAccount") as string ?? + await _settingProvider.GetOrNullAsync(AbpWeChatPaySettings.MchId); - Check.NotNullOrWhiteSpace(payeeAccount, "PayeeAccount"); + Check.NotNullOrWhiteSpace(mchId, "PayeeAccount"); - payment.SetPayeeAccount(payeeAccount); + payment.SetPayeeAccount(mchId); var appId = configurations.GetOrDefault("appid") as string; @@ -91,10 +92,13 @@ public override async Task OnPaymentStartedAsync(Payment payment, ExtraPropertyD var outTradeNo = payment.Id.ToString("N"); - var result = await _serviceProviderPayService.UnifiedOrderAsync( + var serviceProviderPayService = + await _abpWeChatPayServiceFactory.CreateAsync(mchId); + + var result = await serviceProviderPayService.UnifiedOrderAsync( appId: appId, subAppId: null, - mchId: payment.PayeeAccount, + mchId: mchId, subMchId: null, deviceInfo: PaymentServiceWeChatPayConsts.DeviceInfo, body: configurations.GetOrDefault("body") as string ?? "EasyAbpPaymentService", @@ -108,7 +112,7 @@ public override async Task OnPaymentStartedAsync(Payment payment, ExtraPropertyD timeExpire: null, goodsTag: configurations.GetOrDefault("goods_tag") as string, notifyUrl: configurations.GetOrDefault("notify_url") as string - ?? await _settingProvider.GetOrNullAsync(WeChatPaySettings.NotifyUrl), + ?? await _settingProvider.GetOrNullAsync(AbpWeChatPaySettings.NotifyUrl), tradeType: configurations.GetOrDefault("trade_type") as string, productId: null, limitPay: configurations.GetOrDefault("limit_pay") as string, diff --git a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.HttpApi/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayHttpApiModule.cs b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.HttpApi/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayHttpApiModule.cs index b3b248a6..c6e32329 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.HttpApi/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayHttpApiModule.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/src/EasyAbp.PaymentService.WeChatPay.HttpApi/EasyAbp/PaymentService/WeChatPay/PaymentServiceWeChatPayHttpApiModule.cs @@ -1,4 +1,4 @@ -using EasyAbp.Abp.WeChat.Pay.HttpApi; +using EasyAbp.Abp.WeChat.Pay; using Localization.Resources.AbpUi; using EasyAbp.PaymentService.WeChatPay.Localization; using Volo.Abp.AspNetCore.Mvc; diff --git a/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaymentServiceWeChatPayHandlerTests.cs b/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaidWeChatPayEventHandlerTests.cs similarity index 77% rename from modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaymentServiceWeChatPayHandlerTests.cs rename to modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaidWeChatPayEventHandlerTests.cs index 6665f479..f761a43a 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaymentServiceWeChatPayHandlerTests.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaidWeChatPayEventHandlerTests.cs @@ -2,31 +2,37 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Xml; -using EasyAbp.Abp.WeChat.Pay.Infrastructure.OptionResolve; +using EasyAbp.Abp.WeChat.Pay.Options; +using EasyAbp.Abp.WeChat.Pay.RequestHandling; +using EasyAbp.Abp.WeChat.Pay.Services; using EasyAbp.Abp.WeChat.Pay.Services.Pay; using EasyAbp.PaymentService.Payments; using EasyAbp.PaymentService.WeChatPay.PaymentRecords; using EasyAbp.PaymentService.WeChatPay.RefundRecords; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using NSubstitute; using Shouldly; using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; using Xunit; namespace EasyAbp.PaymentService.WeChatPay.WeChatCallbackHandlers; -public class PaymentServiceWeChatPayHandlerTests : WeChatPayDomainTestBase +public class PaidWeChatPayEventHandlerTests : WeChatPayDomainTestBase { + protected AbpWeChatPayOptions AbpWeChatPayOptions { get; set; } protected IPaymentRepository PaymentRepository { get; set; } protected IPaymentRecordRepository PaymentRecordRepository { get; set; } - protected ServiceProviderPayService ServiceProviderPayService { get; set; } protected IRefundRecordRepository RefundRecordRepository { get; set; } - protected PaymentServiceWeChatPayHandler PaymentServiceWeChatPayHandler { get; set; } + protected PaidWeChatPayEventHandler PaidWeChatPayEventHandler { get; set; } + protected IAbpWeChatPayServiceFactory AbpWeChatPayServiceFactory { get; set; } - public PaymentServiceWeChatPayHandlerTests() + public PaidWeChatPayEventHandlerTests() { - PaymentServiceWeChatPayHandler = ServiceProvider.GetRequiredService(); + AbpWeChatPayOptions = ServiceProvider.GetRequiredService>().Value; + PaidWeChatPayEventHandler = ServiceProvider.GetRequiredService(); RefundRecordRepository = ServiceProvider.GetRequiredService(); } @@ -38,8 +44,8 @@ protected override void AfterAddApplication(IServiceCollection services) PaymentRecordRepository = Substitute.For(); services.AddTransient(_ => PaymentRecordRepository); - ServiceProviderPayService = Substitute.For(); - services.AddTransient(_ => ServiceProviderPayService); + AbpWeChatPayServiceFactory = Substitute.For(); + services.AddTransient(_ => AbpWeChatPayServiceFactory); } [Fact] @@ -90,6 +96,8 @@ protected static Payment GetNewPayment() payment.SetProperty("trade_type", "JSAPI"); payment.SetProperty("prepay_id", "123456"); payment.SetProperty("code_url", "123456"); + + payment.SetPayeeAccount("10000100"); return payment; } @@ -143,20 +151,25 @@ protected virtual async Task HandleAsync(Payment payment) "); - ServiceProviderPayService + var serviceProviderPayWeService = + Substitute.For(AbpWeChatPayOptions, + new AbpLazyServiceProvider(ServiceProvider)); + + AbpWeChatPayServiceFactory.CreateAsync() + .ReturnsForAnyArgs(serviceProviderPayWeService); + + serviceProviderPayWeService .RefundAsync(null, null, null, null, null, null, null, 0, 0, null, null, null, null) .ReturnsForAnyArgs(_ => xmlDocumentRefund); await WithUnitOfWorkAsync(async () => { - var context = new WeChatPayHandlerContext + (await PaidWeChatPayEventHandler.HandleAsync(new WeChatPayEventModel { + Options = AbpWeChatPayOptions, WeChatRequestXmlData = xmlDocument, - IsSuccess = true - }; - - await PaymentServiceWeChatPayHandler.HandleAsync(context); - context.IsSuccess.ShouldBeTrue(); + DecryptedXmlData = null + })).Success.ShouldBeTrue(); }); } } \ No newline at end of file diff --git a/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaymentServiceWeChatPayRefundHandler.cs b/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/RefundWeChatPayEventHandlerTests.cs similarity index 84% rename from modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaymentServiceWeChatPayRefundHandler.cs rename to modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/RefundWeChatPayEventHandlerTests.cs index 09d3f7f0..7faef04d 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/PaymentServiceWeChatPayRefundHandler.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.Domain.Tests/WeChatCallbackHandlers/RefundWeChatPayEventHandlerTests.cs @@ -2,12 +2,14 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Xml; -using EasyAbp.Abp.WeChat.Pay.Infrastructure.OptionResolve; +using EasyAbp.Abp.WeChat.Pay.Options; +using EasyAbp.Abp.WeChat.Pay.RequestHandling; using EasyAbp.PaymentService.Payments; using EasyAbp.PaymentService.Refunds; using EasyAbp.PaymentService.WeChatPay.RefundRecords; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using NSubstitute; using Shouldly; using Volo.Abp.Data; @@ -15,17 +17,19 @@ namespace EasyAbp.PaymentService.WeChatPay.WeChatCallbackHandlers; -public class PaymentServiceWeChatPayRefundHandlerTests : WeChatPayDomainTestBase +public class RefundWeChatPayEventHandlerTests : WeChatPayDomainTestBase { + protected AbpWeChatPayOptions AbpWeChatPayOptions { get; set; } protected IPaymentRepository PaymentRepository { get; set; } protected IRefundRepository RefundRepository { get; set; } protected IRefundRecordRepository RefundRecordRepository { get; set; } - protected PaymentServiceWeChatPayRefundHandler PaymentServiceWeChatPayRefundHandler { get; set; } + protected RefundWeChatPayEventHandler RefundWeChatPayEventHandler { get; set; } - public PaymentServiceWeChatPayRefundHandlerTests() + public RefundWeChatPayEventHandlerTests() { - PaymentServiceWeChatPayRefundHandler = - ServiceProvider.GetRequiredService(); + AbpWeChatPayOptions = ServiceProvider.GetRequiredService>().Value; + RefundWeChatPayEventHandler = + ServiceProvider.GetRequiredService(); } protected override void AfterAddApplication(IServiceCollection services) @@ -91,7 +95,7 @@ protected static Refund GetNewRefund(Payment payment) new(Guid.NewGuid(), payment.PaymentItems[0].Id, 10m, null, null), new(Guid.NewGuid(), payment.PaymentItems[1].Id, 20m, null, null) }); - + payment.StartRefund(refund); return refund; @@ -123,6 +127,11 @@ protected virtual async Task HandleAsync(Payment payment, [CanBeNull] Refund ref +"); + + var decryptedXmlDocument = new XmlDocument(); + decryptedXmlDocument.LoadXml(@$" + @@ -137,18 +146,16 @@ protected virtual async Task HandleAsync(Payment payment, [CanBeNull] Refund ref - + "); await WithUnitOfWorkAsync(async () => { - var context = new WeChatPayHandlerContext + (await RefundWeChatPayEventHandler.HandleAsync(new WeChatPayEventModel { + Options = AbpWeChatPayOptions, WeChatRequestXmlData = xmlDocument, - IsSuccess = true - }; - - await PaymentServiceWeChatPayRefundHandler.HandleAsync(context); - context.IsSuccess.ShouldBeTrue(); + DecryptedXmlData = decryptedXmlDocument + })).Success.ShouldBeTrue(); }); } } \ No newline at end of file diff --git a/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.TestBase/PaymentServiceWeChatPayTestBaseModule.cs b/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.TestBase/PaymentServiceWeChatPayTestBaseModule.cs index 1882c7c7..80ed6980 100644 --- a/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.TestBase/PaymentServiceWeChatPayTestBaseModule.cs +++ b/modules/EasyAbp.PaymentService.WeChatPay/test/EasyAbp.PaymentService.WeChatPay.TestBase/PaymentServiceWeChatPayTestBaseModule.cs @@ -1,4 +1,5 @@ -using EasyAbp.PaymentService.WeChatPay; +using EasyAbp.Abp.WeChat.Pay.Options; +using EasyAbp.PaymentService.WeChatPay; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Authorization; @@ -18,6 +19,12 @@ public class PaymentServiceWeChatPayTestBaseModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAlwaysAllowAuthorization(); + + Configure(options => + { + options.MchId = "10000100"; + options.ApiKey = ""; + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context)