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 { getErrorMessage } from "@bff/core/utils/error.util";
|
||||
import type {
|
||||
FreebitConfig,
|
||||
FreebitAuthRequest,
|
||||
FreebitAuthResponse,
|
||||
AuthRequest as FreebitAuthRequest,
|
||||
AuthResponse as FreebitAuthResponse,
|
||||
} from "@customer-portal/domain/sim/providers/freebit";
|
||||
import { Providers } from "@customer-portal/domain/sim";
|
||||
import { FreebitError } from "./freebit-error.service";
|
||||
|
||||
interface FreebitConfig {
|
||||
baseUrl: string;
|
||||
oemId: string;
|
||||
oemKey: string;
|
||||
timeout: number;
|
||||
retryAttempts: number;
|
||||
detailsEndpoint?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class FreebitAuthService {
|
||||
private readonly config: FreebitConfig;
|
||||
@ -60,10 +69,10 @@ export class FreebitAuthService {
|
||||
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,
|
||||
oemKey: this.config.oemKey,
|
||||
};
|
||||
});
|
||||
|
||||
const response = await fetch(`${this.config.baseUrl}/authOem/`, {
|
||||
method: "POST",
|
||||
@ -75,13 +84,15 @@ export class FreebitAuthService {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = (await response.json()) as FreebitAuthResponse;
|
||||
if (data.resultCode !== "100") {
|
||||
const json = (await response.json()) as unknown;
|
||||
const data = Providers.Freebit.mapper.transformFreebitAuthResponse(json);
|
||||
|
||||
if (data.resultCode !== "100" || !data.authKey) {
|
||||
throw new FreebitError(
|
||||
`Authentication failed: ${data.status.message}`,
|
||||
`Authentication failed: ${data.status?.message ?? "Unknown error"}`,
|
||||
data.resultCode,
|
||||
data.status.statusCode,
|
||||
data.status.message
|
||||
data.status?.statusCode,
|
||||
data.status?.message
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,4 @@
|
||||
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 { Providers } from "@customer-portal/domain/sim";
|
||||
|
||||
@ -12,21 +7,21 @@ export class FreebitMapperService {
|
||||
/**
|
||||
* Map Freebit account details response to SimDetails
|
||||
*/
|
||||
mapToSimDetails(response: FreebitAccountDetailsResponse): SimDetails {
|
||||
mapToSimDetails(response: unknown): SimDetails {
|
||||
return Providers.Freebit.transformFreebitAccountDetails(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Freebit traffic info response to SimUsage
|
||||
*/
|
||||
mapToSimUsage(response: FreebitTrafficInfoResponse): SimUsage {
|
||||
mapToSimUsage(response: unknown): SimUsage {
|
||||
return Providers.Freebit.transformFreebitTrafficInfo(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@ -5,16 +5,15 @@ import { FreebitClientService } from "./freebit-client.service";
|
||||
import { FreebitMapperService } from "./freebit-mapper.service";
|
||||
import { FreebitAuthService } from "./freebit-auth.service";
|
||||
import type {
|
||||
FreebitAccountDetailsResponse,
|
||||
FreebitTrafficInfoResponse,
|
||||
FreebitTopUpResponse,
|
||||
FreebitQuotaHistoryResponse,
|
||||
FreebitPlanChangeResponse,
|
||||
FreebitAddSpecResponse,
|
||||
FreebitCancelPlanResponse,
|
||||
FreebitEsimReissueResponse,
|
||||
FreebitEsimAddAccountResponse,
|
||||
FreebitEsimAccountActivationResponse,
|
||||
TopUpResponse,
|
||||
PlanChangeResponse,
|
||||
AddSpecResponse,
|
||||
CancelPlanResponse,
|
||||
CancelAccountResponse,
|
||||
EsimReissueResponse,
|
||||
EsimAddAccountResponse,
|
||||
EsimActivationResponse,
|
||||
QuotaHistoryRequest,
|
||||
} from "@customer-portal/domain/sim/providers/freebit";
|
||||
import type {
|
||||
FreebitTopUpRequest,
|
||||
@ -73,7 +72,7 @@ export class FreebitOperationsService {
|
||||
])
|
||||
);
|
||||
|
||||
let response: FreebitAccountDetailsResponse | undefined;
|
||||
let response: Providers.Freebit.mapper.FreebitAccountDetailsResponse | undefined;
|
||||
let lastError: unknown;
|
||||
|
||||
for (const ep of candidates) {
|
||||
@ -82,7 +81,7 @@ export class FreebitOperationsService {
|
||||
this.logger.warn(`Retrying Freebit account details with alternative endpoint: ${ep}`);
|
||||
}
|
||||
response = await this.client.makeAuthenticatedRequest<
|
||||
FreebitAccountDetailsResponse,
|
||||
Providers.Freebit.mapper.FreebitAccountDetailsResponse,
|
||||
typeof request
|
||||
>(ep, request);
|
||||
break;
|
||||
@ -120,7 +119,7 @@ export class FreebitOperationsService {
|
||||
const request: FreebitTrafficInfoRequest = Providers.Freebit.schemas.trafficInfo.parse({ account });
|
||||
|
||||
const response = await this.client.makeAuthenticatedRequest<
|
||||
FreebitTrafficInfoResponse,
|
||||
Providers.Freebit.mapper.FreebitTrafficInfoResponse,
|
||||
typeof request
|
||||
>("/mvno/getTrafficInfo/", request);
|
||||
|
||||
@ -159,7 +158,7 @@ export class FreebitOperationsService {
|
||||
? { ...baseRequest, runTime: payload.options?.scheduledAt }
|
||||
: baseRequest;
|
||||
|
||||
await this.client.makeAuthenticatedRequest<FreebitTopUpResponse, typeof request>(
|
||||
await this.client.makeAuthenticatedRequest<TopUpResponse, typeof request>(
|
||||
endpoint,
|
||||
request
|
||||
);
|
||||
@ -198,8 +197,8 @@ export class FreebitOperationsService {
|
||||
});
|
||||
|
||||
const response = await this.client.makeAuthenticatedRequest<
|
||||
FreebitQuotaHistoryResponse,
|
||||
FreebitQuotaHistoryRequest
|
||||
Providers.Freebit.mapper.FreebitQuotaHistoryResponse,
|
||||
QuotaHistoryRequest
|
||||
>("/mvno/getQuotaHistory/", request);
|
||||
|
||||
return this.mapper.mapToSimTopUpHistory(response, account);
|
||||
@ -239,10 +238,10 @@ export class FreebitOperationsService {
|
||||
runTime: parsed.scheduledAt,
|
||||
};
|
||||
|
||||
const response = await this.client.makeAuthenticatedRequest<
|
||||
FreebitPlanChangeResponse,
|
||||
typeof request
|
||||
>("/mvno/changePlan/", request);
|
||||
const response = await this.client.makeAuthenticatedRequest<PlanChangeResponse, typeof request>(
|
||||
"/mvno/changePlan/",
|
||||
request
|
||||
);
|
||||
|
||||
this.logger.log(`Successfully changed plan for account ${parsed.account} to ${parsed.newPlanCode}`, {
|
||||
account: parsed.account,
|
||||
@ -314,7 +313,7 @@ export class FreebitOperationsService {
|
||||
payload.contractLine = features.networkType;
|
||||
}
|
||||
|
||||
await this.client.makeAuthenticatedRequest<FreebitAddSpecResponse, typeof payload>(
|
||||
await this.client.makeAuthenticatedRequest<AddSpecResponse, typeof payload>(
|
||||
"/master/addSpec/",
|
||||
payload
|
||||
);
|
||||
@ -352,7 +351,7 @@ export class FreebitOperationsService {
|
||||
runTime: parsed.runDate,
|
||||
};
|
||||
|
||||
await this.client.makeAuthenticatedRequest<FreebitCancelPlanResponse, typeof request>(
|
||||
await this.client.makeAuthenticatedRequest<CancelPlanResponse, typeof request>(
|
||||
"/mvno/releasePlan/",
|
||||
request
|
||||
);
|
||||
@ -381,7 +380,7 @@ export class FreebitOperationsService {
|
||||
requestDatas: [{ kind: "MVNO", account }],
|
||||
};
|
||||
|
||||
await this.client.makeAuthenticatedRequest<FreebitEsimReissueResponse, typeof request>(
|
||||
await this.client.makeAuthenticatedRequest<EsimReissueResponse, typeof request>(
|
||||
"/mvno/reissueEsim/",
|
||||
request
|
||||
);
|
||||
@ -422,14 +421,14 @@ export class FreebitOperationsService {
|
||||
planCode: parsed.planCode,
|
||||
});
|
||||
|
||||
const request: FreebitEsimAddAccountRequest = {
|
||||
const payload: FreebitEsimAddAccountRequest = {
|
||||
...requestPayload,
|
||||
authKey: await this.auth.getAuthKey(),
|
||||
};
|
||||
|
||||
await this.client.makeAuthenticatedRequest<FreebitEsimAddAccountResponse, FreebitEsimAddAccountRequest>(
|
||||
await this.client.makeAuthenticatedRequest<EsimAddAccountResponse, FreebitEsimAddAccountRequest>(
|
||||
"/mvno/esim/addAcnt/",
|
||||
request
|
||||
payload
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
// Use JSON request for PA05-41
|
||||
await this.client.makeAuthenticatedJsonRequest<
|
||||
FreebitEsimAccountActivationResponse,
|
||||
typeof payload
|
||||
>("/mvno/esim/addAcct/", payload);
|
||||
await this.client.makeAuthenticatedJsonRequest<EsimActivationResponse, typeof payload>(
|
||||
"/mvno/esim/addAcct/",
|
||||
payload
|
||||
);
|
||||
|
||||
this.logger.log("Successfully activated new eSIM account via PA05-41", {
|
||||
account,
|
||||
|
||||
@ -47,6 +47,7 @@ export type CancelAccountResponse = ReturnType<typeof Mapper.transformFreebitCan
|
||||
export type EsimReissueResponse = ReturnType<typeof Mapper.transformFreebitEsimReissueResponse>;
|
||||
export type EsimAddAccountResponse = ReturnType<typeof Mapper.transformFreebitEsimAddAccountResponse>;
|
||||
export type EsimActivationResponse = ReturnType<typeof Mapper.transformFreebitEsimActivationResponse>;
|
||||
export type AuthResponse = ReturnType<typeof Mapper.transformFreebitAuthResponse>;
|
||||
|
||||
export * from "./mapper";
|
||||
export * from "./raw.types";
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
type FreebitAccountDetailsRaw,
|
||||
type FreebitTrafficInfoRaw,
|
||||
type FreebitQuotaHistoryRaw,
|
||||
type FreebitAuthResponseRaw,
|
||||
type FreebitTopUpRaw,
|
||||
type FreebitAddSpecRaw,
|
||||
type FreebitPlanChangeRaw,
|
||||
@ -18,6 +19,7 @@ import {
|
||||
freebitAccountDetailsRawSchema,
|
||||
freebitTrafficInfoRawSchema,
|
||||
freebitQuotaHistoryRawSchema,
|
||||
freebitAuthResponseRawSchema,
|
||||
freebitTopUpRawSchema,
|
||||
freebitAddSpecRawSchema,
|
||||
freebitPlanChangeRawSchema,
|
||||
@ -206,4 +208,10 @@ export function transformFreebitEsimActivationResponse(raw: unknown) {
|
||||
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 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