文档完成使用DocuSign API启动签名过程时,不会按预期向每个收件人发送通知

时间:2018-06-06 08:28:44

标签: docusignapi

我正在通过Docusign API通过Docusign模板测试文档签名。文档签名完成后,每个收件人都应该收到一份文档完成通知,其中包含查看文档的链接。但是,当使用DocuSign API启动签名过程时,文档完成通知不会按预期发送给每个收件人。请指导我的帮助链接。

我还想知道如何设置在签名完成后发送给每个收件人的证书完成文件。对此有任何帮助表示赞赏。

由于

2 个答案:

答案 0 :(得分:1)

我看到你为供应商角色以外的所有类型的签名者设置clientUserId。现在为签名者设置clientUserId告诉DocuSign您正在应用中实施嵌入式签名。作为嵌入式签名,因此默认和设计,DocuSign不会向嵌入式签名者发送任何类型的电子邮件通知。要使DocuSign发送带有完成证明的完成电子邮件,您需要修改DocuSign帐户中的签名设置。在您的DS帐户中,Go To Admin - &gt;来自Select Signing Settings部分下方左侧导航的SIGNING AND SENDING。然后,滚动到“签名设置”页面底部的Envelope Delivery部分,如下面的屏幕截图所示,选择向嵌入式签名者发送完成电子邮件,并选择选择将完成证书附加到信封< / strong>即可。这应该可以解决您的问题。

enter image description here

答案 1 :(得分:-1)

请在下面找到创建和发送信封以及为代理和购买者角色发起签名的代码。

[授权]

[HttpPost]

[ValidateAntiForgeryToken]

public JsonResult Create(CreateContractViewModel viewModel)
{
    if (!ModelState.IsValid)
        return Json(new { success = false, errors=ModelStateExtensions.GetErrors(ViewData.ModelState.Values) },  JsonRequestBehavior.AllowGet);


try
{
    #region "Validation"

    if (viewModel.Purchasers == null) //only allow max. of 2 purchasers at this point in time.
        return Json(new { success = false, errors = "Minimum of one Purchaser is required." },
            JsonRequestBehavior.AllowGet);
    if (viewModel.Purchasers.Count > 2) //only allow max. of 2 purchasers at this point in time.
        return Json(new { success = false, errors = "Number of Purchasers allowed exceed." },
            JsonRequestBehavior.AllowGet);

    #endregion
     // Get template based on drop down selection.
    var envTemplate = Templates.Get(viewModel.SelectTemplateId);

    // Assign all parties. eg. recipients, signers, and CCs
    var docusignRecipients = envTemplate.Recipients;
    var signers = docusignRecipients.Signers;
    var carbonCopies = docusignRecipients.CarbonCopies;
    var templateRolesList = new List<TemplateRole>();

    if (viewModel.Purchasers.Count == 1) //remove Purchaser 2 if there's only 1 Purchaser needed.
    {
        var remove = signers.SingleOrDefault(x => x.RoleName.Equals(RoleNames.Purchaser_2));
        if (remove != null)
            signers.Remove(remove);
    }

    // Minimum of 1 Purchaser must exist.
    var purchaser1 = viewModel.Purchasers[0];
    var purchaser2 = viewModel.Purchasers.Count > 1
        ? viewModel.Purchasers[1]
        : new Purchaser();

    #region "Setup Template Roles"

    // Recipients
    var envelopeRecipients = new Recipients
    {
        RecipientCount = docusignRecipients.RecipientCount,
        Signers = new List<Signer>(),
        CarbonCopies = new List<CarbonCopy>()
    };

    // Signers
    TemplateRoles.Signers.AddRoles(viewModel, signers, purchaser1, purchaser2, envelopeRecipients,
        docusignRecipients);
    // Carbon Copies
    TemplateRoles.CarbonCopies.AddRoles(carbonCopies, envelopeRecipients, docusignRecipients);

    #endregion

    #region "Prepare & Create Envelope"

    // Server template
    var serverTemplates = new List<ServerTemplate>
            {
                new ServerTemplate
                {
                    Sequence = "1",
                    TemplateId = viewModel.SelectTemplateId
                }
            };
    // Server inline template
    var serverInlineTemplates = new List<InlineTemplate>
            {
                new InlineTemplate
                {
                    Sequence = "2",
                    Recipients = envelopeRecipients
                }
            };


    // refactor this part to a new method.
    var documentFactory = new DocumentFactory(viewModel.SelectTemplateId, _documentService);

    var type = viewModel.OptionalInserts.GetType();
    var optionalInserts = type.GetProperties();
    var templateList = new List<CompositeTemplate>();
    foreach (var insert in optionalInserts)
    {
        var value = insert.GetValue(viewModel.OptionalInserts);
        var isChecked = (bool)value;
        if (!isChecked) continue;

        var template = documentFactory.GetTemplate(insert.Name);
        var compositeTemplate = template.Compose();
        templateList.Add(compositeTemplate);
    }

    // Prepare composite template, combining the Server and Inline templates
    var compositeTemplates = new List<CompositeTemplate>
            {
                new CompositeTemplate
                {
                    ServerTemplates = serverTemplates,
                    InlineTemplates = serverInlineTemplates
                }
            };
    templateList.ForEach(t => compositeTemplates.Add(t));


    // Create Envelope Definition
    var envDef = Envelopes.CreateEnvDef(envTemplate, compositeTemplates);

    // Create Envelope
    var envSummary = Envelopes.CreateEnvelope(envDef);

    #endregion

    #region "Generate View Url"

    // Generate recipient Url - Agent as 1st recipient by default
    var agent = envelopeRecipients.Signers.SingleOrDefault(x => x.RoleName.Equals(RoleNames.Agent));
    if (agent == null)
        return
            Json(
                new
                {
                    success = false,
                    errors = "No Agent role has been found.",
                    JsonRequestBehavior.AllowGet
                });


    var returnUrl = Url.Action("Sign", "Contract",
      new { envelopeId = envSummary.EnvelopeId, routingOrder = agent.RoutingOrder, selectedTemplateId = viewModel.SelectTemplateId });//modified on 15-6-2017
                                                                                                                                      // Get View Options.
    var viewOptions = DocuSign.Recipients.ViewRequest(returnUrl, agent.ClientUserId, agent.Name, agent.Email);
    // Create Recipient View
    var view = Envelopes.CreateRecipientView(envSummary.EnvelopeId, viewOptions);

    #endregion

    return Json(new { success = true, returnUrl = view.Url, JsonRequestBehavior.AllowGet });
}
catch (Exception e)
{
    return Json(new
    {
        success = false,
        errors = e.Message,
        JsonRequestBehavior.AllowGet
    });
}

}

  public ActionResult Sign(CreateContractViewModel viewModel)
    //public ActionResult Sign() //previous code
    {
        var paramEvent = Request.QueryString["event"];
        var paramEnvId = Request.QueryString["envelopeId"];
        var paramRoutingOrder = Request.QueryString["routingOrder"];
        var selectedTemplateId = Request.QueryString["selectedTemplateId"];
        var contractIdQueryString = Request.QueryString["contractId"];


        // Validation
        if (string.IsNullOrEmpty(paramEvent) || string.IsNullOrEmpty(paramEnvId) ||
            string.IsNullOrEmpty(paramRoutingOrder) || (paramEvent != SigningStatus.Signing_Complete))
            return View("Error");

        // Get next Signer
        var recipients = Envelopes.ListRecipients(paramEnvId);
        var signers = recipients.Signers;

        ///////addded on 25/5/2017 to check docusign value extraction

        //var cfe = Envelopes.ListRecipientsWithTags(paramEnvId);
        //Envelopes.ListCustomFields(paramEnvId);
        //List<TextCustomField> tcfList = cfe.TextCustomFields;
        //foreach (var tcf in tcfList)
        //{
        //    string dfd = tcf.FieldId;
        //    string ddfdfd = tcf.Name;
        //    string sdf = tcf.Value;
        //    //string str = cfe.TextCustomFields[0].FieldId;
        //}
        //EnvelopesApi envelopesApi = new EnvelopesApi();
        //CustomFieldsEnvelope cfe = envelopesApi.ListCustomFields(accountId, _templateId2);
        //TemplateCustomFields cfUpdate = new TemplateCustomFields();
        //cfUpdate.TextCustomFields = new System.Collections.Generic.List<TextCustomField>();
        //TextCustomField tcf = new TextCustomField();
        //tcf.FieldId = cfe.TextCustomFields[0].FieldId;

        // Get template based on drop down selection.
        //var envTemplate = Templates.Get(viewModel.SelectTemplateId);
        //// Assign all parties. eg. recipients, signers, and CCs
        //var docusignRecipients = envTemplate.Recipients;
        //var signers1 = docusignRecipients.Signers;
        int ContractId = 0;

        if (contractIdQueryString != null && contractIdQueryString !="")
        {
            ContractId = int.Parse(contractIdQueryString.Trim());
        }


        ContractId= GetTabs(signers, selectedTemplateId, paramRoutingOrder, ContractId);


        /////
        //note:ClientUserId is made null only for the Vendor role in  TemplateRoles.Signers.AddRoles method, so that
        //signing continues for the Agent and Purchaser roles only
        var nextSigner = (from s in signers
                          where
                          !string.IsNullOrEmpty(s.ClientUserId) &&
                          (Convert.ToInt32(s.RoutingOrder) > Convert.ToInt32(paramRoutingOrder))
                          orderby s.RoutingOrder
                          select s).FirstOrDefault();

        //added following on 06/06/2018 to prevent workflow from proceeding to the next signers. But this will prevent capturing signed dates by signers
        //if( paramEvent == "signing_complete" && paramRoutingOrder == "1")
        // {
        //     return View("Completed");
        // }

        // return View("Completed");

        //

        #region Code that proceeds workflow to the next signer. Need to have an option to allow agent to go for following approach which allows purchaser to sign via the application or, another option that allows purchaser to receive an email notification for completing signing as done in above commented code
        // No next Signer redirect to Completed page.
        if (nextSigner == null) return View("Completed"); 

        //var returnUrl = Url.Action("Sign", "Contract",
        //    new
        //    {
        //        envelopeId = paramEnvId,
        //        routingOrder = nextSigner.RoutingOrder,
        //        recipientId = nextSigner.RecipientId
        //    });//original code
        var returnUrl = Url.Action("Sign", "Contract",
           new
           {
               envelopeId = paramEnvId,
               routingOrder = nextSigner.RoutingOrder,
               recipientId = nextSigner.RecipientId,
               selectedTemplateId = selectedTemplateId,
               contractId = ContractId
           });//modified on 19-6-2017           

        // Get View Options.
        var viewOptions = DocuSign.Recipients.ViewRequest(returnUrl, nextSigner.ClientUserId, nextSigner.Name,
            nextSigner.Email);

        // Create Recipient View
        var view = Envelopes.CreateRecipientView(paramEnvId, viewOptions);

        return Redirect(view.Url);
        #endregion
    }


      public static class TemplateRoles
{
    public static class Signers
    {
        public static void AddRoles(CreateContractViewModel viewModel, List<Signer> signers, Purchaser purchaser1, Purchaser purchaser2,
             global::DocuSign.eSign.Model.Recipients r, global::DocuSign.eSign.Model.Recipients recipients)
        {
            try
            {
                foreach (var signer in signers)
                {
                    switch (signer.RoleName)
                    {
                        default:
                            throw new Exception("Unknown Signer role was found on the template.");

region&#34;作用:代理&#34;

                    case RoleNames.Agent:

                        // Fill all Sign tabs for Agent role, which includes Purchaser fields.
                        // Agent role is the first point of the draft, therefore all the fields need to be prefilled.
                        var signerTabs = signer.Tabs;

                        if (signerTabs != null)
                        {
                            if (signerTabs.TextTabs != null)
                            {
                                var signerTextTabs = signerTabs.TextTabs;
                                DocuSign.Tabs.Sign(viewModel, signerTextTabs, purchaser1, purchaser2);
                            }

                            if (signerTabs.CheckboxTabs != null)
                            {
                                var signerCheckboxTabs = signerTabs.CheckboxTabs;
                                DocuSign.Tabs.SignCheckBoxes(viewModel, signerCheckboxTabs, purchaser1, purchaser2);//Assigning check box values
                            }
                        }

                        var agentSigner = recipients.Signers.Find(x => x.RoleName == "Agent");
                        if (agentSigner != null)
                        {
                            var s = new Signer();
                            s = agentSigner;
                            s.RoleName = signer.RoleName;
                            s.Name = signer.Name;
                            s.Email = signer.Email;
                            s.RoutingOrder = signer.RoutingOrder;
                            s.ClientUserId = Guid.NewGuid().ToString();
                            s.Tabs = signerTabs;

                            r.Signers.Add(s);
                        }
                        break;

                    #endregion

                    #region "Role: Purchaser 1"

                    case RoleNames.Purchaser_1:

                        var purchaserSigner = recipients.Signers.Find(x => x.RoleName == "Purchaser 1");
                        if (purchaserSigner != null)
                        {
                            var p1 = new Signer();
                            p1 = purchaserSigner;
                            p1.RoleName = RoleNames.Purchaser_1;
                            p1.Name =
                            (!string.IsNullOrEmpty(purchaser1.CompanyName)
                                ? purchaser1.CompanyName
                                : $"{purchaser1.FirstName} {purchaser1.Surname}");
                            p1.Email = (!string.IsNullOrEmpty(purchaser1.Email) ? purchaser1.Email : null);
                            p1.RoutingOrder = signer.RoutingOrder;
                            p1.ClientUserId = Guid.NewGuid().ToString();
                            p1.Tabs = signer.Tabs;

                            r.Signers.Add(p1);
                        }
                        break;

                    #endregion

                    #region "Role: Purchaser 2"

                    case RoleNames.Purchaser_2:


                        var purchaser2Signer = recipients.Signers.Find(x => x.RoleName == "Purchaser 2");
                        if (purchaser2Signer != null)
                        {
                            var p2 = new Signer();
                            p2 = purchaser2Signer;
                            p2.RoleName = RoleNames.Purchaser_2;
                            p2.Name =
                            (!string.IsNullOrEmpty(purchaser2.CompanyName)
                                ? purchaser2.CompanyName
                                : $"{purchaser2.FirstName} {purchaser2.Surname}");
                            p2.Email = (!string.IsNullOrEmpty(purchaser2.Email) ? purchaser2.Email : null);
                            p2.RoutingOrder = signer.RoutingOrder;
                            p2.ClientUserId = Guid.NewGuid().ToString();
                            p2.Tabs = signer.Tabs;

                            r.Signers.Add(p2);
                        }
                        break;

                    #endregion

                    #region "Role: Vendor"

                    case RoleNames.Vendor: // No embedded signing.

                        var vendorSigner = recipients.Signers.Find(x => x.RoleName == "Vendor");
                        if (vendorSigner != null)
                        {
                            var v = new Signer();
                            v = vendorSigner;
                            v.RoleName = signer.RoleName;
                            v.Name = signer.Name;
                            v.Email = signer.Email;
                            v.RoutingOrder = signer.RoutingOrder;
                            v.ClientUserId = null;

                            r.Signers.Add(v);
                        }
                        break;

                        #endregion
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
}

}