diff --git a/src/Core/Services/IOrganizationService.cs b/src/Core/Services/IOrganizationService.cs index f90946c63f..2df9a946ce 100644 --- a/src/Core/Services/IOrganizationService.cs +++ b/src/Core/Services/IOrganizationService.cs @@ -10,6 +10,7 @@ namespace Bit.Core.Services { Task GetBillingAsync(Organization organization); Task ReplacePaymentMethodAsync(Guid organizationId, string paymentToken); + Task CancelSubscriptionAsync(Guid organizationId, bool endOfPeriod = false); Task> SignUpAsync(OrganizationSignup organizationSignup); Task InviteUserAsync(Guid organizationId, Guid invitingUserId, string email, Enums.OrganizationUserType type, IEnumerable subvaults); diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index 1775029558..4bf5c3932c 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -127,6 +127,39 @@ namespace Bit.Core.Services } } + public async Task CancelSubscriptionAsync(Guid organizationId, bool endOfPeriod = false) + { + var organization = await _organizationRepository.GetByIdAsync(organizationId); + if(organization == null) + { + throw new NotFoundException(); + } + + if(string.IsNullOrWhiteSpace(organization.StripeSubscriptionId)) + { + throw new BadRequestException("Organization has no subscription."); + } + + var subscriptionService = new StripeSubscriptionService(); + var sub = await subscriptionService.GetAsync(organization.StripeCustomerId); + + if(sub == null) + { + throw new BadRequestException("Organization subscription was not found."); + } + + if(sub.Status == "canceled") + { + throw new BadRequestException("Organization subscription is already canceled."); + } + + var canceledSub = await subscriptionService.CancelAsync(sub.Id, endOfPeriod); + if(canceledSub?.Status != "canceled") + { + throw new BadRequestException("Unable to cancel subscription."); + } + } + public async Task> SignUpAsync(OrganizationSignup signup) { var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == signup.Plan && !p.Disabled);