diff --git a/actions/questionnaireActions.js b/actions/questionnaireActions.js
index a533973..5745107 100644
--- a/actions/questionnaireActions.js
+++ b/actions/questionnaireActions.js
@@ -384,7 +384,7 @@ export const removeAttachmentFile = (id) =>
});
}
-export const downloadQuestionnaire = ({ filename, download = true }) =>
+export const downloadQuestionnaire = ({ filename, download = true, base64 = false }) =>
{
console.log("ACTION", "questionnaireActions", "downloadQuestionnaire()", );
@@ -398,23 +398,29 @@ export const downloadQuestionnaire = ({ filename, download = true }) =>
console.log("questionnaire", questionnaire);
const { main, contacts, signatory_person, founder_persons, head_person, non_profit, } = questionnaire;
- const playload = { main, contacts, signatory_person, founder_persons, head_person, non_profit, };
- console.log({ playload });
+ const payload = { main, contacts, signatory_person, founder_persons, head_person, non_profit, };
+ console.log({ payload });
-/* axios.post(`${ process.env.NEXT_PUBLIC_INT_API_HOST }/questionnaire/download`, { questionnaire: playload }, {
+/* axios.post(`${ process.env.NEXT_PUBLIC_INT_API_HOST }/questionnaire/download`, { questionnaire: payload }, {
headers: {
"Authorization": `Bearer ${ cookies_list.jwt }`,
},
})
*/
- axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/download`, { questionnaire: playload, filename }, {
+ const options = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/pdf'
},
- responseType: 'arraybuffer',
- })
+ };
+
+ if(!base64)
+ {
+ options.responseType = "arraybuffer";
+ }
+
+ axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/download`, { questionnaire: payload, filename, base64: download ? false : true }, options)
.then((response) =>
{
if(download)
diff --git a/components/questionnaire/forms/DigitalCertificates.js b/components/questionnaire/forms/DigitalCertificates.js
new file mode 100644
index 0000000..3bb089f
--- /dev/null
+++ b/components/questionnaire/forms/DigitalCertificates.js
@@ -0,0 +1,222 @@
+import React from "react";
+import Link from "next/link";
+import { SpinnerCircular } from "spinners-react";
+import moment from "moment";
+import dynamic from 'next/dynamic';
+import { concatSeries } from 'async';
+import fileDownload from 'js-file-download';
+
+import FormMessage from "./FormMessage";
+import { downloadQuestionnaire, uploadSignedFile } from "../../../actions";
+//import { generateSignature } from "../../../utils/digital_signature";
+
+
+export default class DigitalCertificates extends React.Component
+{
+ constructor(props)
+ {
+ super(props);
+
+ this.state = {
+ loading: true,
+ certificates: [],
+ certificates_error: null,
+ certificate_selected: undefined,
+ signing: false,
+ };
+ this.cryptopro = null;
+ }
+
+ async componentDidMount()
+ {
+ console.log("DC", "CDM");
+ const { CryptoPro } = await import('ruscryptojs');
+
+ this.cryptopro = new CryptoPro();
+ this.cryptopro.init()
+ .then((info) =>
+ {
+ console.log('Initialized', info);
+ this.cryptopro.listCertificates()
+ .then((certificates_list) =>
+ {
+ console.log({ certificates_list });
+
+ concatSeries(certificates_list, (certificate, callback) =>
+ {
+ console.log(certificate.id, certificate.name);
+ this.cryptopro.certificateInfo(certificate.id)
+ .then((cert) =>
+ {
+ if(cert.IsValid)
+ {
+ callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY") } ]);
+ }
+ else
+ {
+ callback(null, []);
+ }
+ });
+ }, (error, certificates) =>
+ {
+ if(certificates.length === 0)
+ {
+ this.setState({ loading: false, certificates_error: "ISSUED" });
+ }
+ else
+ {
+ this.setState({ loading: false, certificates });
+ }
+ });
+ })
+ .catch((error_certificates_list) =>
+ {
+ console.error({ error_certificates_list });
+ this.setState({ loading: false, certificates_error: "CERTIFICATES" });
+ });
+ })
+ .catch((error_init) =>
+ {
+ console.error({ error_init });
+ this.setState({ loading: false, certificates_error: "NOT_INSTALLED" });
+ });
+ }
+
+ _sign = () =>
+ {
+ this.setState({ signing: true }, () =>
+ {
+ const { company, main, onSignDigital } = this.props;
+ const filename = `${ main.inn }_questionnaire_${ moment().format("DDMMYYYY_HHmmss") }.pdf`;
+
+ downloadQuestionnaire({ filename, download: false, base64: true })
+ .then(({ file }) =>
+ {
+ let file_to_sign = file;
+
+ const now = moment().format("DDMMYYYY_HHmmss");
+ this.cryptopro.signData(file_to_sign, this.state.certificate_selected.id)
+ .then(signature =>
+ {
+ uploadSignedFile(signature, company.questionnaire_id, true)
+ .then(() =>
+ {
+ onSignDigital();
+ })
+ .catch(() =>
+ {
+ this.setState({ signing: false });
+ });
+ })
+ .catch((error_sign) =>
+ {
+ console.error({ error_sign });
+ this.setState({ signing: false });
+ })
+ })
+ .catch((e) =>
+ {
+ console.error("exception on sign");
+ console.error(e);
+ });
+ });
+ }
+
+ render()
+ {
+ const { loading, certificates, certificates_error, certificate_selected, signing } = this.state;
+ console.log("render()", { certificates });
+
+ if(loading)
+ {
+ return (
+
+
+
+ );
+ }
+ else
+ {
+ if(certificates_error === null)
+ {
+ return (
+
+
+
Выберите подписанта
+
+
+ { certificates.map((certificate, index) => (
+
+
{ this.setState({ certificate_selected: certificate }) } }
+ />
+
+
+ )) }
+
+
+
+
+
+
+
+
+ )
+ }
+ else
+ {
+ return (
+
+ { certificates_error === "NOT_INSTALLED" && (
+ Плагин КриптоПРО не установлен, посмотрите инструкцию как установить плагин КриптоПРО.> }/>
+ ) }
+ { certificates_error === "CERTIFICATES" && (
+ Плагин КриптоПРО не активирован, пожалуйста, обновите страницу и подтвердите разрешение для сайта на доступ к списку сертификатов.> }/>
+ ) }
+ { certificates_error === "ISSUED" && (
+ Отсутствуют действующие сертификаты.> }/>
+ ) }
+ { certificates_error === "MISMATCH" && (
+ Подписант не соответствует указанному подписанту в анкете.> }/>
+ ) }
+
+
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/questionnaire/forms/Form_3_Signer/index.js b/components/questionnaire/forms/Form_3_Signer/index.js
index 3e44250..6c959dd 100644
--- a/components/questionnaire/forms/Form_3_Signer/index.js
+++ b/components/questionnaire/forms/Form_3_Signer/index.js
@@ -1107,7 +1107,7 @@ class Form_3_Signer extends QuestionnaireForm
{ errors.indexOf("signatory_person.identical") > -1 &&
(
-
+
) }
diff --git a/components/questionnaire/forms/Form_8_Signing/index.js b/components/questionnaire/forms/Form_8_Signing/index.js
index 1c78e82..b7d0790 100644
--- a/components/questionnaire/forms/Form_8_Signing/index.js
+++ b/components/questionnaire/forms/Form_8_Signing/index.js
@@ -9,12 +9,14 @@ import { SpinnerCircular } from "spinners-react";
import { connect } from "react-redux";
import { withRouter } from 'next/router';
import moment from "moment";
+import NoSSR from "@mpth/react-no-ssr";
import QuestionnaireForm from "../QuestionnaireForm";
import { MatchMedia } from '../../../../utils/mediaqueries';
import { reduxWrapper } from '../../../../store';
import DigitalSignaturesList from "../DigitalSignaturesList";
import { downloadQuestionnaire } from "../../../../actions";
+import DigitalCertificates from "../DigitalCertificates";
import FormMessage from "../FormMessage";
class Form_8_Signing extends QuestionnaireForm
@@ -159,8 +161,12 @@ class Form_8_Signing extends QuestionnaireForm
) : (
-
+
+
+
+
) }
+ {/**/}
>
)}
>
diff --git a/package.json b/package.json
index 735928d..6f7a014 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"react-widgets": "^5.5.1",
"redux": "^4.1.2",
"redux-persist": "^6.0.0",
+ "ruscryptojs": "^2.6.1",
"spinners-react": "^1.0.6"
},
"devDependencies": {
diff --git a/pages/api/questionnaire/download.js b/pages/api/questionnaire/download.js
index b4fb9a6..e9389c8 100644
--- a/pages/api/questionnaire/download.js
+++ b/pages/api/questionnaire/download.js
@@ -120,7 +120,7 @@ export default async function handler(req, res)
console.log("API", "questionnaire", "get");
console.log(req.body);
console.log("-".repeat(50));
- const { questionnaire, filename } = req.body;
+ const { questionnaire, filename, base64 } = req.body;
await cors(req, res);
@@ -326,10 +326,17 @@ export default async function handler(req, res)
//res.setHeader('Content-Type', 'application/pdf');
//res.send(pdfBytes);
console.log("pdfBytes.size", pdfBytes, pdfBytes.byteLength);
- res.setHeader("filename", filename);
- res.setHeader('Content-Type', 'application/pdf');
- res.send(Buffer.from(pdfBytes));
-
+ if(base64)
+ {
+ //, 'binary'
+ res.status(200).send(Buffer.from(pdfBytes).toString('base64'));
+ }
+ else
+ {
+ res.setHeader("filename", filename);
+ res.setHeader('Content-Type', 'application/pdf');
+ res.status(200).send(Buffer.from(pdfBytes));
+ }
//res.setHeader('Content-Type', 'application/pdf');
//res.status(200).send(pdfBytes);
}
diff --git a/yarn.lock b/yarn.lock
index ea1e2b7..fdbee09 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2071,6 +2071,11 @@ console-browserify@^1.1.0:
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
+console-polyfill@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/console-polyfill/-/console-polyfill-0.3.0.tgz#84900902a18c47a5eba932be75fa44d23e8af861"
+ integrity sha512-w+JSDZS7XML43Xnwo2x5O5vxB0ID7T5BdqDtyqT6uiCAX2kZAgcWxNaGqT97tZfSHzfOcvrfsDAodKcJ3UvnXQ==
+
constants-browserify@1.0.0, constants-browserify@^1.0.0, constants-browserify@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@@ -4054,6 +4059,11 @@ js-file-download@^0.4.12:
resolved "https://registry.yarnpkg.com/js-file-download/-/js-file-download-0.4.12.tgz#10c70ef362559a5b23cdbdc3bd6f399c3d91d821"
integrity sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==
+js-sha1@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/js-sha1/-/js-sha1-0.6.0.tgz#adbee10f0e8e18aa07cdea807cf08e9183dbc7f9"
+ integrity sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -5954,6 +5964,20 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
+ruscryptojs@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/ruscryptojs/-/ruscryptojs-2.6.1.tgz#f9af6a95d63d8f575f1c65ea510ec586c2ab753b"
+ integrity sha512-CV41M1w02O5Yb9KLUBtDfIgPvgp+OjFxe7nT6uJ8lYyJInNIZeYBsUaegRVto01pNCG353DBlF9DWckJZ6/4Iw==
+ dependencies:
+ console-polyfill "^0.3.0"
+ js-sha1 "^0.6.0"
+ rutoken "^1.0.8"
+
+rutoken@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/rutoken/-/rutoken-1.0.8.tgz#443e16022fa8e1d7c638ba852f91d7fcb3a68be7"
+ integrity sha512-85C4CJk650iZauCmOes2TeQmVjkWviI1ys3E7nDw8pWlMI2mBuLz1fCD30ZjAfnNQ6OL19OMTYDNPFrJ60NfEA==
+
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"