I have been building some pdf forms and using docusign for signatures. The issue I am having with the current one is that docusign goes to "finished" after my 2nd signer signs. The logs show that it is not sending to my 3rd signer but I am unsure how to code the getToken to include the 3rd signer after the 2nd has signed.
Any advice would be very helpful.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
//$GLOBALS['_oneSigner'] = isset($_POST["autorefill"]);
createAndSend();
if(!$GLOBALS['_oneSigner']){
$GLOBALS['_showTwoSignerMessage'] = true;
}
} else if ($_SERVER["REQUEST_METHOD"] == "GET") {
if (isset($_GET["envelopeID"])) {
// Display a message that we are moving on to Signer Number 2
// - unless the message is suppressed (by signing from the GetStatusAndDocs page)
if(isset($_GET['from_gsad'])){
getToken(getStatus($_GET['envelopeID']),$_GET['clientID']);
}else{
$GLOBALS['_showTransitionMessage'] = true;
getToken(getStatus($_GET['envelopeID']),2);
}
} else {
$_SESSION["embedToken"] = "";
}
}
To prevent an email sending and using "Embedded Signing" you need to specify a clientUserId that would tell DocuSign not to send the email and instead expect a call to generate embedded signing url.
See complete code example here - https://developers.docusign.com/esign-rest-api/guides/features/embedding
Related
This is a question about using the DocuSign API, with their C# SDK, to send documents to recipients for digital signing, and then tracking the status changes at recipient level. I am having problems relating the status changes to the respective recipients.
There is one recipient per Envelope. I send a batch using the BulkEnvelopesAPI CreateBulkListRequest method. I then get status changes using the EnvelopesAPI ListStatusChanges method. I can see new documents when they have been sent and I can see status changes when the documents are signed.
However, I cannot relate these status changes to my recipients. So I have added a Custom Field to the Envelope to hold a unique value for the recipient. The ListStatusChanges response contains a list of Envelopes and each Envelope contains a CustomField property, but it is always null. I can get the Envelopes individually using the EnvelopesAPI ListCustomFields method, using the Envelope Id from ListStatusChanges, but this would mean a large number of API calls. I am sending about 4000 documents in batches of 1000. If I have to check envelopes individually, I will tend to hit up against the 1000-per hour API call limit.
So my question is: how do I set a Custom Field on the Envelope such that I can see it in the CustomFields property of the ListStatusChanges response Envelopes, without having to invoke the API for each Envelope in turn?
Here are some code extracts that might help:
When I create the BulkSendList, I create placeholders in its Envelope:
var theEnvelopeDefinition = new EnvelopeDefinition
{
TemplateId = myConfiguration["TemplateId"],
EnvelopeIdStamping = "false",
EmailSubject = myConfiguration["EmailSubject"],
Status = "created",
CustomFields = new CustomFields
{
TextCustomFields =
new List<TextCustomField>
{
new() { Name = "FRN" }
}
}
};
:
:
:
myEnvelopeApi.CreateEnvelope(myAccountId, theEnvelopeDefinition);
When I add recipients to the Bulk Send List, I do this:
var theBulkSendingList = new BulkSendingList
{
BulkCopies = new List<BulkSendingCopy>(),
Name = "Adviser Terms of Business Mailing"
};
foreach (ZurichAdvisersDocuSignControl aWorkItem in myWorkItems)
{
var theBulkSendingCopy = new BulkSendingCopy
{
CustomFields = new List<BulkSendingCopyCustomField>
{
new() { Name = "FRN", Value = aWorkItem.FcaRegistrationNumber },
new() { Name = "EmailAddress", Value = aWorkItem.EmailAddress }
},
EmailSubject = "This is a test email",
Recipients = new List<BulkSendingCopyRecipient>
{
new()
{
Name =
$"{aWorkItem.RecipientFirstName} {aWorkItem.RecipientLastName}",
Email = aWorkItem.EmailAddress,
RecipientId =
"1" // this has to match the envelope and possibly also something in the template
}
},
EmailBlurb =
string.Format(
CultureInfo.InvariantCulture,
theEmailBlurb,
theGreeting,
aWorkItem.RecipientFirstName)
};
theBulkSendingList.BulkCopies.Add(theBulkSendingCopy);
}
BulkSendingList theBulkSendList =
myBulkEnvelopesApi.CreateBulkSendList(myAccountId, theBulkSendingList);
myBulkListId = theBulkSendList.ListId;
When I request status changes I do this:
var theEnvelopeApi = new EnvelopesApi(myApiClient);
var theOptions = new EnvelopesApi.ListStatusChangesOptions
{
fromDate = DateTime.Now
.AddDays(-1)
.ToString("yyyy/MM/dd")
};
// Call the API method:
EnvelopesInformation theResults =
theEnvelopeApi.ListStatusChanges(myAccountId, theOptions);
In theResults of that last step, I get a List of Envelopes, which includes the Envelopes sent by the BulkSendList. They all have a null CustomFields property. They do have a CustomFieldsUri property and if I use that in Postman it does show me the CustomField values that I set in CreateBulkSendList. Or I can invoke ListCustomField one Envelope at a time. But either way that would lead to too many API calls.
Any thoughts? Is there a better way to do what I am trying to do? I could just bite the bullet and implement something that manages the 1000-per-hour API call limit, but the existence of BulkSendLists gave me hope that I'd not need to. Or I could filter the ListStatusChanges call to only show Envelopes where the status has progressed beyond Sent since the last time I checked; this would reduce the number of changes returned and so reduce the number of ListCustomFields calls I need to do per hour, but there is still the risk I hit the limit.
Thanks
Steve
https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopes/liststatuschanges/
See this:
Your C# code should change to :
var theOptions = new EnvelopesApi.ListStatusChangesOptions
{
include = "custom_fields",
fromDate = DateTime.Now.AddDays(-1).ToString("yyyy/MM/dd")
};
Embededed Signing
I created a template by Docusign Web Tool. I followed these steps, the embedded signing page is working but no signing tool was showing up. Even I added all tags/fields on the defined template.
I'm using Golang language and this library
1/ Create envelop using a template id
var sv = envelopes.New(c.credential)
var env = &model.EnvelopeDefinition{
Status: "sent",
TemplateID: c.config.DocusignTermTemplateID,
TemplateRoles: []model.TemplateRole{
{
Email: params.Email,
Name: params.Name,
RoleName: "signed",
ClientUserID: params.ClientID,
DefaultRecipient: true,
},
},
}
envSummary, err := sv.Create(env).Do(context.Background())
if err != nil {
c.CustomLogger.Error(err)
return nil, err
}
2/ Create embedded signing views.
var sv = envelopes.New(c.credential)
var req = sv.ViewsCreateRecipient(params.EnvelopID, &model.RecipientViewRequest{
ClientUserID: params.ClientID,
AuthenticationMethod: "none",
Email: params.Email,
UserName: params.Name,
XFrameOptions: "allow_from",
XFrameOptionsAllowFromURL: c.config.MerchantDashboardURL,
ReturnURL: fmt.Sprintf("%s?client_id=%s", c.config.DocusignCallbackURL, params.ClientID),
})
resp, err := req.Do(context.Background())
if err != nil {
return nil, eris.Wrap(err, err.Error())
}
We (DocuSign) can't provide support about an external library.
Some things to try:
Edit your question to add in the API logs that will show what was actually sent to DocuSign.
Don't use an iFrame for the signing ceremony and first try without the iFrame attributes.
You don't need the DefaultRecipient: true attribute on the Envelope create call.
First try creating the envelope for remote signing (signing via email). Remove the clientUserId setting to accomplish this. Check that the envelope is delivered properly, looks right, etc.
Then add in the embedded sending. This way you can determine if the problem is with the envelope create call or the envelope recipient view call.
A common cause of this is that the template roles aren't aligned between your API call and the template on the server. To confirm, you'll want to check your server template and confirm that the Role Name is signed (as it is in your API call) and that the signer role does not have a pre-filled name and email (as pre-filling the name/email blocks populating those values through the API).
I have this thing working for like 2 years. Then it stopped sending emails to the signers after they signed a document. By the way the document is created from a widget embedded method.
I'm using the PHP SDK of the docusign API. And here's a summary of my code
$envelopeApi = new \DocuSign\eSign\Api\EnvelopesApi($apiClient);
$document = new \DocuSign\eSign\Model\Document();
$document->setDocumentBase64("My document template");
$document->setName("My template name);
$document->setDocumentId("randomly generated document ID");
// creates the sign here
$signHere = new \DocuSign\eSign\Model\SignHere();
$signHere->setAnchorString("Signature:");
$signHere->setAnchorIgnoreIfNotPresent("false");
$signHere->setAnchorUnits("pixels");
$signHere->setAnchorYOffset("50");
$signHere->setAnchorXOffset("5");
$signHere->setDocumentId("The document ID");
$signHere->setRecipientId("The recipient ID, randomly generated");
// add the signature tab to the envelope's list of tabs
$tabs = new \DocuSign\eSign\Model\Tabs();
$tabs->setSignHereTabs(array($signHere));
// add the signer to the envelope
$signer = new \DocuSign\eSign\Model\Signer();
$signer->setName("Recipient Name");
$signer->setEmail("Recipient Email");
$signer->setRecipientId("The recipient ID");
$signer->setTabs($tabs);
$signer->setClientUserId("The client user ID");
// Add a recipient to sign the document
$recipients = new \DocuSign\eSign\Model\Recipients();
$recipients->setSigners(array($signer));
$envelop_definition = new \DocuSign\eSign\Model\EnvelopeDefinition();
$envelop_definition->setEmailSubject("Mail subject");
// set envelope status to "sent" to immediately send the signature request
$envelop_definition->setStatus("sent");
$envelop_definition->setRecipients($recipients);
$envelop_definition->setDocuments(array($document));
// create and send the envelope! (aka signature request)
$envelopeApi->createEnvelope("Owner account ID", $envelop_definition, null);
I knew that by adding the envelope definition status "sent" would send a copy to the signer but thats not the case. Did something happened recently on the API that I have to adapt? I checked the documentation but still the same. So I'm not sure if I'm doing the right thing.
Any help would be greatly appreciated. Thanks in advance.
By setting a ClientUserId for your signer, you are creating a Captive Recipient. If you want DocuSign to do email delivery, remove the ClientUserId parameter and a Remote Recipient will be created instead.
I am trying to integrate docusign embedded signing into my hybrid app and i am loading the signing url in an iframe in my app, but is there any way to add some more custom fields on the fly using that signing url and make it in an unlocked state so that i can drag them where i want, and then make those fields locked at the time of sending to the sender for signing, also how to get the url of that document after he has signed it so that i can view it later.
Since i am a newbie in this please help me.
This is my code to get the signing url
<?php
$min=100;
$max=300;
$random = rand($min,$max);
$recipientId=rand();
require_once('vendor/autoload.php');
//require_once('./docusign-php-client/autoload.php');
// DocuSign account credentials & Integrator Key
$username = "testmail#mail.com";
$password = "test1234";
$integrator_key = "[integrator-key]";
$host = "https://demo.docusign.net/restapi";
// create a new DocuSign configuration and assign host and header(s)
$config = new DocuSign\eSign\Configuration();
$config->setHost($host);
$config->addDefaultHeader("X-DocuSign-Authentication", "{\"Username\":\"" . $username . "\",\"Password\":\"" . $password . "\",\"IntegratorKey\":\"" . $integrator_key . "\"}");
/////////////////////////////////////////////////////////////////////////
// STEP 1: Login() API
/////////////////////////////////////////////////////////////////////////
// instantiate a new docusign api client
$apiClient = new DocuSign\eSign\ApiClient($config);
// we will first make the Login() call which exists in the AuthenticationApi...
$authenticationApi = new DocuSign\eSign\Api\AuthenticationApi($apiClient);
// optional login parameters
$options = new \DocuSign\eSign\Api\AuthenticationApi\LoginOptions();
// call the login() API
$loginInformation = $authenticationApi->login($options);
// parse the login results
if(isset($loginInformation) && count($loginInformation) > 0)
{
// note: defaulting to first account found, user might be a
// member of multiple accounts
$loginAccount = $loginInformation->getLoginAccounts()[0];
if(isset($loginInformation))
{
$accountId = $loginAccount->getAccountId();
if(!empty($accountId))
{
echo "<b>Account ID</b> = $accountId</br>";
}
}
}
/////////////////////////////////////////////////////////////////////////
// STEP 2: Create & Send Envelope with Embedded Recipient
/////////////////////////////////////////////////////////////////////////
// set recipient information
$recipientName = "username";
$recipientEmail = "Test#email.com";
// configure the document we want signed
$documentFileName = "/abcd_test_01.pdf";
$documentName = "abcd_test.pdf";
// instantiate a new envelopeApi object
$envelopeApi = new DocuSign\eSign\Api\EnvelopesApi($apiClient);
// Add a document to the envelope
$document = new DocuSign\eSign\Model\Document();
$document->setDocumentBase64(base64_encode(file_get_contents(__DIR__ . $documentFileName)));
$document->setName($documentName);
$document->setDocumentId("1");
// Create a |SignHere| tab somewhere on the document for the recipient to sign
$signHere = new \DocuSign\eSign\Model\SignHere();
$signHere->setXPosition($random);
$signHere->setYPosition($random);
$signHere->setDocumentId("1");
$signHere->setPageNumber("1");
$signHere->setRecipientId("1");
// add the signature tab to the envelope's list of tabs
$tabs = new DocuSign\eSign\Model\Tabs();
$tabs->setSignHereTabs(array($signHere));
// add a signer to the envelope
$signer = new \DocuSign\eSign\Model\Signer();
$signer->setEmail($recipientEmail);
$signer->setName($recipientName);
$signer->setRecipientId("1");
$signer->setTabs($tabs);
$signer->setClientUserId($recipientId); // must set this to embed the recipient!
// Add a recipient to sign the document
$recipients = new DocuSign\eSign\Model\Recipients();
$recipients->setSigners(array($signer));
$envelop_definition = new DocuSign\eSign\Model\EnvelopeDefinition();
$envelop_definition->setEmailSubject("[DocuSign PHP SDK] - Please sign this doc");
// set envelope status to "sent" to immediately send the signature request
$envelop_definition->setStatus("sent");
$envelop_definition->setRecipients($recipients);
$envelop_definition->setDocuments(array($document));
// create and send the envelope! (aka signature request)
$envelop_summary = $envelopeApi->createEnvelope($accountId, $envelop_definition, null);
echo "<b>Envelope Details: </b><pre>".$envelop_summary ."</pre></br>";
/////////////////////////////////////////////////////////////////////////
// STEP 3: Request Recipient View (aka signing URL)
/////////////////////////////////////////////////////////////////////////
// instantiate a RecipientViewRequest object
$recipient_view_request = new \DocuSign\eSign\Model\RecipientViewRequest();
// set where the recipient is re-directed once they are done signing
$recipient_view_request->setReturnUrl("https://www.docusign.com/develcenter");
// configure the embedded signer
$recipient_view_request->setUserName($recipientName);
$recipient_view_request->setEmail($recipientEmail);
// must reference the same clientUserId that was set for the recipient when they
// were added to the envelope in step 2
$recipient_view_request->setClientUserId($recipientId);
// used to indicate on the certificate of completion how the user authenticated
$recipient_view_request->setAuthenticationMethod("email");
// generate the recipient view! (aka embedded signing URL)
$signingView = $envelopeApi->createRecipientView($accountId, $envelop_summary->getEnvelopeId(), $recipient_view_request);
echo "</br> Signing URL = <a href='" . $signingView->getUrl() . "' target='_blank'>".$signingView->getUrl()."</a></br>";
//MEthod for embedded sending view
$return_url="https://www.docusign.com/devcenter";
$senderView = $envelopeApi->createSenderView($accountId, $envelopeId,
$return_url);
var_dump($senderView->getUrl());
If you want to place additional fields on the document as a sender, you should use the Embedded Sending (or Sender View)
The Embedded Sending view of an envelope allows users to edit the tabs, documents, recipients, and other settings of draft envelopes before sending them out for approval. Similar to Embedded Signing, your app or website can generate a sending URL and integrate directly into your workflow using a Redirect, Webview, or an iFrame.
See here for the code sample.
Q : How to get the url of that document after he has signed it so that i can view it later.
See this answer.
I have created a DocuSign envelope from template. I have stored the envelope id for future operations. Using this envelope id I can only retrieve the envelope that I have created but I need the template id too. Is there any way to retrieve the template id from envelope or FolderItems? Please help :(
I'm not sure if you create an envelope from a Template if the templateId is saved as meta data anywhere in the envelope (I don't believe it is). As such you can simply do that yourself - try using Envelope Custom Fields to store the templateId at the time of creation, and that templateId will then be stored as meta data on that envelope throughout it's lifecycle.
Do a search in the DocuSign API Documentation to find out more about "Envelope Custom Fields". For example, here is the page for how to create them.
Thank you #Ergin. I have tried to implement your idea and it is working. But there are some other issues whatever I have done. I am sharing some parts of my code.
//Getting available folder list of my DocuSign account.
DocuSignServiceRef.AvailableFolders folders = DocuSignHelper.GetDocuSignServiceClient().GetFolderList(new DocuSignServiceRef.FoldersFilter { AccountId = DocuSignHelper.UserID });
//Creating a FolderFilter item to get folder items using this filter.
DocuSignServiceRef.FolderFilter filter = new DocuSignServiceRef.FolderFilter();
filter.AccountId = DocuSignHelper.UserID;
filter.FolderTypeInfo = new DocuSignServiceRef.FolderTypeInfo();
filter.FolderTypeInfo = folders.Folders[1].FolderTypeInfo; //Filter Send Items
//Getting sent items
DocuSignServiceRef.FolderResults results = DocuSignHelper.GetDocuSignServiceClient().GetFolderItems(filter);
if (results != null && results.ResultSetSize > 0)
{
foreach (DocuSignServiceRef.FolderItem item in results.FolderItems)
{
foreach (DocuSignServiceRef.RecipientStatus recipient in item.RecipientStatuses)
{
//Filtering items by Recipient
if (recipient.Email.Equals(RecipientEmail))
{
//Getting envelope of the folder item
DocuSignServiceRef.Envelope sentEnvelope = DocuSignHelper.GetDocuSignServiceClient().RequestEnvelope(item.EnvelopeId, false);
if (sentEnvelope.CustomFields != null)
{
//Checking envelope's custom fields for template id
foreach (DocuSignServiceRef.CustomField customField in sentEnvelope.CustomFields)
{
if (string.Equals(customField.Name, "TemplateID"))
{
if (customField.Value == "{CurrentTemplateID}")
{
HasAlreadySignedSameTemplate = true;
//I will not request the recipient for another signature on same template.
}
}
}
}
}
}
}
}
The above code is working for me. But it is taking too much time to load all Sent items. I can't see any way to set recipient information in FolderFilter. If I can set the recipient's email in filter at the first while I am loading Sent Items then time will be saved for me. Otherwise this code will get unusable.
Have you any idea about modifying my implementation?
If you are creating envelopes with a REST call you can retrieve the info with a call templatesv2/accounts/:accountId/envelopes/:envelopeId/templates
Have a go in the envelope tab. I noticed that envelopes created with a SOAP sdk don't have this information filled in.