2023-10-04 19:29:20 +02:00

269 lines
8.0 KiB
TypeScript

import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import { BackendVariables } from "@Common/config/variables/Variables";
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
import FilesService from "../FilesService/FilesService";
export type EnrollmentResponse = {
url: string;
id: number;
api_key: string;
callback_url: string;
browser_callback_url: string;
client_reference: string;
status: string;
reason: string | null;
create_date: string;
starting_time: string | null;
finished_time: string | null;
};
type EnrollmentInfoResponse = {
status: string;
browser_callback_url: string;
browser_callback_token: string;
user_process_done_time: string | null;
routes: {
uses_biometric: boolean;
datas: {};
document_classes: string[];
constraints: string[];
id: string;
status: string;
}[];
};
type ReportInfoReponse = {
enrollment: {
callback_url: string;
browser_callback_url: string;
client_reference: string;
};
process_uuid: string;
id: number;
status: string;
process_id: number;
external_methods: {
france_connect: {
status: string;
creation_time: string;
starting_time: string;
finished_time: string;
supplier_reference: string;
results: {
france_connect_out_token: [
{
token_type: string;
scope: string;
access_token: string;
expires_in: number;
id_token: string;
expires_at: number;
},
];
france_connect_out_userinfo: [
{
sub: string;
given_name: string;
family_name: string;
birthdate: string;
gender: string;
preferred_username: string;
email: string;
},
];
};
};
};
archive_reference: string;
};
type LoginResponse = {
token: string;
};
@Service()
export default class Id360Service extends BaseService {
private id360Token: string | null = null;
private id360TokenExpiration: number | null = null;
constructor(private variables: BackendVariables, private documentsService: DocumentsService, private filesService: FilesService) {
super();
}
public async createFranceConnectEnrollment() {
const authHeader = `Token ${await this.getId360Token()}`;
const bodyArgs = {
callback_url: `${this.variables.BACK_API_HOST}/id360/customer-callback/`,
browser_callback_url: `${this.variables.APP_HOST}/id360/customer-callback/`,
callback_headers: {},
};
const res = await fetch(
`${this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION}/process/${
this.variables.DOCAPOST_CONNECT_PROCESS_ID
}/enrollment/`,
{
method: "POST",
body: JSON.stringify(bodyArgs),
headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: authHeader },
},
);
const resJson = (await res.json()) as EnrollmentResponse;
return {
franceConnectUrl: `${this.variables.DOCAPOST_BASE_URL}static/process_ui/index.html#/enrollment/${resJson.api_key}`,
processId: resJson.id,
};
}
public async createEnrollment(documentUid: string) {
const authHeader = `Token ${await this.getId360Token()}`;
const bodyArgs = {
callback_url: `${this.variables.BACK_API_HOST}/id360/enrollment-callback/`,
browser_callback_url: `${
this.variables.APP_LABEL + this.variables.BACK_API_HOST + this.variables.APP_ROOT_URL
}/id360/enrollment-callback/`,
client_reference: documentUid,
callback_headers: {},
};
const res = await fetch(
`${this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION}/process/${
this.variables.DOCAPOST_DOCUMENT_PROCESS_ID
}/enrollment/`,
{
method: "POST",
body: JSON.stringify(bodyArgs),
headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: authHeader },
},
);
const resJson = (await res.json()) as EnrollmentResponse;
const route = await this.getRouteId(resJson.api_key);
await this.selectRoute(resJson.api_key, route);
await this.uploadDocument(resJson.api_key, documentUid);
return await this.getReport(resJson.id);
}
public async uploadDocument(apiKey: string, documentUid: string) {
const document = await this.documentsService.getByUidWithFiles(documentUid);
if (document && document.files && document.files.length > 1) {
const IDrecto = await this.filesService.download(document.files[0]!.uid);
const IDverso = await this.filesService.download(document.files[1]!.uid);
const rectoBlobData = new Blob([new Uint8Array(Array.from(IDrecto!.buffer))], { type: "application/octet-stream" });
const versoBlobData = new Blob([new Uint8Array(Array.from(IDverso!.buffer))], { type: "application/octet-stream" });
const resRecto = await fetch(
`${
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
}/enrollment/flow/document/id_document_image/?total_pages=2&uploaded_page=0`,
{
method: "POST",
body: rectoBlobData,
headers: { "Content-Type": "application/octet-stream", Accept: "*/*", "x-api-key": apiKey },
},
);
const resVerso = await fetch(
`${
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
}/enrollment/flow/document/id_document_image/?total_pages=2&uploaded_page=1`,
{
method: "POST",
body: versoBlobData,
headers: { "Content-Type": "application/octet-stream", Accept: "*/*", "x-api-key": apiKey },
},
);
console.log(await resRecto.json(), await resVerso.json());
await this.finalizeEnrollment(apiKey);
}
}
public async getReport(enrollmentId: number) {
const authHeader = `Token ${await this.getId360Token()}`;
const res = await fetch(
`${
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
}/enrollment/${enrollmentId}/report/`,
{
method: "GET",
headers: { "Content-Type": "application/json", Authorization: authHeader },
},
);
return (await res.json()) as ReportInfoReponse;
}
public async getEnrollment(token: string) {
return await fetch(
`${
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
}/enrollment/status/${token}`,
{ method: "GET" },
);
}
public async finalizeEnrollment(apiKey: string) {
return await fetch(
`${
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
}/enrollment/flow/finalize_enrollment/`,
{
method: "POST",
headers: { "x-api-key": apiKey, Accept: "application/json" },
},
);
}
public async getRouteId(apiKey: string) {
const res = await fetch(
`${
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
}/enrollment/flow/enrollment_info/`,
{
method: "GET",
headers: { "x-api-key": apiKey, Accept: "application/json" },
},
);
const resJson = (await res.json()) as EnrollmentInfoResponse;
return resJson.routes[0]!.id;
}
public async selectRoute(apiKey: string, routeId: string) {
return await fetch(
`${
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
}/enrollment/flow/route/${routeId}/select`,
{
method: "POST",
headers: { "x-api-key": apiKey, Accept: "application/json" },
},
);
}
public async getId360Token() {
if (!this.id360Token || !this.id360TokenExpiration || this.id360TokenExpiration < Date.now()) {
this.id360Token = await this.login();
this.id360TokenExpiration = Date.now() + 1000 * 60 * 14; // 14 minutes
}
return this.id360Token;
}
public async login(): Promise<string> {
const bodyArgs = {
username: this.variables.DOCAPOST_APP_ID,
password: this.variables.DOCAPOST_APP_PASSWORD,
};
const res = await fetch(
`${this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION}/user/login/`,
{
method: "POST",
body: JSON.stringify(bodyArgs),
headers: { "Content-Type": "application/json", Accept: "application/json" },
},
);
return ((await res.json()) as LoginResponse).token;
}
}