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

如何使用Python填充DocuSign模板Tabs字段并发送信封

无法填充DocuSign模板中的Tabs字段

我尝试填充DocuSign模板中已创建的文本字段(不同ID),但无论怎么修改代码都无法实现。已经查阅GitHub示例和API文档,当前代码仅能发送信封,无法填充模板里的文本字段。核心需求:

  • 加载指定DocuSign模板
  • 填充模板中指定的Tabs字段
  • 发送信封并确保填充内容显示
  • 不清楚如何将自定义字段与模板字段关联

以下是我尝试的代码:

@classmethod
#ds-snippet-start:eSign2Step2
def make_envelope(cls, args, doc_docx_path, doc_pdf_path):

    # Create the signer recipient model
    signer1 = Signer(
        email=args["signer_email"],
        name=args["signer_name"],
        recipient_id="1",
        routing_order="1",
        role_name = "Parent"
    )
            # Create the cc recipient
    cc1 = CarbonCopy(
        email=args["cc_email"],
        name=args["cc_name"],
        role_name="Representative",
        recipient_id="2"
    )
  # Recipients object:
    recipients_server_template = Recipients(
        carbon_copies=[cc1],
        signers=[signer1]
    )
    # Next, create the second composite template that will
    # include the new document.
    #
    # Create the signer recipient for the added document
    # starting with the tab definition:
    sign_here1 = SignHere(
        anchor_string="Agreed and signed:",
        anchor_y_offset="10",
        anchor_units="pixels",
        anchor_x_offset="20"
    )
    signer1_tabs = Tabs(sign_here_tabs=[sign_here1])

    # Create Signer definition for the added document
    signer1_added_doc = Signer(
        email=args["signer_email"],
        name=args["signer_name"],
        role_name="signer",
        recipient_id="1",
        client_user_id=args["signer_client_id"],
        tabs=signer1_tabs
    )
    recipients_added_doc = Recipients(
        carbon_copies=[cc1], signers=[signer1_added_doc])
    
    # Add a document        
    with open(path.join(demo_docs_path, "MacBook Release A.docx"), "rb") as file:
        docA_docx_bytes = file.read()
    docA_b64 = base64.b64encode(docA_docx_bytes).decode("ascii")
    
    documentA = Document(  # create the DocuSign document object
        document_base64=docA_b64,
        name="Laptop Release",  # can be different from actual file name
        file_extension="docx",  # many different document types are accepted
        document_id="1"  # a label used to reference the doc
    )
    # The order in the docs array determines the order in the envelope
 
    # Create a composite template for the Server template + roles
    comp_template1 = CompositeTemplate(
        composite_template_id="1",
        server_templates=[
            ServerTemplate(sequence="1", template_id="6f3a0b76-2329-4456-89a0-afc13a52aa19")
        ],
        # Add the roles via an inlineTemplate
        inline_templates=[
            InlineTemplate(sequence="2",
                           recipients=recipients_server_template)
        ]
    )
    # Create a composite template for the added document
   # comp_template2 = CompositeTemplate(
    #    composite_template_id="2",
     #   # Add the recipients via an inlineTemplate
      #  inline_templates=[
       #     InlineTemplate(sequence="1", recipients=recipients_added_doc)
        #],
       #document=documentA
    #)
    # The envelope has two recipients.
    # recipient 1 - signer
    # recipient 2 - cc
    # The envelope will be sent first to the signer.
    # After it is signed, a copy is sent to the cc person.

    env = EnvelopeDefinition(
        email_subject="Please sign this document set to receive your Laptop",
        composite_templates=[comp_template1] # , comp_template2]
    )
    env.documents = [documentA] 


    # Create signHere fields (also known as tabs) on the documents,
    # We're using anchor (autoPlace) positioning
    #
    # The DocuSign platform searches throughout your envelope's
    # documents for matching anchor strings. So the
    # signHere2 tab will be used in both document 2 and 3 since they
    # use the same anchor string for their "signer 1" tabs.
    sign_here1 = SignHere(
        anchor_string="Signature:",
        anchor_units="pixels",
        anchor_y_offset="10",
        anchor_x_offset="200"
    )

    sign_here2 = SignHere(
        anchor_string="/sn1/",
        anchor_units="pixels",
        anchor_y_offset="10",
        anchor_x_offset="20"
    )

    """
    Creates envelope
    args -- parameters for the envelope:
    signer_email, signer_name, signer_client_id
    returns an envelope definition
    """

    # Set the values for the fields in the template
    ##
    # Parent Name 1 is a template tab I am trying to reach
    #
    parent_1 = Text(
        document_id="1", page_number="1",
        font="helvetica", font_size="size14",
    )
    parent_1.tab_id ="Text 1"
    parent_1.tab_label ="Parent Name 1"
    parent_1.value = "Tim NORTON"

    # Add the tabs model (including the SignHere tab) to the signer.
    # The Tabs object wants arrays of the different field/tab types
    tabs = Tabs(
        text_tabs=[parent_1, sign_here1, sign_here2]
    )
    
    # create a signer recipient to sign the document, identified by name and email
    # We're setting the parameters via the object creation
    signer = TemplateRole(  # The signer
        email=args["signer_email"], name=args["signer_name"],
        # Setting the client_user_id marks the signer as embedded
        client_user_id=signer_client_id,
        template_id="xxxx0b76-xxxx-xxxx-afc13a52xxxx",
        role_name="Parent",
        tabs=tabs
    )
            
    # create an envelope custom field to save our application's
    # data about the envelope

    custom_field = TextCustomField(
        name="app metadata item",
        required="false",
        show="true",  # Yes, include in the CoC
        value="1234567"
    )

    cf = CustomFields(text_custom_fields=[custom_field])
    env.custom_fields = cf
    env.status = "sent"
    env.template_roles = [signer]
    env.email_subject = "Please sign this release sent from your school for a Laptop"
    

    # Add the tabs model (including the sign_here tabs) to the signer
    # The Tabs object wants arrays of the different field/tab types
    signer1.tabs = Tabs(sign_here_tabs=[sign_here1, sign_here2], text_tabs=[parent_1])

    # Add the recipients to the envelope object
    recipients = Recipients(signers=[signer1])
    env.recipients = recipients


    return env

问题分析

你的代码存在几个关键问题,导致无法填充模板字段:

  1. 配置冲突:同时使用CompositeTemplate和template_roles/recipients配置收件人,DocuSign优先处理复合模板,后者的配置被覆盖。
  2. 字段关联错误:填充模板字段时,错误指定了document_id和page_number(模板已预设字段位置),且字段绑定逻辑混乱。
  3. 文档配置冗余:同时加载模板文档和自定义文档,导致字段定位冲突。

修正方案

1. 简化复合模板配置

使用CompositeTemplate加载模板,在InlineTemplate中统一配置角色和填充字段,避免混用多种收件人配置方式。

2. 正确关联模板字段

填充模板字段时,无需指定位置信息,只需通过tab_label或tab_id匹配模板中的字段,并绑定到对应角色。

修正后的代码

@classmethod
def make_envelope(cls, args):
    # 1. 定义模板字段填充内容
    # 匹配模板中的"Parent Name 1"文本字段
    parent_name_field = Text(
        tab_label="Parent Name 1",
        value="Tim NORTON"
    )

    # 签名字段(模板已定义可省略,需新增则保留)
    sign_here1 = SignHere(
        anchor_string="Signature:",
        anchor_units="pixels",
        anchor_y_offset="10",
        anchor_x_offset="200"
    )

    # 为Parent角色绑定字段
    parent_tabs = Tabs(
        text_tabs=[parent_name_field],
        sign_here_tabs=[sign_here1]
    )

    # 2. 定义收件人角色
    signer1 = Signer(
        email=args["signer_email"],
        name=args["signer_name"],
        recipient_id="1",
        routing_order="1",
        role_name="Parent",
        tabs=parent_tabs,
        client_user_id=args.get("signer_client_id")
    )

    cc1 = CarbonCopy(
        email=args["cc_email"],
        name=args["cc_name"],
        role_name="Representative",
        recipient_id="2"
    )

    recipients = Recipients(
        signers=[signer1],
        carbon_copies=[cc1]
    )

    # 3. 创建复合模板加载指定模板
    comp_template = CompositeTemplate(
        composite_template_id="1",
        server_templates=[
            ServerTemplate(sequence="1", template_id="6f3a0b76-2329-4456-89a0-afc13a52aa19")
        ],
        inline_templates=[
            InlineTemplate(sequence="2", recipients=recipients)
        ]
    )

    # 4. 创建信封并发送
    env = EnvelopeDefinition(
        email_subject="Please sign this release sent from your school for a Laptop",
        composite_templates=[comp_template],
        status="sent"
    )

    # 添加自定义字段(可选)
    custom_field = TextCustomField(
        name="app metadata item",
        required="false",
        show="true",
        value="1234567"
    )
    env.custom_fields = CustomFields(text_custom_fields=[custom_field])

    return env

关键说明

  • 字段匹配规则:确保tab_label/tab_id与DocuSign模板中字段的设置完全一致(区分大小写)。
  • 复合模板优先级:使用模板创建信封时,必须通过CompositeTemplate的inline_templates配置角色和字段,不要直接设置env.recipients或env.template_roles,否则会被覆盖。
  • 文档管理:仅使用模板文档时,不要添加额外的env.documents,避免文档冲突。

内容的提问来源于stack exchange,提问作者Vanderdecken

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 21:17:33