Skip to content

Code Walkthrough _ Embedded Signing

Steve Kreis edited this page Apr 20, 2015 · 2 revisions

Overview

When you are planning your application integration with DocuSign, you should consider how you want to handle the signing process. DocuSign offers two methods of running a Signing Ceremony, known as Remote and Embedded Signing.

Remote signing is when DocuSign sends email invitations to the Recipients, and the Recipients click on a link in the email to go to the DocuSign site and sign the documents. DocuSign takes care of everything – sending emails to the Recipients, handling all of the possible actions that they can take during signing, providing access to the signed documents after the signing ceremony is complete. It’s very easy to use, and doesn’t require any setup so it’s a good choice if you need to get up and running quickly. Here’s how it might work in a sample application.

Let’s say that you have a web application that collects some information from your customer, and prepares an envelope with the documents that the customer needs to sign. You send the envelope, and then inform your customer that they will receive an email from DocuSign, and that they will need to click on the link in the email to start the signing process. Then, once the signing is complete, your application can be notified via a status callback from DocuSign, and you can then take additional steps as necessary.

For some applications this is the most desirable flow, but for others it isn’t. It splits the customer interaction into multiple processes – the customer interacts with your application, then they leave your application and interact with DocuSign, and then they (at some future point) interact with your application again. At any point the customer may abandon the transaction, or forget to complete it. Neither of these outcomes is desirable.

You can avoid these issues by using the Embedded Signing pattern. Embedded Signing allows you to host the signing process in your own application and manage the customer interactions directly. It allows you to put your own processes around the signing ceremony to accomplish complex workflows.

How it works

Embedded Signing works by running a streamlined version of the DocuSign service inside of an iframe in your web application. Your application will make a request to DocuSign to start an Embedded Signing session for a particular Recipient, and DocuSign will provide you with a single use url (known as a RecipientToken) that can be used to start the session.

Your application will then set the iframe’s src attribute to this url, and the Embedded Signing session will start.
While the session is running, DocuSign will conduct the signing ceremony in the iframe. When the Recipient concludes the signing ceremony by signing the documents (or indicating that they do not wish to sign), DocuSign will redirect the iframe to a url, known as a ClientURL, designated by you. When your application detects that the ClientURL is requested, you can then continue with your application workflow.

The RecipientToken

Let’s look at the RecipientToken workflow in more detail.
First, you need to indicate which Recipients can use Embedded Signing when you send the Envelope. You do this by setting the CaptiveInfo object on the Recipient object. You can set the CaptiveInfo object on as many Recipients as you like, but you have to set it when you send the Envelope. The CaptiveInfo object has a single property named ClientUserId, and you must set this to some value that is unique on the Envelope. You can use something simple like “1” or “2”, or you can use some localID that is significant in your application – like a customerId. It just has to be unique on the envelope because this value will be used along with the Recipient’s Name and Email to request the RecipientToken. Remember that while the you can have multiple Recipients with the same Name and Email address (because the same person can act in multiple roles on a single envelope), they must all have different ClientUserIds.

Here’s an example of setting up a Recipient with the CaptiveInfo ClientUserId. In a real application this would have to be done on an Envelope of course – you can review the Create And Send Envelope walkthrough to see a complete Envelope setup.

	//.NET
	Recipient recipient= new Recipient();
	recipient.Email = "test@docusign.com";
	recipient.UserName = "Test User";
	recipient.ID = "1";
	recipient.Type = RecipientTypeCode.Signer;
	recipient.RequireIDLookup = false;
	recipient.CaptiveInfo = new RecipientCaptiveInfo();
	recipient.CaptiveInfo.ClientUserId = "1";
		
	//PHP
	$Recipient = new Recipient();
	$Recipient->Email = "test@docusign.com";
	$Recipient->UserName = "Test User";
	$Recipient->ID = "1";
	$Recipient->Type = "Signer";
	$Recipient->RequireIDLookup =false;
	$Recipient->CaptiveInfo->ClientUserId ="1";
	

Second, you have to get a RecipientToken for each Recipient that you want to have sign. When you get a Token, it is locked to the Recipient that you specify in the parameters. If you are having multiple Recipients sign, you will have request multiple RecipientTokens. Also note that the RecipientToken is a single use token. Once you use it, it is marked as used and if you try to reuse it, you will get an error. The RecipientToken also has a timeout (five minutes by default), so if you request a RecipientToken and try to use it ten minutes later, you will get an error.

The way to get a RecipientToken is the RequestRecipientToken API method. This method has a couple of parameters that we haven’t discussed yet, so let’s cover those and then we’ll show some code samples.

The Authentication Assertion

Part of Embedded Signing is allowing you to authenticate the Recipients who will be signing the documents. In exchange for DocuSign allowing you to do this, you have to supply DocuSign with a record referencing your authentication record, and the time, method, and domain of the authentication. The parameters are:

Parameter Description
AuthenticationID The recordId of your authentication record. For example, if you are tracking authentications in a log table, you could use the logId of the authentication event here.
AuthenticationInstant The date and time that the authentication was performed.
AuthenticationMethod An enumerated value that has common security methods listed, like ‘password’, ‘certificate’, etc.
SecurityDomain An identifier used to distinguish which part of your application performed the authentication. You can pass any value here – you might use the url of your website, or a string value like ‘CustomerPortal’, or your app name, etc.
ClientURLs

ClientURLs are an array of urls that are used when the Signing Ceremony is completed. The Array is keyed by event codes, so you can specify different urls for different events. There are currently 10 different events, and this may increase in the future. The exhaustive list is always specified in the API Documentation, but here is the current list (August 2010):

Event Description
OnSigningComplete The Recipient successfully completed the signing the document.
OnViewingComplete The Recipient successfully viewed the document.
OnCancel The Recipient cancelled the document while viewing the envelope.
OnDecline The recipient declined the envelope.
OnSessionTimeout The recipient session has timed out.
OnTTLExpired If a Recipient Token URL is invoked after it is expired.
OnAccessCodeFailed The Recipient failed to provide the correct Access Code.
OnIdCheckFailed The Recipient failed to pass the ID Check authentication questions.
OnException If an exception is thrown.
OnFaxPending If a faxed in document is pending.

Since there are different event codes, you can decide to use different pages on your site for each event, or you can use a single url with different parameters to indicate which event occurred. This latter method is usually employed just to reduce the amount of code that you maintain in your application.

ClientURLs and Security.
Although DocuSign is using these urls to signal your application, you should always confirm events by checking the status of the transaction whenever you receive one of these events. This is because a clever attacker could determine what your ClientURLs are and attempt to spoof your application by beginning a transaction and then manually requesting the SigningComplete ClientURL which would indicate that the signing is complete when it is not. Always confirm the transaction status when you get the Callback event.

The Code

Ok, let’s look at some sample code for this.

	//.NET
	string EnvelopeId = "Your EnvelopeID Here";

	// All of these three values must match an existing Recipient on the specified Envelope
	string UserName = "Test User";
	string Email = "test@docusign.com";
	string ClientUserId = "1";

	RequestRecipientTokenAuthenticationAssertion assert = new RequestRecipientTokenAuthenticationAssertion();
	assert.AssertionID = "Your AssertionID Here";
	assert.AuthenticationInstant = DateTime.Now;
	assert.AuthenticationMethod = RequestRecipientTokenAuthenticationAssertionAuthenticationMethod.Password;
	assert.SecurityDomain = "YourApp.com";

	RequestRecipientTokenClientURLs clientURLs = new RequestRecipientTokenClientURLs();

	clientURLs.OnAccessCodeFailed = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnAccessCodeFailed";
	clientURLs.OnCancel = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnCancel";
	clientURLs.OnDecline = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnDecline";
	clientURLs.OnException = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnException";
	clientURLs.OnFaxPending = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnFaxPending";
	clientURLs.OnIdCheckFailed = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnIdCheckFailed";
	clientURLs.OnSessionTimeout = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSessionTimeout";
	clientURLs.OnSigningComplete = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSigningComplete";
	clientURLs.OnTTLExpired = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnTTLExpired";
	clientURLs.OnViewingComplete = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnViewingComplete";

	// assumes apiService = preconfigured api proxy
	string RecipientToken = apiService.RequestRecipientToken(EnvelopeId,ClientUserId,UserName,Email,assert,clientURLs);

	// now we would set the iframe src attribute location to RecipientToken.
		
// PHP
	$RequestRecipientTokenParams = new RequestRecipientToken();
	$RequestRecipientTokenParams->EnvelopeID = "Your EnvelopeID Here" ;

	// All of these three values must match an existing Recipient on the specified Envelope
	$RequestRecipientTokenParams->Username = "Test User";
	$RequestRecipientTokenParams->Email = "test@docusign.com";
	$RequestRecipientTokenParams->ClientUserID = "1";
	// 
	$RequestRecipientTokenParams->AuthenticationAssertion->AssertionID = "Your AssertionID Here";
	$RequestRecipientTokenParams->AuthenticationAssertion->AuthenticationInstant = date("Y")."-".date("m")."-".date("d")."T00:00:00.00";
	$RequestRecipientTokenParams->AuthenticationAssertion->AuthenticationMethod = "Password";
	$RequestRecipientTokenParams->AuthenticationAssertion->SecurityDomain = "YourApp.com";

	$RequestRecipientTokenParams->ClientURLs->OnAccessCodeFailed =  "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnAccessCodeFailed";
	$RequestRecipientTokenParams->ClientURLs->OnCancel = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnCancel";
	$RequestRecipientTokenParams->ClientURLs->OnDecline =  "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnDecline";
	$RequestRecipientTokenParams->ClientURLs->OnException = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnException";
	$RequestRecipientTokenParams->ClientURLs->OnFaxPending =  "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnFaxPending";
	$RequestRecipientTokenParams->ClientURLs->OnIdCheckFailed =  "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnIdCheckFailed";
	$RequestRecipientTokenParams->ClientURLs->OnSessionTimeout ="https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSessionTimeout";
	$RequestRecipientTokenParams->ClientURLs->OnSigningComplete =  "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnSigningComplete";
	$RequestRecipientTokenParams->ClientURLs->OnTTLExpired = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnTTLExpired";
	$RequestRecipientTokenParams->ClientURLs->OnViewingComplete = "https://YourApp.com/DocuSignCallback.html?envelopeId=YourEnvelopeId&event=OnViewingComplete";
	
	// assumes $api = preconfigured api proxy
	$RequestRecipientTokenResponse = $api->RequestRecipientToken($RequestRecipientTokenParams);

	$RecipientToken = $RequestRecipientTokenResponse->RequestRecipientTokenResult;

	// now we would set the iframe src attribute location to $RecipientToken.

As you can see, the code is pretty straightforward. One thing to remember is that you have to use absolute, rather than relative, Urls for the ClientURLs. This is because the redirect will be evaluated against the iframe’s current url, rather than the url of your hosting page. It’s best to come up with some function to dynamically build the ClientURLs – for example, by inspecting the current hostname – rather than hardcoding them.

Now that we have the RecipientToken, we just set our iframe’s src attribute to this and let the session run. When the session is complete, the appropriate ClientURL will be loaded in the iframe. You will probably want to break out of the frame at this point – One pattern that you will see in the LoanCo and InsuranceCo samples is the use of a simple html page as the ClientURL, and then that page redirects the top frame to the appropriate page (signingreturn.php or signingreturn.aspx as appropriate) when it loads:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>DocuSign SDK - Frame Pop</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<script type="text/javascript">
		function framepop(){
			if (top.frames.length!=0)
		          top.location='signingreturn.php' + window.location.search;
				}
	</script>

<body onload="framepop();">
</body>
</html>

Then when the actual signingreturn page loads you can inspect the event and envelopeId parameters and check the status of the transaction.

That concludes our walkthrough. I highly recommend that you read the relevant sections of the official API Documentation as well – it covers all the details of the process and is the authoritative guide. And remember to check the DocuSign DevCenter if you have any questions or need additional resources.

Additional Resources