1
0
mirror of https://github.com/bitwarden/server synced 2026-01-06 18:43:36 +00:00

[PM 18701]Optional payment modal after signup (#6014)

* Add endpoint to swap plan frequency

* Add endpoint to swap plan frequency

* Resolve pr comments

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* Refactor the code

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* Refactor for  thr update change frequency

* Add Automatic modal opening

* catch for organization paying with PayPal

---------

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>
This commit is contained in:
cyprain-okeke
2025-07-22 15:57:58 +01:00
committed by GitHub
parent f4e1e2f1f7
commit 8a5823bff7
6 changed files with 143 additions and 0 deletions

View File

@@ -382,4 +382,35 @@ public class OrganizationBillingController(
return TypedResults.Ok(response);
}
[HttpPost("change-frequency")]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<IResult> ChangePlanSubscriptionFrequencyAsync(
[FromRoute] Guid organizationId,
[FromBody] ChangePlanFrequencyRequest request)
{
if (!await currentContext.EditSubscription(organizationId))
{
return Error.Unauthorized();
}
var organization = await organizationRepository.GetByIdAsync(organizationId);
if (organization == null)
{
return Error.NotFound();
}
if (organization.PlanType == request.NewPlanType)
{
return Error.BadRequest("Organization is already on the requested plan frequency.");
}
await organizationBillingService.UpdateSubscriptionPlanFrequency(
organization,
request.NewPlanType);
return TypedResults.Ok();
}
}

View File

@@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
using Bit.Core.Billing.Enums;
namespace Bit.Api.Billing.Models.Requests;
public class ChangePlanFrequencyRequest
{
[Required]
public PlanType NewPlanType { get; set; }
}

View File

@@ -12,6 +12,7 @@ using Bit.Core.Billing.Services;
using Bit.Core.Context;
using Bit.Core.Services;
using Stripe;
using static Bit.Core.Billing.Utilities;
using FreeTrialWarning = Bit.Api.Billing.Models.Responses.Organizations.OrganizationWarningsResponse.FreeTrialWarning;
using InactiveSubscriptionWarning =
Bit.Api.Billing.Models.Responses.Organizations.OrganizationWarningsResponse.InactiveSubscriptionWarning;
@@ -100,6 +101,20 @@ public class OrganizationWarningsQuery(
Provider? provider,
Subscription subscription)
{
if (organization.Enabled && subscription.Status is StripeConstants.SubscriptionStatus.Trialing)
{
var isStripeCustomerWithoutPayment =
subscription.Customer.InvoiceSettings.DefaultPaymentMethodId is null;
var isBraintreeCustomer =
subscription.Customer.Metadata.ContainsKey(BraintreeCustomerIdKey);
var hasNoPaymentMethod = isStripeCustomerWithoutPayment && !isBraintreeCustomer;
if (hasNoPaymentMethod && await currentContext.OrganizationOwner(organization.Id))
{
return new InactiveSubscriptionWarning { Resolution = "add_payment_method_optional_trial" };
}
}
if (organization.Enabled ||
subscription.Status is not StripeConstants.SubscriptionStatus.Unpaid
and not StripeConstants.SubscriptionStatus.Canceled)