api changed
This commit is contained in:
@@ -147,8 +147,8 @@
|
||||
<button
|
||||
class="checkout-btn"
|
||||
(click)="checkout()"
|
||||
[class.disabled]="!termsAccepted"
|
||||
[disabled]="!termsAccepted"
|
||||
[class.disabled]="!termsAccepted || !isAuthenticated()"
|
||||
[disabled]="!termsAccepted || !isAuthenticated()"
|
||||
>
|
||||
{{ 'cart.checkout' | translate }}
|
||||
</button>
|
||||
|
||||
@@ -149,11 +149,6 @@ export class CartComponent implements OnDestroy {
|
||||
alert(this.i18n.t('cart.acceptTerms'));
|
||||
return;
|
||||
}
|
||||
// Auth gate: require Telegram login before payment
|
||||
if (!this.authService.isAuthenticated()) {
|
||||
this.authService.requestLogin();
|
||||
return;
|
||||
}
|
||||
this.openPaymentPopup();
|
||||
}
|
||||
|
||||
@@ -203,10 +198,6 @@ export class CartComponent implements OnDestroy {
|
||||
createPayment(): void {
|
||||
const sessionId = this.authService.session()?.sessionId || '';
|
||||
const partnerQrId = this.getPartnerQrId();
|
||||
if (!partnerQrId) {
|
||||
this.setPaymentError();
|
||||
return;
|
||||
}
|
||||
|
||||
const cartItems = this.items().map((item: CartItem) => ({
|
||||
itemID: item.itemID,
|
||||
@@ -227,22 +218,17 @@ export class CartComponent implements OnDestroy {
|
||||
)
|
||||
: of(null);
|
||||
|
||||
const userIdValue = this.getUrlParam('userid-value') || undefined;
|
||||
const authorizationKey = this.getUrlParam('authorization-key') || undefined;
|
||||
const qrPayload = {
|
||||
qrtype: 'QRDynamic' as const,
|
||||
amount: Number(this.totalPrice()),
|
||||
currency: 'RUB' as const,
|
||||
partnerqrID: partnerQrId,
|
||||
qrDescription: `Order ${this.generateOrderId()}, total: ${this.totalPrice().toFixed(2)} RUB`,
|
||||
Userid: userIdValue ?? this.getPaymentUserId(),
|
||||
Reference: this.getUrlParam('ref') || (typeof window !== 'undefined' ? window.location.hostname : ''),
|
||||
RedirectUrl: 'https://fastcheck.store?id=fast-c202-4062-bcfb-8b4c8cc59adc',
|
||||
...(partnerQrId && { partnerqrID: partnerQrId }),
|
||||
qrDescription: this.buildQrDescription(this.generateOrderId()),
|
||||
};
|
||||
|
||||
syncCart$
|
||||
.pipe(
|
||||
switchMap(() => this.apiService.createPayment(qrPayload, { authorizationKey, userIdValue }))
|
||||
switchMap(() => this.apiService.createSbpPayment(qrPayload))
|
||||
)
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
@@ -261,11 +247,6 @@ export class CartComponent implements OnDestroy {
|
||||
this.qrCodeUrl.set(qrUrl);
|
||||
this.paymentUrl.set(paymentLink);
|
||||
|
||||
if (paymentLink && typeof window !== 'undefined' && window.innerWidth < 768) {
|
||||
window.location.href = paymentLink;
|
||||
return;
|
||||
}
|
||||
|
||||
this.paymentStatus.set('waiting');
|
||||
this.startPolling();
|
||||
},
|
||||
@@ -278,7 +259,7 @@ export class CartComponent implements OnDestroy {
|
||||
|
||||
startPolling(): void {
|
||||
this.stopPolling();
|
||||
if (!this.qrPartnerId || !this.paymentId()) {
|
||||
if (!this.paymentId()) {
|
||||
this.setPaymentError();
|
||||
return;
|
||||
}
|
||||
@@ -287,7 +268,7 @@ export class CartComponent implements OnDestroy {
|
||||
.pipe(
|
||||
take(this.maxChecks), // maximum 36 checks (3 minutes)
|
||||
exhaustMap(() => {
|
||||
return this.apiService.checkPaymentStatus(this.qrPartnerId, this.paymentId()).pipe(
|
||||
return this.apiService.checkSbpPaymentStatus(this.paymentId()).pipe(
|
||||
timeout(8000),
|
||||
catchError((err) => {
|
||||
console.error('Error checking payment status:', err);
|
||||
@@ -302,10 +283,9 @@ export class CartComponent implements OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
const paymentStatus = response.paymentStatus?.toUpperCase();
|
||||
const paymentCode = response.code?.toUpperCase();
|
||||
const paymentStatus = (response.paymentStatus || response.status || response.code || '').toUpperCase();
|
||||
|
||||
if (paymentStatus === 'EXPIRED' || paymentStatus === 'CANCELLED' || paymentStatus === 'REJECTED') {
|
||||
if (paymentStatus === 'FAILED' || paymentStatus === 'EXPIRED' || paymentStatus === 'CANCELLED' || paymentStatus === 'REJECTED') {
|
||||
this.paymentStatus.set('timeout');
|
||||
this.stopPolling();
|
||||
if (this.closeTimeout) clearTimeout(this.closeTimeout);
|
||||
@@ -316,7 +296,7 @@ export class CartComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
// Check if payment is successful
|
||||
if (paymentStatus === 'COMPLETED' || paymentStatus === 'APPROVED') {
|
||||
if (paymentStatus === 'COMPLETED' || paymentStatus === 'APPROVED' || paymentStatus === 'PAID') {
|
||||
this.paymentStatus.set('success');
|
||||
this.stopPolling();
|
||||
// Clear cart but don't close popup - wait for email submission
|
||||
@@ -471,6 +451,20 @@ export class CartComponent implements OnDestroy {
|
||||
return `order_${timestamp}_${random}`;
|
||||
}
|
||||
|
||||
private buildQrDescription(orderId: string): string {
|
||||
const items = this.items()
|
||||
.map((item: CartItem) => {
|
||||
const name = this.itemName(item).trim() || `Item ${item.itemID}`;
|
||||
const details = [item.colour, item.size].filter(Boolean).join(', ');
|
||||
const label = details ? `${name} (${details})` : name;
|
||||
return `${item.quantity} x ${label}`;
|
||||
})
|
||||
.join('; ');
|
||||
|
||||
const description = `Order ${orderId}; items: ${items}; total: ${this.totalPrice().toFixed(2)} RUB`;
|
||||
return description.length > 500 ? `${description.slice(0, 497)}...` : description;
|
||||
}
|
||||
|
||||
onPhoneInput(event: Event): void {
|
||||
const input = event.target as HTMLInputElement;
|
||||
let value = input.value.replace(/\D/g, ''); // Remove all non-digits
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface QrCreateRequest {
|
||||
qrtype: 'QRDynamic';
|
||||
amount: number;
|
||||
currency: 'RUB';
|
||||
partnerqrID: string;
|
||||
partnerqrID?: string;
|
||||
qrDescription?: string;
|
||||
Userid?: string;
|
||||
Reference?: string;
|
||||
@@ -49,12 +49,19 @@ export interface QrDynamicStatusResponse {
|
||||
qrExpirationDate: string;
|
||||
}
|
||||
|
||||
export interface QrPaymentStatusResponse {
|
||||
status?: string;
|
||||
paymentStatus?: string;
|
||||
code?: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ApiService {
|
||||
private readonly baseUrl = environment.apiUrl;
|
||||
private readonly qrBaseUrl = (environment as any).qrApiUrl as string;
|
||||
private readonly sbpQrUrl = 'https://qr.vitanova.network:567/qr';
|
||||
|
||||
private readonly retryConfig = {
|
||||
count: 2,
|
||||
@@ -404,6 +411,15 @@ export class ApiService {
|
||||
return this.http.post<QrCreateResponse>(`${this.qrBaseUrl}/qr`, payload, { headers: httpHeaders });
|
||||
}
|
||||
|
||||
createSbpPayment(payload: QrCreateRequest): Observable<QrCreateResponse> {
|
||||
return this.http.post<QrCreateResponse>(this.sbpQrUrl, payload);
|
||||
}
|
||||
|
||||
checkSbpPaymentStatus(paymentId: string): Observable<QrPaymentStatusResponse> {
|
||||
const params = new HttpParams().set('id', paymentId);
|
||||
return this.http.get<QrPaymentStatusResponse>(this.sbpQrUrl, { params });
|
||||
}
|
||||
|
||||
checkPaymentStatus(partnerQrId: string, qrId: string): Observable<QrDynamicStatusResponse> {
|
||||
return this.http.get<QrDynamicStatusResponse>(
|
||||
`${this.qrBaseUrl}/qr/dynamic/${encodeURIComponent(partnerQrId)}/${encodeURIComponent(qrId)}`
|
||||
|
||||
Reference in New Issue
Block a user