1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

[PM-24964] Stripe-hosted bank account verification (#16220)

* Implement bank account hosted URL verification with webhook handling notification

* [PM-25491] Create org/provider bank account warning needs to be updated
This commit is contained in:
Alex Morask
2025-09-09 12:22:45 -05:00
committed by GitHub
parent 52642056d8
commit 4907820383
11 changed files with 149 additions and 30 deletions

View File

@@ -17,13 +17,18 @@ import {
take,
takeUntil,
tap,
withLatestFrom,
} from "rxjs";
import { catchError } from "rxjs/operators";
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CommandDefinition, MessageListener } from "@bitwarden/messaging";
import { UserId } from "@bitwarden/user-core";
import { SubscriberBillingClient } from "@bitwarden/web-vault/app/billing/clients";
import {
DisplayAccountCreditComponent,
@@ -52,6 +57,7 @@ class RedirectError {
}
type View = {
activeUserId: UserId;
provider: BitwardenSubscriber;
paymentMethod: MaskedPaymentMethod | null;
billingAddress: BillingAddress | null;
@@ -59,6 +65,11 @@ type View = {
taxIdWarning: TaxIdWarningType | null;
};
const BANK_ACCOUNT_VERIFIED_COMMAND = new CommandDefinition<{
providerId: string;
adminId: string;
}>("providerBankAccountVerified");
@Component({
templateUrl: "./provider-payment-details.component.html",
imports: [
@@ -94,15 +105,20 @@ export class ProviderPaymentDetailsComponent implements OnInit, OnDestroy {
const getTaxIdWarning = firstValueFrom(
this.providerWarningsService.getTaxIdWarning$(provider.data as Provider),
);
const getActiveUserId = firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
const [paymentMethod, billingAddress, credit, taxIdWarning] = await Promise.all([
this.billingClient.getPaymentMethod(provider),
this.billingClient.getBillingAddress(provider),
this.billingClient.getCredit(provider),
getTaxIdWarning,
]);
const [activeUserId, paymentMethod, billingAddress, credit, taxIdWarning] = await Promise.all(
[
getActiveUserId,
this.billingClient.getPaymentMethod(provider),
this.billingClient.getBillingAddress(provider),
this.billingClient.getCredit(provider),
getTaxIdWarning,
],
);
return {
activeUserId,
provider,
paymentMethod,
billingAddress,
@@ -131,9 +147,11 @@ export class ProviderPaymentDetailsComponent implements OnInit, OnDestroy {
protected enableTaxIdWarning!: boolean;
constructor(
private accountService: AccountService,
private activatedRoute: ActivatedRoute,
private billingClient: SubscriberBillingClient,
private configService: ConfigService,
private messageListener: MessageListener,
private providerService: ProviderService,
private providerWarningsService: ProviderWarningsService,
private router: Router,
@@ -169,6 +187,33 @@ export class ProviderPaymentDetailsComponent implements OnInit, OnDestroy {
}
});
}
this.messageListener
.messages$(BANK_ACCOUNT_VERIFIED_COMMAND)
.pipe(
withLatestFrom(this.view$),
filter(
([message, view]) =>
message.providerId === view.provider.data.id && message.adminId === view.activeUserId,
),
switchMap(
async ([_, view]) =>
await Promise.all([
this.subscriberBillingClient.getPaymentMethod(view.provider),
this.subscriberBillingClient.getBillingAddress(view.provider),
]),
),
tap(async ([paymentMethod, billingAddress]) => {
if (paymentMethod) {
await this.setPaymentMethod(paymentMethod);
}
if (billingAddress) {
this.setBillingAddress(billingAddress);
}
}),
takeUntil(this.destroy$),
)
.subscribe();
}
ngOnDestroy() {