diff --git a/src/Billing/Controllers/PayPalController.cs b/src/Billing/Controllers/PayPalController.cs index 96f5052ce..2fc8aab4f 100644 --- a/src/Billing/Controllers/PayPalController.cs +++ b/src/Billing/Controllers/PayPalController.cs @@ -1,5 +1,6 @@ using System.Text; using Bit.Billing.Models; +using Bit.Core.AdminConsole.Repositories; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Repositories; @@ -21,6 +22,7 @@ public class PayPalController : Controller private readonly IPaymentService _paymentService; private readonly ITransactionRepository _transactionRepository; private readonly IUserRepository _userRepository; + private readonly IProviderRepository _providerRepository; public PayPalController( IOptions billingSettings, @@ -29,7 +31,8 @@ public class PayPalController : Controller IOrganizationRepository organizationRepository, IPaymentService paymentService, ITransactionRepository transactionRepository, - IUserRepository userRepository) + IUserRepository userRepository, + IProviderRepository providerRepository) { _billingSettings = billingSettings?.Value; _logger = logger; @@ -38,6 +41,7 @@ public class PayPalController : Controller _paymentService = paymentService; _transactionRepository = transactionRepository; _userRepository = userRepository; + _providerRepository = providerRepository; } [HttpPost("ipn")] @@ -83,7 +87,7 @@ public class PayPalController : Controller if (!entityId.HasValue) { - _logger.LogError("PayPal IPN ({Id}): 'custom' did not contain a User ID or Organization ID", transactionModel.TransactionId); + _logger.LogError("PayPal IPN ({Id}): 'custom' did not contain a User ID or Organization ID or provider ID", transactionModel.TransactionId); return BadRequest(); } @@ -260,6 +264,17 @@ public class PayPalController : Controller billingEmail = user.BillingEmailAddress(); } } + else if (transaction.ProviderId.HasValue) + { + var provider = await _providerRepository.GetByIdAsync(transaction.ProviderId.Value); + + if (await _paymentService.CreditAccountAsync(provider, transaction.Amount)) + { + await _providerRepository.ReplaceAsync(provider); + + billingEmail = provider.BillingEmailAddress(); + } + } if (!string.IsNullOrEmpty(billingEmail)) { diff --git a/src/Billing/Controllers/StripeController.cs b/src/Billing/Controllers/StripeController.cs index 037c6f2ad..a2cc06854 100644 --- a/src/Billing/Controllers/StripeController.cs +++ b/src/Billing/Controllers/StripeController.cs @@ -582,6 +582,7 @@ public class StripeController : Controller CreationDate = refund.Created, OrganizationId = parentTransaction.OrganizationId, UserId = parentTransaction.UserId, + ProviderId = parentTransaction.ProviderId, Type = TransactionType.Refund, Gateway = GatewayType.Stripe, GatewayId = refund.Id, @@ -606,7 +607,7 @@ public class StripeController : Controller } var (organizationId, userId, providerId) = await GetEntityIdsFromChargeAsync(charge); - if (!organizationId.HasValue && !userId.HasValue) + if (!organizationId.HasValue && !userId.HasValue && !providerId.HasValue) { _logger.LogWarning("Charge success has no subscriber ids. {ChargeId}", charge.Id); return; diff --git a/test/Billing.Test/Controllers/PayPalControllerTests.cs b/test/Billing.Test/Controllers/PayPalControllerTests.cs index cafc0a965..3c9edd222 100644 --- a/test/Billing.Test/Controllers/PayPalControllerTests.cs +++ b/test/Billing.Test/Controllers/PayPalControllerTests.cs @@ -2,6 +2,7 @@ using Bit.Billing.Controllers; using Bit.Billing.Test.Utilities; using Bit.Core.AdminConsole.Entities; +using Bit.Core.AdminConsole.Repositories; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Repositories; @@ -32,6 +33,7 @@ public class PayPalControllerTests private readonly IPaymentService _paymentService = Substitute.For(); private readonly ITransactionRepository _transactionRepository = Substitute.For(); private readonly IUserRepository _userRepository = Substitute.For(); + private readonly IProviderRepository _providerRepository = Substitute.For(); private const string _defaultWebhookKey = "webhook-key"; @@ -110,7 +112,7 @@ public class PayPalControllerTests HasStatusCode(result, 400); - LoggedError(logger, "PayPal IPN (2PK15573S8089712Y): 'custom' did not contain a User ID or Organization ID"); + LoggedError(logger, "PayPal IPN (2PK15573S8089712Y): 'custom' did not contain a User ID or Organization ID or provider ID"); } [Fact] @@ -542,7 +544,8 @@ public class PayPalControllerTests _organizationRepository, _paymentService, _transactionRepository, - _userRepository); + _userRepository, + _providerRepository); var httpContext = new DefaultHttpContext();