Files
bedolaga-cabinet/src/api/balance.ts
Fringg 2b03e7e514 feat: send language in payment requests for localized descriptions
- Add language field to balance topup and landing purchase requests
- Cap news article featured image height with max-h-96

Cherry-picked from PR #362 (without favicon change — files don't exist)
2026-03-29 05:18:40 +03:00

155 lines
4.5 KiB
TypeScript

import apiClient from './client';
import i18n from '../i18n';
import type {
Balance,
Transaction,
PaymentMethod,
PaginatedResponse,
PendingPayment,
ManualCheckResponse,
SavedCardsResponse,
} from '../types';
export const balanceApi = {
// Get current balance
getBalance: async (): Promise<Balance> => {
const response = await apiClient.get<Balance>('/cabinet/balance');
return response.data;
},
// Get transaction history
getTransactions: async (params?: {
page?: number;
per_page?: number;
type?: string;
}): Promise<PaginatedResponse<Transaction>> => {
const response = await apiClient.get<PaginatedResponse<Transaction>>(
'/cabinet/balance/transactions',
{
params,
},
);
return response.data;
},
// Get available payment methods
getPaymentMethods: async (): Promise<PaymentMethod[]> => {
const response = await apiClient.get<PaymentMethod[]>('/cabinet/balance/payment-methods');
return response.data;
},
// Create top-up payment
createTopUp: async (
amountKopeks: number,
paymentMethod: string,
paymentOption?: string,
): Promise<{
payment_id: string;
payment_url: string;
amount_kopeks: number;
amount_rubles: number;
status: string;
expires_at: string | null;
}> => {
const payload: {
amount_kopeks: number;
payment_method: string;
payment_option?: string;
language?: string;
} = {
amount_kopeks: amountKopeks,
payment_method: paymentMethod,
};
if (paymentOption) {
payload.payment_option = paymentOption;
}
payload.language = i18n.language || 'ru';
const response = await apiClient.post('/cabinet/balance/topup', payload);
return response.data;
},
// Activate promo code
activatePromocode: async (
code: string,
subscriptionId?: number,
): Promise<{
success: boolean;
message?: string;
balance_before?: number;
balance_after?: number;
bonus_description?: string | null;
error?: string;
eligible_subscriptions?: Array<{ id: number; tariff_name: string; days_left: number }>;
code?: string;
}> => {
const response = await apiClient.post('/cabinet/promocode/activate', {
code,
...(subscriptionId ? { subscription_id: subscriptionId } : {}),
});
return response.data;
},
// Create Telegram Stars invoice for Mini App balance top-up
createStarsInvoice: async (
amountKopeks: number,
): Promise<{
invoice_url: string;
stars_amount?: number;
amount_kopeks?: number;
}> => {
const response = await apiClient.post('/cabinet/balance/stars-invoice', {
amount_kopeks: amountKopeks,
});
return response.data;
},
// Get pending payments for manual verification
getPendingPayments: async (params?: {
page?: number;
per_page?: number;
}): Promise<PaginatedResponse<PendingPayment>> => {
const response = await apiClient.get<PaginatedResponse<PendingPayment>>(
'/cabinet/balance/pending-payments',
{
params,
},
);
return response.data;
},
// Get specific pending payment details
getPendingPayment: async (method: string, paymentId: number): Promise<PendingPayment> => {
const response = await apiClient.get<PendingPayment>(
`/cabinet/balance/pending-payments/${encodeURIComponent(method)}/${encodeURIComponent(paymentId)}`,
);
return response.data;
},
// Get latest pending payment by method (fallback when sessionStorage unavailable)
getLatestPayment: async (method: string): Promise<PendingPayment> => {
const response = await apiClient.get<PendingPayment>(
`/cabinet/balance/pending-payments/${encodeURIComponent(method)}/latest`,
);
return response.data;
},
// Manually check payment status
checkPaymentStatus: async (method: string, paymentId: number): Promise<ManualCheckResponse> => {
const response = await apiClient.post<ManualCheckResponse>(
`/cabinet/balance/pending-payments/${encodeURIComponent(method)}/${encodeURIComponent(paymentId)}/check`,
);
return response.data;
},
// Get saved payment methods (cards) for recurrent payments
getSavedCards: async (): Promise<SavedCardsResponse> => {
const response = await apiClient.get<SavedCardsResponse>('/cabinet/balance/saved-cards');
return response.data;
},
// Unlink (delete) a saved payment method
deleteSavedCard: async (id: number): Promise<void> => {
await apiClient.delete(`/cabinet/balance/saved-cards/${id}`);
},
};