Add e-signature support and improve PDF signing process
Introduced `ESignParams` for configurable e-signature settings, including `ApplicationName` and `DefaultReason`. Updated `DocReceiverElementDto` and `PdfSignOptionsDto` to support new properties. Registered `ESignParams` in DI container. Refactored `SignPdfByElementCommand` to include new fields and improved error handling. Added `SignPdfByEnvelopeReceiverCommand` to enable signing documents for envelope receivers. Replaced DevExpress with PdfSharp for PDF rendering in `ReceiverSignedPage.razor`, improving layout and flexibility. Enhanced `PdfSignatureController` with a new endpoint for signing documents by envelope key. Added `DataIntegrityException` for better error handling. Updated `appsettings.json` with `ESignParams` configuration.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using EnvelopeGenerator.Application.Common.Enums;
|
||||
using EnvelopeGenerator.Application.Documents.Queries;
|
||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Domain.Exceptions;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.PdfSigning;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record SignPdfByEnvelopeReceiverCommand : IRequest<Stream>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int EnvelopeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ReceiverId { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class SignPdfByEnvelopeReceiverCommandHandler(IRepository<DocReceiverElement> Repo, IMapper Mapper, ISender Sender) : IRequestHandler<SignPdfByEnvelopeReceiverCommand, Stream>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public async Task<Stream> Handle(SignPdfByEnvelopeReceiverCommand request, CancellationToken cancel)
|
||||
{
|
||||
cancel.ThrowIfCancellationRequested();
|
||||
|
||||
// read elements
|
||||
var elements = await Repo.Where(el => el.ReceiverId == request.ReceiverId && el.Document.EnvelopeId == request.EnvelopeId)
|
||||
.Include(e => e.Receiver)
|
||||
.ToListAsync(cancel) ?? throw new NotFoundException($"No elements found for Envelope ID {request.EnvelopeId} and Receiver ID {request.ReceiverId}.");
|
||||
var elementDtos = Mapper.Map<List<DocReceiverElementDto>>(elements)
|
||||
.OrderBy(e => e.Page)
|
||||
.ThenBy(e => e.Id)
|
||||
.ToList();
|
||||
|
||||
// read secrets for phone number
|
||||
var erSecrets = await Sender.Send(new ReadEnvelopeReceiverSecretQuery()
|
||||
{
|
||||
Envelope = new() { Id = request.EnvelopeId },
|
||||
Receiver = new() { Id = request.ReceiverId }
|
||||
}, cancel) ?? throw new DataIntegrityException($"No secrets found for Envelope ID {request.EnvelopeId} and Receiver ID {request.ReceiverId}.");
|
||||
|
||||
// read document
|
||||
var unsignedDoc = await Sender.Send(new ReadDocumentQuery(EnvelopeId: request.EnvelopeId), cancel);
|
||||
var unsignedDocBytes = unsignedDoc.ByteData ?? throw new NotFoundException($"Document not found for Envelope ID {request.EnvelopeId} and Receiver ID {request.ReceiverId}.");
|
||||
|
||||
Stream doc = new MemoryStream(unsignedDocBytes);
|
||||
|
||||
// sign document for each element
|
||||
foreach (var element in elementDtos)
|
||||
{
|
||||
var lastElement = element == elementDtos.Last();
|
||||
|
||||
var signedDoc = await Sender.Send(new SignPdfByElementCommand
|
||||
{
|
||||
Document = doc,
|
||||
Element = element,
|
||||
CertificationLevel = lastElement ? PdfSignatureCertificationLevel.NoChangesAllowed : PdfSignatureCertificationLevel.FillFormsAndAnnotate,
|
||||
Phone = erSecrets.PhoneNumber
|
||||
}, cancel);
|
||||
|
||||
await doc.DisposeAsync();
|
||||
doc = signedDoc;
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user