mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-27 12:36:14 +01:00
handleCardPayment for incomplete payments
This commit is contained in:
parent
18608a8b63
commit
a4571a2617
2
jslib
2
jslib
@ -1 +1 @@
|
|||||||
Subproject commit 393f6c9c20fb7eded5008b65242ea44e69bc349c
|
Subproject commit e28e820286870df0111bd4feb8a219a3ae360ba7
|
@ -203,6 +203,9 @@
|
|||||||
<h2 class="spaced-header mb-4">{{'paymentInformation' | i18n}}</h2>
|
<h2 class="spaced-header mb-4">{{'paymentInformation' | i18n}}</h2>
|
||||||
<app-payment [hideCredit]="true"></app-payment>
|
<app-payment [hideCredit]="true"></app-payment>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
<ng-container *ngIf="!createOrganization">
|
||||||
|
<app-payment [showMethods]="false"></app-payment>
|
||||||
|
</ng-container>
|
||||||
<small class="text-muted font-italic mt-2 d-block" *ngIf="!createOrganization">
|
<small class="text-muted font-italic mt-2 d-block" *ngIf="!createOrganization">
|
||||||
{{'paymentCharged' | i18n : (interval | i18n) }}</small>
|
{{'paymentCharged' | i18n : (interval | i18n) }}</small>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -169,7 +169,10 @@ export class OrganizationPlansComponent {
|
|||||||
} else {
|
} else {
|
||||||
request.planType = this.plans[this.plan].annualPlanType;
|
request.planType = this.plans[this.plan].annualPlanType;
|
||||||
}
|
}
|
||||||
await this.apiService.postOrganizationUpgrade(this.organizationId, request);
|
const result = await this.apiService.postOrganizationUpgrade(this.organizationId, request);
|
||||||
|
if (!result.success && result.paymentIntentClientSecret != null) {
|
||||||
|
await this.paymentComponent.handleStripeCardPayment(result.paymentIntentClientSecret, null);
|
||||||
|
}
|
||||||
orgId = this.organizationId;
|
orgId = this.organizationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="mb-4 text-lg" *ngIf="showOptions">
|
<div class="mb-4 text-lg" *ngIf="showOptions && showMethods">
|
||||||
<div class="form-check form-check-inline mr-4">
|
<div class="form-check form-check-inline mr-4">
|
||||||
<input class="form-check-input" type="radio" name="Method" id="method-card" [value]="paymentMethodType.Card"
|
<input class="form-check-input" type="radio" name="Method" id="method-card" [value]="paymentMethodType.Card"
|
||||||
[(ngModel)]="method" (change)="changeMethod()">
|
[(ngModel)]="method" (change)="changeMethod()">
|
||||||
@ -24,7 +24,7 @@
|
|||||||
<i class="fa fa-fw fa-dollar"></i> {{'accountCredit' | i18n}}</label>
|
<i class="fa fa-fw fa-dollar"></i> {{'accountCredit' | i18n}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ng-container *ngIf="method === paymentMethodType.Card">
|
<ng-container *ngIf="showMethods && method === paymentMethodType.Card">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group col-4">
|
<div class="form-group col-4">
|
||||||
<label for="stripe-card-number-element">{{'number' | i18n}}</label>
|
<label for="stripe-card-number-element">{{'number' | i18n}}</label>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="method === paymentMethodType.BankAccount">
|
<ng-container *ngIf="showMethods && method === paymentMethodType.BankAccount">
|
||||||
<app-callout type="warning" title="{{'verifyBankAccount' | i18n}}">
|
<app-callout type="warning" title="{{'verifyBankAccount' | i18n}}">
|
||||||
{{'verifyBankAccountInitialDesc' | i18n}} {{'verifyBankAccountFailureWarning' | i18n}}
|
{{'verifyBankAccountInitialDesc' | i18n}} {{'verifyBankAccountFailureWarning' | i18n}}
|
||||||
</app-callout>
|
</app-callout>
|
||||||
@ -81,13 +81,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="method === paymentMethodType.PayPal">
|
<ng-container *ngIf="showMethods && method === paymentMethodType.PayPal">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div id="bt-dropin-container" class="mb-1"></div>
|
<div id="bt-dropin-container" class="mb-1"></div>
|
||||||
<small class="text-muted">{{'paypalClickSubmit' | i18n}}</small>
|
<small class="text-muted">{{'paypalClickSubmit' | i18n}}</small>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="method === paymentMethodType.Credit">
|
<ng-container *ngIf="showMethods && method === paymentMethodType.Credit">
|
||||||
<app-callout type="note">
|
<app-callout type="note">
|
||||||
{{'makeSureEnoughCredit' | i18n}}
|
{{'makeSureEnoughCredit' | i18n}}
|
||||||
</app-callout>
|
</app-callout>
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
|
|
||||||
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
|
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
|
||||||
|
|
||||||
|
import { ApiService } from 'jslib/abstractions/api.service';
|
||||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
|
|
||||||
import { WebConstants } from '../../services/webConstants';
|
import { WebConstants } from '../../services/webConstants';
|
||||||
@ -34,6 +35,7 @@ const StripeElementClasses = {
|
|||||||
templateUrl: 'payment.component.html',
|
templateUrl: 'payment.component.html',
|
||||||
})
|
})
|
||||||
export class PaymentComponent implements OnInit {
|
export class PaymentComponent implements OnInit {
|
||||||
|
@Input() showMethods = true;
|
||||||
@Input() showOptions = true;
|
@Input() showOptions = true;
|
||||||
@Input() method = PaymentMethodType.Card;
|
@Input() method = PaymentMethodType.Card;
|
||||||
@Input() hideBank = false;
|
@Input() hideBank = false;
|
||||||
@ -60,7 +62,7 @@ export class PaymentComponent implements OnInit {
|
|||||||
private stripeCardExpiryElement: any = null;
|
private stripeCardExpiryElement: any = null;
|
||||||
private stripeCardCvcElement: any = null;
|
private stripeCardCvcElement: any = null;
|
||||||
|
|
||||||
constructor(private platformUtilsService: PlatformUtilsService) {
|
constructor(private platformUtilsService: PlatformUtilsService, private apiService: ApiService) {
|
||||||
this.stripeScript = window.document.createElement('script');
|
this.stripeScript = window.document.createElement('script');
|
||||||
this.stripeScript.src = 'https://js.stripe.com/v3/';
|
this.stripeScript.src = 'https://js.stripe.com/v3/';
|
||||||
this.stripeScript.async = true;
|
this.stripeScript.async = true;
|
||||||
@ -162,30 +164,60 @@ export class PaymentComponent implements OnInit {
|
|||||||
reject(err.message);
|
reject(err.message);
|
||||||
});
|
});
|
||||||
} else if (this.method === PaymentMethodType.Card || this.method === PaymentMethodType.BankAccount) {
|
} else if (this.method === PaymentMethodType.Card || this.method === PaymentMethodType.BankAccount) {
|
||||||
let sourceObj: any = null;
|
|
||||||
let createObj: any = null;
|
|
||||||
if (this.method === PaymentMethodType.Card) {
|
if (this.method === PaymentMethodType.Card) {
|
||||||
sourceObj = this.stripeCardNumberElement;
|
this.apiService.postSetupPayment().then((clientSecret) =>
|
||||||
|
this.stripe.handleCardSetup(clientSecret, this.stripeCardNumberElement))
|
||||||
|
.then((result: any) => {
|
||||||
|
if (result.error) {
|
||||||
|
reject(result.error.message);
|
||||||
|
} else if (result.setupIntent && result.setupIntent.status === 'succeeded') {
|
||||||
|
resolve([result.setupIntent.payment_method, this.method]);
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
sourceObj = 'bank_account';
|
this.stripe.createToken('bank_account', this.bank).then((result: any) => {
|
||||||
createObj = this.bank;
|
if (result.error) {
|
||||||
|
reject(result.error.message);
|
||||||
|
} else if (result.token && result.token.id != null) {
|
||||||
|
resolve([result.token.id, this.method]);
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.stripe.createToken(sourceObj, createObj).then((result: any) => {
|
|
||||||
if (result.error) {
|
|
||||||
reject(result.error.message);
|
|
||||||
} else if (result.token && result.token.id != null) {
|
|
||||||
resolve([result.token.id, this.method]);
|
|
||||||
} else {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleStripeCardPayment(clientSecret: string, successCallback: () => Promise<any>): Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (this.showMethods && this.stripeCardNumberElement == null) {
|
||||||
|
reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const handleCardPayment = () => this.showMethods ?
|
||||||
|
this.stripe.handleCardPayment(clientSecret, this.stripeCardNumberElement) :
|
||||||
|
this.stripe.handleCardPayment(clientSecret);
|
||||||
|
return handleCardPayment().then(async (result: any) => {
|
||||||
|
if (result.error) {
|
||||||
|
reject(result.error.message);
|
||||||
|
} else if (result.paymentIntent && result.paymentIntent.status === 'succeeded') {
|
||||||
|
if (successCallback != null) {
|
||||||
|
await successCallback();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private setStripeElement() {
|
private setStripeElement() {
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
if (this.method === PaymentMethodType.Card) {
|
if (this.showMethods && this.method === PaymentMethodType.Card) {
|
||||||
if (this.stripeCardNumberElement == null) {
|
if (this.stripeCardNumberElement == null) {
|
||||||
this.stripeCardNumberElement = this.stripeElements.create('cardNumber', {
|
this.stripeCardNumberElement = this.stripeElements.create('cardNumber', {
|
||||||
style: StripeElementStyle,
|
style: StripeElementStyle,
|
||||||
|
@ -84,8 +84,13 @@ export class PremiumComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
fd.append('additionalStorageGb', (this.additionalStorage || 0).toString());
|
fd.append('additionalStorageGb', (this.additionalStorage || 0).toString());
|
||||||
return this.apiService.postPremium(fd);
|
return this.apiService.postPremium(fd);
|
||||||
}).then(() => {
|
}).then((paymentResponse) => {
|
||||||
return this.finalizePremium();
|
if (!paymentResponse.success && paymentResponse.paymentIntentClientSecret != null) {
|
||||||
|
return this.paymentComponent.handleStripeCardPayment(paymentResponse.paymentIntentClientSecret,
|
||||||
|
() => this.finalizePremium());
|
||||||
|
} else {
|
||||||
|
return this.finalizePremium();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await this.formPromise;
|
await this.formPromise;
|
||||||
|
Loading…
Reference in New Issue
Block a user