Ruby on Rails集成DocuSign:模板信封发送、预填及签收回传问题
问题描述
我正在开发一个基于Ruby on Rails的应用,通过授权码认证集成DocuSign,核心需求是:
- 直接使用DocuSign平台上已包含文档的现有模板发送信封,无需从Rails应用附加额外文档
- 预填模板中的字段值后,再发送给用户签署
- 用户签署完成后,将已签署文档以PDF形式回传到Rails应用
当前进展
- 已完成授权码认证的集成工作
- 能通过现有模板创建并发送信封
- 可获取未签署状态的PDF文件
遇到的问题
- 移除附加文档的代码后,请求失败并返回
document missing错误 - 不清楚如何预填模板中的字段值
- 不知道如何在用户签署完成后获取已签署的PDF文件
现有代码
def send_data_using_template(access_token) template_id = "8f33b649-****-4aa2-804a-01f2*****5e3" recipient_name = "ali676750" recipient_email = "abc@gmail.com" document_file_path = "config/Software licensing agreement.pdf" fields_to_prefill = { "name" => "ahmad", "title" => "software engineer" } signer1 = DocuSign_eSign::Signer.new( email: recipient_email, name: recipient_name, recipientId: '11', routing_order: '11' ) document_base64 = Base64.strict_encode64(File.read(document_file_path)) document = { documentBase64: document_base64, name: File.basename(document_file_path), fileExtension: File.extname(document_file_path).delete('.'), documentId: '1' } tabs = DocuSign_eSign::Tabs.new recipients = DocuSign_eSign::Recipients.new( signers: [signer1], ) envelope_definition = DocuSign_eSign::EnvelopeDefinition.new( emailSubject: "Your subject line here", status: "sent", template_id: template_id, documents: [document], tabs: tabs ) envelope_definition.recipients = recipients response = HTTParty.post("https://demo.docusign.net/restapi/v2.1/accounts/#{ENV['DOCUSIGN_ACCOUNT_ID']}/envelopes", headers: { "Authorization" => "Bearer #{access_token}", "Content-Type" => "application/json" }, body: envelope_definition.to_json) if response.code == 201 puts "Envelope created successfully " envelope_id = response.parsed_response["envelopeId"] response = HTTParty.get( "https://demo.docusign.net/restapi/v2.1/accounts/#{ENV['DOCUSIGN_ACCOUNT_ID']}/envelopes/#{envelope_id}/documents/combined", headers: { "Authorization" => "Bearer #{access_token}" } ) decoded_content = Base64.decode64(response.body) file_path = "config/signed_document.pdf" File.open(file_path, "wb") { |file| file.write(decoded_content) } puts "PDF file saved successfully at #{file_path}" else puts "Error creating envelope: #{response.body}" end end
解决方案
1. 无需附加文档,直接使用模板发送信封
当使用现有模板创建信封时,不能同时指定template_id和documents参数,这会让DocuSign混淆文档来源,从而抛出document missing错误。只需要保留template_id,移除所有文档相关的代码即可。
修改后的核心代码片段:
# 移除所有文档读取、构造的代码 # document_base64 = Base64.strict_encode64(File.read(document_file_path)) # document = { ... } # 创建信封定义时,仅保留必要参数 envelope_definition = DocuSign_eSign::EnvelopeDefinition.new( emailSubject: "Your subject line here", status: "sent", template_id: template_id )
2. 预填模板中的字段值
预填字段需要通过TemplateRole关联签署人和模板中的角色,同时在Tabs中指定字段值(注意字段的tabLabel必须和模板中设置的完全一致)。
修改后的核心代码片段:
# 构造预填的文本字段,tabLabel必须和模板中定义的一致 text_tabs = [ DocuSign_eSign::Text.new( tabLabel: "name", value: "ahmad" ), DocuSign_eSign::Text.new( tabLabel: "title", value: "software engineer" ) ] tabs = DocuSign_eSign::Tabs.new(text_tabs: text_tabs) # 使用TemplateRole关联签署人和模板角色,roleName必须和模板中定义的角色名一致 template_role = DocuSign_eSign::TemplateRole.new( email: recipient_email, name: recipient_name, roleName: "Signer", # 替换为你模板中的角色名称 tabs: tabs ) # 将TemplateRole赋值给信封定义 envelope_definition.template_roles = [template_role]
3. 获取用户签署完成后的PDF
当前代码在信封创建成功后立即拉取文档,此时文档还未被签署。正确的做法是通过**DocuSign Webhook(Connect)**接收签署完成的通知,再拉取已签署的PDF,这是最高效的方式。
步骤1:配置Webhook
在DocuSign控制台中配置Connect:
- 设置通知URL为你的Rails应用接口(比如
/docusign/webhook) - 选择触发事件为
Envelope Completed
步骤2:处理Webhook请求
在Rails中添加对应的控制器动作:
# routes.rb post '/docusign/webhook', to: 'docusign#webhook' # docusign_controller.rb def webhook envelope_id = params[:envelopeId] status = params[:status] # 仅处理签署完成的事件 if status == "completed" access_token = # 从你的token存储中获取有效access token response = HTTParty.get( "https://demo.docusign.net/restapi/v2.1/accounts/#{ENV['DOCUSIGN_ACCOUNT_ID']}/envelopes/#{envelope_id}/documents/combined", headers: { "Authorization" => "Bearer #{access_token}" } ) if response.success? decoded_content = Base64.decode64(response.body) # 保存文件,建议用envelope_id命名避免重复 file_path = "config/signed_document_#{envelope_id}.pdf" File.open(file_path, "wb") { |file| file.write(decoded_content) } end end # 必须返回200状态码给DocuSign,否则会重复发送通知 head :ok end
如果不想使用Webhook,也可以定时轮询信封状态,但Webhook是更优的方案。
内容的提问来源于stack exchange,提问作者Hira
相关产品推荐
相关产品推荐

