changes
This commit is contained in:
171
src/app/pages/fastcheck-page/fastcheck-page.ts
Normal file
171
src/app/pages/fastcheck-page/fastcheck-page.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import { Component, computed, inject, signal } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FastcheckService } from '../../fastcheck.service';
|
||||
import { FASTCHECK_API } from '../../api';
|
||||
|
||||
interface WebSessionResponse {
|
||||
sessionId: string;
|
||||
userId: string;
|
||||
expires: string;
|
||||
userSessionId: string;
|
||||
Status: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-fastcheck-page',
|
||||
imports: [FormsModule, RouterLink],
|
||||
templateUrl: './fastcheck-page.html',
|
||||
styleUrl: './fastcheck-page.scss'
|
||||
})
|
||||
export class FastcheckPage {
|
||||
private http = inject(HttpClient);
|
||||
private store = inject(FastcheckService);
|
||||
private router = inject(Router);
|
||||
|
||||
// Telegram bot used for the sign-in deep link.
|
||||
private readonly telegramBot = 'DexarSupport_bot';
|
||||
|
||||
fastcheckNumber = signal<string>('');
|
||||
fastcheckAmount = signal<number | null>(null);
|
||||
fastcheckCode = signal<string>('');
|
||||
error = signal<string>('');
|
||||
|
||||
popupOpen = signal<boolean>(false);
|
||||
popupLoading = signal<boolean>(false);
|
||||
popupError = signal<string>('');
|
||||
webSessionId = signal<string>('');
|
||||
paid = signal<boolean>(false);
|
||||
private pollHandle: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
telegramLink = computed(() => {
|
||||
const sid = this.webSessionId();
|
||||
return sid
|
||||
? `https://t.me/${this.telegramBot}?start=${encodeURIComponent(sid)}`
|
||||
: `https://t.me/${this.telegramBot}`;
|
||||
});
|
||||
|
||||
qrUrl = computed(() => {
|
||||
const link = this.telegramLink();
|
||||
return `https://api.qrserver.com/v1/create-qr-code/?size=240x240&margin=8&data=${encodeURIComponent(link)}`;
|
||||
});
|
||||
|
||||
constructor() {
|
||||
// Pull autofill data left over by the create page.
|
||||
const created = this.store.consume();
|
||||
if (created) {
|
||||
this.fastcheckNumber.set(created.fastcheck);
|
||||
this.fastcheckAmount.set(created.amount);
|
||||
this.fastcheckCode.set(created.code);
|
||||
}
|
||||
}
|
||||
|
||||
pay(): void {
|
||||
if (!this.fastcheckNumber().trim()) {
|
||||
this.error.set('Введите номер Фастчека');
|
||||
return;
|
||||
}
|
||||
if (!this.fastcheckCode().trim()) {
|
||||
this.error.set('Введите код Фастчека');
|
||||
return;
|
||||
}
|
||||
this.error.set('');
|
||||
this.openPopup();
|
||||
}
|
||||
|
||||
private openPopup(): void {
|
||||
this.popupOpen.set(true);
|
||||
this.popupError.set('');
|
||||
this.paid.set(false);
|
||||
this.popupLoading.set(true);
|
||||
|
||||
this.http.get<WebSessionResponse>(`${FASTCHECK_API}/websession`).subscribe({
|
||||
next: (res) => {
|
||||
this.popupLoading.set(false);
|
||||
this.webSessionId.set(res.sessionId);
|
||||
this.startPolling(res.sessionId);
|
||||
},
|
||||
error: () => {
|
||||
this.popupLoading.set(false);
|
||||
this.popupError.set('Не удалось создать сессию. Попробуйте ещё раз.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
closePopup(): void {
|
||||
this.popupOpen.set(false);
|
||||
this.stopPolling();
|
||||
if (this.webSessionId()) {
|
||||
// Best-effort logout; ignore errors.
|
||||
this.http
|
||||
.request('DELETE', `${FASTCHECK_API}/websession/${this.webSessionId()}`, {
|
||||
body: { sessionId: this.webSessionId() }
|
||||
})
|
||||
.subscribe({ error: () => undefined });
|
||||
}
|
||||
this.webSessionId.set('');
|
||||
}
|
||||
|
||||
private startPolling(sessionId: string): void {
|
||||
this.stopPolling();
|
||||
this.pollHandle = setInterval(() => {
|
||||
this.http
|
||||
.get<WebSessionResponse>(`${FASTCHECK_API}/websession/${sessionId}`)
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
if (res?.Status) {
|
||||
this.stopPolling();
|
||||
this.acceptFastcheck(sessionId);
|
||||
}
|
||||
},
|
||||
error: () => undefined
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
private stopPolling(): void {
|
||||
if (this.pollHandle !== null) {
|
||||
clearInterval(this.pollHandle);
|
||||
this.pollHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
private acceptFastcheck(sessionId: string): void {
|
||||
this.popupLoading.set(true);
|
||||
this.http
|
||||
.post(
|
||||
`${FASTCHECK_API}/fastcheck`,
|
||||
{ fastcheck: this.fastcheckNumber().trim(), code: this.fastcheckCode().trim() },
|
||||
{ headers: { Authorization: JSON.stringify({ sessionID: sessionId }) } }
|
||||
)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.popupLoading.set(false);
|
||||
this.paid.set(true);
|
||||
// Fire-and-forget merchant callback if a return_url is on the page.
|
||||
this.fireMerchantCallback();
|
||||
},
|
||||
error: () => {
|
||||
this.popupLoading.set(false);
|
||||
this.popupError.set('Не удалось принять Фастчек.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private fireMerchantCallback(): void {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const returnUrl = params.get('return_url');
|
||||
if (returnUrl) {
|
||||
setTimeout(() => {
|
||||
window.location.href = `${returnUrl}${returnUrl.includes('?') ? '&' : '?'}fastcheck=${encodeURIComponent(
|
||||
this.fastcheckNumber()
|
||||
)}&status=ok`;
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
onAmountChange(value: number | null): void {
|
||||
this.fastcheckAmount.set(value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user