2020-01-27 11:15:18 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* (c) Copyright Ascensio System Limited 2010-2018
|
|
|
|
*
|
|
|
|
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
|
|
|
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
|
|
|
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
|
|
|
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
|
|
|
*
|
|
|
|
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
|
|
|
*
|
|
|
|
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
|
|
|
*
|
|
|
|
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
|
|
|
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
|
|
|
*
|
|
|
|
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
|
|
|
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
|
|
|
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
|
|
|
* in every copy of the program you distribute.
|
|
|
|
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.IO;
|
|
|
|
using System.Runtime.Serialization;
|
|
|
|
using System.Security;
|
2020-02-05 08:30:04 +00:00
|
|
|
|
2020-02-17 08:58:14 +00:00
|
|
|
using ASC.Common;
|
2020-01-27 11:15:18 +00:00
|
|
|
using ASC.Common.Logging;
|
2020-02-17 08:58:14 +00:00
|
|
|
using ASC.Core;
|
|
|
|
using ASC.Core.Common;
|
2020-01-27 11:15:18 +00:00
|
|
|
using ASC.Core.Users;
|
|
|
|
using ASC.FederatedLogin;
|
|
|
|
using ASC.FederatedLogin.Helpers;
|
|
|
|
using ASC.FederatedLogin.LoginProviders;
|
|
|
|
using ASC.Files.Core;
|
2020-02-17 08:58:14 +00:00
|
|
|
using ASC.Files.Core.Data;
|
|
|
|
using ASC.Files.Core.Security;
|
2020-01-27 11:15:18 +00:00
|
|
|
using ASC.MessagingSystem;
|
|
|
|
using ASC.Web.Core.Files;
|
2020-02-17 08:58:14 +00:00
|
|
|
using ASC.Web.Core.Users;
|
2020-01-27 11:15:18 +00:00
|
|
|
using ASC.Web.Files.Classes;
|
|
|
|
using ASC.Web.Files.HttpHandlers;
|
|
|
|
using ASC.Web.Files.Resources;
|
|
|
|
using ASC.Web.Files.Services.WCFService;
|
|
|
|
using ASC.Web.Files.ThirdPartyApp;
|
|
|
|
using ASC.Web.Files.Utils;
|
|
|
|
using ASC.Web.Studio.Core;
|
2020-02-17 08:58:14 +00:00
|
|
|
|
|
|
|
using DocuSign.eSign.Api;
|
|
|
|
using DocuSign.eSign.Client;
|
|
|
|
using DocuSign.eSign.Model;
|
|
|
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
2020-01-27 11:15:18 +00:00
|
|
|
using Newtonsoft.Json;
|
2020-02-17 08:58:14 +00:00
|
|
|
|
2020-01-27 11:15:18 +00:00
|
|
|
using File = ASC.Files.Core.File;
|
|
|
|
using Folder = ASC.Files.Core.Folder;
|
|
|
|
|
|
|
|
namespace ASC.Web.Files.Helpers
|
|
|
|
{
|
|
|
|
public class DocuSignToken
|
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
public ILog Log { get; set; }
|
|
|
|
|
2020-02-17 08:58:14 +00:00
|
|
|
public const string AppAttr = "docusign";
|
|
|
|
|
|
|
|
public TokenHelper TokenHelper { get; }
|
|
|
|
public AuthContext AuthContext { get; }
|
|
|
|
public DocuSignLoginProvider DocuSignLoginProvider { get; }
|
|
|
|
|
|
|
|
public DocuSignToken(
|
|
|
|
TokenHelper tokenHelper,
|
|
|
|
IOptionsMonitor<ILog> options,
|
|
|
|
AuthContext authContext,
|
|
|
|
DocuSignLoginProvider docuSignLoginProvider)
|
|
|
|
{
|
|
|
|
TokenHelper = tokenHelper;
|
|
|
|
AuthContext = authContext;
|
|
|
|
DocuSignLoginProvider = docuSignLoginProvider;
|
|
|
|
Log = options.CurrentValue;
|
|
|
|
}
|
2020-02-05 08:30:04 +00:00
|
|
|
|
|
|
|
public OAuth20Token GetToken()
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
return TokenHelper.GetToken(AppAttr);
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
public void DeleteToken(Guid? userId = null)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
TokenHelper.DeleteToken(AppAttr, userId);
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
public void SaveToken(OAuth20Token token)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
if (token == null) throw new ArgumentNullException("token");
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
TokenHelper.SaveToken(new Token(token, AppAttr));
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
internal string GetRefreshedToken(OAuth20Token token)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
if (token.IsExpired)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
Log.Info("DocuSign refresh token for user " + AuthContext.CurrentAccount.ID);
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
var refreshed = DocuSignLoginProvider.Instance.RefreshToken(token.RefreshToken);
|
|
|
|
|
|
|
|
if (refreshed != null)
|
|
|
|
{
|
|
|
|
token.AccessToken = refreshed.AccessToken;
|
|
|
|
token.RefreshToken = refreshed.RefreshToken;
|
|
|
|
token.ExpiresIn = refreshed.ExpiresIn;
|
|
|
|
token.Timestamp = DateTime.UtcNow;
|
|
|
|
|
|
|
|
SaveToken(token);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
Log.Error("DocuSign refresh token for user " + AuthContext.CurrentAccount.ID, ex);
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return token.AccessToken;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class DocuSignHelper
|
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
public ILog Log { get; set; }
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
public const string UserField = "userId";
|
|
|
|
|
|
|
|
public static readonly List<string> SupportedFormats = new List<string>
|
|
|
|
{
|
|
|
|
".as", ".asl", ".doc", ".docm", ".docx", ".dot", ".dotm", ".dotx", ".htm", ".html", ".msg", ".pdf", ".pdx", ".rtf", ".txt", ".wpd", ".wps", ".wpt", ".xps",
|
|
|
|
".emz", ".svg", ".svgz", ".vdx", ".vss", ".vst",
|
|
|
|
".bmp", ".cdr", ".dcx", ".gif", ".ico", ".jpg", ".jpeg", ".pct", ".pic", ".png", ".rgb", ".sam", ".tga", ".tif", ".tiff", ".wpg",
|
|
|
|
".dps", ".dpt", ".pot", ".potx", ".pps", ".ppt", ".pptm", ".pptx",
|
|
|
|
".csv", ".et", ".ett", ".xls", ".xlsm", ".xlsx", ".xlt"
|
|
|
|
};
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
public static long MaxFileSize = 25L * 1024L * 1024L;
|
|
|
|
|
2020-02-17 08:58:14 +00:00
|
|
|
public static int MaxEmailLength = 10000;
|
|
|
|
|
|
|
|
public DocuSignToken DocuSignToken { get; }
|
|
|
|
public DocuSignLoginProvider DocuSignLoginProvider { get; }
|
|
|
|
public FileSecurity FileSecurity { get; }
|
|
|
|
public IDaoFactory DaoFactory { get; }
|
|
|
|
public BaseCommonLinkUtility BaseCommonLinkUtility { get; }
|
|
|
|
public UserManager UserManager { get; }
|
|
|
|
public AuthContext AuthContext { get; }
|
|
|
|
public DisplayUserSettingsHelper DisplayUserSettingsHelper { get; }
|
|
|
|
public FileMarker FileMarker { get; }
|
|
|
|
public GlobalFolderHelper GlobalFolderHelper { get; }
|
|
|
|
public FilesMessageService FilesMessageService { get; }
|
|
|
|
public FilesLinkUtility FilesLinkUtility { get; }
|
|
|
|
public IServiceProvider ServiceProvider { get; }
|
|
|
|
|
|
|
|
public DocuSignHelper(
|
|
|
|
DocuSignToken docuSignToken,
|
|
|
|
DocuSignLoginProvider docuSignLoginProvider,
|
|
|
|
FileSecurity fileSecurity,
|
|
|
|
IDaoFactory daoFactory,
|
|
|
|
IOptionsMonitor<ILog> options,
|
|
|
|
BaseCommonLinkUtility baseCommonLinkUtility,
|
|
|
|
UserManager userManager,
|
|
|
|
AuthContext authContext,
|
|
|
|
DisplayUserSettingsHelper displayUserSettingsHelper,
|
|
|
|
FileMarker fileMarker,
|
|
|
|
GlobalFolderHelper globalFolderHelper,
|
|
|
|
FilesMessageService filesMessageService,
|
|
|
|
FilesLinkUtility filesLinkUtility,
|
|
|
|
IServiceProvider serviceProvider)
|
|
|
|
{
|
|
|
|
DocuSignToken = docuSignToken;
|
|
|
|
DocuSignLoginProvider = docuSignLoginProvider;
|
|
|
|
FileSecurity = fileSecurity;
|
|
|
|
DaoFactory = daoFactory;
|
|
|
|
BaseCommonLinkUtility = baseCommonLinkUtility;
|
|
|
|
UserManager = userManager;
|
|
|
|
AuthContext = authContext;
|
|
|
|
DisplayUserSettingsHelper = displayUserSettingsHelper;
|
|
|
|
FileMarker = fileMarker;
|
|
|
|
GlobalFolderHelper = globalFolderHelper;
|
|
|
|
FilesMessageService = filesMessageService;
|
|
|
|
FilesLinkUtility = filesLinkUtility;
|
|
|
|
ServiceProvider = serviceProvider;
|
|
|
|
Log = options.CurrentValue;
|
|
|
|
}
|
2020-02-05 08:30:04 +00:00
|
|
|
|
|
|
|
public bool ValidateToken(OAuth20Token token)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
GetDocuSignAccount(token);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
public string SendDocuSign(object fileId, DocuSignData docuSignData, Dictionary<string, string> requestHeaders)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
if (docuSignData == null) throw new ArgumentNullException("docuSignData");
|
|
|
|
var token = DocuSignToken.GetToken();
|
|
|
|
var account = GetDocuSignAccount(token);
|
|
|
|
|
|
|
|
var configuration = GetConfiguration(account, token);
|
2020-02-05 08:30:04 +00:00
|
|
|
var document = CreateDocument(fileId, docuSignData.Name, docuSignData.FolderId, out var sourceFile);
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
var url = CreateEnvelope(account.AccountId, document, docuSignData, configuration);
|
|
|
|
|
|
|
|
FilesMessageService.Send(sourceFile, requestHeaders, MessageAction.DocumentSendToSign, "DocuSign", sourceFile.Title);
|
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
private DocuSignAccount GetDocuSignAccount(OAuth20Token token)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
if (token == null) throw new ArgumentNullException("token");
|
|
|
|
|
|
|
|
var userInfoString = RequestHelper.PerformRequest(DocuSignLoginProvider.Instance.DocuSignHost + "/oauth/userinfo",
|
2020-02-05 08:30:04 +00:00
|
|
|
headers: new Dictionary<string, string> { { "Authorization", "Bearer " + DocuSignToken.GetRefreshedToken(token) } });
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
Log.Debug("DocuSing userInfo: " + userInfoString);
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
var userInfo = (DocuSignUserInfo)JsonConvert.DeserializeObject(userInfoString, typeof(DocuSignUserInfo));
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
if (userInfo.Accounts == null || userInfo.Accounts.Count == 0) throw new Exception("Account is null");
|
|
|
|
|
|
|
|
var account = userInfo.Accounts[0];
|
|
|
|
return account;
|
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
private DocuSign.eSign.Client.Configuration GetConfiguration(DocuSignAccount account, OAuth20Token token)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
if (account == null) throw new ArgumentNullException("account");
|
|
|
|
if (token == null) throw new ArgumentNullException("token");
|
|
|
|
|
|
|
|
var apiClient = new ApiClient(account.BaseUri + "/restapi");
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
var configuration = new DocuSign.eSign.Client.Configuration { ApiClient = apiClient };
|
2020-01-27 11:15:18 +00:00
|
|
|
configuration.AddDefaultHeader("Authorization", "Bearer " + DocuSignToken.GetRefreshedToken(token));
|
|
|
|
|
|
|
|
return configuration;
|
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
private Document CreateDocument(object fileId, string documentName, string folderId, out File file)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
2020-02-17 08:58:14 +00:00
|
|
|
var fileDao = DaoFactory.FileDao;
|
|
|
|
file = fileDao.GetFile(fileId);
|
|
|
|
if (file == null) throw new Exception(FilesCommonResource.ErrorMassage_FileNotFound);
|
|
|
|
if (!FileSecurity.CanRead(file)) throw new SecurityException(FilesCommonResource.ErrorMassage_SecurityException_ReadFile);
|
|
|
|
if (!SupportedFormats.Contains(FileUtility.GetFileExtension(file.Title))) throw new ArgumentException(FilesCommonResource.ErrorMassage_NotSupportedFormat);
|
|
|
|
if (file.ContentLength > MaxFileSize) throw new Exception(FileSizeComment.GetFileSizeExceptionString(MaxFileSize));
|
|
|
|
|
|
|
|
byte[] fileBytes;
|
|
|
|
using (var stream = fileDao.GetFileStream(file))
|
|
|
|
{
|
|
|
|
var buffer = new byte[16 * 1024];
|
|
|
|
using var ms = new MemoryStream();
|
|
|
|
int read;
|
|
|
|
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
|
|
|
|
{
|
|
|
|
ms.Write(buffer, 0, read);
|
|
|
|
}
|
|
|
|
fileBytes = ms.ToArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(documentName))
|
|
|
|
{
|
|
|
|
documentName = file.Title;
|
|
|
|
}
|
|
|
|
|
|
|
|
var document = new Document
|
|
|
|
{
|
|
|
|
DocumentBase64 = Convert.ToBase64String(fileBytes),
|
2020-02-05 08:30:04 +00:00
|
|
|
DocumentFields = new List<NameValue>
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
new NameValue {Name = FilesLinkUtility.FolderId, Value = folderId},
|
|
|
|
new NameValue {Name = FilesLinkUtility.FileTitle, Value = file.Title},
|
2020-02-17 08:58:14 +00:00
|
|
|
},
|
|
|
|
DocumentId = "1", //file.ID.ToString(),
|
|
|
|
FileExtension = FileUtility.GetFileExtension(file.Title),
|
|
|
|
Name = documentName,
|
|
|
|
};
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
return document;
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
private string CreateEnvelope(string accountId, Document document, DocuSignData docuSignData, DocuSign.eSign.Client.Configuration configuration)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
2020-02-17 08:58:14 +00:00
|
|
|
var eventNotification = new EventNotification
|
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
EnvelopeEvents = new List<EnvelopeEvent>
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
//new EnvelopeEvent {EnvelopeEventStatusCode = DocuSignStatus.Sent.ToString()},
|
|
|
|
//new EnvelopeEvent {EnvelopeEventStatusCode = DocuSignStatus.Delivered.ToString()},
|
|
|
|
new EnvelopeEvent {EnvelopeEventStatusCode = DocuSignStatus.Completed.ToString()},
|
|
|
|
new EnvelopeEvent {EnvelopeEventStatusCode = DocuSignStatus.Declined.ToString()},
|
|
|
|
new EnvelopeEvent {EnvelopeEventStatusCode = DocuSignStatus.Voided.ToString()},
|
2020-02-17 08:58:14 +00:00
|
|
|
},
|
|
|
|
IncludeDocumentFields = "true",
|
|
|
|
//RecipientEvents = new List<RecipientEvent>
|
|
|
|
// {
|
|
|
|
// new RecipientEvent {RecipientEventStatusCode = "Sent"},
|
|
|
|
// new RecipientEvent {RecipientEventStatusCode = "Delivered"},
|
|
|
|
// new RecipientEvent {RecipientEventStatusCode = "Completed"},
|
|
|
|
// new RecipientEvent {RecipientEventStatusCode = "Declined"},
|
|
|
|
// new RecipientEvent {RecipientEventStatusCode = "AuthenticationFailed"},
|
|
|
|
// new RecipientEvent {RecipientEventStatusCode = "AutoResponded"},
|
|
|
|
// },
|
|
|
|
Url = BaseCommonLinkUtility.GetFullAbsolutePath(DocuSignHandler.Path(FilesLinkUtility) + "?" + FilesLinkUtility.Action + "=webhook"),
|
|
|
|
};
|
2020-02-05 08:30:04 +00:00
|
|
|
|
|
|
|
Log.Debug("DocuSign hook url: " + eventNotification.Url);
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
var signers = new List<Signer>();
|
|
|
|
docuSignData.Users.ForEach(uid =>
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
var user = UserManager.GetUsers(uid);
|
2020-02-17 08:58:14 +00:00
|
|
|
signers.Add(new Signer
|
|
|
|
{
|
|
|
|
Email = user.Email,
|
|
|
|
Name = user.DisplayUserName(false, DisplayUserSettingsHelper),
|
|
|
|
RecipientId = user.ID.ToString(),
|
2020-02-05 08:30:04 +00:00
|
|
|
});
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
Log.Error("Signer is undefined", ex);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-02-17 08:58:14 +00:00
|
|
|
var envelopeDefinition = new EnvelopeDefinition
|
|
|
|
{
|
|
|
|
CustomFields = new CustomFields
|
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
TextCustomFields = new List<TextCustomField>
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
2020-02-05 08:30:04 +00:00
|
|
|
new TextCustomField {Name = UserField, Value = AuthContext.CurrentAccount.ID.ToString()},
|
2020-02-17 08:58:14 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
Documents = new List<Document> { document },
|
|
|
|
EmailBlurb = docuSignData.Message,
|
|
|
|
EmailSubject = docuSignData.Name,
|
|
|
|
EventNotification = eventNotification,
|
|
|
|
Recipients = new Recipients
|
|
|
|
{
|
|
|
|
Signers = signers,
|
|
|
|
},
|
|
|
|
Status = "created",
|
2020-02-05 08:30:04 +00:00
|
|
|
};
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
var envelopesApi = new EnvelopesApi(configuration);
|
|
|
|
var envelopeSummary = envelopesApi.CreateEnvelope(accountId, envelopeDefinition);
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
Log.Debug("DocuSign createdEnvelope: " + envelopeSummary.EnvelopeId);
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
var envelopeId = envelopeSummary.EnvelopeId;
|
2020-02-17 08:58:14 +00:00
|
|
|
var url = envelopesApi.CreateSenderView(accountId, envelopeId, new ReturnUrlRequest
|
|
|
|
{
|
|
|
|
ReturnUrl = BaseCommonLinkUtility.GetFullAbsolutePath(DocuSignHandler.Path(FilesLinkUtility) + "?" + FilesLinkUtility.Action + "=redirect")
|
2020-02-05 08:30:04 +00:00
|
|
|
});
|
|
|
|
Log.Debug("DocuSign senderView: " + url.Url);
|
2020-01-27 11:15:18 +00:00
|
|
|
|
|
|
|
return url.Url;
|
|
|
|
}
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
public File SaveDocument(string envelopeId, string documentId, string documentName, object folderId)
|
2020-01-27 11:15:18 +00:00
|
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(envelopeId)) throw new ArgumentNullException("envelopeId");
|
|
|
|
if (string.IsNullOrEmpty(documentId)) throw new ArgumentNullException("documentId");
|
|
|
|
|
|
|
|
var token = DocuSignToken.GetToken();
|
|
|
|
var account = GetDocuSignAccount(token);
|
|
|
|
var configuration = GetConfiguration(account, token);
|
|
|
|
|
2020-02-17 08:58:14 +00:00
|
|
|
var fileDao = DaoFactory.FileDao;
|
|
|
|
var folderDao = DaoFactory.FolderDao;
|
|
|
|
if (string.IsNullOrEmpty(documentName))
|
|
|
|
{
|
|
|
|
documentName = "new.pdf";
|
|
|
|
}
|
|
|
|
|
|
|
|
Folder folder;
|
|
|
|
if (folderId == null
|
|
|
|
|| (folder = folderDao.GetFolder(folderId)) == null
|
|
|
|
|| folder.RootFolderType == FolderType.TRASH
|
|
|
|
|| !FileSecurity.CanCreate(folder))
|
|
|
|
{
|
|
|
|
if (GlobalFolderHelper.FolderMy != null)
|
|
|
|
{
|
|
|
|
folderId = GlobalFolderHelper.FolderMy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw new SecurityException(FilesCommonResource.ErrorMassage_SecurityException_Create);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var file = ServiceProvider.GetService<File>();
|
|
|
|
file.FolderID = folderId;
|
|
|
|
file.Comment = FilesCommonResource.CommentCreateByDocuSign;
|
|
|
|
file.Title = FileUtility.ReplaceFileExtension(documentName, ".pdf");
|
|
|
|
|
|
|
|
var envelopesApi = new EnvelopesApi(configuration);
|
|
|
|
Log.Info("DocuSign webhook get stream: " + documentId);
|
|
|
|
using (var stream = envelopesApi.GetDocument(account.AccountId, envelopeId, documentId))
|
|
|
|
{
|
|
|
|
file.ContentLength = stream.Length;
|
|
|
|
file = fileDao.SaveFile(file, stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
FilesMessageService.Send(file, MessageInitiator.ThirdPartyProvider, MessageAction.DocumentSignComplete, "DocuSign", file.Title);
|
|
|
|
|
|
|
|
FileMarker.MarkAsNew(file);
|
|
|
|
|
2020-02-05 08:30:04 +00:00
|
|
|
return file;
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[DataContract]
|
|
|
|
[DebuggerDisplay("{AccountId} {BaseUri}")]
|
|
|
|
private class DocuSignAccount
|
|
|
|
{
|
|
|
|
[DataMember(Name = "account_id", EmitDefaultValue = false)]
|
|
|
|
public string AccountId { get; set; }
|
|
|
|
|
|
|
|
[DataMember(Name = "base_uri", EmitDefaultValue = false)]
|
|
|
|
public string BaseUri { get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
[DataContract]
|
|
|
|
private class DocuSignUserInfo
|
|
|
|
{
|
|
|
|
[DataMember(Name = "accounts", EmitDefaultValue = false)]
|
|
|
|
public List<DocuSignAccount> Accounts { get; set; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[DataContract(Name = "docusign_data", Namespace = "")]
|
|
|
|
[DebuggerDisplay("{Name}")]
|
|
|
|
public class DocuSignData
|
|
|
|
{
|
|
|
|
[DataMember(Name = "folderId")]
|
|
|
|
public string FolderId { get; set; }
|
|
|
|
|
|
|
|
[DataMember(Name = "message")]
|
|
|
|
public string Message { get; set; }
|
|
|
|
|
|
|
|
[DataMember(Name = "name", IsRequired = true, EmitDefaultValue = false)]
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
|
|
|
[DataMember(Name = "users")]
|
|
|
|
public ItemList<Guid> Users { get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public enum DocuSignStatus
|
|
|
|
{
|
|
|
|
Draft,
|
|
|
|
Sent,
|
|
|
|
Delivered,
|
|
|
|
Completed,
|
|
|
|
Declined,
|
|
|
|
Voided,
|
2020-02-17 08:58:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static class DocuSignHelperExtension
|
|
|
|
{
|
|
|
|
public static DIHelper AddDocuSignTokenService(this DIHelper services)
|
|
|
|
{
|
|
|
|
services.TryAddScoped<DocuSignToken>();
|
|
|
|
return services
|
|
|
|
.AddAuthContextService()
|
|
|
|
.AddDocuSignLoginProviderService()
|
|
|
|
.AddTokenHelperService();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static DIHelper AddDocuSignHelperService(this DIHelper services)
|
|
|
|
{
|
|
|
|
services.TryAddScoped<DocuSignHelper>();
|
|
|
|
|
|
|
|
return services
|
|
|
|
.AddDocuSignLoginProviderService()
|
|
|
|
.AddFileSecurityService()
|
|
|
|
.AddDaoFactoryService()
|
|
|
|
.AddBaseCommonLinkUtilityService()
|
|
|
|
.AddUserManagerService()
|
|
|
|
.AddAuthContextService()
|
|
|
|
.AddDisplayUserSettingsService()
|
|
|
|
.AddFileMarkerService()
|
|
|
|
.AddGlobalFolderHelperService()
|
|
|
|
.AddFilesMessageService()
|
|
|
|
.AddDocuSignTokenService()
|
|
|
|
.AddFilesLinkUtilityService()
|
|
|
|
;
|
|
|
|
}
|
2020-01-27 11:15:18 +00:00
|
|
|
}
|
|
|
|
}
|