You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过DocuSign API传递Salesforce Opportunity ID填充模板?

如何在DocuSign CreateEnvelopeFromTemplatesAndForms调用中动态传递Salesforce Opportunity ID

我看你已经通过CreateEnvelopeFromTemplatesAndForms类实现了信封发送,也正确关联了模板和收件人,现在的核心问题是把动态的Opportunity ID传递给DocuSign模板,让它能拉取对应Salesforce记录的字段值对吧?其实只需要修改代码里自定义字段的赋值逻辑就行,具体步骤如下:

关键修改点

你当前代码里的##SFOpportunity自定义字段值是硬编码的固定ID,我们需要把它替换成控制器中已经获取到的动态oppId变量:

1. 替换硬编码的Opportunity ID

在do_send()方法中,找到自定义字段创建的代码块,把固定值改为this.oppId:

DocuSignTK.CustomField customField1 = new DocuSignTK.CustomField();
customField1.Name = '##SFOpportunity';
// 把硬编码的ID替换为控制器中已赋值的oppId变量
customField1.Value = this.oppId;

2. 确保逻辑完整性

因为你已经在send(String oppId)方法中查询了Opportunity记录并把ID赋值给了this.oppId,所以这个变量在do_send()执行时已经有了正确的动态值,不需要额外查询。

修改后的完整控制器代码

这里是更新后的完整代码,我已经替换了硬编码的Opportunity ID部分:

Public class DS_Recipe_Send_Env_Email_Controller { 
    // 通过邮件发送签署信封
    // 版权所有 (c) 2016 DocuSign, Inc.
    // 许可证:MIT许可证
    // 配置项
    Private static string integration_key = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
    Private static string account_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
    // 注意:必须使用长格式账户ID,包含32位数字和4个连字符(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
    // 该格式的账户ID可在DocuSign管理工具的API和连接部分查看
    Public string signer_email {get;set;} // 必填
    Public string signer_name {get;set;} // 必填
    Public string email_message {get;set;} // 可选
    public string oppId ;
    public string accountName ;
    Public string output {get;set;}
    Public string envelope_id {get;set;}
    Public string error_code {get;set;} // 为空表示无错误
    Public string error_message {get;set;}
    // 通过SFDC命名凭据使用旧版认证
    //Private static string ds_server = 'callout:DocuSign_Legacy_Demo/api/3.0/dsapi.asmx';
    // 若不使用命名凭据:
    Private static string ds_server = 'https://demo.docusign.net/api/3.0/dsapi.asmx'; //https://www.docusign.net/api/3.0/dsapi.asmx
    Private static string trace_value = 'SFDC_004_SOAP_email_send'; // 用于追踪API调用
    Private static string trace_key = 'X-ray';
    Private DocuSignTK.APIServiceSoap api_sender = new DocuSignTK.APIServiceSoap();
    
    Public DS_Recipe_Send_Env_Email_Controller(){}
    
    Public void send(){
        configure_sender();
        do_send();
        if (no_error()) {
            output = '<h2>信封已发送!</h2>';
            output += '<p>信封ID: ' + envelope_id + '</p>';
            output += '<p></p><p>签署人: ' + signer_name + ' <' + signer_email + '></p>';
        } else {
            output = '<h3>问题</h3><p>' + error_message + '</p>';
        }
    }
    
    public void send(String oppId) {
        if(String.isBlank(oppId)) return ;
        Opportunity opp = [SELECT Id, First_Owner__r.Name, First_Owner__r.Email, Account.Name FROM Opportunity WHERE ID = :oppId ] ;
        this.signer_name = opp.First_Owner__r.Name ;
        this.signer_email = opp.First_Owner__r.Email ;
        this.oppId = oppId ;
        this.accountName = opp.Account.Name ;
        send();
    }
    
    Private void configure_sender(){
        api_sender.endpoint_x = ds_server;
        api_sender.inputHttpHeaders_x = new Map<String, String>();
        String auth = '<DocuSignCredentials><Username>xxxxx</Username>' +
            '<Password>xxxxxx</Password>' +
            '<IntegratorKey>' + integration_key + '</IntegratorKey></DocuSignCredentials>';
        api_sender.inputHttpHeaders_x.put('X-DocuSign-Authentication', auth);
        //api_sender.timeout_x = 120000 ;
    }
    
    Private void do_send() {
        // 向signer_name / signer_email发送签署请求
        // 检查输入
        if (String.isBlank(signer_email) || String.isBlank(signer_name) || !signer_email.contains('@')) {
            error_message = '请填写邮箱和姓名字段';
            error_code = 'INPUT_PROBLEM';
            return;
        }
        // 检查配置
        if (integration_key == 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' || account_id == 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx') {
            error_message = '请配置Apex类DS_Recipe_Send_Env_Email_Controller的集成密钥和账户ID。';
            error_code = 'CONFIGURATION_PROBLEM';
            return;
        }
        // 此处提供文件内容
        // 文档数组可包含多种类型的多个文档
        // 所有文档在签署前会转换为PDF
        // fileExtension字段默认为"pdf"
        DocuSignTK.Recipient recipient = new DocuSignTK.Recipient();
        recipient.Email = signer_email;
        recipient.UserName = signer_name;
        recipient.ID = 1;
        recipient.Type_x = 'Signer';
        recipient.RoutingOrder = 1;
        recipient.RoleName = 'Signer 1';
        
        DocuSignTK.ArrayOfRecipient1 recipients = new DocuSignTK.ArrayOfRecipient1();
        recipients.Recipient = new DocuSignTK.Recipient[1];
        recipients.Recipient[0] = recipient;
        
        // 创建要使用的模板,生产环境请修改
        DocuSignTK.TemplateReference templateReference = new DocuSignTK.TemplateReference();
        templateReference.Template = '189c16de-b959-4dc6-bad6-ff47ef66468d';// b3bd42eb-313d-4c2a-bf97-04f2822d1c90
        templateReference.TemplateLocation = 'Server';
        
        DocuSignTK.ArrayOfTemplateReferenceRoleAssignment Roles = new DocuSignTK.ArrayOfTemplateReferenceRoleAssignment();
        Roles.RoleAssignment = new DocuSignTK.TemplateReferenceRoleAssignment[1];
        DocuSignTK.TemplateReferenceRoleAssignment role = new DocuSignTK.TemplateReferenceRoleAssignment();
        role.RoleName = 'Signer 1';
        role.RecipientID = 1;
        Roles.RoleAssignment[0] = role;
        templateReference.RoleAssignments = Roles;
        
        DocuSignTK.CustomField customField1 = new DocuSignTK.CustomField();
        customField1.Name = '##SFOpportunity';
        // 动态传递Opportunity ID
        customField1.Value = this.oppId;
        DocuSignTK.ArrayOfCustomField CustomFieldArray = new DocuSignTK.ArrayOfCustomField();
        CustomFieldArray.CustomField = new DocuSignTK.CustomField[1];
        CustomFieldArray.CustomField[0] = customField1;
        
        // 创建并填充信封信息
        DocuSignTK.EnvelopeInformation envelopeInfo = new DocuSignTK.EnvelopeInformation();
        envelopeInfo.Subject = 'One Park Financial Application for your Signature '+ recipient.UserName;
        envelopeInfo.AccountId = account_id;
        envelopeInfo.EmailBlurb = 'I am sending you this request for your electronic signature, please review and electronically sign by following the link below.';
        envelopeInfo.CustomFields = CustomFieldArray;
        
        // 调用API
        try {
            //DocuSignTK.EnvelopeStatus result = api_sender.CreateAndSendEnvelope(envelope);
            DocuSignTK.ArrayOfTemplateReference TemplateReferenceArray = new DocuSignTK.ArrayOfTemplateReference();
            TemplateReferenceArray.TemplateReference = new DocuSignTK.TemplateReference[1];
            TemplateReferenceArray.TemplateReference[0] = templateReference;
            DocuSignTK.EnvelopeStatus result = new DocuSignTK.EnvelopeStatus();
            if(!Test.isRunningTest()) result = api_sender.CreateEnvelopeFromTemplatesAndForms(
                TemplateReferenceArray, recipients, envelopeInfo, true);
            envelope_id = result.EnvelopeID;
            System.debug('返回成功,envelope_id = ' + envelope_id );
        } catch ( CalloutException e) {
            System.debug('异常 - ' + e );
            error_code = '问题: ' + e;
            error_message = error_code;
        }
    }
    
    Private Boolean no_error() {
        return (String.isEmpty(error_code));
    }
}

额外说明

  • 确保DocuSign模板中配置的关联字段名称##SFOpportunity和代码中的customField1.Name完全一致,大小写也要匹配。
  • 这样传递后,DocuSign会通过这个Opportunity ID关联到Salesforce的对应记录,模板中关联的Salesforce字段就会和集成发送时一样自动填充数据了。

内容的提问来源于stack exchange,提问作者One Park Financial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:49:52