owenbbkp 2020-04-17
之前谈到的Dicusign,都是发送一封邮件给到收件人,然后收件人完成签名的一个过程,那么有的时候,当我们需要直接在页面上打开用户签名的界面,而不是通过邮件的形式,那么就需要开启Docusign的嵌入式签名过程
整体步骤参考 Docusign系列(三)- SOAP方式调用Docusign,本质上来讲,嵌入式签名的形式,即将发送到用户的那封信件的链接,在页面上完成跳转,所以我们首先写一个页面按钮:打开Docusign签名链接(图左),当你点击按钮,会直接跳转到Docusign的签名页面(图右)


页面代码很简单,通过按钮调用Docusign的SOAP接口
<apex:page controller="ShowButtonCtrl" showHeader="false" sidebar="false">
<apex:form >
<apex:pagemessages />
<apex:pageBlock >
<apex:commandButton value="打开Docusign签名链接" action="{!testFunction}"/>
</apex:pageBlock>
</apex:form>
</apex:page>public class ShowButtonCtrl {
public String testFunction(){
String docusignurl = DocusignDemo2.sendWithDocusign(‘8002w000000HXkJ‘);
return docusignurl;
}
}那么关于Docusign部分的代码该怎么做呢?
首先是关于收件人,需要添加新的参数
// 设定一个 Client User Id String signer_user_id = ‘1‘; // 第一个签字 DocusignApi.Recipient firstSigner = new DocusignApi.Recipient(); firstSigner.ID = 1; firstSigner.Type_x = ‘Signer‘;// 收件人类型 - Signer表示需要签字 firstSigner.RoutingOrder = 1;// 签字顺序 firstSigner.Email = ‘XXXXXXX‘; firstSigner.UserName = ‘第一个签字‘; firstSigner.RequireIDLookup = false; // 嵌入式签名的参数 firstSigner.CaptiveInfo = new DocuSignAPI.RecipientCaptiveInfo(); firstSigner.CaptiveInfo.ClientUserID = signer_user_id; firstSigner.CaptiveInfo.EmbeddedRecipientStartURL = ‘SIGN_AT_DOCUSIGN‘;
然后在通过Docusign生成EnvelopeID之后,获取需要跳转的链接:
// 第一步:创建assertion
DocuSignAPI.RequestRecipientTokenAuthenticationAssertion assertion = new DocuSignAPI.RequestRecipientTokenAuthenticationAssertion();
assertion.AssertionID = ‘1‘;
assertion.AuthenticationInstant = Datetime.now();
assertion.AuthenticationMethod = ‘Password‘;
assertion.SecurityDomain = ‘DS_Recipe_Signer_View_Controller‘;
// Salesforce 环境域名
String baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
String signer_return_url = baseURL + ‘?cId=‘ + recordId;
String return_url_base = signer_return_url;
if(return_url_base.contains(‘?‘)) {
return_url_base += ‘&event=‘;
}else {
return_url_base = return_url_base += ‘?event=‘;
}
System.debug(LoggingLevel.INFO , ‘**** return_url_base:‘ + return_url_base);
// 第二步:为电子签名的不同结果创建重定向URL
DocuSignAPI.RequestRecipientTokenClientURLs urls = new DocuSignAPI.RequestRecipientTokenClientURLs();
urls.OnSigningComplete = baseURL + ‘/apex/welcome?conId=‘ + recordId;
urls.OnViewingComplete = return_url_base + ‘viewing_complete‘;
urls.OnCancel = return_url_base + ‘cancel‘;
urls.OnDecline = return_url_base + ‘decline‘;
urls.OnSessionTimeout = return_url_base + ‘session_timeout‘;
urls.OnTTLExpired = return_url_base + ‘ttl_expired‘;
urls.OnException = baseURL + ‘/apex/welcome?conId=‘ + recordId;
urls.OnAccessCodeFailed = return_url_base + ‘failed_access_code‘;
urls.OnIdCheckFailed = return_url_base + ‘failed_id_check‘;
urls.OnFaxPending = return_url_base + ‘fax_pending‘;
System.debug(LoggingLevel.INFO , ‘**** return_url_base:‘ + return_url_base);
String signer_view_url;
Boolean no_error = true;
try {
// 第三步:调用Docusign请求
signer_view_url = dsApi.RequestRecipientToken(envelopeId, signer_user_id, firstSigner.UserName, firstSigner.Email, assertion, urls);
System.debug(LoggingLevel.INFO , ‘**** Received signer_view_url:‘ + signer_view_url);
} catch ( CalloutException e) {
System.debug(LoggingLevel.INFO , ‘**** Exception - ‘ + e );
String error_code = ‘Problem: ‘ + e;
String error_message = error_code;
no_error = false;
}在搞定上面的内容之后,当Docusign签订完成会跳转到 ‘welcome‘ 这个自定义页面,

整体来看,在SOAP的接触上使用嵌入式签名还是很简单的,这样就可以让Docusign能在更多的地方被使用,比如在我们发送出去的Email中,或者其他自定义页面上,赋予了这种电子签名更广泛的应用空间
需要注意的是,这种嵌入式签名的有效期仅仅五分钟,同时在默认情况下,Docusign不会发送之前我们看到的Docusign请求签名的邮件给收件人,这一点从需求上不难理解,毕竟在页面上把合同啥的都签了,也不需要额外的邮件提醒了,不过Docusign也不是完全关闭了这样的通道,在Docusign的管理员界面中,选择Signing Setting页签

在这里,你可以关闭或者启用是否要在嵌入式场景下发送邮件给签名者
最后,附上DocusignDemo2 类的完整代码
public class DocusignDemo2 {
public static String USERID = ‘XXXXX‘;
public static String ACCOUNTID = ‘XXXXX‘;
public static String PASSWORD = ‘XXXXXX‘;
public static String INTEGRATORKEY = ‘XXXXXX‘;
public static String ENDPOINT = ‘https://demo.docusign.net/api/3.0/dsapi.asmx‘;
public static String sendWithDocusign(String recordId){
Contract con = [SELECT id FROM Contract WHERE Id=:recordId];
DocusignApi.DSAPIServiceSoap dsApi = new DocusignApi.DSAPIServiceSoap();
dsApi.endpoint_x = ENDPOINT;
//Set Authentication
String auth = ‘<DocuSignCredentials>‘
+ ‘<Username>‘+ USERID + ‘</Username>‘
+ ‘<Password>‘ + PASSWORD + ‘</Password>‘
+ ‘<IntegratorKey>‘ + INTEGRATORKEY + ‘</IntegratorKey>‘
+ ‘</DocuSignCredentials>‘;
System.debug(‘Setting authentication to: ‘ + auth);
dsApi.inputHttpHeaders_x = new Map<String, String>();
dsApi.inputHttpHeaders_x.put(‘X-DocuSign-Authentication‘, auth);
// 发送Docusign中的模板
DocuSignAPI.TemplateReference templateReference = new DocuSignAPI.TemplateReference();
templateReference.Template = ‘XXXXXXXXX‘;
templateReference.TemplateLocation = ‘Server‘;
DocusignApi.ArrayOfTemplateReference templateReferences = new DocusignApi.ArrayOfTemplateReference();
templateReferences.TemplateReference = new DocusignApi.TemplateReference[]{templateReference};
// 设定一个 Client User Id
String signer_user_id = ‘1‘;
// 第一个签字
DocusignApi.Recipient firstSigner = new DocusignApi.Recipient();
firstSigner.ID = 1;
firstSigner.Type_x = ‘Signer‘;// 收件人类型 - Signer表示需要签字
firstSigner.RoutingOrder = 1;// 签字顺序
firstSigner.Email = ‘XXXXXX‘;
firstSigner.UserName = ‘第一个签字‘;
firstSigner.RequireIDLookup = false;
// 嵌入式签名的参数
firstSigner.CaptiveInfo = new DocuSignAPI.RecipientCaptiveInfo();
firstSigner.CaptiveInfo.ClientUserID = signer_user_id;
firstSigner.CaptiveInfo.EmbeddedRecipientStartURL = ‘SIGN_AT_DOCUSIGN‘;
DocusignApi.ArrayOfRecipient1 recipients = new DocusignApi.ArrayOfRecipient1();
recipients.Recipient = new DocusignApi.Recipient[]{firstSigner};
DocusignApi.EnvelopeInformation envelopeInfo = new DocusignApi.EnvelopeInformation();
envelopeInfo.AccountId = ACCOUNTID;
envelopeInfo.Subject = ‘email subject‘;// Max 100 characters
envelopeInfo.EmailBlurb = ‘email message.‘;// Max 10000 characters
DocusignApi.CustomField platformName = new DocusignApi.CustomField ();
platformName.Name = ‘PlatformName‘;
platformName.Value = ‘Salesforce‘;
platformName.Show = ‘False‘;
DocusignApi.CustomField appName = new DocusignApi.CustomField ();
appName.Name = ‘AppName‘;
appName.Value = ‘DocuSignForSalesforce‘;
appName.Show = ‘False‘;
DocusignApi.CustomField SFContract = new DocusignApi.CustomField ();
SFContract.Name = ‘##SFContract‘;
SFContract.Value = recordId;
SFContract.Show = ‘False‘;
DocusignApi.CustomField DSFSSourceObjectId = new DocusignApi.CustomField ();
DSFSSourceObjectId.Name = ‘DSFSSourceObjectId‘;
DSFSSourceObjectId.Value = recordId + ‘~Contract‘;
DSFSSourceObjectId.Show = ‘False‘;
DocusignApi.ArrayOfCustomField arrayOfCustomFields = new DocusignApi.ArrayOfCustomField();
arrayOfCustomFields.CustomField = new list<DocusignApi.CustomField>();
arrayOfCustomFields.CustomField.add(platformName);
arrayOfCustomFields.CustomField.add(appName);
arrayOfCustomFields.CustomField.add(SFContract);
arrayOfCustomFields.CustomField.add(DSFSSourceObjectId);
System.debug(‘*** arrayOfCustomFields:‘ + arrayOfCustomFields);
envelopeInfo.CustomFields = arrayOfCustomFields;
// 保留信封ID
String envelopeId;
try {
DocusignApi.EnvelopeStatus es = dsApi.CreateEnvelopeFromTemplates(templateReferences,recipients,envelopeInfo,true);
envelopeId = es.EnvelopeID;
System.debug(LoggingLevel.INFO, ‘*** EnvelopeID:‘ + es.EnvelopeID);
System.debug(LoggingLevel.INFO, ‘*** Status:‘ + es.Status);
} catch ( CalloutException e) {
System.debug(‘Exception - ‘ + e );
}
// 第一步:创建assertion
DocuSignAPI.RequestRecipientTokenAuthenticationAssertion assertion = new DocuSignAPI.RequestRecipientTokenAuthenticationAssertion();
assertion.AssertionID = ‘1‘;
assertion.AuthenticationInstant = Datetime.now();
assertion.AuthenticationMethod = ‘Password‘;
assertion.SecurityDomain = ‘DS_Recipe_Signer_View_Controller‘;
// Salesforce 环境域名
String baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
String signer_return_url = baseURL + ‘?cId=‘ + recordId;
String return_url_base = signer_return_url;
if(return_url_base.contains(‘?‘)) {
return_url_base += ‘&event=‘;
}else {
return_url_base = return_url_base += ‘?event=‘;
}
System.debug(LoggingLevel.INFO , ‘**** return_url_base:‘ + return_url_base);
// 第二步:为电子签名的不同结果创建重定向URL
DocuSignAPI.RequestRecipientTokenClientURLs urls = new DocuSignAPI.RequestRecipientTokenClientURLs();
urls.OnSigningComplete = baseURL + ‘/apex/welcome?conId=‘ + recordId;
urls.OnViewingComplete = return_url_base + ‘viewing_complete‘;
urls.OnCancel = return_url_base + ‘cancel‘;
urls.OnDecline = return_url_base + ‘decline‘;
urls.OnSessionTimeout = return_url_base + ‘session_timeout‘;
urls.OnTTLExpired = return_url_base + ‘ttl_expired‘;
// urls.OnException = return_url_base + ‘exception‘;
urls.OnException = baseURL + ‘/apex/welcome?conId=‘ + recordId;
urls.OnAccessCodeFailed = return_url_base + ‘failed_access_code‘;
urls.OnIdCheckFailed = return_url_base + ‘failed_id_check‘;
urls.OnFaxPending = return_url_base + ‘fax_pending‘;
System.debug(LoggingLevel.INFO , ‘**** return_url_base:‘ + return_url_base);
String signer_view_url;
Boolean no_error = true;
try {
// 第三步:调用Docusign请求
signer_view_url = dsApi.RequestRecipientToken(envelopeId, signer_user_id, firstSigner.UserName, firstSigner.Email, assertion, urls);
System.debug(LoggingLevel.INFO , ‘**** Received signer_view_url:‘ + signer_view_url);
} catch ( CalloutException e) {
System.debug(LoggingLevel.INFO , ‘**** Exception - ‘ + e );
String error_code = ‘Problem: ‘ + e;
String error_message = error_code;
no_error = false;
}
String signingUrl;
if (no_error) {
signingUrl = signer_view_url;
System.debug(LoggingLevel.INFO , ‘**** signingUrl:‘ + signingUrl);
}
return signingUrl;
}
}