mirror of
https://github.com/bitwarden/server.git
synced 2025-04-25 23:02:17 -05:00
WIP
This commit is contained in:
parent
8768e69f76
commit
24826ec3bd
bitwarden_license/src/Commercial.Core
src/Core
Billing
Extensions
Services
Services/Implementations
@ -28,6 +28,7 @@ public class RemoveOrganizationFromProviderCommand : IRemoveOrganizationFromProv
|
|||||||
private readonly ISubscriberService _subscriberService;
|
private readonly ISubscriberService _subscriberService;
|
||||||
private readonly IHasConfirmedOwnersExceptQuery _hasConfirmedOwnersExceptQuery;
|
private readonly IHasConfirmedOwnersExceptQuery _hasConfirmedOwnersExceptQuery;
|
||||||
private readonly IPricingClient _pricingClient;
|
private readonly IPricingClient _pricingClient;
|
||||||
|
private readonly IOrganizationAutomaticTaxStrategy _organizationAutomaticTaxStrategy;
|
||||||
|
|
||||||
public RemoveOrganizationFromProviderCommand(
|
public RemoveOrganizationFromProviderCommand(
|
||||||
IEventService eventService,
|
IEventService eventService,
|
||||||
@ -40,7 +41,8 @@ public class RemoveOrganizationFromProviderCommand : IRemoveOrganizationFromProv
|
|||||||
IProviderBillingService providerBillingService,
|
IProviderBillingService providerBillingService,
|
||||||
ISubscriberService subscriberService,
|
ISubscriberService subscriberService,
|
||||||
IHasConfirmedOwnersExceptQuery hasConfirmedOwnersExceptQuery,
|
IHasConfirmedOwnersExceptQuery hasConfirmedOwnersExceptQuery,
|
||||||
IPricingClient pricingClient)
|
IPricingClient pricingClient,
|
||||||
|
IOrganizationAutomaticTaxStrategy organizationAutomaticTaxStrategy)
|
||||||
{
|
{
|
||||||
_eventService = eventService;
|
_eventService = eventService;
|
||||||
_mailService = mailService;
|
_mailService = mailService;
|
||||||
@ -53,6 +55,7 @@ public class RemoveOrganizationFromProviderCommand : IRemoveOrganizationFromProv
|
|||||||
_subscriberService = subscriberService;
|
_subscriberService = subscriberService;
|
||||||
_hasConfirmedOwnersExceptQuery = hasConfirmedOwnersExceptQuery;
|
_hasConfirmedOwnersExceptQuery = hasConfirmedOwnersExceptQuery;
|
||||||
_pricingClient = pricingClient;
|
_pricingClient = pricingClient;
|
||||||
|
_organizationAutomaticTaxStrategy = organizationAutomaticTaxStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemoveOrganizationFromProvider(
|
public async Task RemoveOrganizationFromProvider(
|
||||||
@ -107,7 +110,7 @@ public class RemoveOrganizationFromProviderCommand : IRemoveOrganizationFromProv
|
|||||||
organization.IsValidClient() &&
|
organization.IsValidClient() &&
|
||||||
!string.IsNullOrEmpty(organization.GatewayCustomerId))
|
!string.IsNullOrEmpty(organization.GatewayCustomerId))
|
||||||
{
|
{
|
||||||
await _stripeAdapter.CustomerUpdateAsync(organization.GatewayCustomerId, new CustomerUpdateOptions
|
var customer = await _stripeAdapter.CustomerUpdateAsync(organization.GatewayCustomerId, new CustomerUpdateOptions
|
||||||
{
|
{
|
||||||
Description = string.Empty,
|
Description = string.Empty,
|
||||||
Email = organization.BillingEmail
|
Email = organization.BillingEmail
|
||||||
@ -120,7 +123,6 @@ public class RemoveOrganizationFromProviderCommand : IRemoveOrganizationFromProv
|
|||||||
Customer = organization.GatewayCustomerId,
|
Customer = organization.GatewayCustomerId,
|
||||||
CollectionMethod = StripeConstants.CollectionMethod.SendInvoice,
|
CollectionMethod = StripeConstants.CollectionMethod.SendInvoice,
|
||||||
DaysUntilDue = 30,
|
DaysUntilDue = 30,
|
||||||
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true },
|
|
||||||
Metadata = new Dictionary<string, string>
|
Metadata = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ "organizationId", organization.Id.ToString() }
|
{ "organizationId", organization.Id.ToString() }
|
||||||
@ -130,6 +132,8 @@ public class RemoveOrganizationFromProviderCommand : IRemoveOrganizationFromProv
|
|||||||
Items = [new SubscriptionItemOptions { Price = plan.PasswordManager.StripeSeatPlanId, Quantity = organization.Seats }]
|
Items = [new SubscriptionItemOptions { Price = plan.PasswordManager.StripeSeatPlanId, Quantity = organization.Seats }]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await _organizationAutomaticTaxStrategy.SetCreateOptionsAsync(subscriptionCreateOptions, customer);
|
||||||
|
|
||||||
var subscription = await _stripeAdapter.SubscriptionCreateAsync(subscriptionCreateOptions);
|
var subscription = await _stripeAdapter.SubscriptionCreateAsync(subscriptionCreateOptions);
|
||||||
|
|
||||||
organization.GatewaySubscriptionId = subscription.Id;
|
organization.GatewaySubscriptionId = subscription.Id;
|
||||||
|
@ -40,7 +40,8 @@ public class ProviderBillingService(
|
|||||||
IProviderUserRepository providerUserRepository,
|
IProviderUserRepository providerUserRepository,
|
||||||
IStripeAdapter stripeAdapter,
|
IStripeAdapter stripeAdapter,
|
||||||
ISubscriberService subscriberService,
|
ISubscriberService subscriberService,
|
||||||
ITaxService taxService) : IProviderBillingService
|
ITaxService taxService,
|
||||||
|
IOrganizationAutomaticTaxStrategy organizationAutomaticTaxStrategy) : IProviderBillingService
|
||||||
{
|
{
|
||||||
[RequireFeature(FeatureFlagKeys.P15179_AddExistingOrgsFromProviderPortal)]
|
[RequireFeature(FeatureFlagKeys.P15179_AddExistingOrgsFromProviderPortal)]
|
||||||
public async Task AddExistingOrganization(
|
public async Task AddExistingOrganization(
|
||||||
@ -589,10 +590,6 @@ public class ProviderBillingService(
|
|||||||
|
|
||||||
var subscriptionCreateOptions = new SubscriptionCreateOptions
|
var subscriptionCreateOptions = new SubscriptionCreateOptions
|
||||||
{
|
{
|
||||||
AutomaticTax = new SubscriptionAutomaticTaxOptions
|
|
||||||
{
|
|
||||||
Enabled = true
|
|
||||||
},
|
|
||||||
CollectionMethod = StripeConstants.CollectionMethod.SendInvoice,
|
CollectionMethod = StripeConstants.CollectionMethod.SendInvoice,
|
||||||
Customer = customer.Id,
|
Customer = customer.Id,
|
||||||
DaysUntilDue = 30,
|
DaysUntilDue = 30,
|
||||||
@ -605,6 +602,8 @@ public class ProviderBillingService(
|
|||||||
ProrationBehavior = StripeConstants.ProrationBehavior.CreateProrations
|
ProrationBehavior = StripeConstants.ProrationBehavior.CreateProrations
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await organizationAutomaticTaxStrategy.SetCreateOptionsAsync(subscriptionCreateOptions, customer);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var subscription = await stripeAdapter.SubscriptionCreateAsync(subscriptionCreateOptions);
|
var subscription = await stripeAdapter.SubscriptionCreateAsync(subscriptionCreateOptions);
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
using Stripe;
|
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Extensions;
|
|
||||||
|
|
||||||
public static class SubscriptionCreateOptionsExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to enable automatic tax for given new subscription options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="customer">The existing customer.</param>
|
|
||||||
/// <returns>Returns true when successful, false when conditions are not met.</returns>
|
|
||||||
public static bool EnableAutomaticTax(this SubscriptionCreateOptions options, Customer customer)
|
|
||||||
{
|
|
||||||
// We might only need to check the automatic tax status.
|
|
||||||
if (!customer.HasTaxLocationVerified() && string.IsNullOrWhiteSpace(customer.Address?.Country))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.DefaultTaxRates = [];
|
|
||||||
options.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
using Stripe;
|
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Extensions;
|
|
||||||
|
|
||||||
public static class SubscriptionUpdateOptionsExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to enable automatic tax for given subscription options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="customer">The existing customer to which the subscription belongs.</param>
|
|
||||||
/// <param name="subscription">The existing subscription.</param>
|
|
||||||
/// <returns>Returns true when successful, false when conditions are not met.</returns>
|
|
||||||
public static bool EnableAutomaticTax(
|
|
||||||
this SubscriptionUpdateOptions options,
|
|
||||||
Customer customer,
|
|
||||||
Subscription subscription)
|
|
||||||
{
|
|
||||||
if (subscription.AutomaticTax.Enabled)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We might only need to check the automatic tax status.
|
|
||||||
if (!customer.HasTaxLocationVerified() && string.IsNullOrWhiteSpace(customer.Address?.Country))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.DefaultTaxRates = [];
|
|
||||||
options.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,6 +5,6 @@ namespace Bit.Core.Billing.Services;
|
|||||||
public interface IAutomaticTaxStrategy
|
public interface IAutomaticTaxStrategy
|
||||||
{
|
{
|
||||||
Task<SubscriptionUpdateOptions> GetUpdateOptionsAsync(Subscription subscription);
|
Task<SubscriptionUpdateOptions> GetUpdateOptionsAsync(Subscription subscription);
|
||||||
Task SetCreateOptionsAsync(SubscriptionCreateOptions options, Customer customer = null);
|
Task SetCreateOptionsAsync(SubscriptionCreateOptions options, Customer customer);
|
||||||
Task SetUpdateOptionsAsync(SubscriptionUpdateOptions options, Subscription subscription);
|
Task SetUpdateOptionsAsync(SubscriptionUpdateOptions options, Subscription subscription);
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
using Stripe;
|
using Bit.Core.Billing.Constants;
|
||||||
|
using Stripe;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Services.Implementations.AutomaticTax;
|
namespace Bit.Core.Billing.Services.Implementations.AutomaticTax;
|
||||||
|
|
||||||
public class IndividualAutomaticTaxStrategy : IIndividualAutomaticTaxStrategy
|
public class IndividualAutomaticTaxStrategy : IIndividualAutomaticTaxStrategy
|
||||||
{
|
{
|
||||||
public Task SetCreateOptionsAsync(SubscriptionCreateOptions options, Customer customer = null)
|
public Task SetCreateOptionsAsync(SubscriptionCreateOptions options, Customer customer)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(options);
|
ArgumentNullException.ThrowIfNull(options);
|
||||||
options.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
|
ArgumentNullException.ThrowIfNull(customer);
|
||||||
|
|
||||||
|
options.AutomaticTax = new SubscriptionAutomaticTaxOptions
|
||||||
|
{
|
||||||
|
Enabled = ShouldEnable(customer)
|
||||||
|
};
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,18 +23,23 @@ public class IndividualAutomaticTaxStrategy : IIndividualAutomaticTaxStrategy
|
|||||||
|
|
||||||
ArgumentNullException.ThrowIfNull(options);
|
ArgumentNullException.ThrowIfNull(options);
|
||||||
|
|
||||||
if (subscription.AutomaticTax.Enabled)
|
if (subscription.AutomaticTax.Enabled == ShouldEnable(subscription.Customer))
|
||||||
{
|
{
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
options.AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true };
|
options.AutomaticTax = new SubscriptionAutomaticTaxOptions
|
||||||
|
{
|
||||||
|
Enabled = ShouldEnable(subscription.Customer)
|
||||||
|
};
|
||||||
|
options.DefaultTaxRates = [];
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<SubscriptionUpdateOptions> GetUpdateOptionsAsync(Subscription subscription)
|
public Task<SubscriptionUpdateOptions> GetUpdateOptionsAsync(Subscription subscription)
|
||||||
{
|
{
|
||||||
if (subscription.AutomaticTax.Enabled)
|
if (subscription.AutomaticTax.Enabled == ShouldEnable(subscription.Customer))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -36,10 +48,16 @@ public class IndividualAutomaticTaxStrategy : IIndividualAutomaticTaxStrategy
|
|||||||
{
|
{
|
||||||
AutomaticTax = new SubscriptionAutomaticTaxOptions
|
AutomaticTax = new SubscriptionAutomaticTaxOptions
|
||||||
{
|
{
|
||||||
Enabled = true
|
Enabled = ShouldEnable(subscription.Customer),
|
||||||
}
|
},
|
||||||
|
DefaultTaxRates = []
|
||||||
};
|
};
|
||||||
|
|
||||||
return Task.FromResult(options);
|
return Task.FromResult(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool ShouldEnable(Customer customer)
|
||||||
|
{
|
||||||
|
return customer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,15 @@ namespace Bit.Core.Billing.Services.Implementations.AutomaticTax;
|
|||||||
public class OrganizationAutomaticTaxStrategy(
|
public class OrganizationAutomaticTaxStrategy(
|
||||||
IPricingClient pricingClient) : IOrganizationAutomaticTaxStrategy
|
IPricingClient pricingClient) : IOrganizationAutomaticTaxStrategy
|
||||||
{
|
{
|
||||||
|
private readonly Lazy<Task<IEnumerable<string>>> _familyPriceIdsTask = new(async () =>
|
||||||
|
{
|
||||||
|
var plans = await Task.WhenAll(
|
||||||
|
pricingClient.GetPlanOrThrow(PlanType.FamiliesAnnually2019),
|
||||||
|
pricingClient.GetPlanOrThrow(PlanType.FamiliesAnnually));
|
||||||
|
|
||||||
|
return plans.Select(plan => plan.PasswordManager.StripePlanId);
|
||||||
|
});
|
||||||
|
|
||||||
public async Task<SubscriptionUpdateOptions> GetUpdateOptionsAsync(Subscription subscription)
|
public async Task<SubscriptionUpdateOptions> GetUpdateOptionsAsync(Subscription subscription)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(subscription);
|
ArgumentNullException.ThrowIfNull(subscription);
|
||||||
@ -23,13 +32,14 @@ public class OrganizationAutomaticTaxStrategy(
|
|||||||
AutomaticTax = new SubscriptionAutomaticTaxOptions
|
AutomaticTax = new SubscriptionAutomaticTaxOptions
|
||||||
{
|
{
|
||||||
Enabled = isEnabled.Value
|
Enabled = isEnabled.Value
|
||||||
}
|
},
|
||||||
|
DefaultTaxRates = []
|
||||||
};
|
};
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetCreateOptionsAsync(SubscriptionCreateOptions options, Customer customer = null)
|
public async Task SetCreateOptionsAsync(SubscriptionCreateOptions options, Customer customer)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(options);
|
ArgumentNullException.ThrowIfNull(options);
|
||||||
ArgumentNullException.ThrowIfNull(customer);
|
ArgumentNullException.ThrowIfNull(customer);
|
||||||
@ -59,6 +69,7 @@ public class OrganizationAutomaticTaxStrategy(
|
|||||||
{
|
{
|
||||||
Enabled = isEnabled.Value
|
Enabled = isEnabled.Value
|
||||||
};
|
};
|
||||||
|
options.DefaultTaxRates = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool?> IsEnabledAsync(Subscription subscription)
|
private async Task<bool?> IsEnabledAsync(Subscription subscription)
|
||||||
@ -75,13 +86,9 @@ public class OrganizationAutomaticTaxStrategy(
|
|||||||
|
|
||||||
private async Task<bool> IsNonTaxableNonUsBusinessUseSubscriptionAsync(Subscription subscription)
|
private async Task<bool> IsNonTaxableNonUsBusinessUseSubscriptionAsync(Subscription subscription)
|
||||||
{
|
{
|
||||||
var familyPriceIds = (await Task.WhenAll(
|
var familyPriceIds = await _familyPriceIdsTask.Value;
|
||||||
pricingClient.GetPlanOrThrow(PlanType.FamiliesAnnually2019),
|
|
||||||
pricingClient.GetPlanOrThrow(PlanType.FamiliesAnnually)))
|
|
||||||
.Select(plan => plan.PasswordManager.StripePlanId);
|
|
||||||
|
|
||||||
return subscription.Customer.Address.Country != "US" &&
|
return subscription.Customer.Address.Country != "US" &&
|
||||||
subscription.IsOrganization() &&
|
|
||||||
!subscription.Items.Select(item => item.Price.Id).Intersect(familyPriceIds).Any() &&
|
!subscription.Items.Select(item => item.Price.Id).Intersect(familyPriceIds).Any() &&
|
||||||
!subscription.Customer.TaxIds.Any();
|
!subscription.Customer.TaxIds.Any();
|
||||||
}
|
}
|
||||||
@ -99,10 +106,7 @@ public class OrganizationAutomaticTaxStrategy(
|
|||||||
|
|
||||||
private async Task<bool> IsNonTaxableNonUsBusinessUseSubscriptionAsync(SubscriptionCreateOptions options, Customer customer)
|
private async Task<bool> IsNonTaxableNonUsBusinessUseSubscriptionAsync(SubscriptionCreateOptions options, Customer customer)
|
||||||
{
|
{
|
||||||
var familyPriceIds = (await Task.WhenAll(
|
var familyPriceIds = await _familyPriceIdsTask.Value;
|
||||||
pricingClient.GetPlanOrThrow(PlanType.FamiliesAnnually2019),
|
|
||||||
pricingClient.GetPlanOrThrow(PlanType.FamiliesAnnually)))
|
|
||||||
.Select(plan => plan.PasswordManager.StripePlanId);
|
|
||||||
|
|
||||||
return customer.Address.Country != "US" &&
|
return customer.Address.Country != "US" &&
|
||||||
!options.Items.Select(item => item.Price).Intersect(familyPriceIds).Any() &&
|
!options.Items.Select(item => item.Price).Intersect(familyPriceIds).Any() &&
|
||||||
|
@ -25,7 +25,8 @@ public class PremiumUserBillingService(
|
|||||||
ISetupIntentCache setupIntentCache,
|
ISetupIntentCache setupIntentCache,
|
||||||
IStripeAdapter stripeAdapter,
|
IStripeAdapter stripeAdapter,
|
||||||
ISubscriberService subscriberService,
|
ISubscriberService subscriberService,
|
||||||
IUserRepository userRepository) : IPremiumUserBillingService
|
IUserRepository userRepository,
|
||||||
|
IIndividualAutomaticTaxStrategy individualAutomaticTaxStrategy) : IPremiumUserBillingService
|
||||||
{
|
{
|
||||||
public async Task Credit(User user, decimal amount)
|
public async Task Credit(User user, decimal amount)
|
||||||
{
|
{
|
||||||
@ -318,10 +319,6 @@ public class PremiumUserBillingService(
|
|||||||
|
|
||||||
var subscriptionCreateOptions = new SubscriptionCreateOptions
|
var subscriptionCreateOptions = new SubscriptionCreateOptions
|
||||||
{
|
{
|
||||||
AutomaticTax = new SubscriptionAutomaticTaxOptions
|
|
||||||
{
|
|
||||||
Enabled = customer.Tax?.AutomaticTax == StripeConstants.AutomaticTaxStatus.Supported,
|
|
||||||
},
|
|
||||||
CollectionMethod = StripeConstants.CollectionMethod.ChargeAutomatically,
|
CollectionMethod = StripeConstants.CollectionMethod.ChargeAutomatically,
|
||||||
Customer = customer.Id,
|
Customer = customer.Id,
|
||||||
Items = subscriptionItemOptionsList,
|
Items = subscriptionItemOptionsList,
|
||||||
@ -335,6 +332,8 @@ public class PremiumUserBillingService(
|
|||||||
OffSession = true
|
OffSession = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await individualAutomaticTaxStrategy.SetCreateOptionsAsync(subscriptionCreateOptions, customer);
|
||||||
|
|
||||||
var subscription = await stripeAdapter.SubscriptionCreateAsync(subscriptionCreateOptions);
|
var subscription = await stripeAdapter.SubscriptionCreateAsync(subscriptionCreateOptions);
|
||||||
|
|
||||||
if (usingPayPal)
|
if (usingPayPal)
|
||||||
|
@ -36,6 +36,8 @@ public class StripePaymentService : IPaymentService
|
|||||||
private readonly ITaxService _taxService;
|
private readonly ITaxService _taxService;
|
||||||
private readonly ISubscriberService _subscriberService;
|
private readonly ISubscriberService _subscriberService;
|
||||||
private readonly IPricingClient _pricingClient;
|
private readonly IPricingClient _pricingClient;
|
||||||
|
private readonly IIndividualAutomaticTaxStrategy _individualAutomaticTaxStrategy;
|
||||||
|
private readonly IOrganizationAutomaticTaxStrategy _organizationAutomaticTaxStrategy;
|
||||||
|
|
||||||
public StripePaymentService(
|
public StripePaymentService(
|
||||||
ITransactionRepository transactionRepository,
|
ITransactionRepository transactionRepository,
|
||||||
@ -46,7 +48,9 @@ public class StripePaymentService : IPaymentService
|
|||||||
IFeatureService featureService,
|
IFeatureService featureService,
|
||||||
ITaxService taxService,
|
ITaxService taxService,
|
||||||
ISubscriberService subscriberService,
|
ISubscriberService subscriberService,
|
||||||
IPricingClient pricingClient)
|
IPricingClient pricingClient,
|
||||||
|
IIndividualAutomaticTaxStrategy individualAutomaticTaxStrategy,
|
||||||
|
IOrganizationAutomaticTaxStrategy organizationAutomaticTaxStrategy)
|
||||||
{
|
{
|
||||||
_transactionRepository = transactionRepository;
|
_transactionRepository = transactionRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@ -57,6 +61,8 @@ public class StripePaymentService : IPaymentService
|
|||||||
_taxService = taxService;
|
_taxService = taxService;
|
||||||
_subscriberService = subscriberService;
|
_subscriberService = subscriberService;
|
||||||
_pricingClient = pricingClient;
|
_pricingClient = pricingClient;
|
||||||
|
_individualAutomaticTaxStrategy = individualAutomaticTaxStrategy;
|
||||||
|
_organizationAutomaticTaxStrategy = organizationAutomaticTaxStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ChangeOrganizationSponsorship(
|
private async Task ChangeOrganizationSponsorship(
|
||||||
@ -124,7 +130,7 @@ public class StripePaymentService : IPaymentService
|
|||||||
new SubscriptionPendingInvoiceItemIntervalOptions { Interval = "month" };
|
new SubscriptionPendingInvoiceItemIntervalOptions { Interval = "month" };
|
||||||
}
|
}
|
||||||
|
|
||||||
subUpdateOptions.EnableAutomaticTax(sub.Customer, sub);
|
await _organizationAutomaticTaxStrategy.SetUpdateOptionsAsync(subUpdateOptions, sub);
|
||||||
|
|
||||||
if (!subscriptionUpdate.UpdateNeeded(sub))
|
if (!subscriptionUpdate.UpdateNeeded(sub))
|
||||||
{
|
{
|
||||||
@ -812,20 +818,20 @@ public class StripePaymentService : IPaymentService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(subscriber.GatewaySubscriptionId) &&
|
if (!string.IsNullOrEmpty(subscriber.GatewaySubscriptionId) &&
|
||||||
customer.Subscriptions.Any(sub =>
|
customer.Subscriptions.Any(sub => sub.Id == subscriber.GatewaySubscriptionId))
|
||||||
sub.Id == subscriber.GatewaySubscriptionId &&
|
|
||||||
!sub.AutomaticTax.Enabled) &&
|
|
||||||
customer.HasTaxLocationVerified())
|
|
||||||
{
|
{
|
||||||
var subscriptionUpdateOptions = new SubscriptionUpdateOptions
|
var subscription = await _stripeAdapter.SubscriptionGetAsync(subscriber.GatewaySubscriptionId);
|
||||||
{
|
|
||||||
AutomaticTax = new SubscriptionAutomaticTaxOptions { Enabled = true },
|
|
||||||
DefaultTaxRates = []
|
|
||||||
};
|
|
||||||
|
|
||||||
_ = await _stripeAdapter.SubscriptionUpdateAsync(
|
var subscriptionUpdateOptions = subscriber is User
|
||||||
subscriber.GatewaySubscriptionId,
|
? await _individualAutomaticTaxStrategy.GetUpdateOptionsAsync(subscription)
|
||||||
subscriptionUpdateOptions);
|
: await _organizationAutomaticTaxStrategy.GetUpdateOptionsAsync(subscription);
|
||||||
|
|
||||||
|
if (subscriptionUpdateOptions != null)
|
||||||
|
{
|
||||||
|
_ = await _stripeAdapter.SubscriptionUpdateAsync(
|
||||||
|
subscriber.GatewaySubscriptionId,
|
||||||
|
subscriptionUpdateOptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
Loading…
x
Reference in New Issue
Block a user