Docusign系列(四) - 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; } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM