1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-04 12:40:22 -05:00

[PM-16979] Avoid returning BillingTaxIdTypeInterferenceError when an … (#5252)

* [PM-16979] Avoid returning BillingTaxIdTypeInterferenceError when an empty tax id string is passed

* tests

* fix tests

(cherry picked from commit cc2128c97a74030c530e8f72d929e109ea473df8)
This commit is contained in:
Jonas Hendrickx 2025-01-15 16:05:27 +01:00 committed by Conner Turnbull
parent 549681d179
commit 1e419dde97
No known key found for this signature in database
2 changed files with 73 additions and 2 deletions

View File

@ -119,7 +119,7 @@ public class StripePaymentService : IPaymentService
Subscription subscription;
try
{
if (taxInfo.TaxIdNumber != null && taxInfo.TaxIdType == null)
if (!string.IsNullOrWhiteSpace(taxInfo.TaxIdNumber))
{
taxInfo.TaxIdType = _taxService.GetStripeTaxCode(taxInfo.BillingAddressCountry,
taxInfo.TaxIdNumber);
@ -2058,7 +2058,7 @@ public class StripePaymentService : IPaymentService
}
}
if (!string.IsNullOrEmpty(parameters.TaxInformation.TaxId))
if (!string.IsNullOrWhiteSpace(parameters.TaxInformation.TaxId))
{
var taxIdType = _taxService.GetStripeTaxCode(
options.CustomerDetails.Address.Country,

View File

@ -1,5 +1,6 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Services;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Business;
@ -39,6 +40,11 @@ public class StripePaymentServiceTests
{
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
sutProvider
.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(p => p == taxInfo.BillingAddressCountry), Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns(taxInfo.TaxIdType);
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
{
@ -95,6 +101,12 @@ public class StripePaymentServiceTests
{
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
organization.UseSecretsManager = true;
sutProvider
.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(p => p == taxInfo.BillingAddressCountry), Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns(taxInfo.TaxIdType);
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
{
@ -152,6 +164,12 @@ public class StripePaymentServiceTests
{
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
organization.UseSecretsManager = true;
sutProvider
.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(p => p == taxInfo.BillingAddressCountry), Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns(taxInfo.TaxIdType);
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
{
@ -210,6 +228,11 @@ public class StripePaymentServiceTests
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
paymentToken = "pm_" + paymentToken;
sutProvider
.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(p => p == taxInfo.BillingAddressCountry), Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns(taxInfo.TaxIdType);
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
{
@ -397,6 +420,11 @@ public class StripePaymentServiceTests
{
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
sutProvider
.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(p => p == taxInfo.BillingAddressCountry), Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns(taxInfo.TaxIdType);
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
{
@ -462,6 +490,12 @@ public class StripePaymentServiceTests
{
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
organization.UseSecretsManager = true;
sutProvider
.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(p => p == taxInfo.BillingAddressCountry), Arg.Is<string>(p => p == taxInfo.TaxIdNumber))
.Returns(taxInfo.TaxIdType);
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
{
@ -610,6 +644,43 @@ public class StripePaymentServiceTests
await braintreeGateway.Customer.Received(1).DeleteAsync("Braintree-Id");
}
[Theory]
[BitAutoData("ES", "A5372895732985327895237")]
public async Task PurchaseOrganizationAsync_ThrowsBadRequestException_WhenTaxIdInvalid(string country, string taxId, SutProvider<StripePaymentService> sutProvider, Organization organization, string paymentToken, TaxInfo taxInfo)
{
taxInfo.BillingAddressCountry = country;
taxInfo.TaxIdNumber = taxId;
taxInfo.TaxIdType = null;
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
organization.UseSecretsManager = true;
var stripeAdapter = sutProvider.GetDependency<IStripeAdapter>();
stripeAdapter.CustomerCreateAsync(default).ReturnsForAnyArgs(new Stripe.Customer
{
Id = "C-1",
});
stripeAdapter.SubscriptionCreateAsync(default).ReturnsForAnyArgs(new Stripe.Subscription
{
Id = "S-1",
CurrentPeriodEnd = DateTime.Today.AddDays(10),
});
sutProvider.GetDependency<IGlobalSettings>()
.BaseServiceUri.CloudRegion
.Returns("US");
sutProvider
.GetDependency<ITaxService>()
.GetStripeTaxCode(Arg.Is<string>(p => p == country), Arg.Is<string>(p => p == taxId))
.Returns((string)null);
var actual = await Assert.ThrowsAsync<BadRequestException>(async () => await sutProvider.Sut.PurchaseOrganizationAsync(organization, PaymentMethodType.Card, paymentToken, plan, 0, 0, false, taxInfo, false, 8, 10));
Assert.Equal("billingTaxIdTypeInferenceError", actual.Message);
await stripeAdapter.Received(0).CustomerCreateAsync(Arg.Any<Stripe.CustomerCreateOptions>());
await stripeAdapter.Received(0).SubscriptionCreateAsync(Arg.Any<Stripe.SubscriptionCreateOptions>());
}
[Theory, BitAutoData]
public async Task UpgradeFreeOrganizationAsync_Success(SutProvider<StripePaymentService> sutProvider,
Organization organization, TaxInfo taxInfo)