1

I have a concept tester C# solution working for Docusign.Click - Embed Elastic Signing Agreement. Including retrieving agreement response data by Agreement-Id and Agreements-Info by Client-Id. We are in the situation that in a later month. We may need to send the same elastic signing agreement to the same client-id, for re-signing.

How does one do this?

Can it be done without deleting the prior agreements for this client-id, and without creating a new elastic template?

So far in my testing I have arguments sent into the elastic signing template for client: name, email, company, and date. A change of date has not tripped a new agreement but I get an already agreed response. I checked the response output in debug, and no new agreement-url was generated.

Thanks.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocuSign.Click.Api;
using DocuSign.Click.Client;
using DocuSign.Click.Model;
using DocuSign.Click.Client.Auth;
using DocuSign.eSign.Model;
using static DocuSign.Click.Api.AccountsApi;

namespace DocuSignConsoleTester
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            string integrationKey = "xx..xx";
            string userId = "xx..xx";
            string accountId = "xx..xx";
            string authServer = "account-d.docusign.com"; // for demo environment
            string accountBaseURI = "https://demo.docusign.net/clickapi"; // for demo environment
            string fullName = "xx..xx";
            string email = "xyz@example.com";
            string company = "xx..xx";
            string title = "xx..xx";
            string clickwrapId = "xx..xx";
            string datenow = DateTime.Now.ToString();


            string access_token = GetJwtToken(integrationKey, userId, accountId, authServer);

            Console.WriteLine("Acess_Token: [" + access_token + "]");
            Console.WriteLine("\r\r");

            AccountsApi clickAccountApi = BuildHeader(accountBaseURI, access_token);

            UserAgreementRequest userAgreementRequest = BuildUpdateClickwrapHasAgreedRequest(fullName, email, company, title, datenow);

            ApiResponse<UserAgreementResponse> apiAgreement = CreateAgreement(clickAccountApi, accountId, clickwrapId, userAgreementRequest);

            string AgreedOn = apiAgreement.Data.AgreedOn.ToString();
            string agreementId = apiAgreement.Data.AgreementId;
            string agreementURL = apiAgreement.Data.AgreementUrl;
            string clientUserid = apiAgreement.Data.ClientUserId;
            string createdOn = apiAgreement.Data.CreatedOn.ToString();

            UserAgreementResponse AgreementInfo = GetAgreementInfo(clickAccountApi, accountId, clickwrapId, agreementId);

            List<UserAgreementResponse> ClientAgreementList = GetClientAgreementInfo(clickAccountApi, accountId, clickwrapId, agreementId, clientUserid);

            Console.WriteLine("API response data: ");
            Console.WriteLine(apiAgreement.Data.ToString());
            Console.WriteLine("\r\r");

            Console.WriteLine("Agreement response data: ");
            Console.WriteLine(AgreementInfo.ToString());
            Console.WriteLine("\r\r");

            Console.WriteLine("Client agreement data: ");
            foreach (UserAgreementResponse a in ClientAgreementList)
            {
                Console.WriteLine(a.ToString());
                Console.WriteLine("\r");
            }
            Console.WriteLine("\r\r");

            Console.WriteLine(" End of test run ");

        }

        public static string GetJwtToken(string clientId, string userId, string accountId, string authServer)
        {
            string oauthBasePath = authServer;
            int expiresInHours = 1;
            List<string> scopes = new List<string>() { "signature impersonation click.manage click.send" };
            DocuSignClient dsClient = new DocuSignClient(authServer);
            string rsaKeyBase64 = @"xx..xx==";
            var rsaKeyBytes = Convert.FromBase64String(rsaKeyBase64);
            OAuth.OAuthToken token = dsClient.RequestJWTUserToken(clientId, userId, oauthBasePath, rsaKeyBytes, expiresInHours, scopes);

            return token.access_token.ToString();
        }

        public static AccountsApi BuildHeader(string basePath, string accessToken)
        {
            var dsClient = new DocuSignClient(basePath);
            dsClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
            var clickAccountApi = new AccountsApi(dsClient);

            return clickAccountApi;
        }

        public static UserAgreementRequest BuildUpdateClickwrapHasAgreedRequest(string fullName, string email, string company, string title, string date)
        {
            var userAgreementRequest = new UserAgreementRequest { DocumentData = new Dictionary<string, string>() };
            userAgreementRequest.DocumentData.Add("fullName", fullName);
            userAgreementRequest.DocumentData.Add("email", email);
            userAgreementRequest.DocumentData.Add("company", company);
            userAgreementRequest.DocumentData.Add("title", title);
            userAgreementRequest.DocumentData.Add("date", date);

            userAgreementRequest.ClientUserId = email;

            return userAgreementRequest;
        }

        public static ApiResponse<UserAgreementResponse> CreateAgreement(AccountsApi clickAccountApi, string accountId, string clickwrapId, UserAgreementRequest userAgreementRequest)
        {
            ApiResponse<UserAgreementResponse> response = clickAccountApi.CreateHasAgreedWithHttpInfo(accountId, clickwrapId, userAgreementRequest);

            if (response.StatusCode == 201)
            {
                //return response.Data;
                return response;
            }
            else
            {
                response.Data.AgreementUrl = "Already Agreed";
                return response;
            }

        }

        public static UserAgreementResponse GetAgreementInfo(AccountsApi clickAccountApi, string accountId, string clickwrapId, string agreementId)
        {
            UserAgreementResponse response = clickAccountApi.GetAgreement(accountId, clickwrapId, agreementId);

            return response;
        }

        public static List<UserAgreementResponse> GetClientAgreementInfo(AccountsApi clickAccountApi, string accountId, string clickwrapId, 
                                                                        string agreementId, string clientId)
        {
            GetClickwrapAgreementsOptions gcao = new GetClickwrapAgreementsOptions();
            gcao.clientUserId = clientId;
            ClickwrapAgreementsResponse acctResponse = clickAccountApi.GetClickwrapAgreements(accountId, clickwrapId, gcao);
            List<UserAgreementResponse> usrAgreements = acctResponse.UserAgreements.ToList();

            return usrAgreements;
        }

    }

}



DigDug
  • 25
  • 8

1 Answers1

0

Two ways to do this:

  1. Create a new version of the same elastic template. The user will have to agree to the new version.

  2. Change the clientUserId to something different.

Option 1 is if the reason you are asking them to sign again is because something has changed, and you are going to have the same change for everyone.

Option 2 is if the reason you are asking them to sign again is because the user itself changed somehow. Say now a month passed and they're different in some way.

Both options technically will allow you to have the user sign again without creating a different elastic template.

Inbar Gazit
  • 12,566
  • 1
  • 16
  • 23
  • In the case I'm working on it is a legal statement of condition that could potentially come up monthly, depending on the client. Option 1 would not be ok with the business unit. Option 2 would not be ok with the clients. This really needs option 3, where template and client don't change. Anytime the template is sent to a client, there should be a flag to force signing, regardless if they are on record for previously signing that template. – DigDug Mar 18 '23 at 22:47
  • hmmm, maybe use a regular eSignature with an envelope and not elastic template? you said "sent to the client" and elastic templates are not designed to be sent, you should use an envelope with eSignature – Inbar Gazit Mar 19 '23 at 16:27
  • I'm checking deeper into option 1. Can that new version of the elastic template be done using "Create a new elastic template version" described here-- https://developers.docusign.com/docs/click-api/how-to/elastic-template-versioning/ Is there a way to refer to the PDF for the current version of this elastic template? Basically trip the version count on the elastic template to +1. – DigDug Mar 20 '23 at 16:32
  • yes, you can do that – Inbar Gazit Mar 20 '23 at 17:02
  • Update-- By calling CreateClickwrapVersion I was able to trip a major version increment and require-reacceptance. But, this also removed the dynamic field mapping I put in place through the elastic template web interface. I tried UpdateClickwrapVersion, which per DocuSign Clickwrap documentation, when Require-Reacceptance = true, is supposed to enable reacceptance, and roll up the version number to the next major number, 5.1 to 6.0. This did not work. I have a support ticket open with DS-Support through the subscribed work email. I'll post back when I get more information. – DigDug Apr 04 '23 at 18:14
  • I see that there is a lot of dynamic mapping and formatting options possible via code, but that is impractical with our use. Numerous elastic-templates may get setup if this works. Having to do that level of format coding for each one seems silly. When a web-interface lets you do the same thing when you setup the original elastic template and clickwrap. – DigDug Apr 04 '23 at 18:17
  • Update - DS Support has opened a bug ticket. CreateClickwrapVersion is not supposed to remove the dynamic mapping you add through the GUI. They were able to replicate this issue. Unknown timeline for a fix. – DigDug Jul 06 '23 at 20:18
  • Thanks Doug, Im monitoring this ticket and will update you if I hear anything... – Inbar Gazit Jul 06 '23 at 20:24