Skip to content

Commit 136a0df

Browse files
committed
eg 17
1 parent 4a74c72 commit 136a0df

File tree

4 files changed

+255
-3
lines changed

4 files changed

+255
-3
lines changed

index.js

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const express = require('express')
3232
, eg014 = require('./lib/examples/eg014CollectPayment')
3333
, eg015 = require('./lib/examples/eg015EnvelopeTabData')
3434
, eg016 = require('./lib/examples/eg016SetTabValues')
35+
, eg017 = require('./lib/examples/eg017SetTemplateTabValues')
3536
, eg018 = require('./lib/examples/eg018EnvelopeCustomFieldData')
3637
;
3738

@@ -138,6 +139,8 @@ let app = express()
138139
.post('/eg015', eg015.createController)
139140
.get('/eg016', eg016.getController)
140141
.post('/eg016', eg016.createController)
142+
.get('/eg017', eg017.getController)
143+
.post('/eg017', eg017.createController)
141144
.get('/eg018', eg018.getController)
142145
.post('/eg018', eg018.createController)
143146
;
+249
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/**
2+
* @file
3+
* Example 017: Set template tab (field) values and an envelope custom field value
4+
* @author DocuSign
5+
*/
6+
7+
const path = require('path')
8+
, docusign = require('docusign-esign')
9+
, validator = require('validator')
10+
, dsConfig = require('../../ds_configuration.js').config
11+
;
12+
13+
const eg017SetTemplateTabValues = exports
14+
, eg = 'eg017' // This example reference.
15+
, mustAuthenticate = '/ds/mustAuthenticate'
16+
, minimumBufferMin = 3
17+
;
18+
19+
20+
/**
21+
* Send envelope with a template
22+
* @param {object} req Request obj
23+
* @param {object} res Response obj
24+
*/
25+
eg017SetTemplateTabValues.createController = async (req, res) => {
26+
// Step 1. Check the token
27+
// At this point we should have a good token. But we
28+
// double-check here to enable a better UX to the user.
29+
let tokenOK = req.dsAuthCodeGrant.checkToken(minimumBufferMin);
30+
if (! tokenOK) {
31+
req.flash('info', 'Sorry, you need to re-authenticate.');
32+
// We could store the parameters of the requested operation
33+
// so it could be restarted automatically.
34+
// But since it should be rare to have a token issue here,
35+
// we'll make the user re-enter the form data after
36+
// authentication.
37+
req.dsAuthCodeGrant.setEg(req, eg);
38+
res.redirect(mustAuthenticate);
39+
}
40+
41+
if (!req.session.templateId) {
42+
res.render('pages/examples/eg017SetTemplateTabValues', {
43+
csrfToken: req.csrfToken(),
44+
title: "Send envelope using a template",
45+
templateOk: req.session.templateId,
46+
sourceFile: path.basename(__filename),
47+
sourceUrl: dsConfig.githubExampleUrl + path.basename(__filename),
48+
documentation: dsConfig.documentation + eg,
49+
showDoc: dsConfig.documentation
50+
});
51+
}
52+
53+
// Step 2. Call the worker method
54+
let body = req.body
55+
// Additional data validation might also be appropriate
56+
, signerEmail = validator.escape(body.signerEmail)
57+
, signerName = validator.escape(body.signerName)
58+
, ccEmail = validator.escape(body.ccEmail)
59+
, ccName = validator.escape(body.ccName)
60+
, envelopeArgs = {
61+
templateId: req.session.templateId,
62+
signerEmail: signerEmail,
63+
signerName: signerName,
64+
signerClientId: 1000,
65+
ccEmail: ccEmail,
66+
ccName: ccName,
67+
dsReturnUrl: dsConfig.appUrl + '/ds-return'
68+
}
69+
, args = {
70+
accessToken: req.user.accessToken,
71+
basePath: req.session.basePath,
72+
accountId: req.session.accountId,
73+
envelopeArgs: envelopeArgs
74+
}
75+
, results = null
76+
;
77+
78+
try {
79+
results = await eg017SetTemplateTabValues.worker (args)
80+
}
81+
catch (error) {
82+
let errorBody = error && error.response && error.response.body
83+
// we can pull the DocuSign error code and message from the response body
84+
, errorCode = errorBody && errorBody.errorCode
85+
, errorMessage = errorBody && errorBody.message
86+
;
87+
// In production, may want to provide customized error messages and
88+
// remediation advice to the user.
89+
res.render('pages/error', {err: error, errorCode: errorCode, errorMessage: errorMessage});
90+
}
91+
if (results) {
92+
req.session.envelopeId = results.envelopeId; // Save for use by other examples
93+
// which need an envelopeId
94+
// Redirect the user to the Signing Ceremony
95+
// Don't use an iFrame!
96+
// State can be stored/recovered using the framework's session or a
97+
// query parameter on the returnUrl (see the makeRecipientViewRequest method)
98+
res.redirect(results.redirectUrl);
99+
}
100+
}
101+
102+
/**
103+
* This function does the work of creating the envelope
104+
* @param {object} args
105+
*/
106+
// ***DS.worker.start ***DS.snippet.1.start
107+
eg017SetTemplateTabValues.worker = async (args) => {
108+
// 1. Create envelope definition
109+
let envelopeArgs = args.envelopeArgs
110+
, envelopeDefinition = makeEnvelope(envelopeArgs);
111+
112+
// 2. Create the envelope
113+
let dsApiClient = new docusign.ApiClient();
114+
dsApiClient.setBasePath(args.basePath);
115+
dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
116+
let envelopesApi = new docusign.EnvelopesApi(dsApiClient)
117+
, results = await envelopesApi.createEnvelope(
118+
args.accountId, {envelopeDefinition: envelopeDefinition})
119+
, envelopeId = results.envelopeId
120+
;
121+
122+
// 3. create the recipient view, the Signing Ceremony
123+
let viewRequest = docusign.RecipientViewRequest.constructFromObject({
124+
returnUrl: envelopeArgs.dsReturnUrl,
125+
authenticationMethod: 'none',
126+
email: envelopeArgs.signerEmail,
127+
userName: envelopeArgs.signerName,
128+
clientUserId: envelopeArgs.signerClientId});
129+
130+
// 4. Call the CreateRecipientView API
131+
// Exceptions will be caught by the calling function
132+
results = await envelopesApi.createRecipientView(args.accountId, envelopeId,
133+
{recipientViewRequest: viewRequest});
134+
135+
return ({envelopeId: envelopeId, redirectUrl: results.url})
136+
}
137+
// ***DS.worker.end ***DS.snippet.1.end
138+
139+
// ***DS.snippet.2.start
140+
/**
141+
* Creates envelope from the template
142+
* @function
143+
* @param {Object} args
144+
* @returns {Envelope} An envelope definition
145+
* @private
146+
*/
147+
function makeEnvelope(args){
148+
// The envelope has two recipients.
149+
// recipient 1 - signer
150+
// recipient 2 - cc
151+
// This method sets values for many of the template's tabs.
152+
// It also adds a new tab, and adds a custom metadata field
153+
154+
// create the envelope definition with the template id
155+
let envelopeDefinition = docusign.EnvelopeDefinition.constructFromObject({
156+
templateId: args.templateId, status: 'sent'
157+
});
158+
159+
// Set the values for the fields in the template
160+
// List item
161+
let list1 = docusign.List.constructFromObject({
162+
value: "green", documentId: "1", pageNumber: "1", tabLabel: "list"});
163+
164+
// Checkboxes
165+
let check1 = docusign.Checkbox.constructFromObject({
166+
tabLabel: 'ckAuthorization', selected: "true"})
167+
, check3 = docusign.Checkbox.constructFromObject({
168+
tabLabel: 'ckAgreement', selected: "true"});
169+
// The NOde.js SDK has a bug so it cannot create a Number tab at this time.
170+
//number1 = docusign.Number.constructFromObject({
171+
// tabLabel: "numbersOnly", value: '54321'});
172+
let radioGroup = docusign.RadioGroup.constructFromObject({
173+
groupName: "radio1",
174+
// You only need to provide the radio entry for the entry you're selecting
175+
radios:
176+
[docusign.Radio.constructFromObject({value: "white", selected: "true"})]
177+
});
178+
let text = docusign.Text.constructFromObject({
179+
tabLabel: "text", value: "Jabberwocky!"});
180+
181+
// We can also add a new tab (field) to the ones already in the template:
182+
let textExtra = docusign.Text.constructFromObject({
183+
document_id: "1", page_number: "1",
184+
x_position: "280", y_position: "172",
185+
font: "helvetica", font_size: "size14", tab_label: "added text field",
186+
height: "23", width: "84", required: "false",
187+
bold: 'true', value: args.signerName,
188+
locked: 'false', tab_id: 'name'});
189+
190+
// Pull together the existing and new tabs in a Tabs object:
191+
let tabs = docusign.Tabs.constructFromObject({
192+
checkboxTabs: [check1, check3], // numberTabs: [number1],
193+
radioGroupTabs: [radioGroup], textTabs: [text, textExtra],
194+
listTabs: [list1]
195+
});
196+
// Create the template role elements to connect the signer and cc recipients
197+
// to the template
198+
let signer = docusign.TemplateRole.constructFromObject({
199+
email: args.signerEmail, name: args.signerName,
200+
roleName: 'signer',
201+
clientUserId: args.signerClientId, // change the signer to be embedded
202+
tabs: tabs // Set tab values
203+
});
204+
// Create a cc template role.
205+
let cc = docusign.TemplateRole.constructFromObject({
206+
email: args.ccEmail, name: args.ccName,
207+
roleName: 'cc'
208+
});
209+
// Add the TemplateRole objects to the envelope object
210+
envelopeDefinition.templateRoles = [signer, cc];
211+
// Create an envelope custom field to save the our application's
212+
// data about the envelope
213+
let customField = docusign.TextCustomField.constructFromObject({
214+
name: 'app metadata item',
215+
required: 'false',
216+
show: 'true', // Yes, include in the CoC
217+
value: '1234567'})
218+
, customFields = docusign.CustomFields.constructFromObject({
219+
textCustomFields: [customField]});
220+
envelopeDefinition.customFields = customFields;
221+
222+
return envelopeDefinition;
223+
}
224+
// ***DS.snippet.2.end
225+
226+
/**
227+
* Form page for this application
228+
*/
229+
eg017SetTemplateTabValues.getController = (req, res) => {
230+
// Check that the authentication token is ok with a long buffer time.
231+
// If needed, now is the best time to ask the user to authenticate
232+
// since they have not yet entered any information into the form.
233+
let tokenOK = req.dsAuthCodeGrant.checkToken();
234+
if (tokenOK) {
235+
res.render('pages/examples/eg017SetTemplateTabValues', {
236+
csrfToken: req.csrfToken(),
237+
title: "Set template tab values",
238+
templateOk: req.session.templateId,
239+
sourceFile: path.basename(__filename),
240+
sourceUrl: dsConfig.githubExampleUrl + path.basename(__filename),
241+
documentation: dsConfig.documentation + eg,
242+
showDoc: dsConfig.documentation
243+
});
244+
} else {
245+
// Save the current operation so it will be resumed after authentication
246+
req.dsAuthCodeGrant.setEg(req, eg);
247+
res.redirect(mustAuthenticate);
248+
}
249+
}

views/pages/examples/eg017SetTemplateTabValues.ejs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ radio button and checkbox tabs.</p>
2222
<label for="signerEmail">Signer Email</label>
2323
<input type="email" class="form-control" id="signerEmail" name="signerEmail"
2424
aria-describedby="emailHelp" placeholder="pat@example.com" required
25-
value="<%= signerEmail %>">
25+
value="<%= locals.dsConfig.signerEmail %>">
2626
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
2727
</div>
2828
<div class="form-group">
2929
<label for="signerName">Signer Name</label>
3030
<input type="text" class="form-control" id="signerName" placeholder="Pat Johnson" name="signerName"
31-
value="<%= signerName %>" required>
31+
value="<%= locals.dsConfig.signerName %>" required>
3232
</div>
3333
<div class="form-group">
3434
<label for="ccEmail">CC Email</label>

views/pages/index.ejs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
<a target ='_blank' href="https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/create">Envelopes::create</a>.
151151
</p>
152152

153-
<h4 id="example017">17. <a href="eg017'">Set template tab values</a></h4>
153+
<h4 id="example017">17. <a href="eg017">Set template tab values</a></h4>
154154
<p>This example sets the tab (field) values for a template being used by an envelope.</p>
155155
<p>API method used:
156156
<a target ='_blank' href="https://developers.docusign.com/esign-rest-api/reference/Envelopes/Envelopes/create">Envelopes::create</a>.

0 commit comments

Comments
 (0)