|
| 1 | +/** |
| 2 | + * @file |
| 3 | + * Example 046: Request a signature bt multiple delivery channels |
| 4 | + * @author DocuSign |
| 5 | + */ |
| 6 | + |
| 7 | +const fs = require('fs-extra'); |
| 8 | +const docusign = require('docusign-esign'); |
| 9 | + |
| 10 | +/** |
| 11 | + * This function does the work of creating the envelope and sending it by multiple channels |
| 12 | + */ |
| 13 | +const sendByMultipleChannels = async (args) => { |
| 14 | + // Data for this method |
| 15 | + // args.basePath |
| 16 | + // args.accessToken |
| 17 | + // args.accountId |
| 18 | + |
| 19 | + const dsApiClient = new docusign.ApiClient(); |
| 20 | + dsApiClient.setBasePath(args.basePath); |
| 21 | + dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken); |
| 22 | + const envelopesApi = new docusign.EnvelopesApi(dsApiClient); |
| 23 | + let results = null; |
| 24 | + |
| 25 | + // Make the envelope request body |
| 26 | + const envelope = makeEnvelope(args.envelopeArgs); |
| 27 | + |
| 28 | + // call Envelopes::create API method |
| 29 | + // Exceptions will be caught by the calling function |
| 30 | + //ds-snippet-start:eSign46Step3 |
| 31 | + results = await envelopesApi.createEnvelope(args.accountId, { |
| 32 | + envelopeDefinition: envelope, |
| 33 | + }); |
| 34 | + //ds-snippet-end:eSign46Step3 |
| 35 | + const envelopeId = results.envelopeId; |
| 36 | + |
| 37 | + console.log(`Envelope was created. EnvelopeId ${envelopeId}`); |
| 38 | + return { envelopeId: envelopeId }; |
| 39 | +}; |
| 40 | + |
| 41 | +/** |
| 42 | + * Creates envelope |
| 43 | + * @function |
| 44 | + * @param {Object} args parameters for the envelope |
| 45 | + * @returns {Envelope} An envelope definition |
| 46 | + * @private |
| 47 | + */ |
| 48 | +//ds-snippet-start:eSign46Step2 |
| 49 | +function makeEnvelope(args) { |
| 50 | + // Data for this method |
| 51 | + // args.signerName |
| 52 | + // args.phoneNumber |
| 53 | + // args.countryCode |
| 54 | + // args.ccName |
| 55 | + // args.ccPhoneNumber |
| 56 | + // args.ccCountryCode |
| 57 | + // args.status |
| 58 | + // doc2File |
| 59 | + // doc3File |
| 60 | + |
| 61 | + // document 1 (html) has tag **signature_1** |
| 62 | + // document 2 (docx) has tag /sn1/ |
| 63 | + // document 3 (pdf) has tag /sn1/ |
| 64 | + // |
| 65 | + // The envelope has two recipients. |
| 66 | + // recipient 1 - signer |
| 67 | + // recipient 2 - cc |
| 68 | + // The envelope will be sent first to the signer. |
| 69 | + // After it is signed, a copy is sent to the cc person. |
| 70 | + |
| 71 | + let doc2DocxBytes, doc3PdfBytes; |
| 72 | + // read files from a local directory |
| 73 | + // The reads could raise an exception if the file is not available! |
| 74 | + doc2DocxBytes = fs.readFileSync(args.doc2File); |
| 75 | + doc3PdfBytes = fs.readFileSync(args.doc3File); |
| 76 | + |
| 77 | + // create the envelope definition |
| 78 | + const env = new docusign.EnvelopeDefinition(); |
| 79 | + env.emailSubject = 'Please sign this document set'; |
| 80 | + |
| 81 | + // add the documents |
| 82 | + const doc1 = new docusign.Document(); |
| 83 | + const doc1b64 = Buffer.from(document1(args)).toString('base64'); |
| 84 | + const doc2b64 = Buffer.from(doc2DocxBytes).toString('base64'); |
| 85 | + const doc3b64 = Buffer.from(doc3PdfBytes).toString('base64'); |
| 86 | + doc1.documentBase64 = doc1b64; |
| 87 | + doc1.name = 'Order acknowledgement'; // can be different from actual file name |
| 88 | + doc1.fileExtension = 'html'; // Source data format. Signed docs are always pdf. |
| 89 | + doc1.documentId = '1'; // a label used to reference the doc |
| 90 | + |
| 91 | + // Alternate pattern: using constructors for docs 2 and 3... |
| 92 | + const doc2 = new docusign.Document.constructFromObject({ |
| 93 | + documentBase64: doc2b64, |
| 94 | + name: 'Battle Plan', // can be different from actual file name |
| 95 | + fileExtension: 'docx', |
| 96 | + documentId: '2', |
| 97 | + }); |
| 98 | + |
| 99 | + const doc3 = new docusign.Document.constructFromObject({ |
| 100 | + documentBase64: doc3b64, |
| 101 | + name: 'Lorem Ipsum', // can be different from actual file name |
| 102 | + fileExtension: 'pdf', |
| 103 | + documentId: '3', |
| 104 | + }); |
| 105 | + |
| 106 | + // The order in the docs array determines the order in the envelope |
| 107 | + env.documents = [doc1, doc2, doc3]; |
| 108 | + |
| 109 | + // Create a RecipientPhoneNumber object for the signer's phone number |
| 110 | + const signerPhoneNumber = docusign.RecipientPhoneNumber.constructFromObject({ |
| 111 | + countryCode: args.countryCode, |
| 112 | + number: args.phoneNumber, |
| 113 | + }); |
| 114 | + |
| 115 | + const signerAdditionalNotification = docusign.RecipientAdditionalNotification.constructFromObject({ |
| 116 | + secondaryDeliveryMethod: args.deliveryMethod, |
| 117 | + phoneNumber: signerPhoneNumber |
| 118 | + }); |
| 119 | + |
| 120 | + // Create a signer recipient to sign the document, identified by name and phone number |
| 121 | + // We're setting the parameters via the object constructor |
| 122 | + const signer = docusign.Signer.constructFromObject({ |
| 123 | + name: args.signerName, |
| 124 | + email: args.signerEmail, |
| 125 | + deliveryMethod: 'Email', |
| 126 | + additionalNotifications: [signerAdditionalNotification], |
| 127 | + recipientId: '1', |
| 128 | + routingOrder: '1', |
| 129 | + }); |
| 130 | + |
| 131 | + // routingOrder (lower means earlier) determines the order of deliveries |
| 132 | + // to the recipients. Parallel routing order is supported by using the |
| 133 | + // same integer as the order for two or more recipients. |
| 134 | + |
| 135 | + // Create a RecipientPhoneNumber object for the signer's phone number |
| 136 | + const ccPhoneNumber = docusign.RecipientPhoneNumber.constructFromObject({ |
| 137 | + countryCode: args.ccCountryCode, |
| 138 | + number: args.ccPhoneNumber, |
| 139 | + }); |
| 140 | + |
| 141 | + const ccAdditionalNotification = docusign.RecipientAdditionalNotification.constructFromObject({ |
| 142 | + secondaryDeliveryMethod: args.deliveryMethod, |
| 143 | + phoneNumber: ccPhoneNumber |
| 144 | + }); |
| 145 | + |
| 146 | + // Create a cc recipient to receive a copy of the documents, identified by name and phone number |
| 147 | + // We're setting the parameters via setters |
| 148 | + const cc = new docusign.CarbonCopy.constructFromObject({ |
| 149 | + name: args.ccName, |
| 150 | + email: args.ccEmail, |
| 151 | + routingOrder: '2', |
| 152 | + recipientId: '2', |
| 153 | + deliveryMethod: 'Email', |
| 154 | + additionalNotifications: [ccAdditionalNotification], |
| 155 | + }); |
| 156 | + |
| 157 | + // Create signHere fields (also known as tabs) on the documents, |
| 158 | + // We're using anchor (autoPlace) positioning |
| 159 | + // |
| 160 | + // The DocuSign platform searches throughout your envelope's |
| 161 | + // documents for matching anchor strings. So the |
| 162 | + // signHere2 tab will be used in both document 2 and 3 since they |
| 163 | + // use the same anchor string for their "signer 1" tabs. |
| 164 | + const signHere1 = docusign.SignHere.constructFromObject({ |
| 165 | + anchorString: '**signature_1**', |
| 166 | + anchorYOffset: '10', |
| 167 | + anchorUnits: 'pixels', |
| 168 | + anchorXOffset: '20', |
| 169 | + }); |
| 170 | + const signHere2 = docusign.SignHere.constructFromObject({ |
| 171 | + anchorString: '/sn1/', |
| 172 | + anchorYOffset: '10', |
| 173 | + anchorUnits: 'pixels', |
| 174 | + anchorXOffset: '20', |
| 175 | + }); |
| 176 | + // Tabs are set per recipient / signer |
| 177 | + const signerTabs = docusign.Tabs.constructFromObject({ |
| 178 | + signHereTabs: [signHere1, signHere2], |
| 179 | + }); |
| 180 | + signer.tabs = signerTabs; |
| 181 | + |
| 182 | + // Add the recipients to the envelope object |
| 183 | + const recipients = docusign.Recipients.constructFromObject({ |
| 184 | + signers: [signer], |
| 185 | + carbonCopies: [cc], |
| 186 | + }); |
| 187 | + env.recipients = recipients; |
| 188 | + |
| 189 | + // Request that the envelope be sent by setting |status| to "sent". |
| 190 | + // To request that the envelope be created as a draft, set to "created" |
| 191 | + env.status = args.status; |
| 192 | + |
| 193 | + return env; |
| 194 | +} |
| 195 | + |
| 196 | +/** |
| 197 | + * Creates document 1 |
| 198 | + * @function |
| 199 | + * @private |
| 200 | + * @param {Object} args parameters for the envelope |
| 201 | + * @returns {string} A document in HTML format |
| 202 | + */ |
| 203 | + |
| 204 | +function document1(args) { |
| 205 | + // Data for this method |
| 206 | + // args.signerName |
| 207 | + // args.ccName |
| 208 | + |
| 209 | + return ` |
| 210 | + <!DOCTYPE html> |
| 211 | + <html> |
| 212 | + <head> |
| 213 | + <meta charset="UTF-8"> |
| 214 | + </head> |
| 215 | + <body style="font-family:sans-serif;margin-left:2em;"> |
| 216 | + <h1 style="font-family: 'Trebuchet MS', Helvetica, sans-serif; |
| 217 | + color: darkblue;margin-bottom: 0;">World Wide Corp</h1> |
| 218 | + <h2 style="font-family: 'Trebuchet MS', Helvetica, sans-serif; |
| 219 | + margin-top: 0px;margin-bottom: 3.5em;font-size: 1em; |
| 220 | + color: darkblue;">Order Processing Division</h2> |
| 221 | + <h4>Ordered by ${args.signerName}</h4> |
| 222 | + <p style="margin-top:0em; margin-bottom:0em;">Phone number: ${args.phoneNumber}</p> |
| 223 | + <p style="margin-top:0em; margin-bottom:0em;">Copy to: ${args.ccName}, ${args.ccPhoneNumber}</p> |
| 224 | + <p style="margin-top:3em;"> |
| 225 | + Candy bonbon pastry jujubes lollipop wafer biscuit biscuit. Topping brownie sesame snaps sweet roll pie. Croissant danish biscuit soufflé caramels jujubes jelly. Dragée danish caramels lemon drops dragée. Gummi bears cupcake biscuit tiramisu sugar plum pastry. Dragée gummies applicake pudding liquorice. Donut jujubes oat cake jelly-o. Dessert bear claw chocolate cake gummies lollipop sugar plum ice cream gummies cheesecake. |
| 226 | + </p> |
| 227 | + <!-- Note the anchor tag for the signature field is in white. --> |
| 228 | + <h3 style="margin-top:3em;">Agreed: <span style="color:white;">**signature_1**/</span></h3> |
| 229 | + </body> |
| 230 | + </html> |
| 231 | + `; |
| 232 | +} |
| 233 | +//ds-snippet-end:eSign46Step2 |
| 234 | +module.exports = { sendByMultipleChannels }; |
0 commit comments