Make payment optional trial banner work with Stripe sources API deprecation (#12146)
This commit is contained in:
parent
3fe11b7e5a
commit
0544100e83
|
@ -32,11 +32,11 @@ import {
|
||||||
} from "rxjs/operators";
|
} from "rxjs/operators";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Unassigned,
|
|
||||||
CollectionService,
|
|
||||||
CollectionData,
|
CollectionData,
|
||||||
CollectionDetailsResponse,
|
CollectionDetailsResponse,
|
||||||
|
CollectionService,
|
||||||
CollectionView,
|
CollectionView,
|
||||||
|
Unassigned,
|
||||||
} from "@bitwarden/admin-console/common";
|
} from "@bitwarden/admin-console/common";
|
||||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
|
@ -47,6 +47,7 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
|
@ -241,6 +242,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
protected billingApiService: BillingApiServiceAbstraction,
|
protected billingApiService: BillingApiServiceAbstraction,
|
||||||
private trialFlowService: TrialFlowService,
|
private trialFlowService: TrialFlowService,
|
||||||
|
private organizationBillingService: OrganizationBillingServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
@ -437,13 +439,13 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||||
.map((org) =>
|
.map((org) =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
this.organizationApiService.getSubscription(org.id),
|
this.organizationApiService.getSubscription(org.id),
|
||||||
this.organizationApiService.getBilling(org.id),
|
this.organizationBillingService.getPaymentSource(org.id),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([subscription, billing]) => {
|
map(([subscription, paymentSource]) => {
|
||||||
return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(
|
return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(
|
||||||
org,
|
org,
|
||||||
subscription,
|
subscription,
|
||||||
billing?.paymentSource,
|
paymentSource,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
|
@ -48,6 +48,7 @@ import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
@ -252,6 +253,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private trialFlowService: TrialFlowService,
|
private trialFlowService: TrialFlowService,
|
||||||
protected billingApiService: BillingApiServiceAbstraction,
|
protected billingApiService: BillingApiServiceAbstraction,
|
||||||
|
private organizationBillingService: OrganizationBillingServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
@ -595,15 +597,11 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||||
combineLatest([
|
combineLatest([
|
||||||
of(org),
|
of(org),
|
||||||
this.organizationApiService.getSubscription(org.id),
|
this.organizationApiService.getSubscription(org.id),
|
||||||
this.organizationApiService.getBilling(org.id),
|
this.organizationBillingService.getPaymentSource(org.id),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
map(([org, sub, billing]) => {
|
map(([org, sub, paymentSource]) => {
|
||||||
return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(
|
return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(org, sub, paymentSource);
|
||||||
org,
|
|
||||||
sub,
|
|
||||||
billing?.paymentSource,
|
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
|
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
@ -114,9 +115,9 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
||||||
private smOnboardingTasksService: SMOnboardingTasksService,
|
private smOnboardingTasksService: SMOnboardingTasksService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
|
||||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
private trialFlowService: TrialFlowService,
|
private trialFlowService: TrialFlowService,
|
||||||
|
private organizationBillingService: OrganizationBillingServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@ -144,15 +145,11 @@ export class OverviewComponent implements OnInit, OnDestroy {
|
||||||
combineLatest([
|
combineLatest([
|
||||||
of(org),
|
of(org),
|
||||||
this.organizationApiService.getSubscription(org.id),
|
this.organizationApiService.getSubscription(org.id),
|
||||||
this.organizationApiService.getBilling(org.id),
|
this.organizationBillingService.getPaymentSource(org.id),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
map(([org, sub, billing]) => {
|
map(([org, sub, paymentSource]) => {
|
||||||
return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(
|
return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(org, sub, paymentSource);
|
||||||
org,
|
|
||||||
sub,
|
|
||||||
billing?.paymentSource,
|
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
takeUntil(this.destroy$),
|
takeUntil(this.destroy$),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1213,6 +1213,8 @@ const safeProviders: SafeProvider[] = [
|
||||||
useClass: OrganizationBillingService,
|
useClass: OrganizationBillingService,
|
||||||
deps: [
|
deps: [
|
||||||
ApiServiceAbstraction,
|
ApiServiceAbstraction,
|
||||||
|
BillingApiServiceAbstraction,
|
||||||
|
ConfigService,
|
||||||
KeyServiceAbstraction,
|
KeyServiceAbstraction,
|
||||||
EncryptService,
|
EncryptService,
|
||||||
I18nServiceAbstraction,
|
I18nServiceAbstraction,
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import { BillingSourceResponse } from "@bitwarden/common/billing/models/response/billing.response";
|
||||||
|
import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response";
|
||||||
|
|
||||||
import { OrganizationResponse } from "../../admin-console/models/response/organization.response";
|
import { OrganizationResponse } from "../../admin-console/models/response/organization.response";
|
||||||
import { InitiationPath } from "../../models/request/reference-event.request";
|
import { InitiationPath } from "../../models/request/reference-event.request";
|
||||||
import { PaymentMethodType, PlanType } from "../enums";
|
import { PaymentMethodType, PlanType } from "../enums";
|
||||||
|
@ -41,11 +44,15 @@ export type SubscriptionInformation = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export abstract class OrganizationBillingServiceAbstraction {
|
export abstract class OrganizationBillingServiceAbstraction {
|
||||||
purchaseSubscription: (subscription: SubscriptionInformation) => Promise<OrganizationResponse>;
|
getPaymentSource: (
|
||||||
|
organizationId: string,
|
||||||
|
) => Promise<BillingSourceResponse | PaymentSourceResponse>;
|
||||||
|
|
||||||
startFree: (subscription: SubscriptionInformation) => Promise<OrganizationResponse>;
|
purchaseSubscription: (subscription: SubscriptionInformation) => Promise<OrganizationResponse>;
|
||||||
|
|
||||||
purchaseSubscriptionNoPaymentMethod: (
|
purchaseSubscriptionNoPaymentMethod: (
|
||||||
subscription: SubscriptionInformation,
|
subscription: SubscriptionInformation,
|
||||||
) => Promise<OrganizationResponse>;
|
) => Promise<OrganizationResponse>;
|
||||||
|
|
||||||
|
startFree: (subscription: SubscriptionInformation) => Promise<OrganizationResponse>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,18 @@
|
||||||
import { KeyService } from "../../../../key-management/src/abstractions/key.service";
|
import {
|
||||||
|
BillingApiServiceAbstraction,
|
||||||
|
OrganizationBillingServiceAbstraction,
|
||||||
|
OrganizationInformation,
|
||||||
|
PaymentInformation,
|
||||||
|
PlanInformation,
|
||||||
|
SubscriptionInformation,
|
||||||
|
} from "@bitwarden/common/billing/abstractions";
|
||||||
|
import { BillingSourceResponse } from "@bitwarden/common/billing/models/response/billing.response";
|
||||||
|
import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
|
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||||
|
import { KeyService } from "@bitwarden/key-management";
|
||||||
|
|
||||||
import { ApiService } from "../../abstractions/api.service";
|
import { ApiService } from "../../abstractions/api.service";
|
||||||
import { OrganizationApiServiceAbstraction as OrganizationApiService } from "../../admin-console/abstractions/organization/organization-api.service.abstraction";
|
import { OrganizationApiServiceAbstraction as OrganizationApiService } from "../../admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||||
import { OrganizationCreateRequest } from "../../admin-console/models/request/organization-create.request";
|
import { OrganizationCreateRequest } from "../../admin-console/models/request/organization-create.request";
|
||||||
|
@ -8,14 +22,6 @@ import { EncryptService } from "../../platform/abstractions/encrypt.service";
|
||||||
import { I18nService } from "../../platform/abstractions/i18n.service";
|
import { I18nService } from "../../platform/abstractions/i18n.service";
|
||||||
import { EncString } from "../../platform/models/domain/enc-string";
|
import { EncString } from "../../platform/models/domain/enc-string";
|
||||||
import { OrgKey } from "../../types/key";
|
import { OrgKey } from "../../types/key";
|
||||||
import { SyncService } from "../../vault/abstractions/sync/sync.service.abstraction";
|
|
||||||
import {
|
|
||||||
OrganizationBillingServiceAbstraction,
|
|
||||||
OrganizationInformation,
|
|
||||||
PaymentInformation,
|
|
||||||
PlanInformation,
|
|
||||||
SubscriptionInformation,
|
|
||||||
} from "../abstractions/organization-billing.service";
|
|
||||||
import { PlanType } from "../enums";
|
import { PlanType } from "../enums";
|
||||||
import { OrganizationNoPaymentMethodCreateRequest } from "../models/request/organization-no-payment-method-create-request";
|
import { OrganizationNoPaymentMethodCreateRequest } from "../models/request/organization-no-payment-method-create-request";
|
||||||
|
|
||||||
|
@ -29,6 +35,8 @@ interface OrganizationKeys {
|
||||||
export class OrganizationBillingService implements OrganizationBillingServiceAbstraction {
|
export class OrganizationBillingService implements OrganizationBillingServiceAbstraction {
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
|
private billingApiService: BillingApiServiceAbstraction,
|
||||||
|
private configService: ConfigService,
|
||||||
private keyService: KeyService,
|
private keyService: KeyService,
|
||||||
private encryptService: EncryptService,
|
private encryptService: EncryptService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
|
@ -36,6 +44,23 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async getPaymentSource(
|
||||||
|
organizationId: string,
|
||||||
|
): Promise<BillingSourceResponse | PaymentSourceResponse> {
|
||||||
|
const deprecateStripeSourcesAPI = await this.configService.getFeatureFlag(
|
||||||
|
FeatureFlag.AC2476_DeprecateStripeSourcesAPI,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (deprecateStripeSourcesAPI) {
|
||||||
|
const paymentMethod =
|
||||||
|
await this.billingApiService.getOrganizationPaymentMethod(organizationId);
|
||||||
|
return paymentMethod.paymentSource;
|
||||||
|
} else {
|
||||||
|
const billing = await this.organizationApiService.getBilling(organizationId);
|
||||||
|
return billing.paymentSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async purchaseSubscription(subscription: SubscriptionInformation): Promise<OrganizationResponse> {
|
async purchaseSubscription(subscription: SubscriptionInformation): Promise<OrganizationResponse> {
|
||||||
const request = new OrganizationCreateRequest();
|
const request = new OrganizationCreateRequest();
|
||||||
|
|
||||||
|
@ -58,26 +83,6 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
async startFree(subscription: SubscriptionInformation): Promise<OrganizationResponse> {
|
|
||||||
const request = new OrganizationCreateRequest();
|
|
||||||
|
|
||||||
const organizationKeys = await this.makeOrganizationKeys();
|
|
||||||
|
|
||||||
this.setOrganizationKeys(request, organizationKeys);
|
|
||||||
|
|
||||||
this.setOrganizationInformation(request, subscription.organization);
|
|
||||||
|
|
||||||
this.setPlanInformation(request, subscription.plan);
|
|
||||||
|
|
||||||
const response = await this.organizationApiService.create(request);
|
|
||||||
|
|
||||||
await this.apiService.refreshIdentityToken();
|
|
||||||
|
|
||||||
await this.syncService.fullSync(true);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
async purchaseSubscriptionNoPaymentMethod(
|
async purchaseSubscriptionNoPaymentMethod(
|
||||||
subscription: SubscriptionInformation,
|
subscription: SubscriptionInformation,
|
||||||
): Promise<OrganizationResponse> {
|
): Promise<OrganizationResponse> {
|
||||||
|
@ -100,6 +105,26 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async startFree(subscription: SubscriptionInformation): Promise<OrganizationResponse> {
|
||||||
|
const request = new OrganizationCreateRequest();
|
||||||
|
|
||||||
|
const organizationKeys = await this.makeOrganizationKeys();
|
||||||
|
|
||||||
|
this.setOrganizationKeys(request, organizationKeys);
|
||||||
|
|
||||||
|
this.setOrganizationInformation(request, subscription.organization);
|
||||||
|
|
||||||
|
this.setPlanInformation(request, subscription.plan);
|
||||||
|
|
||||||
|
const response = await this.organizationApiService.create(request);
|
||||||
|
|
||||||
|
await this.apiService.refreshIdentityToken();
|
||||||
|
|
||||||
|
await this.syncService.fullSync(true);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
private async makeOrganizationKeys(): Promise<OrganizationKeys> {
|
private async makeOrganizationKeys(): Promise<OrganizationKeys> {
|
||||||
const [encryptedKey, key] = await this.keyService.makeOrgKey<OrgKey>();
|
const [encryptedKey, key] = await this.keyService.makeOrgKey<OrgKey>();
|
||||||
const [publicKey, encryptedPrivateKey] = await this.keyService.makeKeyPair(key);
|
const [publicKey, encryptedPrivateKey] = await this.keyService.makeKeyPair(key);
|
||||||
|
|
Loading…
Reference in New Issue