1. Общее описание

Сервис Формирования документов предназначен для обеспечения возможности формирования документов, в формате XML и PDF, на основе предварительно подготовленных pebble-шаблонов, с возможностью добавления к сформированным документам электронной подписи.

Внимание

Максимальный размер формируемого отчета не должен превышать 2Гб!

Сервис Формирования документов предназначен для решения следующих задач:

  • формировать документ, на основе поступившего в Витрину запроса, в формате:

    • XML;

    • PDF.

  • отправлять сформированные документы на подпись в сервис Notarius;

  • отправлять сформированные и подписанные документы в СМЭВ4 в виде ответа на пришедший запрос.

Формат обмена электронными сообщениями описан в разделе Спецификация модуля «Сервис Формирования документов» Приложения 1.

1.1. Процесс обработки запроса через модуль «Сервис Формирования документов»

  1. Запрос на предоставление сформированного документа поступает через Агента СМЭВ4, в топик procedure.query.rq.

  2. СМЭВ4-адаптер считывает запрос из топика и передает его в Сервис Формирования документов. Сервис Формирования документов запускает соответствующий пришедшему типу документа pebble-шаблон, собирает данные из Витрины (Prostore) и формирует на основании этих данных JSON-файл.

  3. Из содержащейся в JSON-файле информации формируется итоговая форма документа. Для этого используется Шаблон generate_xml.peb и Шаблон generate_pdf.peb, предназначенные для генерации документов.

  4. В случае, если электронная подпись не требуется, то PDF-документ сразу пересылается в топик report.rs.

  5. Если требуется электронная подпись:

  • PDF-документ и публичная часть SSH-ключа (pub) будут отправлены в Сервис электронной подписи. Сервис электронной подписи сформирует для этого PDF-документа файл подписи (p7s) и вернет его в Сервис Формирования документов.

  • Полученный XML или PDF-файл Сервис Формирования документов отправляет в СМЭВ4-адаптер, в топик report.rs Kafka СМЭВ4-адаптер.

  1. Агент СМЭВ4 проверяет топик и забирает сформированные документы для передачи в СМЭВ4.

Внимание

Следует обратить внимание, что при формировании XML-документов используется - присоединенная подпись (подпись содержится в самом XML-документе).

Для PDF-документов - отсоединенная подпись (подпись документа формируется отдельным файлом), т.е. при формировании PDF-документа сгенерируется два файла: PDF-документ и файл электронной подписи для этого документа.

1.2. Компоненты

Компоненты модуля «Сервис Формирования документов»

Рисунок - 1.1 Компоненты модуля «Сервис Формирования документов»

1.3. Общая архитектура решения

Общая схема взаимодействия модуля «Сервис Формирования документов»

Рисунок - 1.2 Общая схема взаимодействия модуля «Сервис Формирования документов»

1.4. Назначение параметров QueryRequest.parameters[]

Таблица 1.8 Назначение параметров QueryRequest.parameters[]

Индекс параметра в QueryRequest.parameters[]

Тип QueryRequest.parameters[].type

Значение QueryRequest.parameters[].value

0

string

публичная часть сертификата (формат PKCS#7) в кодировке BASE64

1

string

Список запрошенных форматов ПФ (через запятую, без учета регистра).

Допустимые значения (без кавычек):

  • «XML» - файл xml;

  • «PDF» - pdf без ЭП (содержимое «штампика об ЭП» - на усмотрение разработчика шаблона для pdf-файла);

«PDF_SIG» - pdf с открепленной ЭП (содержимое «штампика об ЭП» - на ответственности разработчика шаблона для pdf-файла).

2

параметры для формирования запрашиваемой ПФ, зависят от логики формирования ПФ.

1.5. Примеры шаблонов

1.5.1. Шаблон extract_data.peb

{#формируем sql запрос в переменную passengersquery#}
{% var passengersquery %}
    {% if _0 is empty %}
        select * from auto_db.passenger limit 10
    {% else %}
        select * from auto_db.passenger limit {{ _0 }}
    {% endif %}
{% endvar %}
{# выполняем sql запрос и помещаем результат выполнения в переменную rows.searchpassenger #}
{{ sql("searchpassenger", passengersquery) }}

{% var json_data %}
{
    "passengers": [
    {% for p in rows.searchpassenger %}
    {#  формируем json динамически  #}
        {% if loop.first %}
        {% else %}
            ,
        {% endif %}
        {
            "id": "{{ p.id }}",
            "firstname": "{{ p.firstname }}",
            "middlename": "{{ p.middlename }}",
            "lastname": "{{ p.lastname }}",
            "birthday": "{{ p.birthday }}"
        }
    {% endfor %}
    ]
}
{% endvar %}

{#выведем полученный json в неэкранированной форме#}
{{ json_data | raw }}

1.5.2. Шаблон generate_xml.peb

{#соберем xml документ#}
<passengers>
{% for p in _0.passengers %}
    <passenger id="{{ p.id }}">
        <firstname>{{ p.firstname }}</firstname>
        <middlename>{{ p.middlename }}</middlename>
        <lastname>{{ p.lastname }}</lastname>
        <birthday>{{ p.birthday }}</birthday>
    </passenger>
{% endfor %}
</passengers>

1.5.3. Шаблон generate_pdf.peb

{#соберем html документ#}
<html>
    <head>
    <style>
        table, th, td {
            border: 1px solid black;
        }
    </style>
</head>
    <body>
        <h3>Passengers</h3>
        <table>
            <tr>
                <th>id</th>
                <th>firstname</th>
                <th>middlename</th>
                <th>lastname</th>
                <th>birthday</th>
            </tr>
{% for p in _0.passengers %}
            <tr>
                <td>{{ p.id }}</td>
                <td>{{ p.firstname }}</td>
                <td>{{ p.middlename }}</td>
                <td>{{ p.lastname }}</td>
                <td>{{ p.birthday }}</td>
            </tr>
{% endfor %}
        </table>
    <body>
</html>

1.6. REST запрос к сервису

1.6.1. Запрос

Endpoint: /report

Request type: GET

Headers:

  • Content-type: application/json

content schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "docGenRequest",
  "type": "object",
  "properties": {
    "docName": {
      "type": "string"
    },
    "customerId": {
      "type": [
      "null",
      "string"]
    },
    "customerOgrn": {
      "type": [
      "null",
      "string"]
    },
    "queryMnemonic": {
      "type": [
      "null",
      "string"]
    },
    "parameters": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
        "name": {
            "type": "string"
        },
        "value": {
            "type": [
            "string",
            "number",
            "boolean",
            "null"
            ]
        },
        "mandatory": {
            "type": [
            "boolean",
            "null"
            ]
        },
        "regExp": {
            "type": [
            "string",
            "null"
            ]
        }
      },
      "required": [
        "name",
        "value"
        ]
      }
    }
  },
  "required": [
    "docName",
    "parameters"
  ]
}

1.6.2. Ответ

Ответ должен содержать заголовок с HTTP-кодом ответа и n частей:

  1. Ответ на запрос:

    Код ошибки: (200 OK)

    Content-type: multipart/mixed

  2. Часть, содержащая сгенерированный XML

    Content-Disposition: attachment; name=»xml»; filename=»result.xml»

    Content-type: application/xml

  3. Часть, содержащая metadata для XML

    Content-Disposition: attachment; name=»xml»; filename=»metadata»

    Content-type: text/plain; charset=utf-8

  4. Часть, содержащая сгенерированный PDF

    Content-Disposition: attachment; name=»pdf»; filename=»result.pdf»

    Content-type: application/pdf