Skip to content

Commit 3d65084

Browse files
Merge remote-tracking branch 'origin/master' into feature/refactoring-code-examples
2 parents 722982c + 203a5d9 commit 3d65084

13 files changed

Lines changed: 236 additions & 630 deletions

File tree

README.md

Lines changed: 75 additions & 173 deletions
Large diffs are not rendered by default.

lib/DSJwtAuth.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,17 +203,17 @@ DsJwtAuth.prototype.login = function (req, res, next) {
203203
.catch(e => {
204204
console.log(e);
205205
let body = e.response && e.response.body;
206+
// Determine the source of the error
206207
if (body) {
207-
// DocuSign API problem
208+
// The user needs to grant consent
208209
if (body.error && body.error === 'consent_required') {
209-
// Consent problem
210210
let consent_scopes = this.scopes + " impersonation",
211211
consent_url = `${dsConfig.dsOauthServer}/oauth/auth?response_type=code&` +
212212
`scope=${consent_scopes}&client_id=${dsConfig.dsClientId}&` +
213213
`redirect_uri=${dsConfig.appUrl}/ds/callback`;
214214
res.redirect(consent_url);
215215
} else {
216-
// Some other DocuSign API problem
216+
// Consent has been granted. Show status code for DocuSign API error
217217
this._debug_log(`\nAPI problem: Status code ${e.response.status}, message body:
218218
${JSON.stringify(body, null, 4)}\n\n`);
219219
}

lib/eSignature/examples/sendBinaryDocs.js

Lines changed: 87 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -5,115 +5,83 @@
55
*/
66

77
const fs = require("fs-extra");
8-
const rp = require("request-promise-native");
8+
const nf = require("node-fetch");
99

1010
/**
1111
* This function does the work of creating the envelope by using
1212
* the API directly with multipart mime
1313
* @param {object} args object
1414
*/
15+
// ***DS.snippet.0.start
1516
const sendBinaryDocs = async (args) => {
1617
// Data for this method
1718
// args.basePath
1819
// args.accessToken
1920
// args.accountId
2021
// doc2File: file name for doc 2
2122
// doc3File: file name for doc 3
22-
2323
// Step 1. Make the envelope JSON request body
24-
let envelopeJSON = makeEnvelopeJSON(args.envelopeArgs),
25-
results = null;
24+
let envelopeJSON = makeEnvelopeJSON(args.envelopeArgs)
25+
, results = null
26+
;
2627
// Step 2. Gather documents and their headers
2728
// Read files from a local directory
2829
// The reads could raise an exception if the file is not available!
2930
let documents = [
30-
{
31-
mime: "text/html",
32-
filename: envelopeJSON.documents[0].name,
33-
documentId: envelopeJSON.documents[0].documentId,
34-
bytes: document1(args.envelopeArgs),
35-
},
36-
{
37-
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
38-
filename: envelopeJSON.documents[1].name,
39-
documentId: envelopeJSON.documents[1].documentId,
40-
bytes: fs.readFileSync(args.doc2File),
41-
},
42-
{
43-
mime: "application/pdf",
44-
filename: envelopeJSON.documents[2].name,
45-
documentId: envelopeJSON.documents[2].documentId,
46-
bytes: fs.readFileSync(args.doc3File),
47-
},
31+
{mime: "text/html", filename: envelopeJSON.documents[0].name,
32+
documentId: envelopeJSON.documents[0].documentId,
33+
bytes: document1(args.envelopeArgs)},
34+
{mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
35+
filename: envelopeJSON.documents[1].name,
36+
documentId: envelopeJSON.documents[1].documentId,
37+
bytes: fs.readFileSync(args.doc2File)},
38+
{mime: "application/pdf", filename: envelopeJSON.documents[2].name,
39+
documentId: envelopeJSON.documents[2].documentId,
40+
bytes: fs.readFileSync(args.doc3File)}
4841
];
49-
5042
// Step 3. Create the multipart body
51-
let CRLF = "\r\n",
52-
boundary = "multipartboundary_multipartboundary",
53-
hyphens = "--",
54-
reqBody;
55-
56-
reqBody = Buffer.from(
57-
[
58-
hyphens,
59-
boundary,
60-
CRLF,
61-
"Content-Type: application/json",
43+
let CRLF = "\r\n"
44+
, boundary = "multipartboundary_multipartboundary"
45+
, hyphens = "--"
46+
, reqBody
47+
;
48+
reqBody = Buffer.from([
49+
hyphens, boundary,
50+
CRLF, "Content-Type: application/json",
51+
CRLF, "Content-Disposition: form-data",
6252
CRLF,
63-
"Content-Disposition: form-data",
64-
CRLF,
65-
CRLF,
66-
JSON.stringify(envelopeJSON, null, " "),
67-
].join("")
53+
CRLF, JSON.stringify(envelopeJSON, null, " ")].join('')
6854
);
69-
7055
// Loop to add the documents.
7156
// See section Multipart Form Requests on page https://developers.docusign.com/esign-rest-api/guides/requests-and-responses
72-
documents.forEach((d) => {
73-
reqBody = Buffer.concat([
74-
reqBody,
75-
Buffer.from(
76-
[
77-
CRLF,
78-
hyphens,
79-
boundary,
57+
documents.forEach(d => {
58+
reqBody = Buffer.concat([reqBody, Buffer.from([
59+
CRLF, hyphens, boundary,
60+
CRLF, `Content-Type: ${d.mime}`,
61+
CRLF, `Content-Disposition: file; filename="${d.filename}";documentid=${d.documentId}`,
8062
CRLF,
81-
`Content-Type: ${d.mime}`,
82-
CRLF,
83-
`Content-Disposition: file; filename="${d.filename}";documentid=${d.documentId}`,
84-
CRLF,
85-
CRLF,
86-
].join("")
87-
),
88-
Buffer.from(d.bytes),
89-
]);
90-
});
63+
CRLF].join('')), Buffer.from(d.bytes)]
64+
)
65+
})
9166
// Add closing boundary
92-
reqBody = Buffer.concat([
93-
reqBody,
94-
Buffer.from([CRLF, hyphens, boundary, hyphens, CRLF].join("")),
95-
]);
96-
67+
reqBody = Buffer.concat([reqBody,
68+
Buffer.from([CRLF, hyphens, boundary, hyphens, CRLF].join(''))]);
9769
let options = {
98-
method: "POST",
99-
uri: `${args.basePath}/v2/accounts/${args.accountId}/envelopes`,
100-
auth: { bearer: args.accessToken },
101-
headers: {
102-
Accept: "application/json",
103-
"Content-Type": `multipart/form-data; boundary=${boundary}`,
104-
},
105-
body: reqBody,
106-
};
107-
70+
uri: `${args.basePath}/v2.1/accounts/${args.accountId}/envelopes`,
71+
method: 'POST',
72+
headers: {
73+
'Accept': 'application/json',
74+
'Content-Type': `multipart/form-data; boundary=${boundary}`,
75+
'Authorization': `Bearer ${args.accessToken}`
76+
},
77+
body: reqBody
78+
};
10879
// Step 2. call Envelopes::create API method
10980
// Exceptions will be caught by the calling function
110-
results = await rp(options);
111-
112-
// Since we're using the request library at a low level, the results
113-
// are not automatically JSON parsed.
114-
results = JSON.parse(results);
81+
const response = await nf(options.uri, options);
82+
results = await response.json()
11583
return results;
116-
};
84+
}
11785

11886
/**
11987
* Create envelope JSON
@@ -127,13 +95,12 @@ const sendBinaryDocs = async (args) => {
12795
* @returns {Envelope} An envelope definition
12896
* @private
12997
*/
130-
function makeEnvelopeJSON(args) {
98+
function makeEnvelopeJSON(args){
13199
// Data for this method
132100
// args.signerEmail
133101
// args.signerName
134102
// args.ccEmail
135103
// args.ccName
136-
137104
// document 1 (html) has tag **signature_1**
138105
// document 2 (docx) has tag /sn1/
139106
// document 3 (pdf) has tag /sn1/
@@ -143,48 +110,42 @@ function makeEnvelopeJSON(args) {
143110
// recipient 2 - cc
144111
// The envelope will be sent first to the signer.
145112
// After it is signed, a copy is sent to the cc person.
146-
147113
// create the envelope definition
148114
let envJSON = {};
149-
envJSON.emailSubject = "Please sign this document set";
150-
115+
envJSON.emailSubject = 'Please sign this document set';
151116
// add the documents
152-
let doc1 = {},
153-
doc2 = {},
154-
doc3 = {};
155-
doc1.name = "Order acknowledgement"; // can be different from actual file name
156-
doc1.fileExtension = "html"; // Source data format. Signed docs are always pdf.
157-
doc1.documentId = "1"; // a label used to reference the doc
158-
doc2.name = "Battle Plan"; // can be different from actual file name
159-
doc2.fileExtension = "docx";
160-
doc2.documentId = "2";
161-
doc3.name = "Lorem Ipsum"; // can be different from actual file name
162-
doc3.fileExtension = "pdf";
163-
doc3.documentId = "3";
164-
117+
let doc1 = {}
118+
, doc2 = {}
119+
, doc3 = {}
120+
;
121+
doc1.name = 'Order acknowledgement'; // can be different from actual file name
122+
doc1.fileExtension = 'html'; // Source data format. Signed docs are always pdf.
123+
doc1.documentId = '1'; // a label used to reference the doc
124+
doc2.name = 'Battle Plan'; // can be different from actual file name
125+
doc2.fileExtension = 'docx';
126+
doc2.documentId = '2';
127+
doc3.name = 'Lorem Ipsum'; // can be different from actual file name
128+
doc3.fileExtension = 'pdf';
129+
doc3.documentId = '3';
165130
// The order in the docs array determines the order in the envelope
166131
envJSON.documents = [doc1, doc2, doc3];
167-
168132
// create a signer recipient to sign the document, identified by name and email
169133
// We're setting the parameters via the object creation
170134
let signer1 = {
171-
email: args.signerEmail,
172-
name: args.signerName,
173-
recipientId: "1",
174-
routingOrder: "1",
175-
};
135+
email: args.signerEmail,
136+
name: args.signerName,
137+
recipientId: '1',
138+
routingOrder: '1'};
176139
// routingOrder (lower means earlier) determines the order of deliveries
177140
// to the recipients. Parallel routing order is supported by using the
178141
// same integer as the order for two or more recipients.
179-
180142
// create a cc recipient to receive a copy of the documents, identified by name and email
181143
// We're setting the parameters via setters
182144
let cc1 = {};
183145
cc1.email = args.ccEmail;
184146
cc1.name = args.ccName;
185-
cc1.routingOrder = "2";
186-
cc1.recipientId = "2";
187-
147+
cc1.routingOrder = '2';
148+
cc1.recipientId = '2';
188149
// Create signHere fields (also known as tabs) on the documents,
189150
// We're using anchor (autoPlace) positioning
190151
//
@@ -193,29 +154,23 @@ function makeEnvelopeJSON(args) {
193154
// signHere2 tab will be used in both document 2 and 3 since they
194155
// use the same anchor string for their "signer 1" tabs.
195156
let signHere1 = {
196-
anchorString: "**signature_1**",
197-
anchorYOffset: "10",
198-
anchorUnits: "pixels",
199-
anchorXOffset: "20",
200-
},
201-
signHere2 = {
202-
anchorString: "/sn1/",
203-
anchorYOffset: "10",
204-
anchorUnits: "pixels",
205-
anchorXOffset: "20",
206-
};
157+
anchorString: '**signature_1**',
158+
anchorYOffset: '10', anchorUnits: 'pixels',
159+
anchorXOffset: '20'}
160+
, signHere2 = {
161+
anchorString: '/sn1/',
162+
anchorYOffset: '10', anchorUnits: 'pixels',
163+
anchorXOffset: '20'}
164+
;
207165
// Tabs are set per recipient / signer
208-
let signer1Tabs = { signHereTabs: [signHere1, signHere2] };
166+
let signer1Tabs = {signHereTabs: [signHere1, signHere2]};
209167
signer1.tabs = signer1Tabs;
210-
211168
// Add the recipients to the envelope object
212-
let recipients = { signers: [signer1], carbonCopies: [cc1] };
169+
let recipients = {signers: [signer1], carbonCopies: [cc1]};
213170
envJSON.recipients = recipients;
214-
215171
// Request that the envelope be sent by setting |status| to "sent".
216172
// To request that the envelope be created as a draft, set to "created"
217-
envJSON.status = "sent";
218-
173+
envJSON.status = 'sent';
219174
return envJSON;
220175
}
221176

@@ -227,13 +182,13 @@ function makeEnvelopeJSON(args) {
227182
* @returns {string} A document in HTML format
228183
*/
229184
function document1(args) {
230-
// Data for this method
231-
// args.signerEmail
232-
// args.signerName
233-
// args.ccEmail
234-
// args.ccName
185+
// Data for this method
186+
// args.signerEmail
187+
// args.signerName
188+
// args.ccEmail
189+
// args.ccName
235190

236-
return `
191+
return `
237192
<!DOCTYPE html>
238193
<html>
239194
<head>
@@ -255,7 +210,7 @@ function document1(args) {
255210
<h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3>
256211
</body>
257212
</html>
258-
`;
259-
}
213+
`
214+
}
260215

261216
module.exports = { sendBinaryDocs };

0 commit comments

Comments
 (0)