Files
tbbank-react-native-mobile/src/services/authService.js

539 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import AsyncStorage from '@react-native-async-storage/async-storage';
import { API_CONFIG } from '../constants/api';
class AuthService {
async getStoredToken() {
try {
return await AsyncStorage.getItem('auth_token');
} catch (error) {
return null;
}
}
async makeRequest(endpoint, data, requiresAuth = false, method = 'POST') {
const fullUrl = `${API_CONFIG.BASE_URL}${endpoint}`;
const requestId = Math.random().toString(36).substr(2, 9);
try {
const headers = { ...API_CONFIG.HEADERS };
// Determine body and adjust headers for FormData
let bodyToSend;
if (data instanceof FormData) {
bodyToSend = data;
// Let fetch set correct Content-Type with boundary
if (headers['Content-Type']) delete headers['Content-Type'];
} else {
bodyToSend = data ? JSON.stringify(data) : undefined;
}
// Auto-include token for authenticated requests
if (requiresAuth) {
const token = await this.getStoredToken();
if (token) {
headers.Authorization = `Bearer ${token}`;
}
}
// Log request details
console.log(`\n🚀 [${requestId}] API REQUEST`);
console.log(`📍 URL: ${method} ${fullUrl}`);
console.log(`🔐 Auth Required: ${requiresAuth}`);
console.log(`📝 Headers:`, {
...headers,
Authorization: headers.Authorization ? `Bearer ${headers.Authorization.slice(-10)}...` : 'None'
});
if (data) {
console.log(`📦 Body:`, data);
}
console.log(`⏰ Time: ${new Date().toISOString()}`);
const startTime = Date.now();
const response = await fetch(fullUrl, {
method,
headers,
body: bodyToSend,
});
const endTime = Date.now();
const duration = endTime - startTime;
const result = await response.json();
// Log response details
console.log(`\n✅ [${requestId}] API RESPONSE`);
console.log(`📊 Status: ${response.status} ${response.statusText}`);
console.log(`⏱️ Duration: ${duration}ms`);
console.log(`📄 Response:`, result);
if (!response.ok) {
console.log(`❌ [${requestId}] API ERROR`);
console.log(`🔴 Status: ${response.status}`);
console.log(`💬 Error Message:`, result.message || 'Unknown error');
// Handle token expiration
if (response.status === 401 && requiresAuth) {
console.log(`🔓 [${requestId}] TOKEN EXPIRED - Clearing storage`);
await AsyncStorage.removeItem('auth_token');
await AsyncStorage.removeItem('user_data');
throw new Error('Session expired. Please login again.');
}
throw new Error(result.message || 'An error occurred');
}
console.log(`✨ [${requestId}] REQUEST COMPLETED SUCCESSFULLY\n`);
return result;
} catch (error) {
console.log(`\n💥 [${requestId}] API REQUEST FAILED`);
console.log(`📍 URL: ${method} ${fullUrl}`);
console.log(`🔴 Error:`, error.message);
console.log(`📅 Time: ${new Date().toISOString()}\n`);
throw new Error(error.message || 'Network error');
}
}
async login(phone, password) {
return this.makeRequest(API_CONFIG.ENDPOINTS.AUTH.LOGIN, {
phone: parseInt(phone),
password,
});
}
async register(phone, name, password) {
return this.makeRequest(API_CONFIG.ENDPOINTS.AUTH.REGISTER, {
phone: parseInt(phone),
name,
password,
});
}
async verify(phone, code) {
return this.makeRequest(API_CONFIG.ENDPOINTS.AUTH.VERIFY, {
phone: parseInt(phone),
code: parseInt(code),
});
}
// Authenticated API methods
async getProfile() {
return this.makeRequest('/profile', null, true, 'GET');
}
async updateProfile(data) {
return this.makeRequest('/profile', data, true, 'POST');
}
async getTransactions(page = 1, limit = 20) {
return this.makeRequest(`/user/transactions?page=${page}&limit=${limit}`, null, true, 'GET');
}
async getBalance() {
return this.makeRequest('/user/balance', null, true, 'GET');
}
// NEW: Fetch metrics for dashboard
async getMetrics() {
return this.makeRequest('/metrics', null, true, 'GET');
}
async transferMoney(data) {
return this.makeRequest('/user/transfer', data, true);
}
async payBill(data) {
return this.makeRequest('/user/pay-bill', data, true);
}
async getCards() {
return this.makeRequest('/user/cards', null, true, 'GET');
}
async addCard(data) {
return this.makeRequest('/user/cards', data, true);
}
async blockCard(cardId) {
return this.makeRequest(`/user/cards/${cardId}/block`, null, true);
}
async unblockCard(cardId) {
return this.makeRequest(`/user/cards/${cardId}/unblock`, null, true);
}
async changePassword(currentPassword, newPassword) {
return this.makeRequest('/user/change-password', {
current_password: currentPassword,
new_password: newPassword,
}, true);
}
async deleteAccount() {
return this.makeRequest('/user/delete-account', null, true, 'DELETE');
}
// ================================
// Loan Remaining Order (Karzyň galyndysy)
// ================================
// Helper to read cached user data (for passport details)
async getStoredUser() {
try {
const raw = await AsyncStorage.getItem('user_data');
return raw ? JSON.parse(raw) : null;
} catch (e) {
return null;
}
}
// LIST orders
async getLoanRemainingOrders() {
return this.makeRequest('/loan-remaining-order', null, true, 'GET');
}
// CREATE order (passport can be supplied or fetched from profile)
async createLoanRemainingOrder(accountNumber, passportSerie = null, passportId = null) {
let serie = passportSerie;
let pid = passportId;
if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
}
const payload = {
passport_serie: serie,
passport_id: pid,
account_number: accountNumber,
};
return this.makeRequest('/loan-remaining-order', payload, true, 'POST');
}
// SHOW order details
async getLoanRemainingOrder(orderId) {
return this.makeRequest(`/loan-remaining-order/${orderId}`, null, true, 'GET');
}
// UPDATE order (only account number can change; passport details stay the same)
async updateLoanRemainingOrder(orderId, accountNumber, passportSerie = null, passportId = null) {
let serie = passportSerie;
let pid = passportId;
if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
}
const payload = {
passport_serie: serie,
passport_id: pid,
account_number: accountNumber,
};
return this.makeRequest(`/loan-remaining-order/${orderId}`, payload, true, 'POST');
}
// DELETE order
async deleteLoanRemainingOrder(orderId) {
return this.makeRequest(`/loan-remaining-order/${orderId}`, null, true, 'DELETE');
}
// ================================
// Loan remaining quick check (returns remaining balance info)
// ================================
async getLoanRemainingBalance(accountNumber, passportSerie = null, passportId = null) {
let serie = passportSerie;
let pid = passportId;
if (!serie || !pid) {
const user = await this.getStoredUser();
serie = user?.passport_serie;
pid = user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
}
const query = `passport_serie=${encodeURIComponent(serie)}&passport_id=${encodeURIComponent(pid)}&account_number=${encodeURIComponent(accountNumber)}`;
return this.makeRequest(`/loan-remaining?${query}`, null, true, 'GET');
}
// ================================
// Loan Paid-Off Letter Orders
// ================================
// LIST
async getLoanPaidOffLetterOrders() {
return this.makeRequest('/loan-paid-off-letter-orders', null, true, 'GET');
}
// CREATE
async createLoanPaidOffLetterOrder(data) {
return this.makeRequest('/loan-paid-off-letter-orders', data, true, 'POST');
}
// SHOW
async getLoanPaidOffLetterOrder(orderId) {
return this.makeRequest(`/loan-paid-off-letter-orders/${orderId}`, null, true, 'GET');
}
// UPDATE
async updateLoanPaidOffLetterOrder(orderId, data) {
return this.makeRequest(`/loan-paid-off-letter-orders/${orderId}`, data, true, 'POST');
}
// DELETE
async deleteLoanPaidOffLetterOrder(orderId) {
return this.makeRequest(`/loan-paid-off-letter-orders/${orderId}`, null, true, 'DELETE');
}
// ================================
// Loan Orders (Karz sargytlary)
// ================================
// LIST
async getLoanOrders() {
return this.makeRequest('/loan-order', null, true, 'GET');
}
// CREATE
async createLoanOrder(data) {
return this.makeRequest('/loan-order', data, true, 'POST');
}
// SHOW
async getLoanOrder(orderId) {
return this.makeRequest(`/loan-order/${orderId}`, null, true, 'GET');
}
// UPDATE
async updateLoanOrder(orderId, data) {
return this.makeRequest(`/loan-order/${orderId}`, data, true, 'POST');
}
// DELETE
async deleteLoanOrder(orderId) {
return this.makeRequest(`/loan-order/${orderId}`, null, true, 'DELETE');
}
// ================================
// Card Transactions Orders (Kart hereketleri)
// ================================
// LIST
async getCardTransactionOrders() {
return this.makeRequest('/card-transactions', null, true, 'GET');
}
// CREATE order (auto-fills passport data from stored profile)
async createCardTransactionOrder(cardNumber, cardMonth, cardYear, passportSerie = null, passportId = null) {
let serie = passportSerie;
let pid = passportId;
if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
}
const payload = {
passport_serie: serie,
passport_id: pid,
card_number: cardNumber,
card_month: cardMonth,
card_year: cardYear,
};
return this.makeRequest('/card-transactions', payload, true, 'POST');
}
// SHOW
async getCardTransactionOrder(orderId) {
return this.makeRequest(`/card-transactions/${orderId}`, null, true, 'GET');
}
// UPDATE
async updateCardTransactionOrder(orderId, cardNumber, cardMonth, cardYear, passportSerie = null, passportId = null) {
let serie = passportSerie;
let pid = passportId;
if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
}
const payload = {
passport_serie: serie,
passport_id: pid,
card_number: cardNumber,
card_month: cardMonth,
card_year: cardYear,
};
return this.makeRequest(`/card-transactions/${orderId}`, payload, true, 'POST');
}
// DELETE
async deleteCardTransactionOrder(orderId) {
return this.makeRequest(`/card-transactions/${orderId}`, null, true, 'DELETE');
}
// DOWNLOAD (returns object with url)
async downloadCardTransactions(orderId, startDate, endDate) {
const query = `start_date=${encodeURIComponent(startDate)}&end_date=${encodeURIComponent(endDate)}`;
return this.makeRequest(`/card-transactions-download/${orderId}?${query}`, null, true, 'GET');
}
// ================================
// Card balance quick check (Kart galyndysy)
// ================================
async getCardBalanceQuickCheck(cardNumber = null, cardMonth = null, cardYear = null, passportSerie = null, passportId = null) {
// Fallback to stored user profile for missing fields
let serie = passportSerie;
let pid = passportId;
let cNumber = cardNumber;
let cMonth = cardMonth;
let cYear = cardYear;
if (!serie || !pid || !cNumber || !cMonth || !cYear) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
cNumber = cNumber || user?.card_number;
cMonth = cMonth || user?.card_month;
cYear = cYear || user?.card_year;
}
if (!serie || !pid || !cNumber || !cMonth || !cYear) {
throw new Error('Card or passport details are missing');
}
// Ensure values are properly formatted
const plainCardNumber = String(cNumber).replace(/[^0-9]/g, '').slice(0, 16);
const monthStr = String(cMonth).padStart(2, '0');
const payload = {
passport_serie: serie,
passport_id: pid,
card_number: plainCardNumber,
card_month: monthStr,
card_year: String(cYear),
};
// POST request authenticated (token header will be included if available)
return this.makeRequest('/card-balance-quick-check', payload, true, 'POST');
}
// ================================
// Card Balance Orders (Kart galyndylary)
// ================================
// LIST
async getCardBalanceOrders() {
return this.makeRequest('/card-balances', null, true, 'GET');
}
// CREATE
async createCardBalanceOrder(cardNumber, cardMonth, cardYear, passportSerie = null, passportId = null) {
let serie = passportSerie;
let pid = passportId;
if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
}
const payload = {
passport_serie: serie,
passport_id: pid,
card_number: cardNumber,
card_month: cardMonth,
card_year: cardYear,
};
return this.makeRequest('/card-balances', payload, true, 'POST');
}
// SHOW
async getCardBalanceOrder(orderId) {
return this.makeRequest(`/card-balances/${orderId}`, null, true, 'GET');
}
// UPDATE
async updateCardBalanceOrder(orderId, cardNumber, cardMonth, cardYear, passportSerie = null, passportId = null) {
let serie = passportSerie;
let pid = passportId;
if (!serie || !pid) {
const user = await this.getStoredUser();
serie = serie || user?.passport_serie;
pid = pid || user?.passport_id;
}
if (!serie || !pid) {
throw new Error('Passport details are missing');
}
const payload = {
passport_serie: serie,
passport_id: pid,
card_number: cardNumber,
card_month: cardMonth,
card_year: cardYear,
};
return this.makeRequest(`/card-balances/${orderId}`, payload, true, 'POST');
}
// DELETE
async deleteCardBalanceOrder(orderId) {
return this.makeRequest(`/card-balances/${orderId}`, null, true, 'DELETE');
}
// DOWNLOAD (returns object with card details)
async downloadCardBalances(orderId) {
return this.makeRequest(`/card-balances-download/${orderId}`, null, true, 'GET');
}
// ================================
// Card Requisites Orders (Kart rekwizitler)
// ================================
// LIST
async getCardRequisiteOrders() {
return this.makeRequest('/card-requisites', null, true, 'GET');
}
// CREATE (passport + card info)
async createCardRequisiteOrder(payload) {
/* payload expected keys: passport_serie, passport_id, card_number, card_month, card_year, maybe card_name */
return this.makeRequest('/card-requisites', payload, true, 'POST');
}
// SHOW
async getCardRequisiteOrder(orderId) {
return this.makeRequest(`/card-requisites/${orderId}`, null, true, 'GET');
}
// UPDATE
async updateCardRequisiteOrder(orderId, payload) {
return this.makeRequest(`/card-requisites/${orderId}`, payload, true, 'POST');
}
// DELETE
async deleteCardRequisiteOrder(orderId) {
return this.makeRequest(`/card-requisites/${orderId}`, null, true, 'DELETE');
}
// DOWNLOAD
async downloadCardRequisites(orderId) {
return this.makeRequest(`/card-requisites-download/${orderId}`, null, true, 'GET');
}
}
export default new AuthService();