[accelerator] add support for Google Pay payment
This commit is contained in:
parent
fe1ad86885
commit
481859bc8f
@ -389,13 +389,13 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@if (canPayWithCashapp || canPayWithApplePay) {
|
@if (canPayWithCashapp || canPayWithApplePay || canPayWithGooglePay) {
|
||||||
<div class="col-sm text-center flex-grow-0 d-flex flex-column justify-content-center align-items-center">
|
<div class="col-sm text-center flex-grow-0 d-flex flex-column justify-content-center align-items-center">
|
||||||
<p class="text-nowrap">—<span i18n="or">OR</span>—</p>
|
<p class="text-nowrap">—<span i18n="or">OR</span>—</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@if (canPayWithCashapp || canPayWithApplePay) {
|
@if (canPayWithCashapp || canPayWithApplePay || canPayWithGooglePay) {
|
||||||
<div class="col-sm text-center d-flex flex-column justify-content-center align-items-center">
|
<div class="col-sm text-center d-flex flex-column justify-content-center align-items-center">
|
||||||
<p><ng-container i18n="transaction.pay|Pay button label">Pay</ng-container> <app-fiat [value]="cost"></app-fiat> with</p>
|
<p><ng-container i18n="transaction.pay|Pay button label">Pay</ng-container> <app-fiat [value]="cost"></app-fiat> with</p>
|
||||||
@if (canPayWithCashapp) {
|
@if (canPayWithCashapp) {
|
||||||
@ -405,6 +405,10 @@
|
|||||||
@if (canPayWithCashapp) { <hr class="w-25 mt-2 mb-2"> }
|
@if (canPayWithCashapp) { <hr class="w-25 mt-2 mb-2"> }
|
||||||
<img style="cursor: pointer;" src="/resources/apple-pay.svg" height=55 (click)="moveToStep('applepay')">
|
<img style="cursor: pointer;" src="/resources/apple-pay.svg" height=55 (click)="moveToStep('applepay')">
|
||||||
}
|
}
|
||||||
|
@if (canPayWithGooglePay) {
|
||||||
|
@if (canPayWithCashapp || canPayWithApplePay) { <hr class="w-25 mt-2 mb-2"> }
|
||||||
|
<img style="cursor: pointer;" src="/resources/google-pay.png" height=55 (click)="moveToStep('googlepay')">
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -427,7 +431,7 @@
|
|||||||
<button type="button" class="mt-1 btn btn-secondary btn-sm rounded-pill align-self-center" style="width: 200px" (click)="moveToStep('summary')" i18n="go-back">Go back</button>
|
<button type="button" class="mt-1 btn btn-secondary btn-sm rounded-pill align-self-center" style="width: 200px" (click)="moveToStep('summary')" i18n="go-back">Go back</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} @else if (step === 'cashapp' || step === 'applepay') {
|
} @else if (step === 'cashapp' || step === 'applepay' || step === 'googlepay') {
|
||||||
<!-- Show checkout page -->
|
<!-- Show checkout page -->
|
||||||
<div class="row mb-md-1 text-center" id="confirm-title">
|
<div class="row mb-md-1 text-center" id="confirm-title">
|
||||||
<div class="col-sm" id="confirm-payment-title">
|
<div class="col-sm" id="confirm-payment-title">
|
||||||
@ -443,7 +447,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (step === 'cashapp' && !loadingCashapp || step === 'applepay' && !loadingApplePay) {
|
@if (step === 'cashapp' && !loadingCashapp || step === 'applepay' && !loadingApplePay || step === 'googlepay' && !loadingGooglePay) {
|
||||||
<div class="row text-center mt-1">
|
<div class="row text-center mt-1">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="form-group w-100">
|
<div class="form-group w-100">
|
||||||
@ -466,8 +470,10 @@
|
|||||||
<div id="apple-pay-button" class="apple-pay-button apple-pay-button-white" [style]="loadingApplePay ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''"></div>
|
<div id="apple-pay-button" class="apple-pay-button apple-pay-button-white" [style]="loadingApplePay ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''"></div>
|
||||||
} @else if (step === 'cashapp') {
|
} @else if (step === 'cashapp') {
|
||||||
<div id="cash-app-pay" class="d-inline-block" [style]="loadingCashapp ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''"></div>
|
<div id="cash-app-pay" class="d-inline-block" [style]="loadingCashapp ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''"></div>
|
||||||
|
} @else if (step === 'googlepay') {
|
||||||
|
<div id="google-pay-button" class="d-inline-block" [style]="loadingGooglePay ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''"></div>
|
||||||
}
|
}
|
||||||
@if (loadingCashapp || loadingApplePay) {
|
@if (loadingCashapp || loadingApplePay || loadingGooglePay) {
|
||||||
<div display="d-flex flex-row justify-content-center">
|
<div display="d-flex flex-row justify-content-center">
|
||||||
<span i18n="accelerator.loading-payment-method">Loading payment method...</span>
|
<span i18n="accelerator.loading-payment-method">Loading payment method...</span>
|
||||||
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
|
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
|
||||||
|
@ -47,7 +47,7 @@ export const MIN_BID_RATIO = 1;
|
|||||||
export const DEFAULT_BID_RATIO = 2;
|
export const DEFAULT_BID_RATIO = 2;
|
||||||
export const MAX_BID_RATIO = 4;
|
export const MAX_BID_RATIO = 4;
|
||||||
|
|
||||||
type CheckoutStep = 'quote' | 'summary' | 'checkout' | 'cashapp' | 'applepay' | 'processing' | 'paid' | 'success';
|
type CheckoutStep = 'quote' | 'summary' | 'checkout' | 'cashapp' | 'applepay' | 'googlepay' | 'processing' | 'paid' | 'success';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-accelerate-checkout',
|
selector: 'app-accelerate-checkout',
|
||||||
@ -62,6 +62,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
@Input() scrollEvent: boolean;
|
@Input() scrollEvent: boolean;
|
||||||
@Input() cashappEnabled: boolean = true;
|
@Input() cashappEnabled: boolean = true;
|
||||||
@Input() applePayEnabled: boolean = false;
|
@Input() applePayEnabled: boolean = false;
|
||||||
|
@Input() googlePayEnabled: boolean = true;
|
||||||
@Input() advancedEnabled: boolean = false;
|
@Input() advancedEnabled: boolean = false;
|
||||||
@Input() forceMobile: boolean = false;
|
@Input() forceMobile: boolean = false;
|
||||||
@Input() showDetails: boolean = false;
|
@Input() showDetails: boolean = false;
|
||||||
@ -83,7 +84,6 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private _step: CheckoutStep = 'summary';
|
private _step: CheckoutStep = 'summary';
|
||||||
simpleMode: boolean = true;
|
simpleMode: boolean = true;
|
||||||
paymentMethod: 'cashapp' | 'btcpay';
|
|
||||||
timeoutTimer: any;
|
timeoutTimer: any;
|
||||||
|
|
||||||
authSubscription$: Subscription;
|
authSubscription$: Subscription;
|
||||||
@ -112,11 +112,13 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
// square
|
// square
|
||||||
loadingCashapp = false;
|
loadingCashapp = false;
|
||||||
loadingApplePay = false;
|
loadingApplePay = false;
|
||||||
|
loadingGooglePay = false;
|
||||||
cashappError = false;
|
cashappError = false;
|
||||||
cashappSubmit: any;
|
cashappSubmit: any;
|
||||||
payments: any;
|
payments: any;
|
||||||
cashAppPay: any;
|
cashAppPay: any;
|
||||||
applePay: any;
|
applePay: any;
|
||||||
|
googlePay: any;
|
||||||
conversionsSubscription: Subscription;
|
conversionsSubscription: Subscription;
|
||||||
conversions: any;
|
conversions: any;
|
||||||
|
|
||||||
@ -228,6 +230,11 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
this.insertSquare();
|
this.insertSquare();
|
||||||
this.setupSquare();
|
this.setupSquare();
|
||||||
this.scrollToElementWithTimeout('confirm-title', 'center', 100);
|
this.scrollToElementWithTimeout('confirm-title', 'center', 100);
|
||||||
|
} else if (this._step === 'googlepay' && this.googlePayEnabled) {
|
||||||
|
this.loadingGooglePay = true;
|
||||||
|
this.insertSquare();
|
||||||
|
this.setupSquare();
|
||||||
|
this.scrollToElementWithTimeout('confirm-title', 'center', 100);
|
||||||
} else if (this._step === 'paid') {
|
} else if (this._step === 'paid') {
|
||||||
this.timePaid = Date.now();
|
this.timePaid = Date.now();
|
||||||
this.timeoutTimer = setTimeout(() => {
|
this.timeoutTimer = setTimeout(() => {
|
||||||
@ -443,6 +450,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
await this.requestCashAppPayment();
|
await this.requestCashAppPayment();
|
||||||
} else if (this._step === 'applepay') {
|
} else if (this._step === 'applepay') {
|
||||||
await this.requestApplePayPayment();
|
await this.requestApplePayPayment();
|
||||||
|
} else if (this._step === 'googlepay') {
|
||||||
|
await this.requestGooglePayPayment();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.debug('Error loading Square Payments', e);
|
console.debug('Error loading Square Payments', e);
|
||||||
@ -541,6 +550,92 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GOOGLE PAY
|
||||||
|
*/
|
||||||
|
async requestGooglePayPayment() {
|
||||||
|
if (this.conversionsSubscription) {
|
||||||
|
this.conversionsSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.conversionsSubscription = this.stateService.conversions$.subscribe(
|
||||||
|
async (conversions) => {
|
||||||
|
this.conversions = conversions;
|
||||||
|
if (this.googlePay) {
|
||||||
|
this.googlePay.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
const costUSD = this.cost / 100_000_000 * conversions.USD;
|
||||||
|
const paymentRequest = this.payments.paymentRequest({
|
||||||
|
countryCode: 'US',
|
||||||
|
currencyCode: 'USD',
|
||||||
|
total: {
|
||||||
|
amount: costUSD.toFixed(2),
|
||||||
|
label: 'Total'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.googlePay = await this.payments.googlePay(paymentRequest , {
|
||||||
|
referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.googlePay.attach(`#google-pay-button`, {
|
||||||
|
buttonType: 'pay',
|
||||||
|
onClick: (e) => { console.log(e, 'hi') }
|
||||||
|
});
|
||||||
|
this.loadingGooglePay = false;
|
||||||
|
|
||||||
|
document.getElementById('google-pay-button').addEventListener('click', async event => {
|
||||||
|
event.preventDefault();
|
||||||
|
const tokenResult = await this.googlePay.tokenize();
|
||||||
|
if (tokenResult?.status === 'OK') {
|
||||||
|
const card = tokenResult.details?.card;
|
||||||
|
if (!card || !card.brand || !card.expMonth || !card.expYear || !card.last4) {
|
||||||
|
console.error(`Cannot retreive payment card details`);
|
||||||
|
this.accelerateError = 'apple_pay_no_card_details';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cardTag = md5(`${card.brand}${card.expMonth}${card.expYear}${card.last4}`.toLowerCase());
|
||||||
|
this.servicesApiService.accelerateWithGooglePay$(
|
||||||
|
this.tx.txid,
|
||||||
|
tokenResult.token,
|
||||||
|
cardTag,
|
||||||
|
`accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`,
|
||||||
|
this.accelerationUUID
|
||||||
|
).subscribe({
|
||||||
|
next: () => {
|
||||||
|
this.audioService.playSound('ascend-chime-cartoon');
|
||||||
|
if (this.googlePay) {
|
||||||
|
this.googlePay.destroy();
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.moveToStep('paid');
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
error: (response) => {
|
||||||
|
this.accelerateError = response.error;
|
||||||
|
if (!(response.status === 403 && response.error === 'not_available')) {
|
||||||
|
setTimeout(() => {
|
||||||
|
// Reset everything by reloading the page :D, can be improved
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``));
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let errorMessage = `Tokenization failed with status: ${tokenResult.status}`;
|
||||||
|
if (tokenResult.errors) {
|
||||||
|
errorMessage += ` and errors: ${JSON.stringify(
|
||||||
|
tokenResult.errors,
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
throw new Error(errorMessage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CASHAPP
|
* CASHAPP
|
||||||
*/
|
*/
|
||||||
@ -566,18 +661,14 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
label: 'Total',
|
label: 'Total',
|
||||||
pending: true,
|
pending: true,
|
||||||
productUrl: `${redirectHostname}/tracker/${this.tx.txid}`,
|
productUrl: `${redirectHostname}/tracker/${this.tx.txid}`,
|
||||||
},
|
}
|
||||||
button: { shape: 'semiround', size: 'small', theme: 'light'}
|
|
||||||
});
|
});
|
||||||
this.cashAppPay = await this.payments.cashAppPay(paymentRequest, {
|
this.cashAppPay = await this.payments.cashAppPay(paymentRequest, {
|
||||||
redirectURL: `${redirectHostname}/tracker/${this.tx.txid}`,
|
redirectURL: `${redirectHostname}/tracker/${this.tx.txid}`,
|
||||||
referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`,
|
referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`
|
||||||
button: { shape: 'semiround', size: 'small', theme: 'light'}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.step === 'cashapp') {
|
await this.cashAppPay.attach(`#cash-app-pay`, { theme: 'light', size: 'small', shape: 'semiround' })
|
||||||
await this.cashAppPay.attach(`#cash-app-pay`, { theme: 'light', size: 'small', shape: 'semiround' })
|
|
||||||
}
|
|
||||||
this.loadingCashapp = false;
|
this.loadingCashapp = false;
|
||||||
|
|
||||||
this.cashAppPay.addEventListener('ontokenization', event => {
|
this.cashAppPay.addEventListener('ontokenization', event => {
|
||||||
@ -686,6 +777,13 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
return !!this.estimate?.availablePaymentMethods?.applePay;
|
return !!this.estimate?.availablePaymentMethods?.applePay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get couldPayWithGooglePay() {
|
||||||
|
if (!this.googlePayEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !!this.estimate?.availablePaymentMethods?.googlePay;
|
||||||
|
}
|
||||||
|
|
||||||
get couldPayWithBalance() {
|
get couldPayWithBalance() {
|
||||||
if (!this.hasAccessToBalanceMode) {
|
if (!this.hasAccessToBalanceMode) {
|
||||||
return false;
|
return false;
|
||||||
@ -734,6 +832,22 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get canPayWithGooglePay() {
|
||||||
|
if (!this.googlePayEnabled || !this.conversions) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const paymentMethod = this.estimate?.availablePaymentMethods?.googlePay;
|
||||||
|
if (paymentMethod) {
|
||||||
|
const costUSD = (this.cost / 100_000_000 * this.conversions.USD);
|
||||||
|
if (costUSD >= paymentMethod.min && costUSD <= paymentMethod.max) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
get canPayWithBalance() {
|
get canPayWithBalance() {
|
||||||
if (!this.hasAccessToBalanceMode) {
|
if (!this.hasAccessToBalanceMode) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -141,6 +141,10 @@ export class ServicesApiServices {
|
|||||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/applePay`, { txInput: txInput, cardTag: cardTag, token: token, referenceId: referenceId, accelerationUUID: accelerationUUID });
|
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/applePay`, { txInput: txInput, cardTag: cardTag, token: token, referenceId: referenceId, accelerationUUID: accelerationUUID });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accelerateWithGooglePay$(txInput: string, token: string, cardTag: string, referenceId: string, accelerationUUID: string) {
|
||||||
|
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/googlePay`, { txInput: txInput, cardTag: cardTag, token: token, referenceId: referenceId, accelerationUUID: accelerationUUID });
|
||||||
|
}
|
||||||
|
|
||||||
getAccelerations$(): Observable<Acceleration[]> {
|
getAccelerations$(): Observable<Acceleration[]> {
|
||||||
return this.httpClient.get<Acceleration[]>(`${this.stateService.env.SERVICES_API}/accelerator/accelerations`);
|
return this.httpClient.get<Acceleration[]>(`${this.stateService.env.SERVICES_API}/accelerator/accelerations`);
|
||||||
}
|
}
|
||||||
|
BIN
frontend/src/resources/google-pay.png
Normal file
BIN
frontend/src/resources/google-pay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Loading…
x
Reference in New Issue
Block a user