The In-Person Sign feature is available in DocuSign for electronic signature even if the signer does not have access to email or a computer. With the In Person Signing feature, you set up an envelope normally, but assign it to a DocuSign user who will act as a Signing Host for the process.
The signer goes to the same physical location as the signing host; the host then initiates the signing process and then helps the signer complete the electronic documents. After completing the process, the documents can be saved and printed as needed.
Let we see how we are going implement the In-Person sign feature using apex.
Assume an Account record has multiple Contacts. We need to get the electronic signature from all the contacts associated with this account. Once all the contacts have signed, the document is going to be attached in DocuSign status record under the Account object.
For this you must have the following things.
- You must have a DocuSign account.
- Install DocuSign app into Salesforce account.
- Enable the API key into your DocuSign account.
- Store the DocuSign credential and API key into your custom setting in salesforce.
Here is the code snippet for the In-Person signing in DocuSign:
/*This method is used to Identify the users who are all going to sign the document and make a callout to DocuSign endpoint*/ public pageReference SignNowmultiEmail(){ String account; String UserName; String Password; String IntegratorKey; String endPointURL; String initial = ''; // get the docusign credential, API key and endpointURL from the custom settting. Map<String, DocuSignCredentials Setting__c>credentialSetting = DocuSignCredentialsSetting __c.getAll(); for(DocuSignCredentialsSetting__c credentialIns : credentialSetting.values()){ UserName = credentialIns.name; account = credentialIns.account__c; Password = credentialIns.Password__c; IntegratorKey = credentialIns.IntegratorKey__c; endPointURL = credentialIns.end_Point__c; } String endpoint = endPointURL+'/accounts/ '+account+'/envelopes'; String authorizationHeader= '+UserName+''+Password+ ''+IntegratorKey+''; String status; String email; String recipients = ''; Integer i = 1; String boundary = 'AAA'; // Here we are going to renderAs the page WishLiabilitySignNow_VF page. Pagereference PDF = Page.WishLiability SignNow_VF; PDF.getParameters().put('Id',caseId); try { documentPDF = EncodingUtil.base64Encode (PDF.getContentAsPDF()); }catch(Exception e) { } Map<String,String> recipientMap = new Map<String,String>(); // Store the contact name and email into the recpientMap. for(Contact dbContact : [SELECT Id,Name,AccountId,Email FROM Contact WHERE AccountId =: currentRecId]){ recipientMap.put(key.trim(), 'Participant'); } Account dbAccount = [SELECT Id,EnvelopId__c,SignerMapKeyPair__c FROM Account WHERE Id =: currentRecId]; // Check the envelop is already sent or not.If not then send envelop with recipient who are all going to sign. if(dbAccount.EnvelopId__c == Null){ for(String currString : recipientMap.Keyset()){ String Name = currString; if(recipients != '') recipients = recipients + ','; recipients = recipients + '{'+ ' "email": "kanagaraj@mstsolutions.com",'+ ' "name": "'+Name+'",'+ ' "recipientId":"'+i+'",'+ ' "clientUserId":"'+i+'",'+ ' "tabs": {'+ ' "signHereTabs": [{'+ ' "anchorString":"~s'+i+'",'+ ' "anchorXOffset": "0",'+ ' "anchorYOffset": "0",'+ ' "anchorIgnoreIfNotPresent": "false",'+ ' "anchorUnits": "inches"'+ ' }],'+ ' "dateSignedTabs": [{'+ ' "anchorString": "~date'+i+'",'+ ' "anchorXOffset": "0",'+ ' "fontSize": "Size14",'+ ' "fontColor": "Black",'+ ' "anchorYOffset": "0",'+ ' "anchorIgnoreIfNotPresent": "false",'+ ' "xPosition": "100",'+ ' "yPosition": "72",'+ ' "anchorUnits": "inches"'+ ' }]'+ ' }'+ ' }'; if(!signersKeyPairMap. containsKey(Name)) signersKeyPairMap.put (Name,String.valueof(i)); i++; } //forming payload with the document and recipients. String body = '{'+ ' "status":"sent",'+ ' "enableWetSign": "false",'+ ' "emailBlurb":"",'+ ' "emailSubject": "Liability And Publicity Release Form",'+ ' "enforceSignerVisibility":"True",'+ ' "documents": [{'+ ' "name": "document.pdf",'+ ' "documentId":"1",'+ ' "order":"1",'+ ' "documentBase64":"'+documentPDF+'"'+ ' }],'+ '"recipients": {'+ ' "signers" : ['+recipients+']'+ ' }'+ '}'; String viewBody = '{'+ '"returnUrl": "https://www.docusign.com/ devcenter"'+ '}'; String header = '--'+boundary+'\nContent-Type: application/json\nContent-Disposition: form-data'; String jsonBody = header +'\n\n'+body+'\n\n--'+boundary+'--'; //Callout to Docusign. HttpRequest req = new HttpRequest(); req.setHeader('X-DocuSign-Authentication', authorizationHeader); req.setHeader('Accept',c' application/json'); req.setHeader('Host','demo. docusign.net'); req.setHeader('Content-Length','162100'); req.setHeader('Content-Type','multipart/form-data; boundary='+boundary); req.setEndpoint(endpoint); req.setMethod('POST'); req.setBody(jsonBody); Http http = new Http(); HTTPResponse res; try{ if(recipients != ''){ res = http.send(req); system.debug('response 1'+res.getBody()); //Docusign status record creation. Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped (res.getBody()); if((String) results.get('envelopeId') != '') envelopeId = (String) results.get('envelopeId'); if((String) results.get('status') == 'Sent'){ status = 'Agreement sent'; // Create docusign status record. dsfs__DocuSign_Status__c dsfs= NEW dsfs__DocuSign_Status__c(); dsfs.dsfs__DocuSign_Envelope_ID__c = (String) results.get('envelopeId'); dsfs.dsfs__Case__c= caseId; Insert dsfs; } else status = (String) results.get('errorCode'); } }catch(Exception e){ }} else { //if envelop already sent then get the envelop from the hidden field.and also get the recipient. envelopeId = dbcase.EnvelopId__c; for(String key : dbcase.SignerMapKeyPair__c.split(',')){ String keys = key.trim().split('-')[0]; String value = key.trim().split('-')[1]; signersKeyPairMap.put (keys.trim(),value.trim()); } } return null; } /*This method is used Sign the document by the selected user and send to callout docusign endpoint. */ public Pagereference SubmitAndSign(){ String account; String UserName; String Password; String IntegratorKey; String endPointURL; List relationShipList = new List(); string timmedName = SingerName.trim(); Map<String,DocuSign CredentialsSetting__c> credentialSetting = DocuSignCredentials Setting__c.getAll(); for(DocuSignCredentials Setting__c credentialIns : credentialSetting.values()){ UserName = credentialIns.name; account = credentialIns.account__c; Password = credentialIns.Password__c; IntegratorKey = credentialIns.IntegratorKey__c; endPointURL = credentialIns.end_Point__c; } string endpoint = endPointURL+'/accounts/ '+account+'/envelopes'; String authorizationHeader =‘'+UserName+''+Password+ ''+IntegratorKey+''; string endpoint2 = endPointURL+'/accounts/'+ account+'/envelopes/'+ envelopeId+'/views/recipient'; HttpRequest request = new HttpRequest(); request.setHeader('X-DocuSign-Authentication', authorizationHeader); request.setHeader('Accept', 'application/json'); request.setHeader('Host', 'demo.docusign.net'); request.setHeader('Content-Length','162100'); request.setHeader('Content-Type','application/json'); request.setMethod('POST'); Http httprequest = new Http(); HTTPResponse response; request.setEndpoint(endpoint2); string jsonPayload; system.debug('URL. getSalesforceBaseUrl(). toExternalForm()'+URL. getSalesforceBaseUrl(). toExternalForm()); String baseUrl = URL.getSalesforceBaseUrl(). toExternalForm(); jsonPayload = '{'+ ' "userName": "'+SingerName+'",'+ ' "email": "test@docusign.com",'+ ' "recipientId": "'+signersKeyPairMap.get (timmedName)+'",'+ ' "clientUserId": "'+signersKeyPairMap.get (timmedName)+'",'+ ' "authenticationMethod": "None",'+ ' "returnUrl": "'+baseUrl +'/apex/WishLiabilityForm_VF?Id='+CaseId+'"'+ '}'; request.setBody(jsonPayload); response = httprequest.send(request); Map<String, Object> results = (Map<String, Object>)JSON. deserializeUntyped (response.getBody()); //signersKeyPairMap.remove (SingerName); String sign; for(String name : signersKeyPairMap.KeySet()){ if(sign == '' || sign == Null) sign= name +' - '+ signersKeyPairMap.get(name); else sign = sign+','+ name+' - '+ signersKeyPairMap.get(name);} Account newAccount = new Account(); newAccount.Id = currentRecId; newAccount.SignerMapKeyPair__c = sign; newAccount.EnvelopId__c = envelopeId; update newAccount; PageReference reference=new PageReference((String) results.get('url')); reference.setRedirect(true); return reference; }
Result:
Step 1:
Step 2:
Step 3:
Step 4:
Step 5:  Again do the step 2 and 3
Reference link: