1
0
mirror of https://github.com/bitwarden/server synced 2025-12-22 11:13:27 +00:00

[AC-1938] Update provider payment method (#4140)

* Refactored GET provider subscription

Refactoring this endpoint and its associated tests in preparation for the addition of more endpoints that share similar patterns

* Replaced StripePaymentService call in AccountsController, OrganizationsController

This was made in error during a previous PR. Since this is not related to Consolidated Billing, we want to try not to include it in these changes.

* Removing GetPaymentInformation call from ProviderBillingService

This method is a good call for the SubscriberService as we'll want to extend the functionality to all subscriber types

* Refactored GetTaxInformation to use Billing owned DTO

* Add UpdateTaxInformation to SubscriberService

* Added GetTaxInformation and UpdateTaxInformation endpoints to ProviderBillingController

* Added controller to manage creation of Stripe SetupIntents

With the deprecation of the Sources API, we need to move the bank account creation process to using SetupIntents. This controller brings both the creation of "card" and "us_bank_account" SetupIntents
under billing management.

* Added UpdatePaymentMethod method to SubscriberService

This method utilizes the SetupIntents created by the StripeController from the previous commit when a customer adds a card or us_bank_account payment method (Stripe). We need to cache the most recent SetupIntent for the subscriber so that we know which PaymentMethod is their most recent even when it hasn't been confirmed yet.

* Refactored GetPaymentMethod to use billing owned DTO and check setup intents

* Added GetPaymentMethod and UpdatePaymentMethod endpoints to ProviderBillingController

* Re-added GetPaymentInformation endpoint to consolidate API calls on the payment method page

* Added VerifyBankAccount endpoint to ProviderBillingController in order to finalize bank account payment methods

* Updated BitPayInvoiceRequestModel to support providers

* run dotnet format

* Conner's feedback

* Run dotnet format'
This commit is contained in:
Alex Morask
2024-06-03 11:00:52 -04:00
committed by GitHub
parent b42ebe6f1b
commit 2b43cde99b
34 changed files with 2478 additions and 540 deletions

View File

@@ -1,6 +1,6 @@
using Bit.Core.Billing.Models;
using Bit.Core.Entities;
using Bit.Core.Models.Business;
using Bit.Core.Enums;
using Stripe;
namespace Bit.Core.Billing.Services;
@@ -46,6 +46,24 @@ public interface ISubscriberService
ISubscriber subscriber,
CustomerGetOptions customerGetOptions = null);
/// <summary>
/// Retrieves the account credit, a masked representation of the default payment method and the tax information for the
/// provided <paramref name="subscriber"/>. This is essentially a consolidated invocation of the <see cref="GetPaymentMethod"/>
/// and <see cref="GetTaxInformation"/> methods with a response that includes the customer's <see cref="Stripe.Customer.Balance"/> as account credit in order to cut down on Stripe API calls.
/// </summary>
/// <param name="subscriber">The subscriber to retrieve payment information for.</param>
/// <returns>A <see cref="PaymentInformationDTO"/> containing the subscriber's account credit, masked payment method and tax information.</returns>
Task<PaymentInformationDTO> GetPaymentInformation(
ISubscriber subscriber);
/// <summary>
/// Retrieves a masked representation of the subscriber's payment method for presentation to a client.
/// </summary>
/// <param name="subscriber">The subscriber to retrieve the masked payment method for.</param>
/// <returns>A <see cref="MaskedPaymentMethodDTO"/> containing a non-identifiable description of the subscriber's payment method.</returns>
Task<MaskedPaymentMethodDTO> GetPaymentMethod(
ISubscriber subscriber);
/// <summary>
/// Retrieves a Stripe <see cref="Subscription"/> using the <paramref name="subscriber"/>'s <see cref="ISubscriber.GatewaySubscriptionId"/> property.
/// </summary>
@@ -71,6 +89,16 @@ public interface ISubscriberService
ISubscriber subscriber,
SubscriptionGetOptions subscriptionGetOptions = null);
/// <summary>
/// Retrieves the <see cref="subscriber"/>'s tax information using their Stripe <see cref="Stripe.Customer"/>'s <see cref="Stripe.Customer.Address"/>.
/// </summary>
/// <param name="subscriber">The subscriber to retrieve the tax information for.</param>
/// <returns>A <see cref="TaxInformationDTO"/> representing the <paramref name="subscriber"/>'s tax information.</returns>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="subscriber"/> is <see langword="null"/>.</exception>
/// <remarks>This method opts for returning <see langword="null"/> rather than throwing exceptions, making it ideal for surfacing data from API endpoints.</remarks>
Task<TaxInformationDTO> GetTaxInformation(
ISubscriber subscriber);
/// <summary>
/// Attempts to remove a subscriber's saved payment method. If the Stripe <see cref="Stripe.Customer"/> representing the
/// <paramref name="subscriber"/> contains a valid <b>"btCustomerId"</b> key in its <see cref="Stripe.Customer.Metadata"/> property,
@@ -81,20 +109,34 @@ public interface ISubscriberService
Task RemovePaymentMethod(ISubscriber subscriber);
/// <summary>
/// Retrieves a Stripe <see cref="TaxInfo"/> using the <paramref name="subscriber"/>'s <see cref="ISubscriber.GatewayCustomerId"/> property.
/// Updates the payment method for the provided <paramref name="subscriber"/> using the <paramref name="tokenizedPaymentMethod"/>.
/// The following payment method types are supported: [<see cref="PaymentMethodType.Card"/>, <see cref="PaymentMethodType.BankAccount"/>, <see cref="PaymentMethodType.PayPal"/>].
/// For each type, updating the payment method will attempt to establish a new payment method using the token in the <see cref="TokenizedPaymentMethodDTO"/>. Then, it will
/// remove the exising payment method(s) linked to the subscriber's customer.
/// </summary>
/// <param name="subscriber">The subscriber to retrieve the Stripe customer for.</param>
/// <returns>A Stripe <see cref="TaxInfo"/>.</returns>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="subscriber"/> is <see langword="null"/>.</exception>
/// <remarks>This method opts for returning <see langword="null"/> rather than throwing exceptions, making it ideal for surfacing data from API endpoints.</remarks>
Task<TaxInfo> GetTaxInformationAsync(ISubscriber subscriber);
/// <param name="subscriber">The subscriber to update the payment method for.</param>
/// <param name="tokenizedPaymentMethod">A DTO representing a tokenized payment method.</param>
Task UpdatePaymentMethod(
ISubscriber subscriber,
TokenizedPaymentMethodDTO tokenizedPaymentMethod);
/// <summary>
/// Retrieves a Stripe <see cref="BillingInfo.BillingSource"/> using the <paramref name="subscriber"/>'s <see cref="ISubscriber.GatewayCustomerId"/> property.
/// Updates the tax information for the provided <paramref name="subscriber"/>.
/// </summary>
/// <param name="subscriber">The subscriber to retrieve the Stripe customer for.</param>
/// <returns>A Stripe <see cref="BillingInfo.BillingSource"/>.</returns>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="subscriber"/> is <see langword="null"/>.</exception>
/// <remarks>This method opts for returning <see langword="null"/> rather than throwing exceptions, making it ideal for surfacing data from API endpoints.</remarks>
Task<BillingInfo.BillingSource> GetPaymentMethodAsync(ISubscriber subscriber);
/// <param name="subscriber">The <paramref name="subscriber"/> to update the tax information for.</param>
/// <param name="taxInformation">A <see cref="TaxInformationDTO"/> representing the <paramref name="subscriber"/>'s updated tax information.</param>
Task UpdateTaxInformation(
ISubscriber subscriber,
TaxInformationDTO taxInformation);
/// <summary>
/// Verifies the subscriber's pending bank account using the provided <paramref name="microdeposits"/>.
/// </summary>
/// <param name="subscriber">The subscriber to verify the bank account for.</param>
/// <param name="microdeposits">Deposits made to the subscriber's bank account in order to ensure they have access to it.
/// <a href="https://docs.stripe.com/payments/ach-debit/set-up-payment">Learn more.</a></param>
/// <returns></returns>
Task VerifyBankAccount(
ISubscriber subscriber,
(long, long) microdeposits);
}