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

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

Внимание

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

Сервис Формирования документов выполняет следующие основные функции:

  • Прием REST запроса на создание документа в соответствии со сцецификацией модуля;

  • Запрос необходимых данных для формирования документа в ядре Prostore;

  • Запрос номера документа в Сервисе генерации уникального номера;

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

    • XML;

    • PDF.

  • Отправка сформированных документов на подпись (опционально) в сервис Notarius;

  • Отправка сформированных и подписанных документов в виде ответа на пришедший запрос;

  • Публикация данных о модуле.

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

Прием REST запроса на создание документа

Запрос на создание документа приходит на эндпоинт POST /report. Форматы запроса и ответа модуля описаны в спецификации OpenAPI модуля. После получения из ядра СМЭВ4 запрос на создание документа отправляется напрямую Агентом СМЭВ4.

Запрос данных

Запрос необходимых данных для формирования документа в ядре Prostore выполняется pebble-движком, на основе шаблона извлечения данных для запрашиваемого вида документа. В ответ на запрос данных ядро Prostore возвращает строки данных, в JSON. Если результат не может быть десериализован как JSON, то работа алгоритма прерывается и в ответ на запрос возвращается ошибка 500 Internal Server Error, тело ответа - пустое.

Запрос номера документа

Запрос номера документа осуществляется вызовом запроса GET /api/{service}/number/{counter} Сервиса генерации уникального номера. Вызов осуществляет pebble-движок, на основе шаблона формирования извлечения данных для запрашиваемого вида документа. В адресе запроса service задается полем counter-service.serviceName в настройках модуля, счетчик определяется pebble-шаблоном. В ответе на запрос возвращается следующий номер счетчика, который используется для нумерации отчета.

Формирование документа

Для формирование документа используются шаблоны формирования, в зависимости от запрашиваемого типа представления: XML или PDF. При этом при формировании PDF используется промежуточная трансформация в HTML, из которого формируется финальный PDF документ.

Внимание

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

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

Отправка сформированных документов на подпись

При необходимости подписания документа (представления кроме xml и pdf) осуществляется вызов метода POST/api/v1/sign Агента СМЭВ4. При этом, в зависимости от представления результата:

  • xml_sig - присоединенная подпись

    • Возвращается подписанный фрагмент файла

    • Модуль пересобирает xml с учетом полученного подписанного фрагмента

  • pdf_sig - присоединенная подпись

    • Возвращается подписанный файл

  • xml_detached_sig, pdf_sig - отсоединенная подпись

    • Возвращается электронная подпись в формате p7s

Отправка сформированных и подписанных документов

Сформированный и подписанный документ возвращается в качестве ответа на вызов метода POST /report напрямую Агенту СМЭВ4 для отправки в ядро СМЭВ4.

1.2. Общая схема взаимодействия через Сервис формирования документов

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

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

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

1.3.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.3.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.3.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.4. REST запрос к сервису

openapi: "3.0.2"
info:
  title: Printable-form-service
  version: "1.0"
  description: API сервиса формирования документов
servers:
  - url: 'http://localhost:8081'
paths:
  /report:
    post:
      summary: Запрос на формирование документа
      tags:
        - PrintableForm
      operationId: postReport
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReportRequest'
      responses:
        '200':
          description: OK
          content:
            multipart/mixed:
              schema:
                $ref: '#/components/schemas/ReportResponse'
              examples:
                xml:
                  $ref: '#/components/examples/xml'
                xml_detached_sig:
                  $ref: '#/components/examples/xml_detached_sig'
                pdf:
                  $ref: '#/components/examples/pdf'
                pdf_sig:
                  $ref: '#/components/examples/pdf_sig'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
components:
  schemas:
    ReportRequest:
      description: "Тело запроса на формирование документа"
      type: object
      required:
        - requestId
        - subRequestId
        - datamartMnemonic
        - certificate
        - reportName
        - result
        - params
      properties:
        requestId:
          description: "Идентификатор запроса"
          type: string
          format: uuid
        subRequestId:
          description: "Идентификатор подзапроса"
          type: string
          format: uuid
        datamartMnemonic:
          description: "Мнемоника Витрины данных"
          type: string
        certificate:
          description: "Алиас сертификата"
          type: string
        reportName:
          description: "Название документа, в виде v<версия РЗ>_<мнемоника РЗ>"
          type: string
        result:
          type: array
          description: "Массив необходимых представлений документа, подставляется из параметра doctype РЗ"
          items:
            type: string
            enum:
              - pdf
              - pdf_sig
              - xml
              - xml_detached_sig
        params:
          type: array
          description: "Массив параметров документа, подставляются из оставшихся параметров РЗ"
          items:
            type: string
      example:
        requestId: 9151f21f-43ae-43b4-92f3-f4af67cdf545
        subRequestId: 0151f21f-43ae-43b4-92f3-f4af67cdf546
        datamartMnemonic: demo_view
        certificate: MIIB/AYJKoZIhvcNAQcCoIIB7TCCAekCAQExADALBgkqhkiG9w0BBwGgggHRMIIBzTCCAXigAwIBAgIJANOtR7OLdZp6MAwGCCqFAwcBAQMCBQAwNTELMAkGA1UEBhMCUlUxCzAJBgNVBAoTAlJUMRkwFwYDVQQDDBBibGFzdG9mZl9jYV90ZXN0MB4XDTI0MDYxMzEwMzAxMVoXDTM0MDYxMTEwMzAxMVowLTERMA8GA1UEAwwIaXRvbmVkZXYxCzAJBgNVBAoMAlJUMQswCQYDVQQGEwJSVTBmMB8GCCqFAwcBAQEBMBMGByqFAwICJAAGCCqFAwcBAQICA0MABEBKaYnJXmFy5LaENHYklUpwlZCKtKfT0zrl3ZWWzl617fbfFkx50mZ/TNkMC1bPKw66peyBeiyxH3Ex9GhlhRGNo2owaDAdBgNVHQ4EFgQUkpelMTqUCxHujSJLQlbOI4JXJmwwDgYDVR0PAQH/BAQDAgTwMB8GA1UdIwQYMBaAFG+jo68J8q+Yv7whvdrDSaIFNWUlMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMAwGCCqFAwcBAQMCBQADQQCHGQxmwPCjRNYSNXSYqB40ap5BQBEjaZ8Ortx7iaqH+N1reoNnDG/Mb99Ecm9DjKqsfOiIBpDcTMSm1RSUDYUTMQA=
        reportName: v1_printable_form_address
        result:
          - pdf
        params:
          - 11
          - 0000bcce-fa66-4915-b805-c06e003bc7fb
          - Станислав
          - Тестович
          - Тестов
          - 2022-03-14
          - Picture_7.jpg
    ReportResponse:
      type: string
      description: "Ответ на запрос из n частей, соответствующих запрошенным представлениям документа"
    ErrorMessage:
      type: object
      required:
        - errorMessage
      properties:
        errorMessage:
          description: Сообщение об ошибке
          type: string
  examples:
    xml:
      value: |
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="xml_docType"
        Content-Type: text/plain

        xml
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="xml_content"; filename="document_1.xml"
        Content-Type: application/xml
        Content-Transfer-Encoding: binary

        <?xml version="1.0" encoding="UTF-8" standalone="no"?><root>...</root>

        --9151f21f-43ae-43b4-92f3-f4af67cdf545--
    xml_detached_sig:
      value: |
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="xml_detached_sig_docType"
        Content-Type: text/plain

        xml_detached_sig
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="xml_detached_sig_content"; filename="document_1.xml"
        Content-Type: application/xml
        Content-Transfer-Encoding: binary

        <?xml version="1.0" encoding="UTF-8" standalone="no"?><root>...</root>

        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="xml_detached_sig_detached_sign"; filename="xmlSign.p7s"
        Content-Type: application/octet-stream
        Content-Transfer-Encoding: binary

        <file data>

        --9151f21f-43ae-43b4-92f3-f4af67cdf545--
    pdf:
      value: |
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="pdf_docType"
        Content-Type: text/plain

        pdf
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="pdf_content"; filename="pdfFileName.pdf"
        Content-Type: application/pdf
        Content-Transfer-Encoding: binary

        <file data>

        --9151f21f-43ae-43b4-92f3-f4af67cdf545--
    pdf_sig:
      value: |
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="pdf_sig_docType"
        Content-Type: text/plain

        pdf_sig
        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="pdf_sig_content"; filename="pdfFileName.pdf"
        Content-Type: application/pdf
        Content-Transfer-Encoding: binary

        <file data>

        --9151f21f-43ae-43b4-92f3-f4af67cdf545
        Content-Disposition: form-data; name="pdf_sig_detached_sign"; filename="pdfSign.p7s"
        Content-Type: application/octet-stream
        Content-Transfer-Encoding: binary

        <file data>

        --9151f21f-43ae-43b4-92f3-f4af67cdf545--