Skip to content

Commit

Permalink
Add report
Browse files Browse the repository at this point in the history
  • Loading branch information
diev committed Jul 10, 2024
1 parent c362306 commit c068f7a
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 58 deletions.
3 changes: 2 additions & 1 deletion Api5704/Api.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public class Api

// Extra
public const string auto = nameof(auto); // dlrequest + dlanswer
public const string dir = nameof(dir); // dlrequest + dlanswer
public const string dir = nameof(dir); // (dlrequest + dlanswer) * N
public const string report = nameof(report); // answer xml -> txt

/// <summary>
/// POST
Expand Down
2 changes: 1 addition & 1 deletion Api5704/Api5704.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<RootNamespace>Api5704</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>8.2024.627</Version>
<Version>8.2024.710</Version>
<Company>diev</Company>
<Copyright>2022-2024 Dmitrii Evdokimov</Copyright>
<Description>Предоставление ССП при обращении пользователя к НБКИ как КБКИ-контрагенту в режиме «одного окна» по Указанию Банка России № 5704-У.</Description>
Expand Down
110 changes: 108 additions & 2 deletions Api5704/ApiExtra.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ limitations under the License.
*/
#endregion

using System.Xml;
using System.Text;
using System;
using System.Xml;

namespace Api5704;

public static class ApiExtra
{
private record Agreement(string Id, string Date, string Val, string Sum);

/// <summary>
/// Пакетная обработка папок с запросами (Extra dir).
/// </summary>
Expand Down Expand Up @@ -121,6 +122,9 @@ public static async Task<int> PostRequestFolderAsync(string source, string reque
{
File.Delete(file);
count++;

string report = Path.ChangeExtension(answer, "txt");
await MakeReportAsync(answer, report);
}

Thread.Sleep(1000);
Expand All @@ -130,4 +134,106 @@ public static async Task<int> PostRequestFolderAsync(string source, string reque

return ret;
}

/// <summary>
/// Получение сводного текстового отчета по сведениям в XML.
/// </summary>
/// <param name="answer">Полученный файл с информацией.</param>
/// <param name="report">Имя файла для сводного отчета.</param>
/// <returns>Код возврата (0 - успех, 1 - файл не создан).</returns>
/// <exception cref="Exception"></exception>
public static async Task<int> MakeReportAsync(string answer, string report)
{
XmlDocument doc = new();
doc.Load(answer);

// СведенияОПлатежах
var root = doc.DocumentElement
?? throw new Exception("XML не содержит корневого элемента.");

// Титульная Часть
var title = root.FirstChild
?? throw new Exception("XML не содержит Титульную часть."); ;

// ФИО
var fio = title.FirstChild
?? throw new Exception("XML не содержит ФИО."); //TODO XPath

string fio3 =
$"{fio.ChildNodes[0]?.InnerText} {fio.ChildNodes[1]?.InnerText} {fio.ChildNodes[2]?.InnerText}"
.Trim();

Dictionary<string,Agreement> list = [];

foreach (XmlNode node in root.ChildNodes)
{
// КБКИ
if (!node.LocalName.Equals("КБКИ", StringComparison.Ordinal))
continue;

// Обязательства
var duties = node.FirstChild;

// ОбязательствНет
if (duties is null || !duties.HasChildNodes)
continue;

// БКИ
var bki = duties.FirstChild;

if (bki is null)
continue;

// Договор
foreach (XmlNode agreement in bki.ChildNodes)
{
// УИД
string id = agreement.Attributes!["УИД"]!.Value;

// СреднемесячныйПлатеж
var details = agreement.FirstChild;

if (details is null)
continue;

string date = details.Attributes!["ДатаРасчета"]!.Value;
string val = details.Attributes["Валюта"]!.Value;
string sum = details.InnerText;

Agreement add = new(id, date, val, sum);

if (list.TryGetValue(id, out var found))
{
if (found is null ||
string.Compare(date, found.Date, false) > 0)
{
list.Remove(id);
list.Add(id, add);
continue;
}
}
else
{
list.Add(id, add);
continue;
}
}
}

StringBuilder sb = new();
sb.AppendLine(fio3).AppendLine();
long total = 0;

foreach (var item in list.Values.ToList<Agreement>())
{
sb.AppendLine($"Договор {item.Id} на {item.Date} {item.Val} {item.Sum}");
total += long.Parse(item.Sum.Replace(".", "")); //TODO separate RUB, etc.
}

sb.AppendLine().AppendLine($"Total: {total/100:#.00}");

await File.WriteAllTextAsync(report, sb.ToString(), Encoding.UTF8); //TODO Condig Encoding

return File.Exists(report) ? 0 : 1;
}
}
8 changes: 4 additions & 4 deletions Api5704/Exec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ internal static class Exec
/// <param name="exe">Запускаемая программа.</param>
/// <param name="cmdline">Параметры для запускаемой программы.</param>
/// <exception cref="FileNotFoundException"></exception>
/// <exception cref="SystemException"></exception>
/// <exception cref="Exception"></exception>
public static async Task StartAsync(string exe, string cmdline)
{
if (!File.Exists(exe))
Expand All @@ -40,8 +40,8 @@ public static async Task StartAsync(string exe, string cmdline)
ProcessStartInfo startInfo = new()
{
CreateNoWindow = false,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Normal, // NO .Hidden with CryptoPro!!!
UseShellExecute = true, // NO false with CryptoPro!!!
FileName = exe,
Arguments = cmdline
};
Expand All @@ -61,7 +61,7 @@ public static async Task StartAsync(string exe, string cmdline)
}
catch (Exception ex)
{
throw new SystemException($"Fail to start [\"{exe}\" {cmdline}]", ex);
throw new Exception($"Fail to start [\"{exe}\" {cmdline}]", ex);
}
}
}
6 changes: 3 additions & 3 deletions Api5704/PKCS7.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ limitations under the License.
*/
#endregion

using System.Security.Cryptography.Pkcs; //TODO: Windows only?

namespace Api5704;

/// <summary>
Expand All @@ -34,6 +32,8 @@ internal static class PKCS7
/// <returns>Массив байтов с исходным сообщением без ЭП.</returns>
public static async Task<byte[]> CleanSign(byte[] data)
{
//using System.Security.Cryptography.Pkcs;

//var signedCms = new SignedCms();
//signedCms.Decode(data);

Expand Down Expand Up @@ -64,7 +64,7 @@ public static async Task SignFileAsync(string file, string resultFile)

if (!File.Exists(resultFile))
{
throw new FileNotFoundException("Signed file not created.", resultFile);
throw new FileNotFoundException("Signed file not created. Token not found?", resultFile);
}
}
}
46 changes: 29 additions & 17 deletions Api5704/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ limitations under the License.
*/
#endregion

using System.Text.Json;

using static Api5704.Api;

namespace Api5704;
Expand Down Expand Up @@ -95,6 +93,12 @@ static async Task Main(string[] args)
result = await ApiExtra.PostRequestFolderAsync(args[1], args[2], args[3], args[4]);
break;

case report:
if (args.Length != 3) Usage();
// answer xml -> txt
result = await ApiExtra.MakeReportAsync(args[1], args[2]);
break;

// Unknown
default:
Usage();
Expand Down Expand Up @@ -125,37 +129,45 @@ Api5704 запрос параметры
Запросы API:
dlput – передача от БКИ данных, необходимых для формирования и предоставления
пользователям кредитных историй сведений о среднемесячных платежах Субъекта.
dlrequest – запрос сведений о среднемесячных платежах Субъекта.
dlput – передача от БКИ данных, необходимых для формирования и
предоставления пользователям кредитных историй сведений о
среднемесячных платежах Субъекта.
dlrequest – запрос сведений о среднемесячных платежах Субъекта.
Параметры: request.xml result.xml
dlanswer – получение сведений о среднемесячных платежах Субъекта по
идентификатору ответа.
dlputanswer – получение информации о результатах загрузки данных, необходимых
для формирования и предоставления пользователям кредитных историй сведений
о среднемесячных платежах Субъекта, в базу данных КБКИ.
dlanswer – получение сведений о среднемесячных платежах Субъекта по
идентификатору ответа.
dlputanswer – получение информации о результатах загрузки данных,
необходимых для формирования и предоставления пользователям
кредитных историй сведений о среднемесячных платежах Субъекта,
в базу данных КБКИ.
Параметры: id answer.xml
result.xml answer.xml
certadd – добавление нового сертификата абонента.
certrevoke – отзыв сертификата абонента.
certadd – добавление нового сертификата абонента.
certrevoke – отзыв сертификата абонента.
Параметры: id cert.cer sign.sig result.xml
Запросы расширенные:
auto - запрос (dlrequest) и получение (dlanswer) за один запуск.
auto - запрос (dlrequest) и получение (dlanswer) за один запуск.
Параметры: request.xml result.xml answer.xml
dir - пакетная обработка запросов (auto) из папки.
Это действие по умолчанию, если параметров не указано, но есть папка DirSource в конфиге.
Подробнее см. в README.
dir - пакетная обработка запросов (auto) из папки.
Это действие по умолчанию, если параметров не указано,
но есть папка DirSource в конфиге.
Подробнее см. в README.
Параметры: source request result answer
report - создание текстового сводного отчета по полученным
сведениям XML.
Параметры: source request result answer";
Параметры: answer.xml report.txt";

Console.WriteLine(usage);

Expand Down
25 changes: 16 additions & 9 deletions Api5704/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,46 @@
},
"dlrequest": {
"commandName": "Project",
"commandLineArgs": "dlrequest\r\nrequest.xml\r\nresult.xml"
"commandLineArgs": "dlrequest request.xml result.xml"
},
"dlanswer": {
"commandName": "Project",
"commandLineArgs": "dlanswer\r\ne700e32f-ce85-4f0a-9cee-31b8bc14a7a0\r\nanswer.xml"
"commandLineArgs": "dlanswer e700e32f-ce85-4f0a-9cee-31b8bc14a7a0\r\nanswer.xml"
},
"dlputanswer": {
"commandName": "Project",
"commandLineArgs": "dlputanswer\r\n945cb186-0d50-45ff-8823-797942987638\r\nputanswer.xml"
"commandLineArgs": "dlputanswer 945cb186-0d50-45ff-8823-797942987638\r\nputanswer.xml"
},
"dlput": {
"commandName": "Project",
"commandLineArgs": "dlput\r\nqcb_put.xml.sig\r\nput.result.xml"
"commandLineArgs": "dlput qcb_put.xml.sig put.result.xml"
},
"certadd": {
"commandName": "Project",
"commandLineArgs": "certadd\r\nA6563526-A3F3-4D4E-A923-E41E93F1D921\r\nkontur.cer\r\nkontur.cer.sig\r\ncertadd.result.xml"
"commandLineArgs": "certadd A6563526-A3F3-4D4E-A923-E41E93F1D921\r\nkontur.cer kontur.cer.sig\r\ncertadd.result.xml"
},
"certrevoke": {
"commandName": "Project",
"commandLineArgs": "certrevoke\r\nA6563526-A3F3-4D4E-A923-E41E93F1D921\r\nkontur.cer\r\nkontur.cer.sig\r\ncertrevoke.result.xml"
"commandLineArgs": "certrevoke A6563526-A3F3-4D4E-A923-E41E93F1D921\r\nkontur.cer kontur.cer.sig\r\ncertrevoke.result.xml"
},
"dlanswer file": {
"commandName": "Project",
"commandLineArgs": "dlanswer\r\nresult.xml\r\nanswer2.xml"
"commandLineArgs": "dlanswer result.xml answer2.xml"
},
"dlauto": {
"commandName": "Project",
"commandLineArgs": "dlauto\r\nrequest.xml\r\nresult.xml\r\nanswer3.xml"
"commandLineArgs": "dlauto request.xml result.xml answer3.xml"
},
"dlauto folders": {
"commandName": "Project",
"commandLineArgs": "dlauto\r\nrequests\r\nresults\r\nanswers"
"commandLineArgs": "dlauto requests results answers"
},
"no args but OUT": {
"commandName": "Project"
},
"report": {
"commandName": "Project",
"commandLineArgs": "report answer.xml report.txt"
}
}
}
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@

Полученный файл `answer.xml` содержит искомую информацию с ССП.

## Раширение API дополнительными командами
## Расширение API дополнительными командами

Отправка запроса (`dlrequest`), получение квитанции и сведений
(`dlanswer`) за один запуск - команда `auto`:
Expand Down Expand Up @@ -223,19 +223,30 @@
файл будет считаться обработанным и удален из папки `source`, при этом
он всегда может быть позже найден в папке `request` с датой и guid.

Также к полученному файлу `answer.xml` будет создан текстовый сводный
отчет в файле `answer.txt` рядом с ним.

Отдельно его можно получить командой:

Api5704 REPORT answer.xml report.txt

## Вычисление ХэшКода согласий

Для вычисления ХэшКода служит утилита из состава КриптоПро:

"C:\Program Files (x86)\Crypto Pro\CSP\cpverify.exe" -mk -alg GR3411_2012_256 file.pdf
A36D628486A17D934BE027C9CAF79B27D7CD9E4E49469D97312B40AD6228D26F

Для удобства добавлены макрос `CalcHash` в Api5704.xlsm (указать файл в
диалоге и скопипастить из окна ввода.
Для удобства в Api5704.xlsm добавлены макросы:

- `CalcHash` - указать файл PDF в диалоге, рассчитать (требуется
установленный КриптоПро) и скопипастить из окна ввода.
- `ReadHash` - указать готовый файл TXT в диалоге и скопипастить из
окна ввода.

Также добавлен `hash.cmd`, который надо закинуть в папку с PDF, и он
посчитает и запишет к каждому рядом файл `.txt`, с кодом уже в нижнем
регистре.
посчитает и запишет к каждому PDF рядом файл `.txt`, с кодом уже в
нижнем регистре.

## Проверка ХэшКода на сервисе Госуслуг

Expand Down
Binary file modified XLSM/Api5704.xlsm
Binary file not shown.
Loading

0 comments on commit c068f7a

Please sign in to comment.