From 5562ca9d5e2b43e428b47365918d1cb6145baee7 Mon Sep 17 00:00:00 2001 From: Jonas Hendrickx Date: Mon, 27 Jan 2025 15:28:47 +0100 Subject: [PATCH] WIP (#5210) --- .../Implementations/UpcomingInvoiceHandler.cs | 8 +-- .../OrganizationBillingService.cs | 2 +- .../PremiumUserBillingService.cs | 2 +- .../Implementations/SubscriberService.cs | 20 ++---- .../Implementations/StripePaymentService.cs | 70 ++++++------------- 5 files changed, 30 insertions(+), 72 deletions(-) diff --git a/src/Billing/Services/Implementations/UpcomingInvoiceHandler.cs b/src/Billing/Services/Implementations/UpcomingInvoiceHandler.cs index bd496c6974..c52c03b6aa 100644 --- a/src/Billing/Services/Implementations/UpcomingInvoiceHandler.cs +++ b/src/Billing/Services/Implementations/UpcomingInvoiceHandler.cs @@ -1,7 +1,6 @@ using Bit.Billing.Constants; using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Repositories; -using Bit.Core.Billing.Constants; using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces; using Bit.Core.Repositories; using Bit.Core.Services; @@ -161,18 +160,13 @@ public class UpcomingInvoiceHandler : IUpcomingInvoiceHandler private async Task TryEnableAutomaticTaxAsync(Subscription subscription) { - var customerGetOptions = new CustomerGetOptions { Expand = ["tax"] }; - var customer = await _stripeFacade.GetCustomer(subscription.CustomerId, customerGetOptions); - - if (subscription.AutomaticTax.Enabled || - customer.Tax?.AutomaticTax != StripeConstants.AutomaticTaxStatus.Supported) + if (subscription.AutomaticTax.Enabled) { return subscription; } var subscriptionUpdateOptions = new SubscriptionUpdateOptions { - DefaultTaxRates = [], AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true } }; diff --git a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs index ec9770c59e..201de22525 100644 --- a/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs +++ b/src/Core/Billing/Services/Implementations/OrganizationBillingService.cs @@ -360,7 +360,7 @@ public class OrganizationBillingService( { AutomaticTax = new SubscriptionAutomaticTaxOptions { - Enabled = customer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported + Enabled = true }, CollectionMethod = StripeConstants.CollectionMethod.ChargeAutomatically, Customer = customer.Id, diff --git a/src/Core/Billing/Services/Implementations/PremiumUserBillingService.cs b/src/Core/Billing/Services/Implementations/PremiumUserBillingService.cs index 306ee88eaf..0672a8d5e7 100644 --- a/src/Core/Billing/Services/Implementations/PremiumUserBillingService.cs +++ b/src/Core/Billing/Services/Implementations/PremiumUserBillingService.cs @@ -235,7 +235,7 @@ public class PremiumUserBillingService( { AutomaticTax = new SubscriptionAutomaticTaxOptions { - Enabled = customer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported, + Enabled = true }, CollectionMethod = StripeConstants.CollectionMethod.ChargeAutomatically, Customer = customer.Id, diff --git a/src/Core/Billing/Services/Implementations/SubscriberService.cs b/src/Core/Billing/Services/Implementations/SubscriberService.cs index b2dca19e80..f4cf22ac19 100644 --- a/src/Core/Billing/Services/Implementations/SubscriberService.cs +++ b/src/Core/Billing/Services/Implementations/SubscriberService.cs @@ -661,21 +661,11 @@ public class SubscriberService( } } - if (SubscriberIsEligibleForAutomaticTax(subscriber, customer)) - { - await stripeAdapter.SubscriptionUpdateAsync(subscriber.GatewaySubscriptionId, - new SubscriptionUpdateOptions - { - AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true } - }); - } - - return; - - bool SubscriberIsEligibleForAutomaticTax(ISubscriber localSubscriber, Customer localCustomer) - => !string.IsNullOrEmpty(localSubscriber.GatewaySubscriptionId) && - (localCustomer.Subscriptions?.Any(sub => sub.Id == localSubscriber.GatewaySubscriptionId && !sub.AutomaticTax.Enabled) ?? false) && - localCustomer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported; + await stripeAdapter.SubscriptionUpdateAsync(subscriber.GatewaySubscriptionId, + new SubscriptionUpdateOptions + { + AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }, + }); } public async Task VerifyBankAccount( diff --git a/src/Core/Services/Implementations/StripePaymentService.cs b/src/Core/Services/Implementations/StripePaymentService.cs index 3f9c5c53c6..fb5c7364a5 100644 --- a/src/Core/Services/Implementations/StripePaymentService.cs +++ b/src/Core/Services/Implementations/StripePaymentService.cs @@ -177,11 +177,7 @@ public class StripePaymentService : IPaymentService customer = await _stripeAdapter.CustomerCreateAsync(customerCreateOptions); subCreateOptions.AddExpand("latest_invoice.payment_intent"); subCreateOptions.Customer = customer.Id; - - if (CustomerHasTaxLocationVerified(customer)) - { - subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }; - } + subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }; subscription = await _stripeAdapter.SubscriptionCreateAsync(subCreateOptions); if (subscription.Status == "incomplete" && subscription.LatestInvoice?.PaymentIntent != null) @@ -362,13 +358,10 @@ public class StripePaymentService : IPaymentService customer = await _stripeAdapter.CustomerUpdateAsync(org.GatewayCustomerId, customerUpdateOptions); } - var subCreateOptions = new OrganizationUpgradeSubscriptionOptions(customer.Id, org, plan, upgrade); - - if (CustomerHasTaxLocationVerified(customer)) + var subCreateOptions = new OrganizationUpgradeSubscriptionOptions(customer.Id, org, plan, upgrade) { - subCreateOptions.DefaultTaxRates = []; - subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }; - } + AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true } + }; var (stripePaymentMethod, paymentMethodType) = IdentifyPaymentMethod(customer, subCreateOptions); @@ -527,6 +520,10 @@ public class StripePaymentService : IPaymentService var customerCreateOptions = new CustomerCreateOptions { + Tax = new CustomerTaxOptions + { + ValidateLocation = StripeConstants.ValidateTaxLocationTiming.Immediately + }, Description = user.Name, Email = user.Email, Metadata = stripeCustomerMetadata, @@ -564,6 +561,7 @@ public class StripePaymentService : IPaymentService var subCreateOptions = new SubscriptionCreateOptions { + AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }, Customer = customer.Id, Items = [], Metadata = new Dictionary @@ -583,16 +581,10 @@ public class StripePaymentService : IPaymentService subCreateOptions.Items.Add(new SubscriptionItemOptions { Plan = StoragePlanId, - Quantity = additionalStorageGb + Quantity = additionalStorageGb, }); } - if (CustomerHasTaxLocationVerified(customer)) - { - subCreateOptions.DefaultTaxRates = []; - subCreateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }; - } - var subscription = await ChargeForNewSubscriptionAsync(user, customer, createdStripeCustomer, stripePaymentMethod, paymentMethodType, subCreateOptions, braintreeCustomer); @@ -630,10 +622,7 @@ public class StripePaymentService : IPaymentService SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items) }); - if (CustomerHasTaxLocationVerified(customer)) - { - previewInvoice.AutomaticTax = new InvoiceAutomaticTax { Enabled = true }; - } + previewInvoice.AutomaticTax = new InvoiceAutomaticTax { Enabled = true }; if (previewInvoice.AmountDue > 0) { @@ -691,14 +680,12 @@ public class StripePaymentService : IPaymentService Customer = customer.Id, SubscriptionItems = ToInvoiceSubscriptionItemOptions(subCreateOptions.Items), SubscriptionDefaultTaxRates = subCreateOptions.DefaultTaxRates, + AutomaticTax = new InvoiceAutomaticTaxOptions + { + Enabled = true + } }; - if (CustomerHasTaxLocationVerified(customer)) - { - upcomingInvoiceOptions.AutomaticTax = new InvoiceAutomaticTaxOptions { Enabled = true }; - upcomingInvoiceOptions.SubscriptionDefaultTaxRates = []; - } - var previewInvoice = await _stripeAdapter.InvoiceUpcomingAsync(upcomingInvoiceOptions); if (previewInvoice.AmountDue > 0) @@ -817,7 +804,11 @@ public class StripePaymentService : IPaymentService Items = updatedItemOptions, ProrationBehavior = invoiceNow ? Constants.AlwaysInvoice : Constants.CreateProrations, DaysUntilDue = daysUntilDue ?? 1, - CollectionMethod = "send_invoice" + CollectionMethod = "send_invoice", + AutomaticTax = new SubscriptionAutomaticTaxOptions + { + Enabled = true + } }; if (!invoiceNow && isAnnualPlan && sub.Status.Trim() != "trialing") { @@ -825,13 +816,6 @@ public class StripePaymentService : IPaymentService new SubscriptionPendingInvoiceItemIntervalOptions { Interval = "month" }; } - if (sub.AutomaticTax.Enabled != true && - CustomerHasTaxLocationVerified(sub.Customer)) - { - subUpdateOptions.DefaultTaxRates = []; - subUpdateOptions.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }; - } - if (!subscriptionUpdate.UpdateNeeded(sub)) { // No need to update subscription, quantity matches @@ -1516,13 +1500,11 @@ public class StripePaymentService : IPaymentService if (!string.IsNullOrEmpty(subscriber.GatewaySubscriptionId) && customer.Subscriptions.Any(sub => sub.Id == subscriber.GatewaySubscriptionId && - !sub.AutomaticTax.Enabled) && - CustomerHasTaxLocationVerified(customer)) + !sub.AutomaticTax.Enabled)) { var subscriptionUpdateOptions = new SubscriptionUpdateOptions { - AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true }, - DefaultTaxRates = [] + AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true } }; _ = await _stripeAdapter.SubscriptionUpdateAsync( @@ -2280,14 +2262,6 @@ public class StripePaymentService : IPaymentService } } - /// - /// Determines if a Stripe customer supports automatic tax - /// - /// - /// - private static bool CustomerHasTaxLocationVerified(Customer customer) => - customer?.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported; - // We are taking only first 30 characters of the SubscriberName because stripe provide // for 30 characters for custom_fields,see the link: https://stripe.com/docs/api/invoices/create private static string GetFirstThirtyCharacters(string subscriberName)