Skip to content

Commit 89afda0

Browse files
committed
focused view
1 parent 04380b6 commit 89afda0

File tree

4 files changed

+424
-0
lines changed

4 files changed

+424
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// <copyright file="Eg044FocusedViewController.cs" company="DocuSign">
2+
// Copyright (c) DocuSign. All rights reserved.
3+
// </copyright>
4+
5+
namespace DocuSign.CodeExamples.Views
6+
{
7+
using System;
8+
using DocuSign.CodeExamples.Common;
9+
using DocuSign.CodeExamples.Controllers;
10+
using DocuSign.CodeExamples.Models;
11+
using System.Runtime.InteropServices;
12+
using Microsoft.AspNetCore.Mvc;
13+
using DocuSign.Rooms.Model;
14+
using System.Configuration;
15+
using Microsoft.Extensions.Configuration;
16+
17+
[Area("eSignature")]
18+
[Route("eg044")]
19+
public class FocusedView : EgController
20+
{
21+
private readonly string dsPingUrl;
22+
private readonly string signerClientId = "1000";
23+
private readonly string dsReturnUrl;
24+
private readonly string dsIntegrationKey;
25+
private readonly IConfiguration _configuration;
26+
27+
public FocusedView(DSConfiguration config, IConfiguration configuration, LauncherTexts launcherTexts, IRequestItemsService requestItemsService)
28+
: base(config, launcherTexts, requestItemsService)
29+
{
30+
this.dsPingUrl = config.AppUrl + "/";
31+
this.dsReturnUrl = config.AppUrl + "/dsReturn";
32+
_configuration = configuration;
33+
this.ViewBag.IntegrationKey = this.Configuration["DocuSign:ClientId"];
34+
35+
this.CodeExampleText = this.GetExampleText("eg044", ExamplesAPIType.ESignature);
36+
this.ViewBag.title = this.CodeExampleText.ExampleName;
37+
}
38+
39+
public override string EgName => "eg044";
40+
41+
[HttpPost]
42+
[SetViewBag]
43+
public IActionResult Create(string signerEmail, string signerName)
44+
{
45+
// Data for this method
46+
// signerEmail
47+
// signerName
48+
// dsPingUrl -- class global
49+
// signerClientId -- class global
50+
// dsReturnUrl -- class global
51+
string accessToken = this.RequestItemsService.User.AccessToken;
52+
string basePath = this.RequestItemsService.Session.BasePath + "/restapi";
53+
string accountId = this.RequestItemsService.Session.AccountId;
54+
string docPDF;
55+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
56+
{
57+
docPDF = Convert.ToBoolean(this.Config.QuickACG) ? @"../launcher-csharp/" + this.Config.DocPdf : this.Config.DocPdf;
58+
}
59+
else
60+
{
61+
docPDF = Convert.ToBoolean(this.Config.QuickACG) ? @"..\\launcher-csharp\\" + this.Config.DocPdf : this.Config.DocPdf;
62+
}
63+
64+
// Check the token with minimal buffer time.
65+
bool tokenOk = this.CheckToken(3);
66+
if (!tokenOk)
67+
{
68+
// We could store the parameters of the requested operation
69+
// so it could be restarted automatically.
70+
// But since it should be rare to have a token issue here,
71+
// we'll make the user re-enter the form data after
72+
// authentication.
73+
this.RequestItemsService.EgName = this.EgName;
74+
return this.Redirect("/ds/mustAuthenticate");
75+
}
76+
77+
// Call the method from Examples API to send envelope and generate url for focused view signing
78+
var result = global::ESignature.Examples.FocusedView.SendEnvelopeWithFocusedView(
79+
signerEmail,
80+
signerName,
81+
this.signerClientId,
82+
accessToken,
83+
basePath,
84+
accountId,
85+
docPDF,
86+
this.dsReturnUrl,
87+
this.dsPingUrl);
88+
89+
// Save for future use within the example launcher
90+
this.RequestItemsService.EnvelopeId = result.Item1;
91+
this.ViewBag.Url = result.Item2;
92+
this.ViewBag.IK = this.dsIntegrationKey;
93+
94+
// Redirect the user to the Signing Ceremony
95+
return this.View("embed");
96+
}
97+
}
98+
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// <copyright file="FocusedView.cs" company="DocuSign">
2+
// Copyright (c) DocuSign. All rights reserved.
3+
// </copyright>
4+
5+
namespace ESignature.Examples
6+
{
7+
using System;
8+
using System.Collections.Generic;
9+
using DocuSign.eSign.Api;
10+
using DocuSign.eSign.Client;
11+
using DocuSign.eSign.Model;
12+
using Org.BouncyCastle.Asn1;
13+
using static System.Net.WebRequestMethods;
14+
15+
/// <summary>
16+
/// Used to generate an envelope and allow user to sign it directly from the app without having to open an email.
17+
/// </summary>
18+
public static class FocusedView
19+
{
20+
/// <summary>
21+
/// Creates a new envelope, adds a single document and a signle recipient (signer) and generates a url that is used for embedded signing.
22+
/// </summary>
23+
/// <param name="signerEmail">Email address for the signer</param>
24+
/// <param name="signerName">Full name of the signer</param>
25+
/// <param name="signerClientId">A unique ID for the embedded signing session for this signer</param>
26+
/// <param name="accessToken">Access Token for API call (OAuth)</param>
27+
/// <param name="basePath">BasePath for API calls (URI)</param>
28+
/// <param name="frameAncestors">Array that stores the site URL and demo or prod environement URL</param>
29+
/// <param name="messageOrigins">String that stores the URL for the demo and prod enviornment</param>
30+
/// <param name="accountId">The DocuSign Account ID (GUID or short version) for which the APIs call would be made</param>
31+
/// <param name="docPdf">String of bytes representing the document (pdf)</param>
32+
/// <param name="returnUrl">URL user will be redirected to after they sign</param>
33+
/// <param name="pingUrl">URL that DocuSign will be able to ping to incdicate signing session is active</param>
34+
/// <returns>The envelopeId (GUID) of the resulting Envelope and the URL for the embedded signing</returns>
35+
public static (string, string) SendEnvelopeWithFocusedView(
36+
string signerEmail,
37+
string signerName,
38+
string signerClientId,
39+
string accessToken,
40+
string basePath,
41+
string accountId,
42+
string docPdf,
43+
string returnUrl,
44+
string pingUrl = null)
45+
{
46+
//ds-snippet-start:eSign44Step3
47+
EnvelopeDefinition envelope = MakeEnvelope(signerEmail, signerName, signerClientId, docPdf);
48+
49+
var docuSignClient = new DocuSignClient(basePath);
50+
docuSignClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
51+
52+
EnvelopesApi envelopesApi = new EnvelopesApi(docuSignClient);
53+
EnvelopeSummary results = envelopesApi.CreateEnvelope(accountId, envelope);
54+
string envelopeId = results.EnvelopeId;
55+
//ds-snippet-end:eSign44Step3
56+
57+
//ds-snippet-start:eSign44Step5
58+
RecipientViewRequest viewRequest = MakeRecipientViewRequest(signerEmail, signerName, returnUrl, signerClientId, pingUrl);
59+
60+
// call the CreateRecipientView API
61+
ViewUrl results1 = envelopesApi.CreateRecipientView(accountId, envelopeId, viewRequest);
62+
63+
// Don't use an iFrame!
64+
// State can be stored/recovered using the framework's session or a
65+
// query parameter on the returnUrl (see the makeRecipientViewRequest method)
66+
string redirectUrl = results1.Url;
67+
68+
// returning both the envelopeId as well as the url to be used for embedded signing
69+
return (envelopeId, redirectUrl);
70+
//ds-snippet-end:eSign44Step5
71+
}
72+
73+
//ds-snippet-start:eSign44Step4
74+
public static RecipientViewRequest MakeRecipientViewRequest(string signerEmail, string signerName, string returnUrl, string signerClientId, string pingUrl = null)
75+
{
76+
// Data for this method
77+
// signerEmail
78+
// signerName
79+
// dsPingUrl -- class global
80+
// signerClientId -- class global
81+
// dsReturnUrl -- class global
82+
RecipientViewRequest viewRequest = new RecipientViewRequest();
83+
84+
// Set the url where you want the recipient to go once they are done signing
85+
// should typically be a callback route somewhere in your app.
86+
// The query parameter is included as an example of how
87+
// to save/recover state information during the redirect to
88+
// the DocuSign signing ceremony. It's usually better to use
89+
// the session mechanism of your web framework. Query parameters
90+
// can be changed/spoofed very easily.
91+
viewRequest.ReturnUrl = returnUrl + "?state=123";
92+
93+
// How has your app authenticated the user? In addition to your app's
94+
// authentication, you can include authenticate steps from DocuSign.
95+
// Eg, SMS authentication
96+
viewRequest.AuthenticationMethod = "none";
97+
98+
// Recipient information must match embedded recipient info
99+
// we used to create the envelope.
100+
viewRequest.Email = signerEmail;
101+
viewRequest.UserName = signerName;
102+
viewRequest.ClientUserId = signerClientId;
103+
104+
// DocuSign recommends that you redirect to DocuSign for the
105+
// Signing Ceremony. There are multiple ways to save state.
106+
// To maintain your application's session, use the pingUrl
107+
// parameter. It causes the DocuSign Signing Ceremony web page
108+
// (not the DocuSign server) to send pings via AJAX to your
109+
// app,
110+
// NOTE: The pings will only be sent if the pingUrl is an https address
111+
if (pingUrl != null)
112+
{
113+
viewRequest.PingFrequency = "600"; // seconds
114+
viewRequest.PingUrl = pingUrl; // optional setting
115+
}
116+
117+
viewRequest.FrameAncestors = new List<string> { "https://localhost:44333", "https://apps-d.docusign.com" };
118+
viewRequest.MessageOrigins = new List<string> { "https://apps-d.docusign.com" };
119+
120+
return viewRequest;
121+
}
122+
//ds-snippet-end:eSign44Step4
123+
124+
//ds-snippet-start:eSign44Step2
125+
public static EnvelopeDefinition MakeEnvelope(string signerEmail, string signerName, string signerClientId, string docPdf)
126+
{
127+
// Data for this method
128+
// signerEmail
129+
// signerName
130+
// signerClientId -- class global
131+
// Config.docPdf
132+
byte[] buffer = System.IO.File.ReadAllBytes(docPdf);
133+
134+
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
135+
envelopeDefinition.EmailSubject = "Please sign this document";
136+
Document doc1 = new Document();
137+
138+
string doc1b64 = Convert.ToBase64String(buffer);
139+
140+
doc1.DocumentBase64 = doc1b64;
141+
doc1.Name = "Lorem Ipsum"; // can be different from actual file name
142+
doc1.FileExtension = "pdf";
143+
doc1.DocumentId = "3";
144+
145+
// The order in the docs array determines the order in the envelope
146+
envelopeDefinition.Documents = new List<Document> { doc1 };
147+
148+
// Create a signer recipient to sign the document, identified by name and email
149+
// We set the clientUserId to enable embedded signing for the recipient
150+
// We're setting the parameters via the object creation
151+
Signer signer1 = new Signer
152+
{
153+
Email = signerEmail,
154+
Name = signerName,
155+
ClientUserId = signerClientId,
156+
RecipientId = "1",
157+
};
158+
159+
// Create signHere fields (also known as tabs) on the documents,
160+
// We're using anchor (autoPlace) positioning
161+
//
162+
// The DocuSign platform searches throughout your envelope's
163+
// documents for matching anchor strings.
164+
SignHere signHere1 = new SignHere
165+
{
166+
AnchorString = "/sn1/",
167+
AnchorUnits = "pixels",
168+
AnchorXOffset = "10",
169+
AnchorYOffset = "20",
170+
};
171+
172+
// Tabs are set per recipient / signer
173+
Tabs signer1Tabs = new Tabs
174+
{
175+
SignHereTabs = new List<SignHere> { signHere1 },
176+
};
177+
signer1.Tabs = signer1Tabs;
178+
179+
// Add the recipient to the envelope object
180+
Recipients recipients = new Recipients
181+
{
182+
Signers = new List<Signer> { signer1 },
183+
};
184+
envelopeDefinition.Recipients = recipients;
185+
186+
// Request that the envelope be sent by setting |status| to "sent".
187+
// To request that the envelope be created as a draft, set to "created"
188+
envelopeDefinition.Status = "sent";
189+
190+
return envelopeDefinition;
191+
}
192+
//ds-snippet-end:eSign44Step2
193+
}
194+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<div id="agreement"></div>
2+
3+
<code>
4+
@ViewBag.Url
5+
@ViewBag.IK
6+
</code>
7+
8+
@Html.Raw("<script src='https://docucdn-a.akamaihd.net/demo/1ds/libs/@embedded-js/core/latest/dist/bundle.js'></script>")
9+
10+
<script>
11+
window.DocuSign.loadDocuSign('52957a8d-ec41-47b1-9c8b-c9527c3d9e2b')
12+
.then((docusign) => {
13+
const signing = docusign.signing({
14+
url: '@ViewBag.Url',
15+
displayFormat: 'focused',
16+
style: {
17+
/** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
18+
branding: {
19+
primaryButton: {
20+
/** Background color of primary button */
21+
backgroundColor: '#333',
22+
/** Text color of primary button */
23+
color: '#fff',
24+
}
25+
},
26+
27+
/** High-level components we allow specific overrides for */
28+
signingNavigationButton: {
29+
finishText: 'Complete',
30+
position: 'bottom-center'
31+
}
32+
}
33+
});
34+
35+
signing.on('ready', (event) => {
36+
console.log('UI is rendered');
37+
});
38+
39+
signing.on('sessionEnd', (event) => {
40+
/** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
41+
console.log('sessionend', event);
42+
});
43+
44+
signing.mount('#agreement');
45+
})
46+
.catch((ex) => {
47+
// Any configuration or API limits will be caught here
48+
});</script>
49+
50+
<!DOCTYPE html>
51+
<html>
52+
<head>
53+
<meta charset="utf-8" />
54+
<title>Signing</title>
55+
<style>
56+
html,
57+
body {
58+
padding: 0;
59+
margin: 0;
60+
font: 13px Helvetica, Arial, sans-serif;
61+
}
62+
63+
.docusign-agreement {
64+
height: 800px;
65+
}
66+
</style>
67+
</head>
68+
<body>
69+
<header><h1> Demo</h1></header>
70+
71+
<div class="docusign-agreement" id="docusign"></div>
72+
<script src="script.js"></script>
73+
</body>
74+
</html>
75+
76+
77+
<p><a href="/">@Html.Raw(ViewBag.SupportingTexts.ContinueButton)</a></p>

0 commit comments

Comments
 (0)