Example #1
0
        private static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                ShowUsage();
                return;
            }
            var apiClientId = args[0];
            var apiUrl      = args.Length > 1 ? args[1] : DefaultApiUrl;

            try
            {
                var crypt  = new WinApiCrypt();
                var diadoc = new DiadocApi(apiClientId, apiUrl, crypt);
                new Program(diadoc, crypt).Run();
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
                Environment.Exit(1);
            }
        }
Example #2
0
        protected bool TrySign(byte[] content, out byte[] sign)
        {
            sign = null;
            if (Settings.Value.DebugUseTestSign)
            {
                return(true);
            }

            try {
                sign = new WinApiCrypt().Sign(content, Cert.RawData);
            }
            catch (Win32Exception e) {
                Log.Error($"Ошибка при подписании документа {Payload.Entity.EntityId}", e);
                Manager.Error(e.Message);
                return(false);
            }
            catch (Exception e) {
                Log.Error($"Ошибка при подписании документа {Payload.Entity.EntityId}", e);
                Manager.Error(ErrorHelper.TranslateException(e) ?? "Не удалось подписать документ");
                return(false);
            }
            return(true);
        }
        public static void RunSample()
        {
            Console.WriteLine("Пример аутентификации по сертификату");
            Console.WriteLine("=====================================");

            // Для использования API Диадока требуются:
            // 1. Крипто-API, предоставляемое операционной системой. Для систем на ОС Windows используйте класс WinApiCrypt.
            // 2. Экземпляр класса DiadocApi, проксирующий работу с Диадоком.

            var crypt     = new WinApiCrypt();
            var diadocApi = new DiadocApi(
                Constants.DefaultClientId,
                Constants.DefaultApiUrl,
                crypt);

            // Большинству команд интеграторского интерфейса требуется авторизация.
            // Для этого команды требуют в качестве обязательного параметра так называемый авторизационный токен — массив байтов, однозначно идентифицирующий пользователя.
            // Один из способов авторизации — через логин и пароль пользователя:
            var authTokenByLogin = diadocApi.Authenticate(Constants.DefaultLogin, Constants.DefaultPassword);

            Console.WriteLine("Успешная аутентификация по логину и паролю. Токен: " + authTokenByLogin);

            // Другой способ: через сертификат пользователя:
            var certificate            = new X509Certificate2(File.ReadAllBytes(Constants.CertificatePath));
            var authTokenByCertificate = diadocApi.Authenticate(certificate.RawData);

            Console.WriteLine("Успешная аутентификация по сертификату. Токен: " + authTokenByCertificate);

            // Можно использовать перегрузку, которая сама найдёт сертификат по отпечатку
            var authTokenByCertificateThumbprint = diadocApi.Authenticate(CertificateThumbprint);

            Console.WriteLine("Успешная аутентификация по отпечатку сертификата. Токен: " + authTokenByCertificateThumbprint);

            // В дальнейшем полученный токен следует подставлять в те методы API, где он требуется. (PostMessage и т.п.)
            // Токен длится 24 часа, после его протухания методы начнут возвращать 401, и потребуется вновь получить токен через методы выше.
        }
Example #4
0
        public static void PostLargeNonformalized()
        {
            // Для использования Диадок требуются:
            // 1. крипто-API, предоставляемое операционной системой (доступно через класс WinApiCrypt)
            // 2. экземпляр класса DiadocApi, проксирующий работу с веб-сервисом Диадок
            var crypt = new WinApiCrypt();
            var api   = new DiadocApi(
                DefaultClientId,                                                                        // идентификатор клиента
                DefaultApiUrl,                                                                          // URL веб-сервиса Диадок
                crypt);

            // Можно использовать либо аутентификацию по логину/паролю, либо по сертификату
            var authToken = api.Authenticate(DefaultLogin, DefaultPassword);

            // Для отправки комплекта документов через Диадок требуется подготовить структуру MessageToPost,
            // которая и будет содержать отправляемый комплект документов
            var message = new MessageToPost
            {
                // GUID ящика отправителя
                FromBoxId = DefaultFromBoxId,
                // GUID ящика получателя
                ToBoxId = DefaultToBoxId
            };

            // Читаем содержимое отправляемого файла
            var content = ReadFileContent(FileToSendName);

            // Загружаем отправляемый файл на "полку" (на сервер временного хранения файлов Диадок)
            var uploadedFileShelfName = api.UploadFileToShelf(authToken, content);

            // Для того, чтобы подписать файл, требуется сертификат
            var certContent = ReadFileContent(FileWithCertName);
            var cert        = new X509Certificate2(certContent);

            // Подписываем содержимое файла
            var signature = crypt.Sign(content, cert.RawData);

            // Формируем структуру для представления неформализованного (с точки зрения Диадока) документа
            var attachment = new NonformalizedAttachment
            {
                Comment  = "Комментарий к отправляемому документу",                 // Комментарий к отправляемому документу
                FileName = new FileInfo(FileToSendName).Name,                       // Протокол обмена с Диадок требует наличия имени файла (без пути!)
                NeedRecipientSignature = false,                                     // Требуется ли подпись получателя
                DocumentDate           = DateTime.Now.ToShortDateString(),          // Дата составления документа
                DocumentNumber         = "123",                                     // Номер документа
                CustomDocumentId       = "",                                        // Строковый идентификатор документа (если требуется связать документы в пакете)
                SignedContent          = new SignedContent
                {
                    NameOnShelf = uploadedFileShelfName,                                        // Имя файла, ранее загруженного на "полку"
                    Signature   = signature                                                     // Подпись к отправляемому содержимому
                }
            };

            // Документ подготовлен к отправке. Добавляем его в отправляемое сообщение
            message.AddAttachment(attachment);

            // Отправляем подготовленный комплект документов через Диадок
            var response = api.PostMessage(authToken, message);

            // При необходимости можно обработать ответ сервера (например, можно получить
            // и сохранить для последующей обработки идентификатор сообщения)
            Console.Out.WriteLine("Message was successfully sent.");
            Console.Out.WriteLine("The message ID is: " + response.MessageId);
        }
Example #5
0
        public static void RunSample()
        {
            Console.WriteLine("Пример отправки универсального передаточного документа (УПД) в формате приказа №820");
            Console.WriteLine("===================================================================================");

            // Для использования API Диадока требуются:
            // 1. Крипто-API, предоставляемое операционной системой. Для систем на ОС Windows используйте класс WinApiCrypt.
            // 2. Экземпляр класса DiadocApi, проксирующий работу с Диадоком.
            var crypt     = new WinApiCrypt();
            var diadocApi = new DiadocApi(
                Constants.DefaultClientId,
                Constants.DefaultApiUrl,
                crypt);

            // Авторизуемся в Диадоке. В этом примере используем авторизацию через логин-пароль:
            var authToken = diadocApi.Authenticate(Constants.DefaultLogin, Constants.DefaultPassword);
            // Также можно использовать авторизацию по сертификату, она описана в примере Authenticate.cs

            // Для отправки комплекта документов требуется подготовить структуру MessageToPost,
            // которая и будет содержать отправляемый комплект документов.

            // Для начала, укажем в структуре идентификаторы отправителя и получателя:
            var messageToPost = new MessageToPost
            {
                FromBoxId = Constants.DefaultFromBoxId,
                ToBoxId   = Constants.DefaultToBoxId
            };

            // Перечислим связку идентификаторов, которая характеризует полный формализованный тип документа в Диадоке
            var typeNamedId = "UniversalTransferDocument"; // строковый идентификатор типа УПД
            var function    = "СЧФ";                       // функция, представляющая УПД как счёт-фактуру
            var version     = "utd820_05_01_01_hyphen";    // версия, отвечающая за то, что документ сформирован в формате приказа №820

            // Теперь создадим сам формализованный документ.
            // Мы должны получить xml, которая будет удовлетворять его схеме: https://www.diadoc.ru/docs/laws/mmb-7-15-820
            // C# SDK Диадока позволяет интеграторам создать объект типа UniversalTransferDocumentWithHyphens,
            // который получается из кодогенерации упрощенной xsd-схемы титула документа:
            var userDataContract = BuildUserDataContract();

            // Теперь средствами универсального метода генерации мы получим из упрощенного xml
            // уже реальный титул документа, который будет удовлетворять приказу №820:
            Console.WriteLine("Генерируем титул отправителя...");
            var generatedTitle = diadocApi.GenerateTitleXml(
                authToken,
                Constants.DefaultFromBoxId,
                typeNamedId,
                function,
                version,
                0,
                userDataContract.SerializeToXml());

            Console.WriteLine("Титул отправителя был успешно сгенерирован.");

            // Подпишем полученный титул через WinApiCrypt нашим сертификатом:
            Console.WriteLine("Создаём подпись...");
            var content     = generatedTitle.Content;
            var certificate = new X509Certificate2(File.ReadAllBytes(Constants.CertificatePath));
            var signature   = crypt.Sign(content, certificate.RawData);           // здесь лежит бинарное представление подписи к УПД

            Console.WriteLine("Создана подпись к документу.");

            // Теперь передадим в структуру информацию о файле.
            // Для этого воспользуемся универсальным полем DocumentAttachment — через него можно отправить любой тип.
            var documentAttachment = new DocumentAttachment
            {
                /*
                 * Чтобы Диадок знал, какой тип документа вы хотите отправить,
                 * нужно заполнить поле TypeNamedId (а также Function и Version, если у типа больше одной функции и версии).
                 * Узнать список доступных типов можно через метод-справочник GetDocumentTypes.
                 *
                 * Для наших целей (УПД с функцией СЧФ в формате приказа №820) мы уже подобрали нужную комбинацию выше:
                 */
                TypeNamedId = typeNamedId,
                Function    = function,
                Version     = version,

                // Теперь передадим сам файл УПД и сформированную к нему подпись:
                SignedContent = new SignedContent
                {
                    Content   = content,
                    Signature = signature
                },

                Comment          = "Здесь можно указать любой текстовый комментарий, который нужно оставить к документу",
                CustomDocumentId = "Тут можно указать любой строковый идентификатор, например, для соответствия с вашей учётной системой",

                /*
                 * У каждого типа документа в Диадоке может быть свой набор метаданных.
                 * Их нужно указывать при отправке, если они обязательны.
                 * Узнать набор требуемых метаданных для конкретного набора (тип-функция-версия-порядковый номер титула)
                 * можно через тот же метод-справочник GetDocumentTypes: смотрите поля MetadataItems.
                 *
                 * Для формализованных документов метаданные обычно достаются из xml самим Диадоком.
                 * Если у метаданных указан Source=Xml, отдельно передавать в MessageToPost их не нужно.
                 */
            };

            // Добавим информацию о документе в MessageToPost:
            messageToPost.DocumentAttachments.Add(documentAttachment);

            // Наконец отправляем подготовленный комплект документов через Диадок
            Console.WriteLine("Отправляем пакет из одного УПД с функцией СЧФ...");
            Console.WriteLine("Из ящика: " + messageToPost.FromBoxId);
            Console.WriteLine("В ящик: " + messageToPost.ToBoxId);

            var response = diadocApi.PostMessage(authToken, messageToPost);

            // При необходимости можно обработать ответ сервера (например, можно получить
            // и сохранить для последующей обработки идентификатор сообщения)
            Console.WriteLine("Документ был успешно загружен.");
            Console.WriteLine("MessageID: " + response.MessageId);
            Console.WriteLine("Количество сущностей в сообщении: " + response.Entities.Count);

            // В ответе будет две сущности, т.к. контент и подпись к нему хранятся отдельно друг от друга.
            // Выведем информацию о самом документе. Это можно сделать так:
            var responseDocument = response.Entities.FirstOrDefault(e => string.IsNullOrEmpty(e.ParentEntityId));             // т.к. у документа нет "родительских сущностей"

            Console.WriteLine("Идентификатор документа: " + responseDocument.EntityId);
            Console.WriteLine("Название документа: " + responseDocument.DocumentInfo.Title);
        }
        public static void RunSample()
        {
            Console.WriteLine("Пример отправки неформализованного документа");
            Console.WriteLine("============================================");

            // Для использования API Диадока требуются:
            // 1. Крипто-API, предоставляемое операционной системой. Для систем на ОС Windows используйте класс WinApiCrypt.
            // 2. Экземпляр класса DiadocApi, проксирующий работу с Диадоком.

            var crypt     = new WinApiCrypt();
            var diadocApi = new DiadocApi(
                Constants.DefaultClientId,
                Constants.DefaultApiUrl,
                crypt);

            // Авторизуемся в Диадоке. В этом примере используем авторизацию через логин-пароль:
            var authToken = diadocApi.Authenticate(Constants.DefaultLogin, Constants.DefaultPassword);
            // Также можно использовать авторизацию по сертификату, она описана в примере Authenticate.cs

            // Для отправки комплекта документов требуется подготовить структуру MessageToPost,
            // которая и будет содержать отправляемый комплект документов.

            // Для начала, укажем в структуре идентификаторы отправителя и получателя:
            var messageToPost = new MessageToPost
            {
                FromBoxId = Constants.DefaultFromBoxId,
                ToBoxId   = Constants.DefaultToBoxId
            };

            // Подготовим контент и подпишем его через WinApiCrypt нашим сертификатом:
            var content = File.ReadAllBytes(NonformalizedDocumentPath);             // здесь лежит бинарное представление неформализованного документа

            Console.WriteLine("Создаём подпись...");
            var certificate = new X509Certificate2(File.ReadAllBytes(Constants.CertificatePath));
            var signature   = crypt.Sign(content, certificate.RawData);           // здесь лежит бинарное представление подписи к документу

            Console.WriteLine("Создана подпись к документу.");


            // Теперь передадим в структуру информацию о файле.
            // Для этого воспользуемся универсальным полем DocumentAttachment — через него можно отправить любой тип.
            var documentAttachment = new DocumentAttachment
            {
                /*
                 * Чтобы Диадок знал, какой тип документа вы хотите отправить,
                 * нужно заполнить поле TypeNamedId (а также Function и Version, если у типа больше одной функции и версии).
                 * Узнать список доступных типов можно через метод-справочник GetDocumentTypes.
                 */
                TypeNamedId = "nonformalized",

                // Теперь передадим сам файл неформализованного документа и сформированную к нему подпись:
                SignedContent = new SignedContent
                {
                    Content   = content,
                    Signature = signature
                },

                Comment          = "Здесь можно указать любой текстовый комментарий, который нужно оставить к документу",
                CustomDocumentId = "Тут можно указать любой строковый идентификатор, например, для соответствия с вашей учётной системой",

                /*
                 * У каждого типа документа в Диадоке может быть свой набор метаданных.
                 * Их нужно указывать при отправке, если они обязательны.
                 * Узнать набор требуемых метаданных для конкретного набора (тип-функция-версия-порядковый номер титула)
                 * можно через тот же метод-справочник GetDocumentTypes: смотрите поля MetadataItems.
                 *
                 * Для нашего случая, связки nonformalized-default-v1, часть ответа метода GetDocumentTypes выглядит так:
                 *
                 * "MetadataItems": [
                 *      {
                 *              "Id": "FileName",
                 *              "Type": "String",
                 *              "IsRequired": true,
                 *              "Source": "User"
                 *      },
                 *      {
                 *              "Id": "DocumentNumber",
                 *              "Type": "String",
                 *              "IsRequired": false,
                 *              "Source": "User"
                 *      },
                 *      {
                 *              "Id": "DocumentDate",
                 *              "Type": "Date",
                 *              "IsRequired": false,
                 *              "Source": "User"
                 *      }
                 * ]
                 *
                 * Это нужно читать так: для отправки неформализованного документа
                 * обязательно нужно указывать только те метаданные, у которых IsRequired=true,
                 * а источник: User. Под условие подходит только FileName — имя файла документа.
                 *
                 * Другие метаданные (DocumentNumber — номер документа, DocumentDate — дата документа) необязательны к заполнению,
                 * но их можно указать, и тогда Диадок будет возвращать их при запросе документа,
                 * будет отображать в веб-интерфейсе и т.п.
                 */

                Metadata =
                {
                    new MetadataItem
                    {
                        Key = "FileName",
                        // Из эстетических соображений можно обрезать расширение файла, но это необязательно.
                        // Указанное здесь значение будет влиять на то, как неформализованный документ будет называться в Диадоке.
                        // Оно может отличаться от реального названия файла.
                        Value = Path.GetFileNameWithoutExtension(NonformalizedDocumentPath)
                    }
                }
            };

            // Добавим информацию о документе в MessageToPost:
            messageToPost.DocumentAttachments.Add(documentAttachment);

            // Наконец отправляем подготовленный комплект документов через Диадок

            Console.WriteLine("Отправляем пакет из одного неформализованного документа...");
            Console.WriteLine("Из ящика: " + messageToPost.FromBoxId);
            Console.WriteLine("В ящик: " + messageToPost.ToBoxId);

            var response = diadocApi.PostMessage(authToken, messageToPost);

            // При необходимости можно обработать ответ сервера (например, можно получить
            // и сохранить для последующей обработки идентификатор сообщения)
            Console.WriteLine("Документ был успешно загружен.");
            Console.WriteLine("MessageID: " + response.MessageId);
            Console.WriteLine("Количество сущностей в сообщении: " + response.Entities.Count);

            // В ответе будет две сущности, т.к. контент и подпись к нему хранятся отдельно друг от друга.
            // Выведем информацию о самом документе. Это можно сделать так:
            var responseDocument = response.Entities.FirstOrDefault(e => string.IsNullOrEmpty(e.ParentEntityId));             // т.к. у документа нет "родительских сущностей"

            Console.WriteLine("Идентификатор документа: " + responseDocument.EntityId);
            Console.WriteLine("Название документа: " + responseDocument.DocumentInfo.Title);
        }
        public static void RunSample()
        {
            Console.WriteLine("Пример отправки документа через Полку.");
            Console.WriteLine("Актуально для тяжеловесных файлов (больше мегабайта)");
            Console.WriteLine("====================================================");

            // Для использования API Диадока требуются:
            // 1. Крипто-API, предоставляемое операционной системой. Для систем на ОС Windows используйте класс WinApiCrypt.
            // 2. Экземпляр класса DiadocApi, проксирующий работу с Диадоком.

            var crypt     = new WinApiCrypt();
            var diadocApi = new DiadocApi(
                Constants.DefaultClientId,
                Constants.DefaultApiUrl,
                crypt);

            // Авторизуемся в Диадоке. В этом примере используем авторизацию через логин-пароль:
            var authToken = diadocApi.Authenticate(Constants.DefaultLogin, Constants.DefaultPassword);
            // Также можно использовать авторизацию по сертификату, она описана в примере Authenticate.cs

            // Для отправки комплекта документов требуется подготовить структуру MessageToPost,
            // которая и будет содержать отправляемый комплект документов.

            // Для начала, укажем в структуре идентификаторы отправителя и получателя:
            var messageToPost = new MessageToPost
            {
                FromBoxId = Constants.DefaultFromBoxId,
                ToBoxId   = Constants.DefaultToBoxId
            };

            // Отправим контент на Полку — временное хранилище для файлов, представляемое через API Диадока:

            var content = File.ReadAllBytes(NonformalizedDocumentPath);             // здесь лежит бинарное представление неформализованного документа

            Console.WriteLine("Загружаем документ на Полку...");
            var uploadedFileShelfName = diadocApi.UploadFileToShelf(authToken, content);

            Console.WriteLine("Успешно. Путь до документа на Полке: " + uploadedFileShelfName);

            // Подпишем контент через WinApiCrypt нашим сертификатом и тоже отправим на Полку:
            var certificate = new X509Certificate2(File.ReadAllBytes(Constants.CertificatePath));

            Console.WriteLine("Создаём подпись...");
            var signature = crypt.Sign(content, certificate.RawData);             // здесь лежит бинарное представление подписи к документу

            Console.WriteLine("Создана подпись к документу.");

            Console.WriteLine("Загружаем подпись на Полку...");
            var uploadedSignatureShelfName = diadocApi.UploadFileToShelf(authToken, signature);

            Console.WriteLine("Успешно. Путь до подписи на Полке: " + uploadedSignatureShelfName);

            // Теперь передадим в структуру информацию о файле.
            // Подробности заполнения типа и метаданных можно посмотреть в примере PostNonformalizedDocument.cs
            var documentAttachment = new DocumentAttachment
            {
                TypeNamedId = "nonformalized",

                // Здесь мы передаём не само бинарное представление, а только путь до Полки:
                SignedContent = new SignedContent
                {
                    NameOnShelf          = uploadedFileShelfName,
                    SignatureNameOnShelf = uploadedSignatureShelfName
                },

                Metadata =
                {
                    new MetadataItem
                    {
                        Key   = "FileName",
                        Value = Path.GetFileNameWithoutExtension(NonformalizedDocumentPath)
                    }
                }
            };

            // Добавим информацию о документе в MessageToPost:
            messageToPost.DocumentAttachments.Add(documentAttachment);

            // Наконец отправляем подготовленный комплект документов через Диадок

            Console.WriteLine("Отправляем пакет из одного неформализованного документа...");
            Console.WriteLine("Из ящика: " + messageToPost.FromBoxId);
            Console.WriteLine("В ящик: " + messageToPost.ToBoxId);

            var response = diadocApi.PostMessage(authToken, messageToPost);

            // При необходимости можно обработать ответ сервера (например, можно получить
            // и сохранить для последующей обработки идентификатор сообщения)
            Console.WriteLine("Документ был успешно загружен.");
            Console.WriteLine("MessageID: " + response.MessageId);
            Console.WriteLine("Количество сущностей в сообщении: " + response.Entities.Count);

            // В ответе будет две сущности, т.к. контент и подпись к нему хранятся отдельно друг от друга.
            // Выведем информацию о самом документе. Это можно сделать так:
            var responseDocument = response.Entities.FirstOrDefault(e => string.IsNullOrEmpty(e.ParentEntityId));             // т.к. у документа нет "родительских сущностей"

            Console.WriteLine("Идентификатор документа: " + responseDocument.EntityId);
            Console.WriteLine("Название документа: " + responseDocument.DocumentInfo.Title);
        }
Example #8
0
        public static void RunSample()
        {
            Console.WriteLine("Пример добавления извещения о получении к документу");
            Console.WriteLine("===================================================");

            // Для использования API Диадока требуются:
            // 1. Крипто-API, предоставляемое операционной системой. Для систем на ОС Windows используйте класс WinApiCrypt.
            // 2. Экземпляр класса DiadocApi, проксирующий работу с Диадоком.
            var crypt     = new WinApiCrypt();
            var diadocApi = new DiadocApi(
                Constants.DefaultClientId,
                Constants.DefaultApiUrl,
                crypt);

            // Авторизуемся в Диадоке. В этом примере используем авторизацию через логин-пароль:
            var authToken = diadocApi.Authenticate(Constants.DefaultLogin, Constants.DefaultPassword);
            // Также можно использовать авторизацию по сертификату, она описана в примере Authenticate.cs

            // Поищем в ящике документы, для которых нужно создать и подписать извещение о получении (он же ИоП).
            // Это можно сделать несколькими способами. Один из вариантов — через фильтрацию методом GetDocuments
            var documentList = diadocApi.GetDocuments(
                authToken,
                new DocumentsFilter
            {
                // Если вы успешно выполняли пример из PostUniversalTransferDocument820.cs,
                // в качестве ящика можно подставить ящик получателя
                BoxId          = BoxId,
                FilterCategory = "Any.InboundHaveToCreateReceipt"                         // этот фильтр читается так: входящий документ любого типа, для которого нужно создать ИоП (на любую сущность)
            });

            // В зависимости от документооборота, ИоПы могут быть и на другие сущности:
            // например, при работе с счетом-фактурой требуется отправить ИоП на подтверждение оператора ЭДО.
            // Подробнее о всех сущностях можно прочитать в документации:
            // http://api-docs.diadoc.ru/ru/latest/http/GenerateReceiptXml.html
            // http://api-docs.diadoc.ru/ru/latest/howto/example_receive_invoice.html

            // Поэтому для примера из выборки возьмём первый подходящий документ, для которого нет ИоПа только к титулу отправителя:
            string messageId  = null;
            string documentId = null;

            foreach (var document in documentList.Documents)
            {
                var message = diadocApi.GetMessage(authToken, BoxId, document.MessageId);
                if (!HasReceiptForAttachment(message, document.EntityId))
                {
                    messageId  = document.MessageId;
                    documentId = document.EntityId;
                    break;
                }
            }

            if (messageId == null && documentId == null)
            {
                Console.WriteLine("Подходящих документов нет, завершаем работу примера.");
                return;
            }

            Console.WriteLine($"Берём документ с идентификаторами MessageId={messageId}, EntityId={documentId}");

            // Теперь приступим к созданию самого извещения о получении.
            // Это — технологический документ в формате XML.
            // Самый простой способ получить его: использовать соответствующий метод генерации
            Console.WriteLine("Создаём извещение о получении...");
            var generatedReceipt = diadocApi.GenerateReceiptXml(
                authToken,
                BoxId,
                messageId,
                documentId,                 // здесь указываем идентификатор титула, т.к. мы создаём ИоП именно к нему
                new Signer
            {
                SignerDetails = new SignerDetails
                {
                    FirstName  = "Иван",
                    Patronymic = "Иванович",
                    Surname    = "Иванов",
                    Inn        = "7750370238",
                    JobTitle   = "директор"
                }
            });

            Console.WriteLine("Извещение о получении сгенерировано.");

            // ИоП, как и любой документ, также должен быть подписан. Создаём к нему подпись
            Console.WriteLine("Создаём подпись...");
            var content     = generatedReceipt.Content;
            var certificate = new X509Certificate2(File.ReadAllBytes(Constants.CertificatePath));
            var signature   = crypt.Sign(content, certificate.RawData);

            Console.WriteLine("Создана подпись к извещению о получении.");

            // Теперь мы готовы к отправке ИоПа. Делается это через метод PostMessagePatch
            var messagePatchToPost = new MessagePatchToPost
            {
                BoxId     = BoxId,
                MessageId = messageId
            };

            var receiptAttachment = new ReceiptAttachment
            {
                ParentEntityId = documentId,                 // наш ИоП будет относиться к документу, поэтому явно показываем, к какой сущности мы создаем ИоП
                SignedContent  = new SignedContent
                {
                    Content   = content,
                    Signature = signature
                }
            };

            messagePatchToPost.Receipts.Add(receiptAttachment);

            var response = diadocApi.PostMessagePatch(authToken, messagePatchToPost);

            Console.WriteLine("Извещение о получении было успешно загружено.");

            var receipt = response.Entities.First(
                e => e.ParentEntityId == documentId &&
                (e.AttachmentType == AttachmentType.Receipt ||
                 e.AttachmentType == AttachmentType.InvoiceReceipt));

            Console.WriteLine($"Идентификатор: {receipt.EntityId}");
        }