mirror of
https://github.com/mempool/mempool.git
synced 2025-01-19 05:34:03 +01:00
[accelerator] add support for Google Pay payment
This commit is contained in:
parent
fe1ad86885
commit
481859bc8f
@ -389,13 +389,13 @@
|
||||
</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">
|
||||
<p class="text-nowrap">—<span i18n="or">OR</span>—</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (canPayWithCashapp || canPayWithApplePay) {
|
||||
@if (canPayWithCashapp || canPayWithApplePay || canPayWithGooglePay) {
|
||||
<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>
|
||||
@if (canPayWithCashapp) {
|
||||
@ -405,6 +405,10 @@
|
||||
@if (canPayWithCashapp) { <hr class="w-25 mt-2 mb-2"> }
|
||||
<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>
|
||||
@ -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>
|
||||
</div>
|
||||
</div>
|
||||
} @else if (step === 'cashapp' || step === 'applepay') {
|
||||
} @else if (step === 'cashapp' || step === 'applepay' || step === 'googlepay') {
|
||||
<!-- Show checkout page -->
|
||||
<div class="row mb-md-1 text-center" id="confirm-title">
|
||||
<div class="col-sm" id="confirm-payment-title">
|
||||
@ -443,7 +447,7 @@
|
||||
</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="col-sm">
|
||||
<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>
|
||||
} @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>
|
||||
} @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">
|
||||
<span i18n="accelerator.loading-payment-method">Loading payment method...</span>
|
||||
<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 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({
|
||||
selector: 'app-accelerate-checkout',
|
||||
@ -62,6 +62,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
@Input() scrollEvent: boolean;
|
||||
@Input() cashappEnabled: boolean = true;
|
||||
@Input() applePayEnabled: boolean = false;
|
||||
@Input() googlePayEnabled: boolean = true;
|
||||
@Input() advancedEnabled: boolean = false;
|
||||
@Input() forceMobile: boolean = false;
|
||||
@Input() showDetails: boolean = false;
|
||||
@ -83,7 +84,6 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
|
||||
private _step: CheckoutStep = 'summary';
|
||||
simpleMode: boolean = true;
|
||||
paymentMethod: 'cashapp' | 'btcpay';
|
||||
timeoutTimer: any;
|
||||
|
||||
authSubscription$: Subscription;
|
||||
@ -112,11 +112,13 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
// square
|
||||
loadingCashapp = false;
|
||||
loadingApplePay = false;
|
||||
loadingGooglePay = false;
|
||||
cashappError = false;
|
||||
cashappSubmit: any;
|
||||
payments: any;
|
||||
cashAppPay: any;
|
||||
applePay: any;
|
||||
googlePay: any;
|
||||
conversionsSubscription: Subscription;
|
||||
conversions: any;
|
||||
|
||||
@ -228,6 +230,11 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
this.insertSquare();
|
||||
this.setupSquare();
|
||||
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') {
|
||||
this.timePaid = Date.now();
|
||||
this.timeoutTimer = setTimeout(() => {
|
||||
@ -443,6 +450,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
await this.requestCashAppPayment();
|
||||
} else if (this._step === 'applepay') {
|
||||
await this.requestApplePayPayment();
|
||||
} else if (this._step === 'googlepay') {
|
||||
await this.requestGooglePayPayment();
|
||||
}
|
||||
} catch (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
|
||||
*/
|
||||
@ -566,18 +661,14 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
label: 'Total',
|
||||
pending: true,
|
||||
productUrl: `${redirectHostname}/tracker/${this.tx.txid}`,
|
||||
},
|
||||
button: { shape: 'semiround', size: 'small', theme: 'light'}
|
||||
}
|
||||
});
|
||||
this.cashAppPay = await this.payments.cashAppPay(paymentRequest, {
|
||||
redirectURL: `${redirectHostname}/tracker/${this.tx.txid}`,
|
||||
referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`,
|
||||
button: { shape: 'semiround', size: 'small', theme: 'light'}
|
||||
referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`
|
||||
});
|
||||
|
||||
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.cashAppPay.addEventListener('ontokenization', event => {
|
||||
@ -686,6 +777,13 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
return !!this.estimate?.availablePaymentMethods?.applePay;
|
||||
}
|
||||
|
||||
get couldPayWithGooglePay() {
|
||||
if (!this.googlePayEnabled) {
|
||||
return false;
|
||||
}
|
||||
return !!this.estimate?.availablePaymentMethods?.googlePay;
|
||||
}
|
||||
|
||||
get couldPayWithBalance() {
|
||||
if (!this.hasAccessToBalanceMode) {
|
||||
return false;
|
||||
@ -734,6 +832,22 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
||||
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() {
|
||||
if (!this.hasAccessToBalanceMode) {
|
||||
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 });
|
||||
}
|
||||
|
||||
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[]> {
|
||||
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…
Reference in New Issue
Block a user