diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 8e3494a..7c931b6 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -139,6 +139,11 @@ export class AuthController { // Lock session in Redis with IP await this.sessionService.lockSession(agentConfig.ozonetelAgentId, memberId, clientIp); + // Force-refresh Ozonetel API token on login + this.ozonetelAgent.refreshToken().catch(err => { + this.logger.warn(`Ozonetel token refresh on login failed: ${err.message}`); + }); + // Login to Ozonetel with agent-specific credentials const ozAgentPassword = process.env.OZONETEL_AGENT_PASSWORD ?? 'Test123$'; this.ozonetelAgent.loginAgent({ diff --git a/src/ozonetel/ozonetel-agent.service.ts b/src/ozonetel/ozonetel-agent.service.ts index 8267b1d..789d6e3 100644 --- a/src/ozonetel/ozonetel-agent.service.ts +++ b/src/ozonetel/ozonetel-agent.service.ts @@ -22,6 +22,10 @@ export class OzonetelAgentService { return this.cachedToken; } + return this.refreshToken(); + } + + async refreshToken(): Promise { const url = `https://${this.apiDomain}/ca_apis/CAToken/generateToken`; this.logger.log('Generating CloudAgent API token'); @@ -32,7 +36,7 @@ export class OzonetelAgentService { const data = response.data; if (data.token) { this.cachedToken = data.token; - this.tokenExpiry = Date.now() + 55 * 60 * 1000; + this.tokenExpiry = Date.now() + 10 * 60 * 1000; // 10 min cache (Ozonetel expires in ~15 min) this.logger.log('CloudAgent token generated successfully'); return data.token; } @@ -40,6 +44,12 @@ export class OzonetelAgentService { throw new Error(data.message ?? 'Token generation failed'); } + private invalidateToken(): void { + this.cachedToken = null; + this.tokenExpiry = 0; + } + + async loginAgent(params: { agentId: string; password: string; @@ -83,6 +93,7 @@ export class OzonetelAgentService { this.logger.log(`Agent login response: ${JSON.stringify(data)}`); return data; } catch (error: any) { + if (error?.response?.status === 401) this.invalidateToken(); this.logger.error(`Agent login failed: ${error.message}`); throw error; } @@ -111,10 +122,10 @@ export class OzonetelAgentService { 'Content-Type': 'application/json', }, }); - this.logger.log(`Manual dial response: ${JSON.stringify(response.data)}`); return response.data; } catch (error: any) { + if (error?.response?.status === 401) this.invalidateToken(); const responseData = error?.response?.data ? JSON.stringify(error.response.data) : ''; this.logger.error(`Manual dial failed: ${error.message} ${responseData}`); throw error; @@ -304,6 +315,7 @@ export class OzonetelAgentService { } return []; } catch (error: any) { + if (error?.response?.status === 401) this.invalidateToken(); this.logger.error(`Abandon calls failed: ${error.message}`); return []; } @@ -393,6 +405,7 @@ export class OzonetelAgentService { } return null; } catch (error: any) { + if (error?.response?.status === 401) this.invalidateToken(); this.logger.error(`Agent summary failed: ${error.message}`); return null; } @@ -422,6 +435,7 @@ export class OzonetelAgentService { } return '00:00:00'; } catch (error: any) { + if (error?.response?.status === 401) this.invalidateToken(); this.logger.error(`AHT failed: ${error.message}`); return '00:00:00'; } @@ -459,6 +473,7 @@ export class OzonetelAgentService { this.logger.log(`Agent logout response: ${JSON.stringify(response.data)}`); return response.data; } catch (error: any) { + if (error?.response?.status === 401) this.invalidateToken(); this.logger.error(`Agent logout failed: ${error.message}`); throw error; }