diff --git a/examples/operations.ts b/examples/operations.ts new file mode 100644 index 0000000..11cf34d --- /dev/null +++ b/examples/operations.ts @@ -0,0 +1,21 @@ +import * as izly from "../src"; +import { read } from "./_persisted-session"; + +void async function main () { + const identification = await read(); + + const payments = await izly.operations(identification, izly.OperationKind.Payment, 5); + const topup = await izly.operations(identification, izly.OperationKind.TopUp, 5); + + console.info("- Payments -"); + for (const payment of payments) { + const priceAsString = `${payment.amount.toPrecision(3)} EUR`; + console.info(payment.date.toLocaleString("fr-FR"), "paid", priceAsString); + } + + console.info("- Top-up -"); + for (const operation of topup) { + const priceAsString = `${operation.amount.toPrecision(3)} EUR`; + console.info(operation.date.toLocaleString("fr-FR"), "received", priceAsString); + } +}(); diff --git a/src/api/index.ts b/src/api/index.ts index 01faeb8..4c9d56f 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -2,6 +2,7 @@ export * from "./balance"; export * from "./contact"; export * from "./information"; export * from "./login"; +export * from "./operations"; export * from "./qr-pay"; export * from "./refresh"; export * from "./tokenize"; diff --git a/src/api/operations.ts b/src/api/operations.ts new file mode 100644 index 0000000..bf8b22d --- /dev/null +++ b/src/api/operations.ts @@ -0,0 +1,50 @@ +import { defaultFetcher, type Fetcher, type Request } from "@literate.ink/utilities"; +import { CLIENT_TYPE, SERVICE_VERSION } from "~/core/constants"; +import { decodeFormattedDate } from "~/decoders/date"; +import type { Identification, Operation } from "~/models"; + +export const OperationKind = { + TopUp: 0, + Transfer: 1, + Payment: 2 +} as const; + +export type OperationKind = typeof OperationKind[keyof typeof OperationKind]; + +/** + * @returns a list of the last operations + */ +export const operations = async (identification: Identification, kind: OperationKind, limit = 15, fetcher: Fetcher = defaultFetcher): Promise> => { + // transactionGroup=2 means history of operations + const url = new URL(`https://rest.izly.fr/Service/PublicService.svc/rest/GetHomePageOperations?transactionGroup=${kind}&top=${limit}`); + const request: Request = { + url, + headers: { + version: "2.0", + channel: "AIZ", + format: "T", + model: "A", + clientVersion: SERVICE_VERSION, + smoneyClientType: CLIENT_TYPE, + language: "fr", + userId: identification.identifier, + sessionId: identification.sessionID, + "Authorization": `Bearer ${identification.accessToken}` + } + }; + + const response = await fetcher(request); + const json = JSON.parse(response.content); + + return json.GetHomePageOperationsResult.Result.map((operation: any) => ({ + id: operation.Id, + amount: operation.Amount, + date: decodeFormattedDate(operation.Date), + isCredit: operation.IsCredit, + message: operation.Message as string | null, + type: operation.OperationType, + status: operation.Status + } as Operation)); +}; + + diff --git a/src/decoders/date.ts b/src/decoders/date.ts new file mode 100644 index 0000000..2bcfea9 --- /dev/null +++ b/src/decoders/date.ts @@ -0,0 +1 @@ +export const decodeFormattedDate = (date: string) => new Date(parseInt(date.substring(6, date.length - 2).split("+")[0])); diff --git a/src/models/index.ts b/src/models/index.ts index 964950d..b75bb58 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -3,4 +3,5 @@ export * from "./errors"; export * from "./balance"; export * from "./configuration"; export * from "./identification"; +export * from "./operation"; export * from "./profile"; diff --git a/src/models/operation.ts b/src/models/operation.ts new file mode 100644 index 0000000..a0c3960 --- /dev/null +++ b/src/models/operation.ts @@ -0,0 +1,19 @@ +export type Operation = Readonly<{ + id: number + amount: number + date: Date + isCredit: boolean + message: string | null + type: 2 | 7 + status: number +}>; + +// TODO: not sure what "type" means here, is it an enum ? + +// on operation 0: +// "Message": "Carte bancaire", +// "OperationType": 7 + +// on operation 2: +// "Message": null, +// "OperationType": 2,