mirror of
https://github.com/bitwarden/server
synced 2026-01-06 18:43:36 +00:00
[PM-28662] Fix Individual Premium automatically disabled due to duplicate subscription leftover from failed payment (#6663)
* Fix the Bug * Address the hardcode issue * Fix the tailing test * resolve the lint issue
This commit is contained in:
@@ -109,8 +109,7 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
|
||||
break;
|
||||
}
|
||||
|
||||
if (subscription.Status is StripeSubscriptionStatus.Unpaid &&
|
||||
subscription.Items.Any(i => i.Price.Id is IStripeEventUtilityService.PremiumPlanId or IStripeEventUtilityService.PremiumPlanIdAppStore))
|
||||
if (await IsPremiumSubscriptionAsync(subscription))
|
||||
{
|
||||
await CancelSubscription(subscription.Id);
|
||||
await VoidOpenInvoices(subscription.Id);
|
||||
@@ -118,6 +117,20 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
|
||||
|
||||
await _userService.DisablePremiumAsync(userId.Value, currentPeriodEnd);
|
||||
|
||||
break;
|
||||
}
|
||||
case StripeSubscriptionStatus.Incomplete when userId.HasValue:
|
||||
{
|
||||
// Handle Incomplete subscriptions for Premium users that have open invoices from failed payments
|
||||
// This prevents duplicate subscriptions when users retry the subscription flow
|
||||
if (await IsPremiumSubscriptionAsync(subscription) &&
|
||||
subscription.LatestInvoice is { Status: StripeInvoiceStatus.Open })
|
||||
{
|
||||
await CancelSubscription(subscription.Id);
|
||||
await VoidOpenInvoices(subscription.Id);
|
||||
await _userService.DisablePremiumAsync(userId.Value, currentPeriodEnd);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case StripeSubscriptionStatus.Active when organizationId.HasValue:
|
||||
@@ -190,6 +203,13 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> IsPremiumSubscriptionAsync(Subscription subscription)
|
||||
{
|
||||
var premiumPlans = await _pricingClient.ListPremiumPlans();
|
||||
var premiumPriceIds = premiumPlans.SelectMany(p => new[] { p.Seat.StripePriceId, p.Storage.StripePriceId }).ToHashSet();
|
||||
return subscription.Items.Any(i => premiumPriceIds.Contains(i.Price.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the provider subscription status has changed from a non-active to an active status type
|
||||
/// If the previous status is already active(active,past-due,trialing),canceled,or null, then this will return false.
|
||||
|
||||
Reference in New Issue
Block a user