Refactor Freebit integration services to enhance type safety and maintainability by utilizing updated provider methods and removing deprecated types. Update authentication and mapping logic to align with the new domain structure, improving data handling consistency across services. Introduce new response transformation methods for Freebit authentication, ensuring robust error handling and streamlined integration.
This commit is contained in:
parent
12c3dc976f
commit
c206598615
@ -3,12 +3,21 @@ import { ConfigService } from "@nestjs/config";
|
|||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util";
|
import { getErrorMessage } from "@bff/core/utils/error.util";
|
||||||
import type {
|
import type {
|
||||||
FreebitConfig,
|
AuthRequest as FreebitAuthRequest,
|
||||||
FreebitAuthRequest,
|
AuthResponse as FreebitAuthResponse,
|
||||||
FreebitAuthResponse,
|
|
||||||
} from "@customer-portal/domain/sim/providers/freebit";
|
} from "@customer-portal/domain/sim/providers/freebit";
|
||||||
|
import { Providers } from "@customer-portal/domain/sim";
|
||||||
import { FreebitError } from "./freebit-error.service";
|
import { FreebitError } from "./freebit-error.service";
|
||||||
|
|
||||||
|
interface FreebitConfig {
|
||||||
|
baseUrl: string;
|
||||||
|
oemId: string;
|
||||||
|
oemKey: string;
|
||||||
|
timeout: number;
|
||||||
|
retryAttempts: number;
|
||||||
|
detailsEndpoint?: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FreebitAuthService {
|
export class FreebitAuthService {
|
||||||
private readonly config: FreebitConfig;
|
private readonly config: FreebitConfig;
|
||||||
@ -60,10 +69,10 @@ export class FreebitAuthService {
|
|||||||
throw new Error("Freebit API not configured: FREEBIT_OEM_KEY is missing");
|
throw new Error("Freebit API not configured: FREEBIT_OEM_KEY is missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
const request: FreebitAuthRequest = {
|
const request = Providers.Freebit.schemas.auth.parse({
|
||||||
oemId: this.config.oemId,
|
oemId: this.config.oemId,
|
||||||
oemKey: this.config.oemKey,
|
oemKey: this.config.oemKey,
|
||||||
};
|
});
|
||||||
|
|
||||||
const response = await fetch(`${this.config.baseUrl}/authOem/`, {
|
const response = await fetch(`${this.config.baseUrl}/authOem/`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -75,13 +84,15 @@ export class FreebitAuthService {
|
|||||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = (await response.json()) as FreebitAuthResponse;
|
const json = (await response.json()) as unknown;
|
||||||
if (data.resultCode !== "100") {
|
const data = Providers.Freebit.mapper.transformFreebitAuthResponse(json);
|
||||||
|
|
||||||
|
if (data.resultCode !== "100" || !data.authKey) {
|
||||||
throw new FreebitError(
|
throw new FreebitError(
|
||||||
`Authentication failed: ${data.status.message}`,
|
`Authentication failed: ${data.status?.message ?? "Unknown error"}`,
|
||||||
data.resultCode,
|
data.resultCode,
|
||||||
data.status.statusCode,
|
data.status?.statusCode,
|
||||||
data.status.message
|
data.status?.message
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
import { Injectable } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
import type {
|
|
||||||
FreebitAccountDetailsResponse,
|
|
||||||
FreebitTrafficInfoResponse,
|
|
||||||
FreebitQuotaHistoryResponse,
|
|
||||||
} from "@customer-portal/domain/sim/providers/freebit";
|
|
||||||
import type { SimDetails, SimTopUpHistory, SimUsage } from "@customer-portal/domain/sim";
|
import type { SimDetails, SimTopUpHistory, SimUsage } from "@customer-portal/domain/sim";
|
||||||
import { Providers } from "@customer-portal/domain/sim";
|
import { Providers } from "@customer-portal/domain/sim";
|
||||||
|
|
||||||
@ -12,21 +7,21 @@ export class FreebitMapperService {
|
|||||||
/**
|
/**
|
||||||
* Map Freebit account details response to SimDetails
|
* Map Freebit account details response to SimDetails
|
||||||
*/
|
*/
|
||||||
mapToSimDetails(response: FreebitAccountDetailsResponse): SimDetails {
|
mapToSimDetails(response: unknown): SimDetails {
|
||||||
return Providers.Freebit.transformFreebitAccountDetails(response);
|
return Providers.Freebit.transformFreebitAccountDetails(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map Freebit traffic info response to SimUsage
|
* Map Freebit traffic info response to SimUsage
|
||||||
*/
|
*/
|
||||||
mapToSimUsage(response: FreebitTrafficInfoResponse): SimUsage {
|
mapToSimUsage(response: unknown): SimUsage {
|
||||||
return Providers.Freebit.transformFreebitTrafficInfo(response);
|
return Providers.Freebit.transformFreebitTrafficInfo(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map Freebit quota history response to SimTopUpHistory
|
* Map Freebit quota history response to SimTopUpHistory
|
||||||
*/
|
*/
|
||||||
mapToSimTopUpHistory(response: FreebitQuotaHistoryResponse, account: string): SimTopUpHistory {
|
mapToSimTopUpHistory(response: unknown, account: string): SimTopUpHistory {
|
||||||
return Providers.Freebit.transformFreebitQuotaHistory(response, account);
|
return Providers.Freebit.transformFreebitQuotaHistory(response, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,16 +5,15 @@ import { FreebitClientService } from "./freebit-client.service";
|
|||||||
import { FreebitMapperService } from "./freebit-mapper.service";
|
import { FreebitMapperService } from "./freebit-mapper.service";
|
||||||
import { FreebitAuthService } from "./freebit-auth.service";
|
import { FreebitAuthService } from "./freebit-auth.service";
|
||||||
import type {
|
import type {
|
||||||
FreebitAccountDetailsResponse,
|
TopUpResponse,
|
||||||
FreebitTrafficInfoResponse,
|
PlanChangeResponse,
|
||||||
FreebitTopUpResponse,
|
AddSpecResponse,
|
||||||
FreebitQuotaHistoryResponse,
|
CancelPlanResponse,
|
||||||
FreebitPlanChangeResponse,
|
CancelAccountResponse,
|
||||||
FreebitAddSpecResponse,
|
EsimReissueResponse,
|
||||||
FreebitCancelPlanResponse,
|
EsimAddAccountResponse,
|
||||||
FreebitEsimReissueResponse,
|
EsimActivationResponse,
|
||||||
FreebitEsimAddAccountResponse,
|
QuotaHistoryRequest,
|
||||||
FreebitEsimAccountActivationResponse,
|
|
||||||
} from "@customer-portal/domain/sim/providers/freebit";
|
} from "@customer-portal/domain/sim/providers/freebit";
|
||||||
import type {
|
import type {
|
||||||
FreebitTopUpRequest,
|
FreebitTopUpRequest,
|
||||||
@ -73,7 +72,7 @@ export class FreebitOperationsService {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
let response: FreebitAccountDetailsResponse | undefined;
|
let response: Providers.Freebit.mapper.FreebitAccountDetailsResponse | undefined;
|
||||||
let lastError: unknown;
|
let lastError: unknown;
|
||||||
|
|
||||||
for (const ep of candidates) {
|
for (const ep of candidates) {
|
||||||
@ -82,7 +81,7 @@ export class FreebitOperationsService {
|
|||||||
this.logger.warn(`Retrying Freebit account details with alternative endpoint: ${ep}`);
|
this.logger.warn(`Retrying Freebit account details with alternative endpoint: ${ep}`);
|
||||||
}
|
}
|
||||||
response = await this.client.makeAuthenticatedRequest<
|
response = await this.client.makeAuthenticatedRequest<
|
||||||
FreebitAccountDetailsResponse,
|
Providers.Freebit.mapper.FreebitAccountDetailsResponse,
|
||||||
typeof request
|
typeof request
|
||||||
>(ep, request);
|
>(ep, request);
|
||||||
break;
|
break;
|
||||||
@ -120,7 +119,7 @@ export class FreebitOperationsService {
|
|||||||
const request: FreebitTrafficInfoRequest = Providers.Freebit.schemas.trafficInfo.parse({ account });
|
const request: FreebitTrafficInfoRequest = Providers.Freebit.schemas.trafficInfo.parse({ account });
|
||||||
|
|
||||||
const response = await this.client.makeAuthenticatedRequest<
|
const response = await this.client.makeAuthenticatedRequest<
|
||||||
FreebitTrafficInfoResponse,
|
Providers.Freebit.mapper.FreebitTrafficInfoResponse,
|
||||||
typeof request
|
typeof request
|
||||||
>("/mvno/getTrafficInfo/", request);
|
>("/mvno/getTrafficInfo/", request);
|
||||||
|
|
||||||
@ -159,7 +158,7 @@ export class FreebitOperationsService {
|
|||||||
? { ...baseRequest, runTime: payload.options?.scheduledAt }
|
? { ...baseRequest, runTime: payload.options?.scheduledAt }
|
||||||
: baseRequest;
|
: baseRequest;
|
||||||
|
|
||||||
await this.client.makeAuthenticatedRequest<FreebitTopUpResponse, typeof request>(
|
await this.client.makeAuthenticatedRequest<TopUpResponse, typeof request>(
|
||||||
endpoint,
|
endpoint,
|
||||||
request
|
request
|
||||||
);
|
);
|
||||||
@ -198,8 +197,8 @@ export class FreebitOperationsService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const response = await this.client.makeAuthenticatedRequest<
|
const response = await this.client.makeAuthenticatedRequest<
|
||||||
FreebitQuotaHistoryResponse,
|
Providers.Freebit.mapper.FreebitQuotaHistoryResponse,
|
||||||
FreebitQuotaHistoryRequest
|
QuotaHistoryRequest
|
||||||
>("/mvno/getQuotaHistory/", request);
|
>("/mvno/getQuotaHistory/", request);
|
||||||
|
|
||||||
return this.mapper.mapToSimTopUpHistory(response, account);
|
return this.mapper.mapToSimTopUpHistory(response, account);
|
||||||
@ -239,10 +238,10 @@ export class FreebitOperationsService {
|
|||||||
runTime: parsed.scheduledAt,
|
runTime: parsed.scheduledAt,
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await this.client.makeAuthenticatedRequest<
|
const response = await this.client.makeAuthenticatedRequest<PlanChangeResponse, typeof request>(
|
||||||
FreebitPlanChangeResponse,
|
"/mvno/changePlan/",
|
||||||
typeof request
|
request
|
||||||
>("/mvno/changePlan/", request);
|
);
|
||||||
|
|
||||||
this.logger.log(`Successfully changed plan for account ${parsed.account} to ${parsed.newPlanCode}`, {
|
this.logger.log(`Successfully changed plan for account ${parsed.account} to ${parsed.newPlanCode}`, {
|
||||||
account: parsed.account,
|
account: parsed.account,
|
||||||
@ -314,7 +313,7 @@ export class FreebitOperationsService {
|
|||||||
payload.contractLine = features.networkType;
|
payload.contractLine = features.networkType;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.client.makeAuthenticatedRequest<FreebitAddSpecResponse, typeof payload>(
|
await this.client.makeAuthenticatedRequest<AddSpecResponse, typeof payload>(
|
||||||
"/master/addSpec/",
|
"/master/addSpec/",
|
||||||
payload
|
payload
|
||||||
);
|
);
|
||||||
@ -352,7 +351,7 @@ export class FreebitOperationsService {
|
|||||||
runTime: parsed.runDate,
|
runTime: parsed.runDate,
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.client.makeAuthenticatedRequest<FreebitCancelPlanResponse, typeof request>(
|
await this.client.makeAuthenticatedRequest<CancelPlanResponse, typeof request>(
|
||||||
"/mvno/releasePlan/",
|
"/mvno/releasePlan/",
|
||||||
request
|
request
|
||||||
);
|
);
|
||||||
@ -381,7 +380,7 @@ export class FreebitOperationsService {
|
|||||||
requestDatas: [{ kind: "MVNO", account }],
|
requestDatas: [{ kind: "MVNO", account }],
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.client.makeAuthenticatedRequest<FreebitEsimReissueResponse, typeof request>(
|
await this.client.makeAuthenticatedRequest<EsimReissueResponse, typeof request>(
|
||||||
"/mvno/reissueEsim/",
|
"/mvno/reissueEsim/",
|
||||||
request
|
request
|
||||||
);
|
);
|
||||||
@ -422,14 +421,14 @@ export class FreebitOperationsService {
|
|||||||
planCode: parsed.planCode,
|
planCode: parsed.planCode,
|
||||||
});
|
});
|
||||||
|
|
||||||
const request: FreebitEsimAddAccountRequest = {
|
const payload: FreebitEsimAddAccountRequest = {
|
||||||
...requestPayload,
|
...requestPayload,
|
||||||
authKey: await this.auth.getAuthKey(),
|
authKey: await this.auth.getAuthKey(),
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.client.makeAuthenticatedRequest<FreebitEsimAddAccountResponse, FreebitEsimAddAccountRequest>(
|
await this.client.makeAuthenticatedRequest<EsimAddAccountResponse, FreebitEsimAddAccountRequest>(
|
||||||
"/mvno/esim/addAcnt/",
|
"/mvno/esim/addAcnt/",
|
||||||
request
|
payload
|
||||||
);
|
);
|
||||||
|
|
||||||
this.logger.log(`Successfully reissued eSIM profile via addAcnt for account ${parsed.account}`, {
|
this.logger.log(`Successfully reissued eSIM profile via addAcnt for account ${parsed.account}`, {
|
||||||
@ -515,10 +514,10 @@ export class FreebitOperationsService {
|
|||||||
Providers.Freebit.schemas.esimActivationRequest.parse(payload);
|
Providers.Freebit.schemas.esimActivationRequest.parse(payload);
|
||||||
|
|
||||||
// Use JSON request for PA05-41
|
// Use JSON request for PA05-41
|
||||||
await this.client.makeAuthenticatedJsonRequest<
|
await this.client.makeAuthenticatedJsonRequest<EsimActivationResponse, typeof payload>(
|
||||||
FreebitEsimAccountActivationResponse,
|
"/mvno/esim/addAcct/",
|
||||||
typeof payload
|
payload
|
||||||
>("/mvno/esim/addAcct/", payload);
|
);
|
||||||
|
|
||||||
this.logger.log("Successfully activated new eSIM account via PA05-41", {
|
this.logger.log("Successfully activated new eSIM account via PA05-41", {
|
||||||
account,
|
account,
|
||||||
|
|||||||
@ -47,6 +47,7 @@ export type CancelAccountResponse = ReturnType<typeof Mapper.transformFreebitCan
|
|||||||
export type EsimReissueResponse = ReturnType<typeof Mapper.transformFreebitEsimReissueResponse>;
|
export type EsimReissueResponse = ReturnType<typeof Mapper.transformFreebitEsimReissueResponse>;
|
||||||
export type EsimAddAccountResponse = ReturnType<typeof Mapper.transformFreebitEsimAddAccountResponse>;
|
export type EsimAddAccountResponse = ReturnType<typeof Mapper.transformFreebitEsimAddAccountResponse>;
|
||||||
export type EsimActivationResponse = ReturnType<typeof Mapper.transformFreebitEsimActivationResponse>;
|
export type EsimActivationResponse = ReturnType<typeof Mapper.transformFreebitEsimActivationResponse>;
|
||||||
|
export type AuthResponse = ReturnType<typeof Mapper.transformFreebitAuthResponse>;
|
||||||
|
|
||||||
export * from "./mapper";
|
export * from "./mapper";
|
||||||
export * from "./raw.types";
|
export * from "./raw.types";
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
type FreebitAccountDetailsRaw,
|
type FreebitAccountDetailsRaw,
|
||||||
type FreebitTrafficInfoRaw,
|
type FreebitTrafficInfoRaw,
|
||||||
type FreebitQuotaHistoryRaw,
|
type FreebitQuotaHistoryRaw,
|
||||||
|
type FreebitAuthResponseRaw,
|
||||||
type FreebitTopUpRaw,
|
type FreebitTopUpRaw,
|
||||||
type FreebitAddSpecRaw,
|
type FreebitAddSpecRaw,
|
||||||
type FreebitPlanChangeRaw,
|
type FreebitPlanChangeRaw,
|
||||||
@ -18,6 +19,7 @@ import {
|
|||||||
freebitAccountDetailsRawSchema,
|
freebitAccountDetailsRawSchema,
|
||||||
freebitTrafficInfoRawSchema,
|
freebitTrafficInfoRawSchema,
|
||||||
freebitQuotaHistoryRawSchema,
|
freebitQuotaHistoryRawSchema,
|
||||||
|
freebitAuthResponseRawSchema,
|
||||||
freebitTopUpRawSchema,
|
freebitTopUpRawSchema,
|
||||||
freebitAddSpecRawSchema,
|
freebitAddSpecRawSchema,
|
||||||
freebitPlanChangeRawSchema,
|
freebitPlanChangeRawSchema,
|
||||||
@ -206,4 +208,10 @@ export function transformFreebitEsimActivationResponse(raw: unknown) {
|
|||||||
return freebitEsimAddAccountRawSchema.parse(raw);
|
return freebitEsimAddAccountRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitEsimActivationResponse = ReturnType<typeof transformFreebitEsimActivationResponse>;
|
||||||
|
|
||||||
|
export function transformFreebitAuthResponse(raw: unknown): FreebitAuthResponseRaw {
|
||||||
|
return freebitAuthResponseRawSchema.parse(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -166,3 +166,16 @@ export const freebitQuotaHistoryRawSchema = z.object({
|
|||||||
|
|
||||||
export type FreebitQuotaHistoryRaw = z.infer<typeof freebitQuotaHistoryRawSchema>;
|
export type FreebitQuotaHistoryRaw = z.infer<typeof freebitQuotaHistoryRawSchema>;
|
||||||
|
|
||||||
|
export const freebitAuthResponseRawSchema = z.object({
|
||||||
|
resultCode: z.string().optional(),
|
||||||
|
status: z
|
||||||
|
.object({
|
||||||
|
message: z.string().optional(),
|
||||||
|
statusCode: z.union([z.string(), z.number()]).optional(),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
authKey: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type FreebitAuthResponseRaw = z.infer<typeof freebitAuthResponseRawSchema>;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user