637e51d7f9
Tests / frontend-test (push) Successful in 1m24s
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/timur.gorodetskiy/request-portal/pulls/23
102 lines
5.2 KiB
TypeScript
102 lines
5.2 KiB
TypeScript
import { AadHttpClient, HttpClientResponse } from '@microsoft/sp-http';
|
|
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
|
import { EDO_API_CLIENT_ID, getEdoApiBaseUrl } from '../config';
|
|
import { EdoRequestError } from './edoErrors';
|
|
import { IFioParts } from './fio';
|
|
|
|
/** Путь приёма документов на подпись от интеграций (TANSU ЭДО, multipart/form-data). */
|
|
const SIGNING_REQUESTS_PATH = '/api/v1/integration/signing-requests';
|
|
|
|
/** Файл на подпись и компания, от имени которой он идёт (по её сертификату Sigex в ЭДО). */
|
|
/** Как портал называет себя в ЭДО. */
|
|
export const EDO_SOURCE_NAME = 'Портал заявок';
|
|
|
|
export interface IEdoSigningFile {
|
|
name: string;
|
|
content: Blob;
|
|
/** БИН компании файла. У сотрудника-совместителя файлы одного запроса идут от разных компаний. */
|
|
companyBin: string;
|
|
}
|
|
|
|
/** Что отправляем в ЭДО: одного получателя, он же подписант (физлицо), и файлы. */
|
|
export interface IEdoSigningRequest {
|
|
/** Подписывающий: ЭДО заводит его по ИИН, если нет, и зовёт подписать письмом. */
|
|
recipient: { iin: string; email: string; name: IFioParts };
|
|
/** Кому сообщать о подписи; пусто — никому. */
|
|
initiatorEmail?: string;
|
|
files: IEdoSigningFile[];
|
|
}
|
|
|
|
/** Ответ ЭДО: то, что нужно показать пользователю. */
|
|
export interface IEdoSigningResult {
|
|
/** Кабинет получателя без ключа: войти по ЭЦП или через Microsoft. */
|
|
cabinetUrl: string;
|
|
documents: Array<{
|
|
id: string;
|
|
fileName: string;
|
|
}>;
|
|
}
|
|
|
|
/** Ответ ЭДО в snake_case — только поля, которые читаем. */
|
|
interface IEdoResponseBody {
|
|
cabinet_url?: string;
|
|
documents?: Array<{ id?: string; file_name?: string }>;
|
|
}
|
|
|
|
/**
|
|
* Отправляет документы на подпись в ЭДО одним запросом: либо принимаются все, либо ни один.
|
|
*
|
|
* Токен берётся для приложения ЭДО текущего пользователя (AadHttpClient), поэтому в ЭДО
|
|
* запрос приходит от того, кто нажал «Согласовать», — он заводится там автоматически при
|
|
* первом обращении. Адрес ЭДО — свойство веб-части edoApiBaseUrl.
|
|
*/
|
|
export async function submitSigningRequest(
|
|
context: WebPartContext,
|
|
request: IEdoSigningRequest
|
|
): Promise<IEdoSigningResult> {
|
|
const baseUrl = getEdoApiBaseUrl();
|
|
const client = await context.aadHttpClientFactory.getClient(EDO_API_CLIENT_ID);
|
|
|
|
// Content-Type не задаём: браузер сам допишет boundary для multipart.
|
|
const form = new FormData();
|
|
form.append('iin', request.recipient.iin);
|
|
form.append('email', request.recipient.email);
|
|
form.append('last_name', request.recipient.name.lastName);
|
|
form.append('first_name', request.recipient.name.firstName);
|
|
if (request.recipient.name.middleName) form.append('middle_name', request.recipient.name.middleName);
|
|
if (request.initiatorEmail) form.append('initiator_email', request.initiatorEmail);
|
|
// Так ЭДО подпишет документ в колонке «Кто отправил», а не техническим client_id.
|
|
form.append('service_initiator_name', EDO_SOURCE_NAME);
|
|
// БИН файлов — одним полем JSON-массивом строк, по порядку файлов: общий company_bin не нужен,
|
|
// подписант один (физлицо). Повторяющиеся поля ЭДО не принимает (400 invalid_file_company_bins_format).
|
|
for (const file of request.files) {
|
|
form.append('files', file.content, file.name);
|
|
}
|
|
form.append('file_company_bins', JSON.stringify(request.files.map((file) => file.companyBin)));
|
|
|
|
let response: HttpClientResponse;
|
|
try {
|
|
response = await client.post(`${baseUrl}${SIGNING_REQUESTS_PATH}`, AadHttpClient.configurations.v1, { body: form });
|
|
} catch (e) {
|
|
// Сеть/сертификат: у браузера для таких случаев одно сообщение «Failed to fetch»,
|
|
// а причина (недоверенный сертификат, ЭДО выключен, адрес не тот) видна только в консоли.
|
|
console.error('ЭДО недоступен', e);
|
|
throw new Error(
|
|
`ЭДО (${baseUrl}) недоступен. Проверьте, что сервер запущен и браузер доверяет его сертификату`
|
|
);
|
|
}
|
|
|
|
if (!response.ok) {
|
|
throw new EdoRequestError(response.status, await response.text());
|
|
}
|
|
|
|
const body = (await response.json()) as IEdoResponseBody;
|
|
return {
|
|
cabinetUrl: body.cabinet_url || '',
|
|
documents: (body.documents || []).map((d) => ({
|
|
id: d.id || '',
|
|
fileName: d.file_name || ''
|
|
}))
|
|
};
|
|
}
|