zoukankan      html  css  js  c++  java
  • Docusign系列(四)

    之前谈到的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页签

     在这里,你可以关闭或者启用是否要在嵌入式场景下发送邮件给签名者,同时设置一个 CaptiveInfo 参数(参数说明

    最后,附上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;
         // EmbeddedRecipientStartURL –这是发件人提供的用于重定向收件人的有效URL字符串。
         // 使用此选项时,嵌入式收件人仍会像远程收件人一样从DocuSign接收电子邮件,但是当单击电子邮件中的文档链接时,
         // 收件人将通过DocuSign重定向到该URL以完成其操作
         // 路由到URL时,由发送者的系统(服务器响应URL)决定是否请求接收者令牌启动签名会话。
         // 如果此节点使用值SIGN_AT_DOCUSIGN,则收件人将直接在DocuSign上定向到嵌入式签名或查看过程。
         // 签名或查看操作由DocuSign系统启动,并且交易活动和完成证书记录将对此进行反映。在所有其他方面,
         // 该过程与任何合作伙伴都会发起的嵌入式签名或查看操作相同
    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;
        }
    }
  • 相关阅读:
    PHP——语句和时间函数
    数据库——环境初建改端口和密码(转)
    PHP——初学,基础
    数据库——常用函数
    数据库——触发器(转)
    数据库——浅谈数据库中的存储过程(转)
    JavaScrip——简单练习(抓错误信息,for循环,日期)
    数据库——练习题答案
    django 创建APP 后找不到 templates文件夹下的Html文件。
    POSTGRESQL 9.1 FATAL: password authentication failed for user "postgres"
  • 原文地址:https://www.cnblogs.com/luqinghua/p/12719480.html
Copyright © 2011-2022 走看看