├── demo_documents └── World_Wide_Corp_salary.docx ├── .vscode ├── settings.json ├── extensions.json └── launch.json ├── force-app └── main │ └── default │ ├── classes │ ├── TransformPDF.cls-meta.xml │ ├── UnitTestExample.cls-meta.xml │ ├── BulkSendWriteback.cls-meta.xml │ ├── SendToNewContact.cls-meta.xml │ ├── BulkSendingController.cls-meta.xml │ ├── CreateMergeFieldInEnvelope.cls-meta.xml │ ├── EmbeddedSigningController.cls-meta.xml │ ├── InPersonSigningController.cls-meta.xml │ ├── DocuSignStatusTriggerHandler.cls-meta.xml │ ├── SendEnvelopeWithTabsController.cls-meta.xml │ ├── SendEnvelopeFromTriggerController.cls-meta.xml │ ├── SendEnvelopeWithReminderController.cls-meta.xml │ ├── SendMultipleEnvelopesController.cls-meta.xml │ ├── DocuSignStatusTriggerHandler.cls │ ├── SendToNewContact.cls │ ├── TransformPDF.cls │ ├── UnitTestExample.cls │ ├── SendEnvelope.cls │ ├── EmbeddedSigningController.cls │ ├── SendEnvelopeFromTriggerController.cls │ ├── SendEnvelopeWithReminderController.cls │ ├── InPersonSigningController.cls │ ├── CreateMergeFieldInEnvelope.cls │ ├── BulkSendingController.cls │ ├── SendMultipleEnvelopesController.cls │ ├── BulkSendWriteback.cls │ └── SendEnvelopeWithTabsController.cls │ ├── triggers │ ├── Trigger_ContactAfterUpdate.trigger-meta.xml │ └── Trigger_ContactAfterUpdate.trigger │ ├── lwc │ ├── embeddedSigningComponent │ │ ├── embeddedSigningComponent.html │ │ ├── embeddedSigningComponent.js-meta.xml │ │ └── embeddedSigningComponent.js │ └── .eslintrc.json │ └── aura │ └── .eslintrc.json ├── .prettierignore ├── sfdx-project.json ├── scripts ├── soql │ └── account.soql └── apex │ └── hello.apex ├── .prettierrc ├── .eslintignore ├── .forceignore ├── config └── project-scratch-def.json ├── .gitignore ├── LICENSE ├── package.json └── README.md /demo_documents/World_Wide_Corp_salary.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docusign/code-examples-apex/HEAD/demo_documents/World_Wide_Corp_salary.docx -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.exclude": { 3 | "**/node_modules": true, 4 | "**/bower_components": true, 5 | "**/.sfdx": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "salesforce.salesforcedx-vscode", 4 | "redhat.vscode-xml", 5 | "dbaeumer.vscode-eslint", 6 | "esbenp.prettier-vscode" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /force-app/main/default/classes/TransformPDF.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 58.0 4 | Active 5 | -------------------------------------------------------------------------------- /force-app/main/default/classes/UnitTestExample.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 56.0 4 | Active 5 | -------------------------------------------------------------------------------- /force-app/main/default/classes/BulkSendWriteback.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 58.0 4 | Active 5 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendToNewContact.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 58.0 4 | Active 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # List files or directories below to ignore them when running prettier 2 | # More information: https://prettier.io/docs/en/ignore.html 3 | # 4 | 5 | **/staticresources/** 6 | .localdevserver 7 | .sfdx 8 | .vscode 9 | 10 | coverage/ -------------------------------------------------------------------------------- /force-app/main/default/classes/BulkSendingController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 52.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/CreateMergeFieldInEnvelope.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 57.0 4 | Active 5 | -------------------------------------------------------------------------------- /force-app/main/default/classes/EmbeddedSigningController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 50.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/InPersonSigningController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 52.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/DocuSignStatusTriggerHandler.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 52.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendEnvelopeWithTabsController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 52.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/triggers/Trigger_ContactAfterUpdate.trigger-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 58.0 4 | Active 5 | -------------------------------------------------------------------------------- /sfdx-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageDirectories": [ 3 | { 4 | "path": "force-app", 5 | "default": true 6 | } 7 | ], 8 | "namespace": "", 9 | "sfdcLoginUrl": "https://login.salesforce.com", 10 | "sourceApiVersion": "50.0" 11 | } 12 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendEnvelopeFromTriggerController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 52.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendEnvelopeWithReminderController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 52.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendMultipleEnvelopesController.cls-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 52.0 4 | Active 5 | 6 | -------------------------------------------------------------------------------- /force-app/main/default/lwc/embeddedSigningComponent/embeddedSigningComponent.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /scripts/soql/account.soql: -------------------------------------------------------------------------------- 1 | // Use .soql files to store SOQL queries. 2 | // You can execute queries in VS Code by selecting the 3 | // query text and running the command: 4 | // SFDX: Execute SOQL Query with Currently Selected Text 5 | 6 | SELECT Id, Name FROM Account 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "overrides": [ 4 | { 5 | "files": "**/lwc/**/*.html", 6 | "options": { "parser": "lwc" } 7 | }, 8 | { 9 | "files": "*.{cmp,page,component}", 10 | "options": { "parser": "html" } 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /force-app/main/default/lwc/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@salesforce/eslint-config-lwc/recommended", "prettier"], 3 | "overrides": [ 4 | { 5 | "files": ["*.test.js"], 6 | "rules": { 7 | "@lwc/lwc/no-unexpected-wire-adapter-usages": "off" 8 | } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /force-app/main/default/aura/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["@salesforce/eslint-plugin-aura"], 3 | "extends": ["plugin:@salesforce/eslint-plugin-aura/recommended", "prettier"], 4 | "rules": { 5 | "func-names": "off", 6 | "vars-on-top": "off", 7 | "no-unused-expressions": "off" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/lwc/**/*.css 2 | **/lwc/**/*.html 3 | **/lwc/**/*.json 4 | **/lwc/**/*.svg 5 | **/lwc/**/*.xml 6 | **/aura/**/*.auradoc 7 | **/aura/**/*.cmp 8 | **/aura/**/*.css 9 | **/aura/**/*.design 10 | **/aura/**/*.evt 11 | **/aura/**/*.json 12 | **/aura/**/*.svg 13 | **/aura/**/*.tokens 14 | **/aura/**/*.xml 15 | .sfdx -------------------------------------------------------------------------------- /.forceignore: -------------------------------------------------------------------------------- 1 | # List files or directories below to ignore them when running force:source:push, force:source:pull, and force:source:status 2 | # More information: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm 3 | # 4 | 5 | package.xml 6 | 7 | # LWC configuration files 8 | **/jsconfig.json 9 | **/.eslintrc.json 10 | 11 | # LWC Jest 12 | **/__tests__/** -------------------------------------------------------------------------------- /config/project-scratch-def.json: -------------------------------------------------------------------------------- 1 | { 2 | "orgName": "Org Name", 3 | "edition": "Developer", 4 | "features": [], 5 | "settings": { 6 | "lightningExperienceSettings": { 7 | "enableS1DesktopEnabled": true 8 | }, 9 | "securitySettings": { 10 | "passwordPolicies": { 11 | "enableSetPasswordInApi": true 12 | } 13 | }, 14 | "mobileSettings": { 15 | "enableS1EncryptedStoragePref2": false 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /force-app/main/default/lwc/embeddedSigningComponent/embeddedSigningComponent.js-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 50.0 4 | true 5 | 6 | lightning__AppPage 7 | lightning__RecordPage 8 | lightning__HomePage 9 | 10 | 11 | -------------------------------------------------------------------------------- /scripts/apex/hello.apex: -------------------------------------------------------------------------------- 1 | // Use .apex files to store anonymous Apex. 2 | // You can execute anonymous Apex in VS Code by selecting the 3 | // apex text and running the command: 4 | // SFDX: Execute Anonymous Apex with Currently Selected Text 5 | // You can also execute the entire file by running the command: 6 | // SFDX: Execute Anonymous Apex with Editor Contents 7 | 8 | string tempvar = 'Enter_your_name_here'; 9 | System.debug('Hello World!'); 10 | System.debug('My name is ' + tempvar); -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch Apex Replay Debugger", 9 | "type": "apex-replay", 10 | "request": "launch", 11 | "logFile": "${command:AskForLogFileName}", 12 | "stopOnEntry": true, 13 | "trace": true 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /force-app/main/default/classes/DocuSignStatusTriggerHandler.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex11Step3 2 | public class DocuSignStatusTriggerHandler{ 3 | @future (callout=true) 4 | // Handler for Order complete 5 | public static void handleOrderComplete(final Id contactId) { 6 | // Call the SendEnvelopeFromTriggerController class sendEnvelope method to invoke the DocuSign API's for sending envelope 7 | SendEnvelopeFromTriggerController.sendEnvelope(contactId); 8 | } 9 | } 10 | //ds-snippet-end:Apex11Step3 11 | 12 | -------------------------------------------------------------------------------- /force-app/main/default/triggers/Trigger_ContactAfterUpdate.trigger: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex11Step4 2 | trigger Trigger_ContactAfterUpdate on Contact (after insert, after update, after delete) { 3 | if (trigger.isUpdate) 4 | { 5 | for(contact aC : trigger.new) 6 | { 7 | if (aC.DocuSign_Status__c=='Email DocuSign') // Test Field called on the contact. This is not a DocuSignStatus Object 8 | { 9 | DocuSignStatusTriggerHandler.handleOrderComplete(aC.Id); 10 | } 11 | } 12 | } 13 | } 14 | //ds-snippet-end:Apex11Step4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used for Git repositories to specify intentionally untracked files that Git should ignore. 2 | # If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore 3 | # For useful gitignore templates see: https://github.com/github/gitignore 4 | 5 | # Salesforce cache 6 | .sfdx/ 7 | .localdevserver/ 8 | 9 | # LWC VSCode autocomplete 10 | **/lwc/jsconfig.json 11 | 12 | # LWC Jest coverage reports 13 | coverage/ 14 | 15 | # SOQL Query Results 16 | **/scripts/soql/query-results 17 | 18 | # Logs 19 | logs 20 | *.log 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # Dependency directories 26 | node_modules/ 27 | 28 | # Eslint cache 29 | .eslintcache 30 | 31 | # MacOS system files 32 | .DS_Store 33 | 34 | # Windows system files 35 | Thumbs.db 36 | ehthumbs.db 37 | [Dd]esktop.ini 38 | $RECYCLE.BIN/ 39 | -------------------------------------------------------------------------------- /force-app/main/default/lwc/embeddedSigningComponent/embeddedSigningComponent.js: -------------------------------------------------------------------------------- 1 | import { LightningElement, api } from 'lwc'; 2 | import sendEnvelope from '@salesforce/apex/EmbeddedSigningController.sendEnvelope'; 3 | import getEmbeddedSigningUrl from '@salesforce/apex/EmbeddedSigningController.getEmbeddedSigningUrl'; 4 | 5 | export default class EmbeddedSigningComponent extends LightningElement { 6 | 7 | template = '2712xxxx-xxxx-xxxx-xxxx-xxxxf9b8fa5f'; 8 | description = 'Embedded Signing'; 9 | @api recordId; 10 | handleClick() { 11 | sendEnvelope({template: this.template, description: this.description, recordId: this.recordId}) 12 | .then((envelopeId) => ( 13 | getEmbeddedSigningUrl({ 14 | envId: envelopeId, 15 | url: window.location.href 16 | }) 17 | )) 18 | .then((signingUrl) => { 19 | window.location.href = signingUrl; 20 | }) 21 | .catch((error) => { 22 | console.log('Error:'); 23 | console.log(error); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2021 DocuSign, Inc. (https://www.docusign.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "salesforce-app", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "Salesforce App", 6 | "scripts": { 7 | "lint": "npm run lint:lwc && npm run lint:aura", 8 | "lint:aura": "eslint **/aura/**", 9 | "lint:lwc": "eslint **/lwc/**", 10 | "test": "npm run test:unit", 11 | "test:unit": "sfdx-lwc-jest", 12 | "test:unit:watch": "sfdx-lwc-jest --watch", 13 | "test:unit:debug": "sfdx-lwc-jest --debug", 14 | "test:unit:coverage": "sfdx-lwc-jest --coverage", 15 | "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"", 16 | "prettier:verify": "prettier --list-different \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"" 17 | }, 18 | "devDependencies": { 19 | "@prettier/plugin-xml": "^0.12.0", 20 | "@salesforce/eslint-config-lwc": "^0.7.0", 21 | "@salesforce/eslint-plugin-aura": "^1.4.0", 22 | "@salesforce/sfdx-lwc-jest": "^0.9.2", 23 | "eslint": "^7.6.0", 24 | "eslint-config-prettier": "^6.11.0", 25 | "husky": "^4.2.1", 26 | "lint-staged": "^10.0.7", 27 | "prettier": "^2.0.5", 28 | "prettier-plugin-apex": "^1.6.0" 29 | }, 30 | "husky": { 31 | "hooks": { 32 | "pre-commit": "lint-staged" 33 | } 34 | }, 35 | "lint-staged": { 36 | "**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}": [ 37 | "prettier --write" 38 | ], 39 | "**/{aura|lwc}/**": [ 40 | "eslint" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendToNewContact.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex9Step1 2 | public class SendToNewContact { 3 | //ds-snippet-end:Apex9Step1 4 | 5 | //ds-snippet-start:Apex9Step4 6 | @InvocableMethod 7 | public static List sendEnvelope(List record) { 8 | Contact mySource = record.get(0); 9 | sendEnvelopeInFuture(mySource.Id); 10 | return Null; 11 | } 12 | //ds-snippet-end:Apex9Step4 13 | 14 | //ds-snippet-start:Apex9Step3 15 | @future(callout = true) 16 | public static void sendEnvelopeInFuture(Id mySourceId) { 17 | createAndSendEnvelope(mySourceId); 18 | } 19 | //ds-snippet-end:Apex9Step3 20 | 21 | //ds-snippet-start:Apex9Step2 22 | public static Id createAndSendEnvelope(Id mySourceId) { 23 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope( 24 | new dfsle.Entity(mySourceId) 25 | ); 26 | Contact myContact = [SELECT Name, Email FROM Contact WHERE Id = :mySourceId LIMIT 1]; 27 | dfsle.Recipient myRecipient = dfsle.Recipient.fromSource( 28 | myContact.Name, 29 | myContact.Email, 30 | null, 31 | 'Signer1', 32 | new dfsle.Entity(myContact.Id) 33 | ); 34 | myEnvelope = myEnvelope.withRecipients(new List { myRecipient }); 35 | dfsle.UUID myTemplateId = dfsle.UUID.parse('8dafd5dd-xxxx-xxxx-xxxx-542f35b227f7'); 36 | dfsle.Document myDocument = dfsle.Document.fromTemplate( 37 | myTemplateId, 38 | 'Services Framework Agreement' 39 | ); 40 | myEnvelope = myEnvelope.withDocuments( 41 | new List { myDocument } 42 | ); 43 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 44 | myEnvelope, 45 | true 46 | ); 47 | return myEnvelope.Id; 48 | } 49 | //ds-snippet-end:Apex9Step2 50 | 51 | //ds-snippet-start:Apex9Step1 52 | } 53 | //ds-snippet-end:Apex9Step1 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apex Toolkit Code Examples 2 | 3 | ### Github repo: https://github.com/docusign/code-examples-apex 4 | 5 | This GitHub repo includes code examples for Docusign's Apex Toolkit. The Apex Toolkit is a set of predefined Apex methods, classes, and utilities that encapsulate a set of the Docusign eSignature API functionality similar to an SDK, enabling you to integrate Docusign and Salesforce functionality into your Apex code. 6 | 7 | ## Installation 8 | 9 | ### Prerequisites 10 | 11 | 1. A free [Docusign developer account](https://go.docusign.com/o/sandbox/); create one if you don't already have one. 12 | 1. A Salesforce Developer Edition (account). 13 | 1. [Install the Apex Toolkit](https://developers.docusign.com/docs/salesforce/how-to/apex-toolkit-install/). 14 | 1. Visual Studio Code. Your Visual Studio Code should be set up with the necessary [Salesforce development tools](https://trailhead.salesforce.com/content/learn/projects/set-up-your-lightning-web-components-developer-tools/install-development-tools) including the [Salesforce CLI](https://developer.salesforce.com/tools/sfdxcli). 15 | 1. The [Salesforce Extension Pack for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode) 16 | 17 | ### Installation steps 18 | 19 | 1. Authorize your Salesforce Developer Account within Visual Studio Code. To do this press command + shift + P (on a Mac) or Ctrl + Shift + P (on Windows) to open the Command Palette. Then type SFDX:Authorize an Org and press Enter. In the browser window that opens, log into your Salesforce Developer Organization, then on 20 | the next screen, click Allow to grant access. 21 | 1. Download or clone the **code-examples-apex** repo. 22 | 1. Replace any placeholder IDs from the example code with template IDs or other IDs corresponding with your Docusign and Salesforce accounts. 23 | 1. Deploy the code to Salesforce. To do this, navigate to the force-app/main/default folder in the menu on the left and right-click default, then select SFDX: Deploy Source to Org. Now when you sign into your Salesforce Developer Edition (account) you will find the clases and Lightning Web Components defined in this project. 24 | -------------------------------------------------------------------------------- /force-app/main/default/classes/TransformPDF.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex8Step1 2 | public class TransformPDF { 3 | public static void sendEnvelope() { 4 | //ds-snippet-end:Apex8Step1 5 | //ds-snippet-start:Apex8Step2 6 | Id mySourceId = '0034xxxxxxxxxx4QAE'; // The Salesforce Contact ID of the sender 7 | // Create an empty envelope. 8 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope( 9 | new dfsle.Entity(mySourceId)); 10 | 11 | // We will use a Salesforce Contact ID as a Recipient here 12 | Contact myContact = [SELECT Id, Name, Email FROM Contact WHERE Id = '0034xxxxxxxxxxcQAG']; 13 | // Use the Recipient.fromSource method to create the Recipient 14 | dfsle.Recipient myRecipient = dfsle.Recipient.fromSource( 15 | myContact.Name, // Recipient name 16 | myContact.Email, // Recipient email 17 | null, //Optional phone number 18 | 'Signer 1', //Role Name. Specify the exact role name from template 19 | new dfsle.Entity(myContact.Id)); 20 | // Add Recipient to the Envelope 21 | myEnvelope = myEnvelope.withRecipients(new List { myRecipient }); 22 | //ds-snippet-end:Apex8Step2 23 | 24 | //ds-snippet-start:Apex8Step3 25 | Id myFileId = [SELECT id from ContentVersion where ContentDocumentId = '0694xxxxxxxxxxyQAD' LIMIT 1].id; // Content version ID of document to send 26 | dfsle.Document myDocument = dfsle.DocumentService.getDocuments(ContentVersion.getSObjectType(), new Set { myFileId }).get(0); 27 | myDocument.withPdfOptions(new dfsle.Document.PdfOptions( 28 | true, // Whether to transform PDF form fields 29 | 1)); // The recipient for which to apply the tags 30 | 31 | //Add document to the Envelope 32 | myEnvelope = myEnvelope.withDocuments(new List { myDocument }); 33 | //ds-snippet-end:Apex8Step3 34 | 35 | //ds-snippet-start:Apex8Step4 36 | // Send the envelope 37 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 38 | myEnvelope, 39 | true); 40 | //ds-snippet-end:Apex8Step4 41 | 42 | //ds-snippet-start:Apex8Step1 43 | } 44 | } 45 | //ds-snippet-end:Apex8Step1 -------------------------------------------------------------------------------- /force-app/main/default/classes/UnitTestExample.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex12Step1 2 | @IsTest 3 | public with sharing class UnitTestExample { 4 | 5 | @IsTest 6 | public static void testSendEnvelope() { 7 | //ds-snippet-end:Apex12Step1 8 | 9 | //ds-snippet-start:Apex12Step2 10 | // Mock the DocuSign eSignature API 11 | dfsle.TestUtils.setMock(new dfsle.ESignatureAPIMock()); 12 | 13 | // Run the test as a DocuSign Sender. This is required by dfsle.EnvelopeService.sendEnvelope 14 | System.runAs(dfsle.UserMock.createDocuSignSender()) { 15 | 16 | // Create test data 17 | Account myAccount = new Account(Name = 'Test Account'); 18 | insert myAccount; 19 | 20 | Contact myContact = new Contact( 21 | AccountId = myAccount.Id, 22 | FirstName = 'Test', 23 | LastName = 'Contact', 24 | Phone = '555-1234-5678', 25 | Email = 'test.contact@example.com'); 26 | insert myContact; 27 | 28 | // Create a test envelope with one document and one recipient 29 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope(new dfsle.Entity(myAccount.Id)) 30 | .withDocuments(new List { 31 | dfsle.Document.fromTemplate( 32 | dfsle.UUID.randomUUID(), 33 | 'test template') 34 | }) 35 | .withRecipients(new List { 36 | dfsle.Recipient.fromSource( 37 | myContact.FirstName + ' ' + myContact.LastName, 38 | myContact.Email, 39 | myContact.Phone, 40 | 'Signer 1', 41 | new dfsle.Entity(myContact.Id)) 42 | }); 43 | } 44 | //ds-snippet-end:Apex12Step2 45 | 46 | //ds-snippet-start:Apex12Step3 47 | // Perform the test 48 | Test.startTest(); 49 | dfsle.Envelope myResult = dfsle.EnvelopeService.sendEnvelope(myEnvelope, true); 50 | Test.stopTest(); 51 | 52 | // Verify the results 53 | System.assertNotEquals(null, myResult); 54 | //ds-snippet-end:Apex12Step3 55 | 56 | //ds-snippet-start:Apex12Step1 57 | } 58 | } 59 | //ds-snippet-end:Apex12Step1 60 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendEnvelope.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex1Step1 2 | public class SendEnvelope { 3 | public static void sendEnvelopeMethod(){ 4 | //ds-snippet-end:Apex1Step1 5 | 6 | //ds-snippet-start:Apex1Step2 7 | Id mySourceId; // The ID of the initiating Salesforce object 8 | String templateId; // The ID of the DocuSign template 9 | 10 | // Create an empty envelope 11 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope( 12 | new dfsle.Entity(mySourceId)); 13 | // The initiating Salesforce entity 14 | //ds-snippet-end:Apex1Step2 15 | 16 | //ds-snippet-start:Apex1Step3 17 | // We will use a Salesforce contact record as a Recipient here 18 | Contact myContact = [SELECT Id, Name, Email FROM Contact LIMIT 1]; 19 | 20 | //use the Recipient.fromSource method to create the Recipient 21 | dfsle.Recipient myRecipient = dfsle.Recipient.fromSource( 22 | myContact.Name, // Recipient name 23 | myContact.Email, // Recipient email 24 | null, // Optional phone number 25 | 'Signer 1', // Role Name. Specify the exact role name from template 26 | new dfsle.Entity(myContact.Id)); // Source object for the recipient 27 | 28 | // Add a recipient to the envelope 29 | myEnvelope = myEnvelope.withRecipients(new List { myRecipient }); 30 | //ds-snippet-end:Apex1Step3 31 | 32 | //ds-snippet-start:Apex1Step4 33 | // myTemplateId contains the DocuSign Id of the DocuSign Template 34 | dfsle.UUID myTemplateId = dfsle.UUID.parse(templateId); 35 | 36 | // create a new document for the Envelope 37 | dfsle.Document myDocument = dfsle.Document.fromTemplate( 38 | myTemplateId, // Template Id in dfsle.UUID format 39 | 'myTemplate'); // Name of the template 40 | 41 | //add document to the envelope 42 | myEnvelope = myEnvelope.withDocuments(new List { myDocument }); 43 | //ds-snippet-end:Apex1Step4 44 | 45 | //ds-snippet-start:Apex1Step5 46 | // Send the envelope 47 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 48 | myEnvelope, // The envelope to send 49 | true); // True to send the envelope now 50 | //ds-snippet-end:Apex1Step5 51 | //ds-snippet-start:Apex1Step1 52 | } 53 | } 54 | //ds-snippet-end:Apex1Step1 -------------------------------------------------------------------------------- /force-app/main/default/classes/EmbeddedSigningController.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex2Step1 2 | public class EmbeddedSigningController { 3 | //ds-snippet-end:Apex2Step1 4 | /** 5 | * sendEnvelope method (String) 6 | * Get Salesforce user ID 7 | * Create an envelope 8 | * Specify embedded signing 9 | * Add a document template 10 | * Send the envelope immediately 11 | * Return the envelope ID to the controller as a string 12 | */ 13 | 14 | //ds-snippet-start:Apex2Step2 15 | @AuraEnabled 16 | public static String sendEnvelope(String template, String description, Id recordId) { 17 | Id mySourceId = recordId; // The ID of the initiating Salesforce object 18 | 19 | // Create an empty envelope and add a Salesforce Document and embedded signer recipient 20 | // The embedded signer will be the current user with sequence and routing order 1 and role "Signer 1" by default 21 | dfsle.Envelope dsEnvelope = dfsle.EnvelopeService.getEmptyEnvelope( 22 | new dfsle.Entity(mySourceId)) // The initiating Salesforce entity--current SF user (salesperson) 23 | .withDocuments(new List { 24 | dfsle.Document.fromTemplate(dfsle.UUID.parse(template), description) 25 | }) 26 | .withRecipients(new List { 27 | dfsle.Recipient.newEmbeddedSigner() // An embedded signer 28 | } 29 | ); 30 | 31 | // Send the envelope. 32 | dsEnvelope = dfsle.EnvelopeService.sendEnvelope( 33 | dsEnvelope, // The envelope to send 34 | true // Send now? 35 | ); 36 | // Return string value of DocuSign envelope ID 37 | return String.valueOf(dsEnvelope.docuSignId); 38 | } 39 | //ds-snippet-end:Apex2Step2 40 | 41 | /** 42 | * getEmbeddedSigningUrl method (String) 43 | * Get the envelope ID 44 | * Get the post-signing URL 45 | * Generate an embedded signing URL 46 | * Return the embedded signing URL as a string 47 | */ 48 | 49 | //ds-snippet-start:Apex2Step3 50 | @AuraEnabled 51 | public static String getEmbeddedSigningUrl(String envId, String url) { 52 | Url mySigningUrl = dfsle.SigningService.getEmbeddedSigningUrl( 53 | dfsle.UUID.parse(envId), // envId value as a UUID 54 | new URL(url) // url value as a URL 55 | ); 56 | // Return string value of Url to controller 57 | return mySigningUrl.toExternalForm(); 58 | } 59 | //ds-snippet-end:Apex2Step3 60 | //ds-snippet-start:Apex2Step1 61 | } 62 | //ds-snippet-end:Apex2Step1 63 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendEnvelopeFromTriggerController.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex11Step1 2 | public with sharing class SendEnvelopeFromTriggerController { 3 | public class EnvelopeSendResponse { 4 | 5 | public String message {get; private set;} 6 | public Boolean status {get; private set;} 7 | 8 | public EnvelopeSendResponse(final String message, final Boolean status){ 9 | this.message = message; 10 | this.status = status; 11 | } 12 | } 13 | //ds-snippet-end:Apex11Step1 14 | 15 | //ds-snippet-start:Apex11Step2 16 | public static EnvelopeSendResponse sendEnvelope(final Id mySourceId) { 17 | EnvelopeSendResponse response; 18 | try { 19 | 20 | // Capture customer details 21 | Contact myCustomer = [SELECT Id, Name, Email FROM Contact WHERE Id =:mySourceId]; 22 | 23 | // Create an empty envelope 24 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope 25 | (new dfsle.Entity(mySourceId)); 26 | 27 | // Setup recipient data 28 | dfsle.Recipient myRecipient = dfsle.Recipient.fromSource 29 | (myCustomer.Name, myCustomer.Email, null, 'Signer 1', new dfsle.Entity(mySourceId)); 30 | 31 | 32 | // Add Recipient to the Envelope 33 | myEnvelope = myEnvelope.withRecipients(new List { myRecipient }); 34 | 35 | // myTemplateId contains the DocuSign Id of the DocuSign Template 36 | dfsle.UUID myTemplateId = dfsle.UUID.parse('bf7ca600-XXXX-XXXX-XXXX-06e7f3b9e8ce'); 37 | 38 | // Create a new document for the Envelope 39 | dfsle.Document myDocument = dfsle.Document.fromTemplate( 40 | myTemplateId, // templateId in dfsle.UUID format 41 | 'myTemplate'); // The name of the template 42 | 43 | // Add document to the Envelope 44 | myEnvelope = myEnvelope.withDocuments(new List { myDocument }); 45 | 46 | // Send the envelope 47 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 48 | myEnvelope, // The envelope to send 49 | true); // Send now? 50 | 51 | response = new EnvelopeSendResponse('Envelope sent successfully', true); 52 | } 53 | catch(Exception ex) { 54 | response = new EnvelopeSendResponse(ex.getMessage(), false); 55 | } 56 | return response; 57 | } 58 | //ds-snippet-end:Apex11Step2 59 | //ds-snippet-start:Apex11Step1 60 | } 61 | //ds-snippet-end:Apex11Step1 -------------------------------------------------------------------------------- /force-app/main/default/classes/SendEnvelopeWithReminderController.cls: -------------------------------------------------------------------------------- 1 | public class SendEnvelopeWithReminderController { 2 | public static void sendEnvelopeMethod(){ 3 | Id mySourceId = '0XXXXXXXXXXXXXXXXE'; // The ID of the initiating Salesforce object. 4 | 5 | // Set up notification 6 | //ds-snippet-start:Apex6Step2 7 | dfsle.Notifications notifySigner = new dfsle.Notifications( 8 | true, // Indicates that the recipient should be reminded to sign 9 | 2, // Number of days to wait before sending a reminder 10 | 1, // Number of days between reminders 11 | true, // Whether or not the envelope expires and is voided 12 | 90, // How many days before the envelope expires 13 | 10, // Number of days before expiration to remind the recipient 14 | false // Placeholder for deprecated field 15 | ); 16 | //ds-snippet-end:Apex6Step2 17 | 18 | //ds-snippet-start:Apex6Step3 19 | // Create an empty envelope. 20 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope( 21 | new dfsle.Entity(mySourceId)); 22 | // The initiating Salesforce entity. 23 | 24 | // We will use a Salesforce contact record as a Recipient here 25 | // We will use a Salesforce contact record as a Recipient here 26 | Contact myContact = [SELECT Id, Name, Email FROM Contact WHERE Id = '00xxxxxxxxxxxxxxAR']; 27 | 28 | // Use the Recipient.fromSource method to create the Recipient 29 | dfsle.Recipient myRecipient = dfsle.Recipient.fromSource( 30 | myContact.Name, // Recipient name 31 | myContact.Email, // Recipient email 32 | null, // Optional phone number 33 | 'Signer 1', // Role Name. Specify the exact role name from template 34 | new dfsle.Entity(myContact.Id)); // Source object for the Recipient 35 | 36 | // Add Recipient to the Envelope 37 | myEnvelope = myEnvelope.withRecipients(new List { myRecipient }); 38 | 39 | // myTemplateId contains the DocuSign Id of the DocuSign Template 40 | dfsle.UUID myTemplateId = dfsle.UUID.parse('8dafxxxx-xxxx-xxxx-xxxx-xxxxxxxx27f7'); 41 | 42 | // Create a new document for the Envelope 43 | dfsle.Document myDocument = dfsle.Document.fromTemplate( 44 | myTemplateId, // templateId in dfsle.UUID format 45 | 'myTemplate'); // name of the template 46 | 47 | // Add document to the Envelope 48 | myEnvelope = myEnvelope.withDocuments(new List { myDocument }); 49 | // Add notification to the envelope 50 | myEnvelope = myEnvelope.withNotifications(notifySigner); 51 | //ds-snippet-end:Apex6Step3 52 | 53 | // Send the envelope 54 | //ds-snippet-start:Apex6Step4 55 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 56 | myEnvelope, // The envelope to send 57 | true); // Indicates that the envelope should be sent now 58 | //ds-snippet-end:Apex6Step4 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /force-app/main/default/classes/InPersonSigningController.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex7Step1 2 | public class InPersonSigningController { 3 | public static Id sendWithInPerson(){ 4 | //ds-snippet-end:Apex7Step1 5 | 6 | //ds-snippet-start:Apex7Step2 7 | //Get the Salesforce account ID 8 | Opportunity myOpportunity = [SELECT Id FROM Opportunity WHERE Name = 'My Opportunity' LIMIT 1]; 9 | // Create an empty envelope with Opportunity Id as the source Id 10 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope(new dfsle.Entity(myOpportunity.Id)); 11 | //ds-snippet-end:Apex7Step2 12 | 13 | //ds-snippet-start:Apex7Step3 14 | dfsle.Recipient InPerson = new dfsle.Recipient( 15 | null, //Source Id 16 | 'inPersonSigner',//Type of recipient 17 | 1, //Sequence 18 | 2, //routing order 19 | new dfsle.Recipient.Role('Customer',null), //role -used to match role 20 | //on template if using a template 21 | 'InPerson Signer', //inPerson Recipient name 22 | 'example@example.com', //inPerson Recipient Email 23 | null, //signing group 24 | null, //phone 25 | //Don't need recipient auth for embedded in SF cause you have SF auth 26 | //new dfsle.Recipient.Authentication(null, true, new List{'147852369'}),//Authentication - may need to adjust this - can be null 27 | null,//no Authentication 28 | null, //note 29 | null, //EmailSettings 30 | 'Host Name', //host name This is the name of the host for InPerson 31 | 'host@example.com', //host email email of host 32 | true, //sign now 33 | null, //source 34 | false, //read only 35 | false); //required 36 | // add Recipient to the Envelope 37 | myEnvelope = myEnvelope.withRecipients(new List { InPerson }); 38 | //ds-snippet-end:Apex7Step3 39 | 40 | //ds-snippet-start:Apex7Step4 41 | // myTemplateId contains the DocuSign Id of the DocuSign Template 42 | dfsle.UUID myTemplateId = dfsle.UUID.parse('801c741b-xxxx-xxxx-xxxx-23a050e0dd51'); 43 | // Create a new document for the Envelope 44 | dfsle.Document myDocument = dfsle.Document.fromTemplate( 45 | myTemplateId, // templateId in dfsle.UUID format 46 | 'myTemplate'); // Name of the template 47 | 48 | myEnvelope = myEnvelope.withDocuments(new List { myDocument }); 49 | //ds-snippet-end:Apex7Step4 50 | 51 | //ds-snippet-start:Apex7Step5 52 | // Send the envelope 53 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 54 | myEnvelope, // The envelope to send 55 | true); // Send or Draft 56 | 57 | System.debug(myEnvelope.Id); 58 | return myEnvelope.Id; 59 | //ds-snippet-end:Apex7Step5 60 | 61 | //ds-snippet-start:Apex7Step1 62 | } 63 | } 64 | //ds-snippet-end:Apex7Step1 -------------------------------------------------------------------------------- /force-app/main/default/classes/CreateMergeFieldInEnvelope.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex10Step1 2 | public with sharing class CreateMergeFieldInEnvelope { 3 | 4 | @AuraEnabled 5 | public static void sendEnvelope() { 6 | //ds-snippet-end:Apex10Step1 7 | 8 | //ds-snippet-start:Apex10Step2 9 | Id mySourceId = '00XXXXXXXXXXXXXXAM'; // The ID of the initiating Salesforce Opportunity 10 | 11 | // Create an empty envelope 12 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope( 13 | new dfsle.Entity(mySourceId)); 14 | // The initiating Salesforce entity 15 | 16 | // Add document to the envelope 17 | Id myDocumentId = '00XXXXXXXXXXXXXXA4'; // The ID of a document stored in a Salesforce library 18 | Id myFileId = [SELECT id from ContentVersion where ContentDocumentId = :myDocumentId LIMIT 1].id; 19 | myEnvelope = myEnvelope.withDocuments(dfsle.DocumentService.getDocuments(ContentVersion.getSObjectType(), new Set { myFileId })); 20 | //ds-snippet-end:Apex10Step2 21 | 22 | //ds-snippet-start:Apex10Step3 23 | //Define a merge field 24 | //This field will be associated with the initiating source object represented by mySourceId 25 | dfsle.Tab.MergeField myMergeField = new dfsle.Tab.MergeField ( 26 | 'opportunity.name', //The data that this merge field will pull its value from 27 | null, //N/A 28 | null, //N/A 29 | true, //Allows writeback to the Salesforce object 30 | false //Whether or not the field is read only for the sender 31 | ); 32 | 33 | //Create a text tab that will be mapped to the merge field 34 | dfsle.Tab myTextTab = new dfsle.TextTab() 35 | .withMergeField(myMergeField) //Associate this tab with the mergeField 36 | .withReadOnly(false) //true = read only or locked 37 | .withPosition(new dfsle.Tab.Position(1, 1, 200, 300, null, null)) 38 | .withDataLabel('Contact Name'); 39 | //ds-snippet-end:Apex10Step3 40 | 41 | 42 | //ds-snippet-start:Apex10Step4 43 | // Create a new recipient 44 | Id myContactId = '00XXXXXXXXXXXXXXA4'; 45 | Contact myContact = [SELECT Id, Name, Email FROM Contact WHERE Id = :myContactId]; 46 | 47 | dfsle.Recipient myRecipient = dfsle.Recipient.fromSource( 48 | myContact.Name, // Signer name 49 | myContact.Email, // Signer email 50 | null, // Signer phone number 51 | null, // Template role n/a 52 | null) // No Salesforce association 53 | .withTabs(new List { // Associate the tabs with this recipient 54 | myTextTab 55 | }); 56 | 57 | // Add recipient to the envelope 58 | myEnvelope = myEnvelope.withRecipients(new List { myRecipient }); 59 | //ds-snippet-end:Apex10Step4 60 | 61 | //ds-snippet-start:Apex10Step5 62 | // Send the envelope 63 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 64 | myEnvelope, // The envelope to send 65 | true); // Send now? 66 | //ds-snippet-end:Apex10Step5 67 | 68 | //ds-snippet-start:Apex10Step1 69 | } 70 | } 71 | //ds-snippet-end:Apex10Step1 -------------------------------------------------------------------------------- /force-app/main/default/classes/BulkSendingController.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex3Step1 2 | public with sharing class BulkSendingClass{ 3 | //ds-snippet-end:Apex3Step1 4 | 5 | /** 6 | * buildList Method 7 | * Requires Chatter group ID 8 | * Create a persistant list of group members 9 | * Return an ID of the list 10 | */ 11 | 12 | //ds-snippet-start:Apex3Step2 13 | @AuraEnabled 14 | public static Id buildList(){ 15 | 16 | Id myGroupId = '0FXXXXXXXXXXXXXXAC'; // Substitute this value with your Chatter group ID 17 | // Build a list membership from a Chatter group 18 | // Recipient authentication, email settings, or private notes may be overridden using the Recipient.with* methods 19 | // Envelope email settings and notifications may also be overridden per copy using the Envelope.with* methods 20 | 21 | List myBulkCopies = new List(); 22 | for (CollaborationGroupMember m : [ 23 | SELECT Member.Id, Member.Name, Member.Email 24 | FROM CollaborationGroupMember 25 | WHERE CollaborationGroupId = :myGroupId 26 | ]) { 27 | myBulkCopies.add(dfsle.Envelope.newBulkCopy( 28 | dfsle.Recipient.newBulkRecipient( 29 | m.Member.Name, 30 | m.Member.Email, 31 | new dfsle.Entity(m.Member.Id) // Source Salesforce object 32 | ) 33 | .withRole('SignerOne') 34 | )); 35 | } 36 | 37 | // Create the bulk list. This list persists after sending and may be reused for multiple batches of envelopes 38 | dfsle.BulkList myList = dfsle.BulkSendService.createLists(new List { 39 | dfsle.BulkList.newList( 40 | 'My bulk list', // List name 41 | myBulkCopies, // Envelope copies 42 | new dfsle.Entity(myGroupId)) // The Salesforce source object 43 | })[0]; 44 | 45 | // Save the ID for later operations 46 | Id myListId = myList.id; 47 | System.debug(LoggingLevel.INFO, myListId); 48 | return myListId; 49 | 50 | } 51 | //ds-snippet-end:Apex3Step2 52 | 53 | 54 | //ds-snippet-start:Apex3Step3 55 | @future(callout=true) 56 | /** 57 | * bulkSendEnvelopes method 58 | * Use myListId from buildList method 59 | * Assign myStatusId to the result of the BulkSendService call 60 | */ 61 | public static void bulkSendEnvelopes(Id myListId){ 62 | 63 | dfsle.UUID myTemplateId = dfsle.UUID.parse('3d9fac4b-xxxx-xxxx-xxxx-6cd70d70f8ed'); // Substitute with your template ID 64 | dfsle.Document myDocument = dfsle.Document.fromTemplate( 65 | myTemplateId, // templateId in dfsle.UUID format 66 | 'myTemplate'); // name of the template 67 | 68 | // Create the draft bulk envelope. This will have exactly one placeholder bulk recipient 69 | dfsle.Envelope myEnvelope = dfsle.BulkSendService.getDraftEnvelope( 70 | new List { myDocument }, null); // Optional Salesforce source entity 71 | 72 | // Send envelope with a placeholder bulk recipient 73 | dfsle.BulkList.Result myResult = dfsle.BulkSendService.sendEnvelope(myListId, myEnvelope); 74 | 75 | } 76 | //ds-snippet-end:Apex3Step3 77 | 78 | //ds-snippet-start:Apex3Step1 79 | } 80 | //ds-snippet-end:Apex3Step1 81 | -------------------------------------------------------------------------------- /force-app/main/default/classes/SendMultipleEnvelopesController.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex4Step1 2 | public with sharing class SendMultipleEnvelopesController { 3 | public static void SendMultipleEnvelopes() { 4 | //ds-snippet-end:Apex4Step1 5 | 6 | //ds-snippet-start:Apex4Step2 7 | // Get up to 99 contacts in the "Prepared" offer stage 8 | List contacts = [SELECT Id, Name FROM Contact WHERE OfferStage__c = 'Prepared' LIMIT 99]; 9 | 10 | // Build a list of offer envelopes to send 11 | List envelopes = new List(); 12 | for (Contact c : contacts) { 13 | // Get an empty envelope with org defaults 14 | envelopes.add(dfsle.EnvelopeService.getEmptyEnvelope(new dfsle.Entity(c.Id)) 15 | // Customize the email subject and message 16 | .withEmail('Offer Letter for ' + c.Name, c.Name + ', please review and sign the enclosed offer letter.') 17 | // Add linked offer letter to envelope 18 | .withDocuments(dfsle.DocumentService.getLinkedDocuments( 19 | ContentVersion.getSObjectType(), 20 | new Set { c.Id }, 21 | true)) 22 | // Add the contact as a recipient 23 | .withRecipients(dfsle.RecipientService.getRecipients( 24 | Contact.getSObjectType(), 25 | new Set { c.Id }))); 26 | } 27 | //ds-snippet-end:Apex4Step2 28 | 29 | //ds-snippet-start:Apex4Step3 30 | // Send the envelopes and determine which envelopes were sent successfully 31 | // Filter out unsuccessfully sent envelopes 32 | List contactsToUpdate = new List(); 33 | List sentEnvelopes = new List(); 34 | for (dfsle.Envelope envelope : dfsle.EnvelopeService.sendEnvelopes(envelopes)) { 35 | if (envelope.error == null) { 36 | // Envelope sent successfully 37 | sentEnvelopes.add(envelope); 38 | contactsToUpdate.add(new Contact( 39 | Id = envelope.source.id, 40 | OfferStage__c = 'Out for Signature')); 41 | } else { 42 | // Handle send error 43 | System.debug('Envelope error: ' + envelope.error); 44 | } 45 | } 46 | 47 | // Update the Contact offer stage to "Out for Signature" 48 | update contactsToUpdate; 49 | //ds-snippet-end:Apex4Step3 50 | 51 | //ds-snippet-start:Apex4Step4 52 | List savedEnvelopes = dfsle.EnvelopeService.saveSentEnvelopes(sentEnvelopes); 53 | //ds-snippet-end:Apex4Step4 54 | 55 | //ds-snippet-start:Apex4Step5 56 | // Build a list of Contact IDs to query 57 | Set contactIds = new Set(); 58 | for (dfsle.Envelope envelope : savedEnvelopes) { 59 | contactIds.add(envelope.source.id); 60 | } 61 | 62 | // Retrieve the most recent envelope statuses from the Salesforce source objects 63 | // The status results are sorted oldest to newest 64 | List statuses = dfsle.StatusService.getStatus( 65 | contactIds, // Envelope source object IDs 66 | 99); // Maximum number of records to return 67 | 68 | // Display or take action on the returned statuses 69 | //ds-snippet-end:Apex4Step5 70 | //ds-snippet-start:Apex4Step1 71 | } 72 | } 73 | //ds-snippet-end:Apex4Step1 74 | -------------------------------------------------------------------------------- /force-app/main/default/classes/BulkSendWriteback.cls: -------------------------------------------------------------------------------- 1 | public class BulkSendWriteback { 2 | //ds-snippet-start:Apex13Step4 3 | @AuraEnabled 4 | public static Id buildList(){ 5 | 6 | List myBulkCopies = new List(); 7 | //SOQL is used to gather up the list of recipients to send to. In this case we get all contacts who have the bulk send checkbox set as true 8 | for (Contact m : [SELECT Contact.FirstName, Contact.LastName, Contact.Email, Contact.Id FROM contact where contact.Bulk_Send__c = true LIMIT 5]) 9 | { 10 | 11 | //To use merge fields and document writeback with bulk sending we have to add in the following custom fields. You first need to add them to your account under "Settings" -> "Envelope Custom Fields" 12 | // You need to create two envelope custom fields with the Field Name set as ##SFSource and ##SFDocumentWriteBack 13 | // https://developers.docusign.com/docs/salesforce/apex-toolkit-reference/customfield.html 14 | dfsle.CustomField sourceId = new dfsle.CustomField('text', '##SFSource', m.Id+'~Contact', null, false, true); // DocuSign custom field to capture Salesforce record Id. Replace ##SFSource with the name for your custom field 15 | dfsle.CustomField writeBackId = new dfsle.CustomField('text', '##SFDocumentWriteBack', m.Id+'~NamePDF~0~1', null, false, true); // DocuSign custom field to initiate document write back to Salesforce. 16 | 17 | //Create our recipients for the envelope 18 | myBulkCopies.add(dfsle.Envelope.newBulkCopy( 19 | dfsle.Recipient.newBulkRecipient( 20 | m.FirstName + ' ' + m.LastName, 21 | m.Email, 22 | null) // Source Salesforce object 23 | //The role needs to match up exactly with the role on your template. 24 | .withRole('Signer')) 25 | .withCustomFields(new List{ sourceId, writeBackId })); // DocuSign Custom Fields 26 | } 27 | // Create the bulk list. This list persists after sending and may be reused for multiple batches of envelopes 28 | dfsle.BulkList myList = dfsle.BulkSendService.createLists(new List { 29 | dfsle.BulkList.newList( 30 | 'My bulk list', // List name 31 | myBulkCopies, // Envelope copies 32 | null) // The Salesforce source object 33 | })[0]; 34 | // Save the ID for later operations 35 | Id myListId = myList.id; 36 | System.debug(LoggingLevel.INFO, myListId); 37 | return myListId; 38 | 39 | } 40 | //ds-snippet-end:Apex13Step4 41 | 42 | //ds-snippet-start:Apex13Step5 43 | @future(callout=true) 44 | /** 45 | * bulkSendEnvelopes method 46 | * Use myListId from buildList method 47 | */ 48 | public static void bulkSendEnvelopes(Id myListId){ 49 | 50 | dfsle.UUID myTemplateId = dfsle.UUID.parse('3df1fb4c-xxxx-xxxx-xxxx-cdf3cb0fe6b1'); // Substitute with your template ID 51 | dfsle.Document myDocument = dfsle.Document.fromTemplate( 52 | myTemplateId, // templateId in dfsle.UUID format 53 | 'myTemplate'); // name of the template 54 | 55 | // Create the draft bulk envelope. This will have exactly one placeholder bulk recipient 56 | dfsle.Envelope myEnvelope = dfsle.BulkSendService.getDraftEnvelope( 57 | new List { myDocument }, null); // Optional Salesforce source entity 58 | 59 | // Send envelope with a placeholder bulk recipient 60 | dfsle.BulkList.Result myResult = dfsle.BulkSendService.sendEnvelope(myListId, myEnvelope); 61 | System.debug(myResult); 62 | } 63 | //ds-snippet-end:Apex13Step5 64 | 65 | } -------------------------------------------------------------------------------- /force-app/main/default/classes/SendEnvelopeWithTabsController.cls: -------------------------------------------------------------------------------- 1 | //ds-snippet-start:Apex5Step1 2 | public with sharing class SendEnvelopeWithTabsController { 3 | 4 | @AuraEnabled 5 | 6 | public static void sendEnvelopeWithTabs() { 7 | //ds-snippet-end 8 | //ds-snippet-start:Apex5Step2 9 | Id mySourceId = '00XXXXXXXXXXXXXXAM'; // The ID of the initiating Salesforce object 10 | 11 | // Create an empty envelope 12 | dfsle.Envelope myEnvelope = dfsle.EnvelopeService.getEmptyEnvelope( 13 | new dfsle.Entity(mySourceId)); 14 | // The initiating Salesforce entity 15 | //ds-snippet-end 16 | 17 | //ds-snippet-start:Apex5Step3 18 | Id myDocumentId = '06XXXXXXXXXXXXXXAQ'; // The ID of a document stored in a Salesforce library 19 | Id myFileId = [SELECT id from ContentVersion where ContentDocumentId = :myDocumentId LIMIT 1].id; 20 | 21 | // Add document to the envelope 22 | myEnvelope = myEnvelope.withDocuments(dfsle.DocumentService.getDocuments(ContentVersion.getSObjectType(), new Set { myFileId })); 23 | //ds-snippet-end 24 | 25 | // Create an Initial Here tab 26 | //ds-snippet-start:Apex5Step4 27 | dfsle.Tab myInitialHereTab = new dfsle.InitialHereTab() 28 | .withRequired(true) // Signing optional 29 | .withPosition(new dfsle.Tab.Position( 30 | 1, // The document to use 31 | 1, // Page number on the document 32 | 320, // X position 33 | 290, // Y position 34 | null, // Default width 35 | null)); // Default height 36 | 37 | // Create a Text tab 38 | dfsle.Tab myTextTab = new dfsle.TextTab() 39 | .withRequired(true) // Signer must enter value 40 | .withPosition(new dfsle.Tab.Position( 41 | 1, // The document to use 42 | 1, // Page number on the document 43 | 210, // X position 44 | 305, // Y position 45 | 100, // 100 pixels wide 46 | null)); // Default height 47 | 48 | // Create a Sign Here tab 49 | dfsle.Tab mySignHereTab = new dfsle.SignHereTab() 50 | .withScale(1.5) // 1.5 scale 51 | .withRequired(true) // Signing mandatory 52 | .withAnchor(new dfsle.Tab.Anchor( 53 | 'signed', // Anchor string 54 | false, // Do not allow white space in anchor string 55 | false, // Anchor string is not case sensitive 56 | 'right', // Horizontal alignment in relation to the anchor text 57 | true, // Ignore if the anchor text is not present in the document 58 | true, // Must match the value of the anchor string in its entirety 59 | 'pixels', // Unit of the x and y offset properties 60 | 20, // X offset 61 | 0)); // Y offset 62 | 63 | // Create a Date Signed tab 64 | dfsle.Tab myDateSignedTab = new dfsle.DateSignedTab() 65 | .withFormatting(new dfsle.Tab.Formatting( 66 | 'Helvetica', // Font 67 | 'default', // Font color 68 | 14, // 14pt size, 69 | true, // Bold 70 | false, // Italic 71 | false, // Underline 72 | false, // Conceal value 73 | false)) // Fixed width 74 | .withPosition(new dfsle.Tab.Position( 75 | 1, // The document to use 76 | 1, // Page number on the document 77 | 330, // X position 78 | 470, // Y position 79 | null, // Default width 80 | null)); // Default height 81 | //ds-snippet-end 82 | 83 | 84 | // Create a new recipient 85 | //ds-snippet-start:Apex5Step5 86 | dfsle.Recipient myRecipient = dfsle.Recipient.fromSource( 87 | 'Lily TheGSD', // Signer name 88 | 'lilythegsd@gmail.com', // Signer email 89 | null, // Signer phone number 90 | 'Signer 1', // Signer role 91 | null) // No Salesforce association 92 | .withTabs(new List { // Associate the tabs with this recipient 93 | myInitialHereTab, 94 | myTextTab, 95 | mySignHereTab, 96 | myDateSignedTab 97 | }); 98 | 99 | // Add recipient to the envelope 100 | myEnvelope = myEnvelope.withRecipients(new List { myRecipient }); 101 | //ds-snippet-end 102 | 103 | // Send the envelope 104 | //ds-snippet-start:Apex5Step6 105 | myEnvelope = dfsle.EnvelopeService.sendEnvelope( 106 | myEnvelope, // The envelope to send 107 | true); // Send now? 108 | //ds-snippet-end 109 | //ds-snippet-start:Apex5Step1 110 | } 111 | } 112 | //ds-snippet-end --------------------------------------------------------------------------------