1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[AC-2959] ACH Direct Debit POC (#10746)

* (No Logic) Fix typo in billing-api-service.abstraction file name

* (Cleanup) Remove payment method components and API methods from provider portal

Product team decided not to have a payment method page in the provider portal for consolidated billing. This just removes all the unused components and API methods.

* Add organization endpoints to support new payment method behavior

* Add payment-v2.component

This component existed in the libs folder because we used it for the provider portal, but since we've removed payment functionality from the provider portal, I moved it into web in this commit.

* (No Logic) Move existing payment.component into new payment component folder

* Add verify-bank-account.component

This component existed in the libs folder because we used it for the provider portal, but since we've removed payment functionality from the provider portal, I moved it into web in this commit.

* Add adjust-payment-dialog-v2.component

* (No Logic) Move existing adjust-payment-dialog.component into new adjust-payment-dialog component folder

* Add organization-payment-method.component

* Add feature flag: AC-2476-deprecate-stripe-sources-api

* Pivot organization payment method route on new feature flag

* Fix broken test
This commit is contained in:
Alex Morask
2024-08-28 10:48:22 -04:00
committed by GitHub
parent b0ffac04af
commit a58642e370
47 changed files with 623 additions and 481 deletions

View File

@@ -2,5 +2,3 @@ export * from "./add-account-credit-dialog/add-account-credit-dialog.component";
export * from "./invoices/invoices.component";
export * from "./invoices/no-invoices.component";
export * from "./manage-tax-information/manage-tax-information.component";
export * from "./select-payment-method/select-payment-method.component";
export * from "./verify-bank-account/verify-bank-account.component";

View File

@@ -1,151 +0,0 @@
<form [formGroup]="formGroup" [bitSubmit]="submit">
<div class="tw-mb-4 tw-text-lg">
<bit-radio-group formControlName="paymentMethod">
<bit-radio-button id="card-payment-method" [value]="PaymentMethodType.Card">
<bit-label>
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i>
{{ "creditCard" | i18n }}
</bit-label>
</bit-radio-button>
<bit-radio-button
id="bank-payment-method"
[value]="PaymentMethodType.BankAccount"
*ngIf="showBankAccount"
>
<bit-label>
<i class="bwi bwi-fw bwi-bank" aria-hidden="true"></i>
{{ "bankAccount" | i18n }}
</bit-label>
</bit-radio-button>
<bit-radio-button
id="paypal-payment-method"
[value]="PaymentMethodType.PayPal"
*ngIf="showPayPal"
>
<bit-label>
<i class="bwi bwi-fw bwi-paypal" aria-hidden="true"></i>
{{ "payPal" | i18n }}
</bit-label>
</bit-radio-button>
<bit-radio-button
id="credit-payment-method"
[value]="PaymentMethodType.Credit"
*ngIf="showAccountCredit"
>
<bit-label>
<i class="bwi bwi-fw bwi-dollar" aria-hidden="true"></i>
{{ "accountCredit" | i18n }}
</bit-label>
</bit-radio-button>
</bit-radio-group>
</div>
<!-- Card -->
<ng-container *ngIf="usingCard">
<div class="tw-grid tw-grid-cols-2 tw-gap-4 tw-mb-4">
<div class="tw-col-span-1">
<label for="stripe-card-number">{{ "number" | i18n }}</label>
<div id="stripe-card-number" class="form-control stripe-form-control"></div>
</div>
<div class="tw-col-span-1 tw-flex tw-items-end">
<img
src="../../images/cards.png"
alt="Visa, MasterCard, Discover, AmEx, JCB, Diners Club, UnionPay"
class="tw-max-w-full"
/>
</div>
<div class="tw-col-span-1">
<label for="stripe-card-expiry">{{ "expiration" | i18n }}</label>
<div id="stripe-card-expiry" class="form-control stripe-form-control"></div>
</div>
<div class="tw-col-span-1">
<div class="tw-flex">
<label for="stripe-card-cvc">
{{ "securityCode" | i18n }}
</label>
<a
href="https://www.cvvnumber.com/cvv.html"
tabindex="-1"
target="_blank"
rel="noreferrer"
class="ml-auto"
appA11yTitle="{{ 'learnMore' | i18n }}"
>
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
</a>
</div>
<div id="stripe-card-cvc" class="form-control stripe-form-control"></div>
</div>
</div>
</ng-container>
<!-- Bank Account -->
<ng-container *ngIf="showBankAccount && usingBankAccount">
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
{{ "verifyBankAccountInitialDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}
</app-callout>
<div class="tw-grid tw-grid-cols-2 tw-gap-4" formGroupName="bankInformation">
<bit-form-field class="tw-col-span-1" disableMargin>
<bit-label>{{ "routingNumber" | i18n }}</bit-label>
<input
bitInput
id="routingNumber"
type="text"
formControlName="routingNumber"
required
appInputVerbatim
/>
</bit-form-field>
<bit-form-field class="tw-col-span-1" disableMargin>
<bit-label>{{ "accountNumber" | i18n }}</bit-label>
<input
bitInput
id="accountNumber"
type="text"
formControlName="accountNumber"
required
appInputVerbatim
/>
</bit-form-field>
<bit-form-field class="tw-col-span-1" disableMargin>
<bit-label>{{ "accountHolderName" | i18n }}</bit-label>
<input
id="accountHolderName"
bitInput
type="text"
formControlName="accountHolderName"
required
appInputVerbatim
/>
</bit-form-field>
<bit-form-field class="tw-col-span-1" disableMargin>
<bit-label>{{ "bankAccountType" | i18n }}</bit-label>
<bit-select id="accountHolderType" formControlName="accountHolderType" required>
<bit-option [value]="''" label="-- {{ 'select' | i18n }} --"></bit-option>
<bit-option
[value]="'company'"
label="{{ 'bankAccountTypeCompany' | i18n }}"
></bit-option>
<bit-option
[value]="'individual'"
label="{{ 'bankAccountTypeIndividual' | i18n }}"
></bit-option>
</bit-select>
</bit-form-field>
</div>
</ng-container>
<!-- PayPal -->
<ng-container *ngIf="showPayPal && usingPayPal">
<div class="tw-mb-3">
<div id="braintree-container" class="tw-mb-1 tw-content-center"></div>
<small class="tw-text-muted">{{ "paypalClickSubmit" | i18n }}</small>
</div>
</ng-container>
<!-- Account Credit -->
<ng-container *ngIf="showAccountCredit && usingAccountCredit">
<app-callout type="info">
{{ "makeSureEnoughCredit" | i18n }}
</app-callout>
</ng-container>
<button *ngIf="!!onSubmit" bitButton bitFormButton buttonType="primary" type="submit">
{{ "submit" | i18n }}
</button>
</form>

View File

@@ -1,159 +0,0 @@
import { Component, Input, OnDestroy, OnInit } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
import {
BillingApiServiceAbstraction,
BraintreeServiceAbstraction,
StripeServiceAbstraction,
} from "@bitwarden/common/billing/abstractions";
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
import { TokenizedPaymentMethod } from "@bitwarden/common/billing/models/domain";
@Component({
selector: "app-select-payment-method",
templateUrl: "./select-payment-method.component.html",
})
export class SelectPaymentMethodComponent implements OnInit, OnDestroy {
@Input() protected showAccountCredit: boolean = true;
@Input() protected showBankAccount: boolean = true;
@Input() protected showPayPal: boolean = true;
@Input() private startWith: PaymentMethodType = PaymentMethodType.Card;
@Input() protected onSubmit: (tokenizedPaymentMethod: TokenizedPaymentMethod) => Promise<void>;
private destroy$ = new Subject<void>();
protected formGroup = this.formBuilder.group({
paymentMethod: [this.startWith],
bankInformation: this.formBuilder.group({
routingNumber: ["", [Validators.required]],
accountNumber: ["", [Validators.required]],
accountHolderName: ["", [Validators.required]],
accountHolderType: ["", [Validators.required]],
}),
});
protected PaymentMethodType = PaymentMethodType;
constructor(
private billingApiService: BillingApiServiceAbstraction,
private braintreeService: BraintreeServiceAbstraction,
private formBuilder: FormBuilder,
private stripeService: StripeServiceAbstraction,
) {}
async tokenizePaymentMethod(): Promise<TokenizedPaymentMethod> {
const type = this.selected;
if (this.usingStripe) {
const clientSecret = await this.billingApiService.createSetupIntent(type);
if (this.usingBankAccount) {
const token = await this.stripeService.setupBankAccountPaymentMethod(clientSecret, {
accountHolderName: this.formGroup.value.bankInformation.accountHolderName,
routingNumber: this.formGroup.value.bankInformation.routingNumber,
accountNumber: this.formGroup.value.bankInformation.accountNumber,
accountHolderType: this.formGroup.value.bankInformation.accountHolderType,
});
return {
type,
token,
};
}
if (this.usingCard) {
const token = await this.stripeService.setupCardPaymentMethod(clientSecret);
return {
type,
token,
};
}
}
if (this.usingPayPal) {
const token = await this.braintreeService.requestPaymentMethod();
return {
type,
token,
};
}
return null;
}
submit = async () => {
const tokenizedPaymentMethod = await this.tokenizePaymentMethod();
await this.onSubmit(tokenizedPaymentMethod);
};
ngOnInit(): void {
this.stripeService.loadStripe(
{
cardNumber: "#stripe-card-number",
cardExpiry: "#stripe-card-expiry",
cardCvc: "#stripe-card-cvc",
},
this.startWith === PaymentMethodType.Card,
);
if (this.showPayPal) {
this.braintreeService.loadBraintree(
"#braintree-container",
this.startWith === PaymentMethodType.PayPal,
);
}
this.formGroup
.get("paymentMethod")
.valueChanges.pipe(takeUntil(this.destroy$))
.subscribe((type) => {
this.onPaymentMethodChange(type);
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
this.stripeService.unloadStripe();
if (this.showPayPal) {
this.braintreeService.unloadBraintree();
}
}
private onPaymentMethodChange(type: PaymentMethodType): void {
switch (type) {
case PaymentMethodType.Card: {
this.stripeService.mountElements();
break;
}
case PaymentMethodType.PayPal: {
this.braintreeService.createDropin();
break;
}
}
}
private get selected(): PaymentMethodType {
return this.formGroup.value.paymentMethod;
}
protected get usingAccountCredit(): boolean {
return this.selected === PaymentMethodType.Credit;
}
protected get usingBankAccount(): boolean {
return this.selected === PaymentMethodType.BankAccount;
}
protected get usingCard(): boolean {
return this.selected === PaymentMethodType.Card;
}
protected get usingPayPal(): boolean {
return this.selected === PaymentMethodType.PayPal;
}
private get usingStripe(): boolean {
return this.usingBankAccount || this.usingCard;
}
}

View File

@@ -1,18 +0,0 @@
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
<p>{{ "verifyBankAccountDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}</p>
<form [formGroup]="formGroup" [bitSubmit]="submit">
<bit-form-field class="tw-mr-2 tw-w-40">
<bit-label>{{ "amountX" | i18n: "1" }}</bit-label>
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount1" />
<span bitPrefix>$0.</span>
</bit-form-field>
<bit-form-field class="tw-mr-2 tw-w-40">
<bit-label>{{ "amountX" | i18n: "2" }}</bit-label>
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount2" />
<span bitPrefix>$0.</span>
</bit-form-field>
<button type="submit" bitButton bitFormButton buttonType="primary">
{{ "submit" | i18n }}
</button>
</form>
</app-callout>

View File

@@ -1,33 +0,0 @@
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { FormBuilder, FormControl, Validators } from "@angular/forms";
@Component({
selector: "app-verify-bank-account",
templateUrl: "./verify-bank-account.component.html",
})
export class VerifyBankAccountComponent {
@Input() onSubmit?: (amount1: number, amount2: number) => Promise<void>;
@Output() verificationSubmitted = new EventEmitter();
protected formGroup = this.formBuilder.group({
amount1: new FormControl<number>(null, [
Validators.required,
Validators.min(0),
Validators.max(99),
]),
amount2: new FormControl<number>(null, [
Validators.required,
Validators.min(0),
Validators.max(99),
]),
});
constructor(private formBuilder: FormBuilder) {}
submit = async () => {
if (this.onSubmit) {
await this.onSubmit(this.formGroup.value.amount1, this.formGroup.value.amount2);
}
this.verificationSubmitted.emit();
};
}

View File

@@ -7,8 +7,6 @@ import {
InvoicesComponent,
NoInvoicesComponent,
ManageTaxInformationComponent,
SelectPaymentMethodComponent,
VerifyBankAccountComponent,
} from "@bitwarden/angular/billing/components";
import {
AsyncActionsModule,
@@ -116,8 +114,6 @@ import { IconComponent } from "./vault/components/icon.component";
InvoicesComponent,
NoInvoicesComponent,
ManageTaxInformationComponent,
SelectPaymentMethodComponent,
VerifyBankAccountComponent,
TwoFactorIconComponent,
],
exports: [
@@ -153,8 +149,6 @@ import { IconComponent } from "./vault/components/icon.component";
InvoicesComponent,
NoInvoicesComponent,
ManageTaxInformationComponent,
SelectPaymentMethodComponent,
VerifyBankAccountComponent,
TwoFactorIconComponent,
],
providers: [

View File

@@ -1,10 +1,10 @@
import { ProviderOrganizationOrganizationDetailsResponse } from "@bitwarden/common/admin-console/models/response/provider/provider-organization.response";
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
import { ExpandedTaxInfoUpdateRequest } from "@bitwarden/common/billing/models/request/expanded-tax-info-update.request";
import { TokenizedPaymentMethodRequest } from "@bitwarden/common/billing/models/request/tokenized-payment-method.request";
import { UpdatePaymentMethodRequest } from "@bitwarden/common/billing/models/request/update-payment-method.request";
import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request";
import { InvoicesResponse } from "@bitwarden/common/billing/models/response/invoices.response";
import { PaymentInformationResponse } from "@bitwarden/common/billing/models/response/payment-information.response";
import { PaymentMethodResponse } from "@bitwarden/common/billing/models/response/payment-method.response";
import { SubscriptionCancellationRequest } from "../../billing/models/request/subscription-cancellation.request";
import { OrganizationBillingMetadataResponse } from "../../billing/models/response/organization-billing-metadata.response";
@@ -33,6 +33,8 @@ export abstract class BillingApiServiceAbstraction {
organizationId: string,
) => Promise<OrganizationBillingMetadataResponse>;
getOrganizationPaymentMethod: (organizationId: string) => Promise<PaymentMethodResponse>;
getPlans: () => Promise<ListResponse<PlanResponse>>;
getProviderClientInvoiceReport: (providerId: string, invoiceId: string) => Promise<string>;
@@ -43,37 +45,31 @@ export abstract class BillingApiServiceAbstraction {
getProviderInvoices: (providerId: string) => Promise<InvoicesResponse>;
/**
* @deprecated This endpoint is currently deactivated.
*/
getProviderPaymentInformation: (providerId: string) => Promise<PaymentInformationResponse>;
getProviderSubscription: (providerId: string) => Promise<ProviderSubscriptionResponse>;
updateOrganizationPaymentMethod: (
organizationId: string,
request: UpdatePaymentMethodRequest,
) => Promise<void>;
updateOrganizationTaxInformation: (
organizationId: string,
request: ExpandedTaxInfoUpdateRequest,
) => Promise<void>;
updateProviderClientOrganization: (
providerId: string,
organizationId: string,
request: UpdateClientOrganizationRequest,
) => Promise<any>;
/**
* @deprecated This endpoint is currently deactivated.
*/
updateProviderPaymentMethod: (
providerId: string,
request: TokenizedPaymentMethodRequest,
) => Promise<void>;
updateProviderTaxInformation: (
providerId: string,
request: ExpandedTaxInfoUpdateRequest,
) => Promise<void>;
/**
* @deprecated This endpoint is currently deactivated.
*/
verifyProviderBankAccount: (
providerId: string,
verifyOrganizationBankAccount: (
organizationId: string,
request: VerifyBankAccountRequest,
) => Promise<void>;
}

View File

@@ -1,5 +1,5 @@
export * from "./account/billing-account-profile-state.service";
export * from "./billilng-api.service.abstraction";
export * from "./billing-api.service.abstraction";
export * from "./organization-billing.service";
export * from "./payment-processors/braintree.service.abstraction";
export * from "./payment-processors/stripe.service.abstraction";

View File

@@ -1,4 +1,2 @@
export * from "./bank-account";
export * from "./masked-payment-method";
export * from "./tax-information";
export * from "./tokenized-payment-method";

View File

@@ -1,17 +0,0 @@
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
import { MaskedPaymentMethodResponse } from "@bitwarden/common/billing/models/response/masked-payment-method.response";
export class MaskedPaymentMethod {
type: PaymentMethodType;
description: string;
needsVerification: boolean;
static from(response: MaskedPaymentMethodResponse | undefined) {
if (response === undefined) {
return null;
}
return {
...response,
};
}
}

View File

@@ -1,14 +0,0 @@
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
import { TokenizedPaymentMethod } from "@bitwarden/common/billing/models/domain";
export class TokenizedPaymentMethodRequest {
type: PaymentMethodType;
token: string;
static From(tokenizedPaymentMethod: TokenizedPaymentMethod): TokenizedPaymentMethodRequest {
const request = new TokenizedPaymentMethodRequest();
request.type = tokenizedPaymentMethod.type;
request.token = tokenizedPaymentMethod.token;
return request;
}
}

View File

@@ -1,6 +1,6 @@
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
export type TokenizedPaymentMethod = {
export class TokenizedPaymentSourceRequest {
type: PaymentMethodType;
token: string;
};
}

View File

@@ -0,0 +1,7 @@
import { ExpandedTaxInfoUpdateRequest } from "@bitwarden/common/billing/models/request/expanded-tax-info-update.request";
import { TokenizedPaymentSourceRequest } from "@bitwarden/common/billing/models/request/tokenized-payment-source.request";
export class UpdatePaymentMethodRequest {
paymentSource: TokenizedPaymentSourceRequest;
taxInformation: ExpandedTaxInfoUpdateRequest;
}

View File

@@ -1,13 +0,0 @@
import { BaseResponse } from "../../../models/response/base.response";
export class OrganizationRisksSubscriptionFailureResponse extends BaseResponse {
organizationId: string;
risksSubscriptionFailure: boolean;
constructor(response: any) {
super(response);
this.organizationId = this.getResponseProperty("OrganizationId");
this.risksSubscriptionFailure = this.getResponseProperty("RisksSubscriptionFailure");
}
}

View File

@@ -1,22 +1,25 @@
import { BaseResponse } from "../../../models/response/base.response";
import { MaskedPaymentMethodResponse } from "./masked-payment-method.response";
import { PaymentSourceResponse } from "./payment-source.response";
import { TaxInfoResponse } from "./tax-info.response";
export class PaymentInformationResponse extends BaseResponse {
export class PaymentMethodResponse extends BaseResponse {
accountCredit: number;
paymentMethod?: MaskedPaymentMethodResponse;
paymentSource?: PaymentSourceResponse;
subscriptionStatus?: string;
taxInformation?: TaxInfoResponse;
constructor(response: any) {
super(response);
this.accountCredit = this.getResponseProperty("AccountCredit");
const paymentMethod = this.getResponseProperty("PaymentMethod");
if (paymentMethod) {
this.paymentMethod = new MaskedPaymentMethodResponse(paymentMethod);
const paymentSource = this.getResponseProperty("PaymentSource");
if (paymentSource) {
this.paymentSource = new PaymentSourceResponse(paymentSource);
}
this.subscriptionStatus = this.getResponseProperty("SubscriptionStatus");
const taxInformation = this.getResponseProperty("TaxInformation");
if (taxInformation) {
this.taxInformation = new TaxInfoResponse(taxInformation);

View File

@@ -1,7 +1,7 @@
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
import { BaseResponse } from "@bitwarden/common/models/response/base.response";
export class MaskedPaymentMethodResponse extends BaseResponse {
export class PaymentSourceResponse extends BaseResponse {
type: PaymentMethodType;
description: string;
needsVerification: boolean;

View File

@@ -1,5 +1,8 @@
import { ProviderOrganizationOrganizationDetailsResponse } from "@bitwarden/common/admin-console/models/response/provider/provider-organization.response";
import { UpdatePaymentMethodRequest } from "@bitwarden/common/billing/models/request/update-payment-method.request";
import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request";
import { InvoicesResponse } from "@bitwarden/common/billing/models/response/invoices.response";
import { PaymentMethodResponse } from "@bitwarden/common/billing/models/response/payment-method.response";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { ToastService } from "@bitwarden/components";
@@ -9,10 +12,7 @@ import { BillingApiServiceAbstraction } from "../../billing/abstractions";
import { PaymentMethodType } from "../../billing/enums";
import { ExpandedTaxInfoUpdateRequest } from "../../billing/models/request/expanded-tax-info-update.request";
import { SubscriptionCancellationRequest } from "../../billing/models/request/subscription-cancellation.request";
import { TokenizedPaymentMethodRequest } from "../../billing/models/request/tokenized-payment-method.request";
import { VerifyBankAccountRequest } from "../../billing/models/request/verify-bank-account.request";
import { OrganizationBillingMetadataResponse } from "../../billing/models/response/organization-billing-metadata.response";
import { PaymentInformationResponse } from "../../billing/models/response/payment-information.response";
import { PlanResponse } from "../../billing/models/response/plan.response";
import { ListResponse } from "../../models/response/list.response";
import { CreateClientOrganizationRequest } from "../models/request/create-client-organization.request";
@@ -85,6 +85,19 @@ export class BillingApiService implements BillingApiServiceAbstraction {
return new OrganizationBillingMetadataResponse(r);
}
async getOrganizationPaymentMethod(organizationId: string): Promise<PaymentMethodResponse> {
const response = await this.execute(() =>
this.apiService.send(
"GET",
"/organizations/" + organizationId + "/billing/payment-method",
null,
true,
true,
),
);
return new PaymentMethodResponse(response);
}
async getPlans(): Promise<ListResponse<PlanResponse>> {
const r = await this.apiService.send("GET", "/plans", null, false, true);
return new ListResponse(r, PlanResponse);
@@ -123,19 +136,6 @@ export class BillingApiService implements BillingApiServiceAbstraction {
return new InvoicesResponse(response);
}
async getProviderPaymentInformation(providerId: string): Promise<PaymentInformationResponse> {
const response = await this.execute(() =>
this.apiService.send(
"GET",
"/providers/" + providerId + "/billing/payment-information",
null,
true,
true,
),
);
return new PaymentInformationResponse(response);
}
async getProviderSubscription(providerId: string): Promise<ProviderSubscriptionResponse> {
const response = await this.execute(() =>
this.apiService.send(
@@ -149,6 +149,32 @@ export class BillingApiService implements BillingApiServiceAbstraction {
return new ProviderSubscriptionResponse(response);
}
async updateOrganizationPaymentMethod(
organizationId: string,
request: UpdatePaymentMethodRequest,
): Promise<void> {
return await this.apiService.send(
"PUT",
"/organizations/" + organizationId + "/billing/payment-method",
request,
true,
false,
);
}
async updateOrganizationTaxInformation(
organizationId: string,
request: ExpandedTaxInfoUpdateRequest,
): Promise<void> {
return await this.apiService.send(
"PUT",
"/organizations/" + organizationId + "/billing/tax-information",
request,
true,
false,
);
}
async updateProviderClientOrganization(
providerId: string,
organizationId: string,
@@ -163,19 +189,6 @@ export class BillingApiService implements BillingApiServiceAbstraction {
);
}
async updateProviderPaymentMethod(
providerId: string,
request: TokenizedPaymentMethodRequest,
): Promise<void> {
return await this.apiService.send(
"PUT",
"/providers/" + providerId + "/billing/payment-method",
request,
true,
false,
);
}
async updateProviderTaxInformation(providerId: string, request: ExpandedTaxInfoUpdateRequest) {
return await this.apiService.send(
"PUT",
@@ -186,10 +199,13 @@ export class BillingApiService implements BillingApiServiceAbstraction {
);
}
async verifyProviderBankAccount(providerId: string, request: VerifyBankAccountRequest) {
async verifyOrganizationBankAccount(
organizationId: string,
request: VerifyBankAccountRequest,
): Promise<void> {
return await this.apiService.send(
"POST",
"/providers/" + providerId + "/billing/payment-method/verify-bank-account",
"/organizations/" + organizationId + "/billing/payment-method/verify-bank-account",
request,
true,
false,

View File

@@ -33,6 +33,7 @@ export enum FeatureFlag {
DelayFido2PageScriptInitWithinMv2 = "delay-fido2-page-script-init-within-mv2",
AccountDeprovisioning = "pm-10308-account-deprovisioning",
NotificationBarAddLoginImprovements = "notification-bar-add-login-improvements",
AC2476_DeprecateStripeSourcesAPI = "AC-2476-deprecate-stripe-sources-api",
}
export type AllowedFeatureFlagTypes = boolean | number | string;
@@ -76,6 +77,7 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.DelayFido2PageScriptInitWithinMv2]: FALSE,
[FeatureFlag.AccountDeprovisioning]: FALSE,
[FeatureFlag.NotificationBarAddLoginImprovements]: FALSE,
[FeatureFlag.AC2476_DeprecateStripeSourcesAPI]: FALSE,
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;